
1) 【一句话结论】
采用基于UART的通信协议,数据帧包含帧头、数据长度、数据内容、CRC16校验码,通过CRC校验检测错误并设计重传机制,确保电机控制指令与上位机可靠通信。
2) 【原理/概念讲解】
0xAA(起始帧,表示数据有效)。0x02),防止数据截断。0x01表示启动,0x02表示停止)。0x1021)计算校验码,能检测突发错误(如连续比特错误)。3) 【对比与适用场景】
| 校验方式 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 奇偶校验 | 每字节添加1位校验位,使1的个数为奇/偶 | 简单,仅能检测奇数个错误 | 低速、短距离(如传感器) | 无法检测偶数错误,可靠性低 |
| 校验和 | 对数据域求和取低8位 | 简单,易受数据分布影响 | 低速、短距离 | 可能漏检偶数错误 |
| CRC16 | 对数据域进行多项式除法,生成16位校验码 | 检测能力强(可检测突发错误) | 高速、长距离(如电机控制) | 计算复杂,需预定义多项式 |
4) 【示例】
0xAA 0x02 0x01 0x02 0x1A 0x27
0xAA(起始)、长度0x02(数据2字节)、数据0x01(启动)、0x02(停止)、CRC160x1A27(校验码)。void send_motor_cmd(uint8_t start, uint8_t stop) {
uint8_t frame[6];
frame[0] = 0xAA; // 帧头
frame[1] = 2; // 数据长度
frame[2] = start; // 数据1(启动)
frame[3] = stop; // 数据2(停止)
uint16_t crc = calculate_crc16(frame, 4); // 计算CRC
frame[4] = (crc >> 8) & 0xFF; // 高位
frame[5] = crc & 0xFF; // 低位
uart_send(frame, 6); // 发送6字节
}
void recv_motor_cmd() {
uint8_t rx[6];
if (uart_receive(rx, 6) == 6) { // 接收6字节
if (rx[0] != 0xAA) return; // 帧头错误
uint16_t calc_crc = calculate_crc16(rx, 4); // 计算CRC
if (calc_crc != (rx[4] << 8) | rx[5]) {
send_ack(0); // 发送NACK,请求重传
return;
}
handle_motor(rx[2], rx[3]); // 执行控制
}
}
5) 【面试口播版答案】
“面试官您好,针对人体工学椅电机控制与上位机的通信,我设计了一个基于UART的通信协议。数据帧包含帧头(0xAA标识起始)、长度字段(1字节,表示数据字节数)、数据域(电机控制命令,如启动/停止)、CRC16校验(2字节,用于错误检测)。错误检测通过CRC16多项式计算校验码,接收端验证后处理数据;若中断导致数据丢失,采用ARQ协议重传。例如,发送启动命令时,帧为0xAA 0x02 0x01 0x00 0x1A 0x27,其中0x1A27是CRC校验码,接收端确认后执行电机启动。”
6) 【追问清单】
0x1021(X^16+X^12+X^5+1),这是常用的CRC16-CCITT多项式。7) 【常见坑/雷区】