stm32串口数据包
·
阻塞轮询方式
// 发送数据
int std::fputc(int ch, FILE* f) {
HAL_UART_Transmit(&huart3, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
return ch;
}
//接收数据
int std::fgetc(FILE* f) {
uint8_t ch;
HAL_UART_Receive(&huart3, &ch, 1, HAL_MAX_DELAY);
return ch;
}
中断式
固定长度
// 定长
char rx_data[5]; // 每次接收一个字节
uint8_t rx_len = sizeof(rx_data);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) {
if (huart->Instance == USART3) {
HAL_UART_Transmit_IT(&huart3, (uint8_t*)"www", 3); // 回传接收到的字节
HAL_UART_Receive_IT(&huart3, (uint8_t*)&rx_data, rx_len); // 重新启用接收中断
}
}
void receive(void) {
HAL_UART_Receive_IT(&huart3, (uint8_t*)&rx_data, rx_len); // 开始逐字节接收
}
不定长
// 不定长,终止位
uint8_t rx_data[100] = {0}; // 用于接收和回传的数据
uint8_t buf;
uint16_t size = sizeof(rx_data);
uint8_t index = 0; // 当前缓冲区索引
// 接收完成回调
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART3) {
rx_data[index++]=buf;
if (index >= 0 && (buf == '#' || buf == '\n')) {
// 检测到结束符,回传所有接收到的数据
HAL_UART_Transmit_IT(&huart3, rx_data,index); // 回传所有数据
}
HAL_UART_Receive_IT(&huart3, &buf, 1);
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART3) {
for(uint8_t i = 0;i<index;i++){
rx_data[i]= '0';
}
index = 0; // 重置索引
}
}
// 初始化接收
void receive() {
index = 0;
HAL_UART_Receive_IT(&huart3, &buf, 1);
}
解包
typedef enum {
RED = 0,
GREEN = 1,
BLUE = 2,
red = 3,
green = 4,
blue = 5,
UNKNOWN = -1 // 用于表示未知颜色
} color_t;
typedef struct node {
float x;
float y;
uint8_t color;
}point;
point node[CLASS] = { 0 };// 用于存储接收到的坐标和颜色
uint8_t rx_data[CLASS][50] = { 0 }; // 用于接收数据缓冲区
uint16_t size = sizeof(rx_data);
uint8_t buf;
uint8_t count = 0, index = 0;
uint8_t start = 0, next = 0, end = 0;
// 颜色字符串转序号
color_t string_to_color(const char* str) {
if (strcmp(str, "RED") == 0)
return RED;
else if (strcmp(str, "GREEN") == 0)
return GREEN;
else if (strcmp(str, "BLUE") == 0)
return BLUE;
else if (strcmp(str, "red") == 0)
return red;
else if (strcmp(str, "green") == 0)
return green;
else if (strcmp(str, "blue") == 0)
return blue;
return UNKNOWN;
}
// 解析数据
void parse_data(char* data, point* p) {
// char* color_str;
if (sscanf(data, "%f,%f,%d", &p->x, &p->y, p->color) == 3) {
//p->color = string_to_color(color_str); // 将颜色转换为枚举值
}
}
// 结构体入队列*************
void queue(point* p) {
}
// 重置状态
void restart() {
buf = 0;
count = 0;
index = 0;
start = 0;
next = 0;
end = 0;
for (uint8_t i = 0; i < CLASS; i++) {
memset(rx_data[i], 0, sizeof(rx_data[i]));
}
for (uint8_t i = 0; i < CLASS; i++) {
node[i].x = 0;
node[i].y = 0;
node[i].color = UNKNOWN;
}
}
uint8_t s[100];
uint8_t i = 0;
// @125.05,256.55,0|255.47,896.05,1|1024.05,204.92,2|#
// 60*(6*2*6+5+2+2*6) = 60*
// 接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) {
if (huart->Instance == USART3) {
// 状态
switch (buf)
{
case '@':
start = 1;
next = 0;
end = 0;
break;
case '|':
next = 1;
start = 0;
end = 0;
break;
case '#':
end = 1;
start = 0;
next = 0;
break;
default:
break;
}
if (start && next == 0 && end == 0 && buf != '@') {
rx_data[count][index++] = buf; // 将接收到的数据存入缓冲区
s[i++] = buf;
}
else if (next && end == 0 && start == 0) {
parse_data(rx_data[count], &node[count]); //解包
// queue(&node[count]); // 入队列
count++;
index = 0;
next = 0;
start = 1; //继续接收
}
else if (end && start == 0 && next == 0) {
// HAL_UART_Transmit_IT(&huart3, (uint8_t *)"Data Received\n", 14);
HAL_UART_Transmit_IT(&huart3, s, i);
restart(); // 重置状态
}
HAL_UART_Receive_IT(&huart3, &buf, 1);
}
}
// 发送完成回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart) {
if (huart->Instance == USART3) {
i = 0;
memset(s, 0, sizeof(s));
}
}
// 主函数中调用此函数以启动接收
void receive(void) {
index = 0;
HAL_UART_Receive_IT(&huart3, &buf, 1);
}
版本2
typedef struct node {
float x;
float y;
uint8_t color;
}point;
point node[CLASS] = { 0 };// 用于存储接收到的坐标和颜色
uint8_t rx_data[CLASS][50] = { 0 }; // 用于接收数据缓冲区
uint16_t size = sizeof(rx_data);
uint8_t buf;
uint8_t count = 0, index = 0;
uint8_t start = 0, next = 0, end = 0;
// 解析数据
void parse_data(char* data, point* p) {
if (sscanf(data, "%f,%f,%d", &p->x, &p->y, p->color) == 3) {
// 解析成功
}
}
// 结构体入队列*************
void queue(point* p) {
}
// 重置状态
void restart() {
buf = 0;
count = 0;
index = 0;
start = 0;
next = 0;
end = 0;
for (uint8_t i = 0; i < CLASS; i++) {
memset(rx_data[i], 0, sizeof(rx_data[i]));
}
for (uint8_t i = 0; i < CLASS; i++) {
node[i].x = 0;
node[i].y = 0;
node[i].color = 255;
}
}
uint8_t s[100];
uint8_t i = 0;
// @125.05,256.55,0|255.47,896.05,1|1024.05,204.92,2|#
// 60*(6*2*6+5+2+2*6) = 60*
// 接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) {
if (huart->Instance == USART3) {
// 状态
switch (buf)
{
case '@':
start = 1;
next = 0;
end = 0;
break;
case '|':
next = 1;
start = 0;
end = 0;
break;
case '#':
end = 1;
start = 0;
next = 0;
break;
default:
break;
}
if (start && next == 0 && end == 0 && buf != '@') {
rx_data[count][index++] = buf; // 将接收到的数据存入缓冲区
s[i++] = buf;
}
else if (next && end == 0 && start == 0) {
parse_data(rx_data[count], &node[count]); //解包
// queue(&node[count]); // 入队列
count++;
index = 0;
next = 0;
start = 1; //继续接收
}
else if (end && start == 0 && next == 0) {
// HAL_UART_Transmit_IT(&huart3, (uint8_t *)"Data Received\n", 14);
HAL_UART_Transmit_IT(&huart3, s, i);
restart(); // 重置状态
}
HAL_UART_Receive_IT(&huart3, &buf, 1);
}
}
// 发送完成回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart) {
if (huart->Instance == USART3) {
i = 0;
memset(s, 0, sizeof(s));
}
}
// 主函数中调用此函数以启动接收
void receive(void) {
index = 0;
HAL_UART_Receive_IT(&huart3, &buf, 1);
}
DMA
定长
char rx_data[5]; // 每次接收一个字节
uint8_t rx_len = sizeof(rx_data);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart) {
if (huart->Instance == USART3) {
HAL_UART_Transmit_DMA(&huart3, (uint8_t*)&rx_data, 3); // 回传接收到的字节
HAL_UART_Receive_DMA(&huart3, (uint8_t*)&rx_data, rx_len); // 重新启用接收中断
}
}
void receive(void) {
HAL_UART_Receive_DMA(&huart3, (uint8_t*)&rx_data, rx_len); // 开始逐字节接收
}
不定长
uint8_t rx_data[125] = { 0 }; // 每次接收一个字节
uint8_t rx_len = sizeof(rx_data);
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size) {
if (huart->Instance == USART3) {
HAL_UART_Transmit_DMA(&huart3, rx_data, Size); // 回传接收到的字节
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_data, rx_len);
}
}
void start_usart3() {
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_data, rx_len);
}
DMA当接收的数据量打到一半的rx_len的时候也会触发这个空闲中断,所以需要关闭掉这个玩意。上面的代码是有问题的哦!
下面是关闭传输过半就发生的代码:
uint8_t rx_data[125] = { 0 }; // 每次接收一个字节
uint8_t rx_len = sizeof(rx_data);
// DMA当接收的数据量打到一半的rx_len的时候也会触发这个空闲中断,所以需要判断一下
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size) {
if (huart->Instance == USART3) {
HAL_UART_Transmit_DMA(&huart3, rx_data, Size); // 回传接收到的字节
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_data, rx_len);
__HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
}
}
void start_usart3() {
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_data, rx_len);
__HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
}
解包
/*
DMA操作
*/
typedef struct node {
float x;
float y;
uint8_t color;
}point;
point node[CLASS] = { 0 };// 用于存储接收到的坐标和颜色
uint8_t rx_data[125] = { 0 }; // 用于接收数据缓冲区
uint8_t rx_buffer[CLASS][50] = { 0 }; // 用于存储接收到的字符串
uint16_t size = sizeof(rx_data);
uint8_t count = 0, index = 0;
// @125.05,256.55,0|255.47,896.05,1|1024.05,204.92,2|#
uint8_t s[100];
uint8_t i;
// 字符串数据存入结构体
void parse_data(char* data, point* p) {
if (sscanf(data, "%f,%f,%d", &p->x, &p->y, p->color) == 3) {
// 解析成功
}
}
void clear() {
memset(rx_buffer, 0, sizeof(rx_buffer));
memset(rx_data, 0, sizeof(rx_data));
memset(node, 0, sizeof(node));
memset(s, 0, sizeof(s));
count = 0;
index = 0;
i = 0;
}
// 解析字符串
uint8_t parse_string(char* data, uint8_t len) {
char* p = data;
uint8_t flag = 0x00; // 判断是否为完整的数据包
while (*p != '\0') {
if (*p == '@') {
p++;
flag = flag | 0x01;
}
else if (*p == '|') {
parse_data((char*)rx_buffer[count], &node[count]);
index = 0;
count++;
p++;
}
else if (*p == '#') {
s[i++] = '\n';
flag = flag | 0x10;
}
else {
s[i++] = *p;
rx_buffer[count][index++] = *p;
p++;
}
}
if(flag!=0x11){
clear();
}
return 1;
}
// 结构体入队列*************
void queue(point* p) {
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size) {
if (huart->Instance == USART3) {
parse_string((char*)rx_data, Size);
// queue();
HAL_UART_Transmit_DMA(&huart3, s, i); // 回传接收到的字节
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_data, sizeof(rx_data));
__HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART3)
{
clear(); // 清空缓冲区
}
}
void start_usart3() {
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx_data, sizeof(rx_data));
__HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
}
更多推荐

所有评论(0)