本项目使用 UART 协议,通过结构化数据包控制左右轮电机的 PWM 和转向。
每个数据包结构如下:
[HEAD0][HEAD1][LEN][CMD][DATA...][CRC]
| 字段 |
长度 |
描述 |
| HEAD0 |
1字节 |
固定为 0xAA |
| HEAD1 |
1字节 |
固定为 0x55 |
| LEN |
1字节 |
后续长度:CMD + DATA + CRC |
| CMD |
1字节 |
命令字 |
| DATA |
0~8字节 |
命令参数 |
| CRC |
1字节 |
CRC8 校验(多项式 0x07) |
注意:最大总包长为 1+1+1+1+8+1 = 13 字节
| CMD |
功能 |
数据长度 |
参数描述 |
| 0x01 |
设置PWM |
4字节 |
uint16_t leftPWM + uint16_t rightPWM |
| 0x02 |
设置轮子方向 |
2字节 |
uint8_t leftDir + uint8_t rightDir |
uint8_t crc8_update(uint8_t crc, const uint8_t* data, uint8_t len)
{
for (uint8_t i = 0; i < len; i++) {
crc ^= data[i];
for (uint8_t j = 0; j < 8; j++) {
crc = (crc & 0x80) ? (crc << 1) ^ 0x07 : (crc << 1);
}
}
return crc;
}
| 项目 |
设置 |
| 波特率 |
115200 |
| 数据位 |
8 |
| 停止位 |
1 |
| 校验位 |
None |
| 控制流 |
无 |
| 功能 |
GPIO 口 |
描述 |
| 左轮前进 |
PB15 |
设置为 1 |
| 左轮后退 |
PB14 |
设置为 1 |
| 右轮前进 |
PA10 |
设置为 1 |
| 右轮后退 |
PA11 |
设置为 1 |
| 左轮PWM |
TIM1_CH1 |
通常接电机驱动 |
| 右轮PWM |
TIM1_CH2 |
通常接电机驱动 |
#define PACK_HEAD_0 0xAA
#define PACK_HEAD_1 0x55
uint8_t crc8_update(uint8_t crc, const uint8_t* data, uint8_t len);
// 构建并发送数据包
int BuildPacket(uint8_t cmd, const uint8_t* data, uint8_t dataLen, uint8_t* out)
{
uint8_t len = 1 + dataLen + 1;
out[0] = PACK_HEAD_0;
out[1] = PACK_HEAD_1;
out[2] = len;
out[3] = cmd;
memcpy(&out[4], data, dataLen);
uint8_t crc = crc8_update(0, &out[2], 1 + 1 + dataLen); // LEN + CMD + DATA
out[4 + dataLen] = crc;
return 5 + dataLen;
}
void SendSetPWM(int fd, uint16_t left, uint16_t right)
{
uint8_t data[4] = {
left & 0xFF, left >> 8,
right & 0xFF, right >> 8
};
uint8_t packet[16];
int len = BuildPacket(0x01, data, 4, packet);
write(fd, packet, len);
}
void SendSetDirection(int fd, uint8_t leftDir, uint8_t rightDir)
{
uint8_t data[2] = { leftDir, rightDir };
uint8_t packet[16];
int len = BuildPacket(0x02, data, 2, packet);
write(fd, packet, len);
}
int OpenSerial(const char* device)
{
int fd = open(device, O_RDWR | O_NOCTTY | O_SYNC);
struct termios tty;
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
// 配置位宽、停止位等…
tcsetattr(fd, TCSANOW, &tty);
return fd;
}
- 包头校验失败自动重启状态机(已实现)
- 可添加返回 ACK/NAK 功能(扩展项)
- 支持设置 PID 等扩展命令(CMD > 0x10 预留)
© 2025 STM32 LCAR