T-Box 车载终端方案
T-Box 系统架构
硬件架构
┌─────────────────────────────────────────────────────────┐
│ T-Box 硬件架构 │
│ │
│ 电源管理 │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 12V/24V 汽车电源 → 防反接 → 过压保护 → DC-DC │ │
│ │ → 3.8V(模组)/ 3.3V(MCU)/ 1.8V(传感器) │ │
│ └──────────────────────────────────────────────────┘ │
│ │
│ 核心处理 │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ 主控 SoC │ │ 蜂窝模组 │ │ GNSS 模组 │ │
│ │ i.MX8M │ │ RG520N │ │ LC29H / LG69T │ │
│ │ (NXP) │ │ (5G) │ │ (高精度+DR) │ │
│ └──────────┘ └──────────┘ └──────────────────────┘ │
│ │
│ 车辆接口 │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ CAN FD │ │ LIN 总线 │ │ 以太网(100BASE-T1)│ │
│ │ 控制器 │ │ 控制器 │ │ 车载以太网 │ │
│ └──────────┘ └──────────┘ └──────────────────────┘ │
│ │
│ 存储与安全 │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ eMMC 32G │ │ HSM 安全 │ │ 加速度传感器 │ │
│ │ 数据存储 │ │ 芯片 │ │ (碰撞检测) │ │
│ └──────────┘ └──────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────┘软件架构
应用层:
TSP 通信客户端 / OTA 管理 / 数据采集 / eCall
中间件:
MQTT 客户端 / TLS 安全 / 数据压缩 / 日志管理
操作系统:
Linux(Yocto)或 Android Automotive
驱动层:
CAN 驱动 / GNSS 驱动 / 蜂窝驱动 / 传感器驱动CAN 总线数据采集
CAN FD 配置
c
#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/socket.h>
#include <net/if.h>
// 打开 CAN 接口
int open_can_socket(const char *interface) {
int sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
struct ifreq ifr;
strcpy(ifr.ifr_name, interface);
ioctl(sock, SIOCGIFINDEX, &ifr);
struct sockaddr_can addr = {
.can_family = AF_CAN,
.can_ifindex = ifr.ifr_ifindex
};
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
return sock;
}
// 读取 CAN 帧
void read_can_data(int sock) {
struct can_frame frame;
while (1) {
int nbytes = read(sock, &frame, sizeof(frame));
if (nbytes < 0) break;
printf("CAN ID: 0x%03X, DLC: %d, Data:",
frame.can_id, frame.can_dlc);
for (int i = 0; i < frame.can_dlc; i++) {
printf(" %02X", frame.data[i]);
}
printf("\n");
// 解析特定 CAN 消息
parse_can_message(frame.can_id, frame.data, frame.can_dlc);
}
}
// 解析车辆 CAN 消息(示例:车速)
void parse_can_message(uint32_t can_id, uint8_t *data, uint8_t dlc) {
switch (can_id) {
case 0x3B3: // 车速(示例 ID,实际因车型而异)
{
uint16_t speed_raw = (data[0] << 8) | data[1];
float speed = speed_raw * 0.01f; // 0.01 km/h 分辨率
printf("Vehicle Speed: %.1f km/h\n", speed);
}
break;
case 0x3D9: // 发动机转速
{
uint16_t rpm_raw = (data[2] << 8) | data[3];
float rpm = rpm_raw * 0.25f; // 0.25 RPM 分辨率
printf("Engine RPM: %.0f\n", rpm);
}
break;
}
}TSP 通信协议
MQTT 上报格式
json
// 车辆状态上报(每30秒)
{
"vin": "LSVNV2182E2100001",
"timestamp": 1716192000,
"location": {
"lat": 31.2304,
"lng": 121.4737,
"altitude": 10.5,
"speed": 60.5,
"heading": 90.0,
"accuracy": 1.5
},
"vehicle": {
"speed": 60.5,
"rpm": 2000,
"fuel_level": 75,
"coolant_temp": 90,
"odometer": 12345.6,
"gear": "D"
},
"battery": {
"voltage": 12.8,
"soc": 85
},
"network": {
"rsrp": -85,
"sinr": 15,
"operator": "46000"
}
}远程控制指令
json
// TSP 下发远程控制指令
{
"cmd_id": "CMD_20240520_001",
"vin": "LSVNV2182E2100001",
"timestamp": 1716192000,
"command": "remote_lock",
"params": {
"action": "lock",
"timeout": 30
}
}
// T-Box 响应
{
"cmd_id": "CMD_20240520_001",
"vin": "LSVNV2182E2100001",
"timestamp": 1716192005,
"result": "success",
"message": "Vehicle locked successfully"
}OTA 升级方案
整车 OTA 架构
OTA 服务器(云端)
↓ HTTPS 下载
T-Box(下载和验证固件包)
↓ CAN/以太网
各 ECU(接收固件,执行升级)
- 发动机 ECU
- 变速箱 ECU
- 车身控制 ECU
- 仪表盘 ECUT-Box OTA 实现
c
// OTA 升级流程
typedef enum {
OTA_STATE_IDLE,
OTA_STATE_CHECKING,
OTA_STATE_DOWNLOADING,
OTA_STATE_VERIFYING,
OTA_STATE_INSTALLING,
OTA_STATE_COMPLETE,
OTA_STATE_FAILED
} OTAState;
typedef struct {
OTAState state;
char version[32];
char download_url[256];
uint32_t file_size;
uint32_t downloaded;
uint8_t md5[16];
} OTAContext;
// 检查更新
int ota_check_update(OTAContext *ctx) {
// 向 OTA 服务器查询最新版本
char url[256];
snprintf(url, sizeof(url),
"https://ota.example.com/check?vin=%s&version=%s",
get_vin(), get_current_version());
// HTTP GET 请求
char response[4096];
int ret = http_get(url, response, sizeof(response));
if (ret != 0) return -1;
// 解析响应
cJSON *json = cJSON_Parse(response);
if (cJSON_GetObjectItem(json, "has_update")->valueint) {
strncpy(ctx->version,
cJSON_GetObjectItem(json, "version")->valuestring, 32);
strncpy(ctx->download_url,
cJSON_GetObjectItem(json, "url")->valuestring, 256);
ctx->file_size = cJSON_GetObjectItem(json, "size")->valueint;
ctx->state = OTA_STATE_DOWNLOADING;
return 1; // 有更新
}
cJSON_Delete(json);
return 0; // 无更新
}
// 下载固件(断点续传)
int ota_download(OTAContext *ctx) {
FILE *fp = fopen("/tmp/firmware.bin", "wb");
// 支持断点续传
long resume_pos = get_resume_position();
char range_header[64];
snprintf(range_header, sizeof(range_header),
"Range: bytes=%ld-", resume_pos);
// HTTP 下载(带进度回调)
http_download(ctx->download_url, fp, range_header,
ota_progress_callback, ctx);
fclose(fp);
return 0;
}eCall 紧急救援
eCall 是欧盟强制要求的车辆紧急呼叫系统(EU 2015/758 法规):
c
// eCall 触发条件
typedef enum {
ECALL_TRIGGER_MANUAL, // 手动触发(按钮)
ECALL_TRIGGER_AUTO_CRASH // 自动触发(碰撞传感器)
} ECallTrigger;
// 碰撞检测
void check_crash_sensor(void) {
// 读取加速度传感器
float ax, ay, az;
read_accelerometer(&ax, &ay, &az);
// 计算合加速度
float total_g = sqrt(ax*ax + ay*ay + az*az);
// 超过阈值(通常 4-8g)触发 eCall
if (total_g > 6.0f) {
trigger_ecall(ECALL_TRIGGER_AUTO_CRASH);
}
}
// 触发 eCall
void trigger_ecall(ECallTrigger trigger) {
// 1. 获取当前位置
GNSSData location;
get_gnss_location(&location);
// 2. 构建 MSD(最小数据集)
MSD msd = {
.message_identifier = 1,
.control = {
.test_call = 0,
.position_can_be_trusted = 1,
.vehicle_type = VEHICLE_TYPE_PASSENGER_CAR
},
.timestamp = get_utc_time(),
.vehicle_location = {
.latitude = (int32_t)(location.latitude * 1e7),
.longitude = (int32_t)(location.longitude * 1e7)
},
.vin = get_vin()
};
// 3. 拨打 eCall 号码(欧洲:112,中国:120)
make_ecall_call("112", &msd);
}