4. FlexRay静态段帧收发测试
任务目标
在车联网WAVE协议栈中,WSMP(WAVE Short Message Protocol)位于WAVE协议栈的传输层,负责在WAVE上层应用与下层LLC之间传递短消息。本案例实现WSMP消息的封装与解析核心逻辑,支持将应用层载荷封装为符合IEEE 1609.3标准的WSMP帧,并能从接收到的字节流中正确解析出各字段。
核心实现
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define WSMP_VERSION 0x03
#define WSMP_HEADER_LEN 8
#define MAX_PAYLOAD 1400
typedef struct {
uint8_t version;
uint8_t psid[4]; // Provider Service Identifier
uint8_t channel;
uint8_t dataRate;
uint8_t power;
uint8_t *payload;
uint16_t payloadLen;
} WSMP_Msg;
// 封装:生成WSMP帧(含头部+载荷)
uint16_t wsmp_encode(WSMP_Msg *msg, uint8_t *outBuf, uint16_t bufSize) {
if (!msg || !outBuf || bufSize < WSMP_HEADER_LEN + msg->payloadLen)
return 0;
if (msg->payloadLen > MAX_PAYLOAD)
return 0;
uint16_t idx = 0;
outBuf[idx++] = (msg->version << 4) | 0x0C; // 高4位版本,低4位为头部长度(8字节)
outBuf[idx++] = msg->psid[0];
outBuf[idx++] = msg->psid[1];
outBuf[idx++] = msg->psid[2];
outBuf[idx++] = msg->psid[3];
outBuf[idx++] = (msg->channel << 4) | (msg->dataRate & 0x0F);
outBuf[idx++] = msg->power;
outBuf[idx++] = (msg->payloadLen >> 8) & 0xFF;
outBuf[idx++] = msg->payloadLen & 0xFF;
memcpy(outBuf + idx, msg->payload, msg->payloadLen);
return WSMP_HEADER_LEN + msg->payloadLen;
}
// 解析:从WSMP帧中提取各字段
int wsmp_decode(const uint8_t *frame, uint16_t frameLen, WSMP_Msg *msg) {
if (!frame || !msg || frameLen < WSMP_HEADER_LEN)
return -1;
msg->version = (frame[0] >> 4) & 0x0F;
uint8_t hdrLen = (frame[0] & 0x0F) * 4; // 低4位表示头部长度(单位4字节)
if (hdrLen != WSMP_HEADER_LEN || frameLen < hdrLen)
return -2;
msg->psid[0] = frame[1];
msg->psid[1] = frame[2];
msg->psid[2] = frame[3];
msg->psid[3] = frame[4];
msg->channel = (frame[5] >> 4) & 0x0F;
msg->dataRate = frame[5] & 0x0F;
msg->power = frame[6];
msg->payloadLen = (frame[7] << 8) | frame[8];
if (hdrLen + msg->payloadLen > frameLen)
return -3;
msg->payload = (uint8_t *)frame + hdrLen;
return 0;
}
// 测试入口
int main() {
uint8_t payload[] = {0xDE, 0xAD, 0xBE, 0xEF};
WSMP_Msg tx = {
.version = WSMP_VERSION,
.psid = {0x00, 0x00, 0x00, 0x01},
.channel = 0x02,
.dataRate = 0x03,
.power = 0x10,
.payload = payload,
.payloadLen = sizeof(payload)
};
uint8_t buf[64];
uint16_t len = wsmp_encode(&tx, buf, sizeof(buf));
if (len == 0) {
printf("encode failed\n");
return 1;
}
WSMP_Msg rx;
memset(&rx, 0, sizeof(rx));
if (wsmp_decode(buf, len, &rx) != 0) {
printf("decode failed\n");
return 1;
}
// 验证字段一致性
if (rx.version == tx.version &&
memcmp(rx.psid, tx.psid, 4) == 0 &&
rx.channel == tx.channel &&
rx.dataRate == tx.dataRate &&
rx.power == tx.power &&
rx.payloadLen == tx.payloadLen &&
memcmp(rx.payload, tx.payload, tx.payloadLen) == 0) {
printf("PASS: encode/decode round-trip OK\n");
return 0;
} else {
printf("FAIL: field mismatch\n");
return 1;
}
}
编译与运行
gcc -o wsmp_demo wsmp_demo.c
./wsmp_demo
验证方法
程序执行后输出 PASS: encode/decode round-trip OK 即表示封装与解析逻辑正确。该验证通过将同一消息先封装再解析,比对所有字段(版本、PSID、信道、速率、功率、载荷长度与内容)是否完全一致,确保编解码互为逆操作。
关键说明
- WSMP头部固定为8字节:第1字节高4位为版本号(3),低4位表示头部长度(值为2,表示8字节,单位4字节);第2~5字节为4字节PSID;第6字节高4位为信道号、低4位为数据速率;第7字节为发射功率;第8~9字节为载荷长度(大端序)。
- 本实现聚焦WSMP核心编解码逻辑,未包含WAVE协议栈中LLC封装、信道竞争等底层处理,实际接入时需将生成的WSMP帧交由下层LLC子层发送。
- PSID采用4字节表示,符合IEEE 1609.3中PSID的通用格式;若需支持1字节短PSID,可在此框架上扩展。