pref: 优化接收帧解析

基本能够稳定接收,理论上不需超时处理 close #1
This commit is contained in:
bmy
2024-03-20 10:31:23 +08:00
parent 9215d91eb5
commit 0a943fd849

View File

@@ -7,14 +7,14 @@
#include "lwrb.h" #include "lwrb.h"
#include "crc16.h" #include "crc16.h"
uint8_t frame_buffer_recv[(2 * (4 + 8))]; uint8_t frame_buffer_recv[(2 * (4 + 8)) + 1];
uint8_t frame_buffer_send[4 + 8]; uint8_t frame_buffer_send[4 + 8];
uint8_t frame_parse_busy; uint8_t frame_parse_busy;
fifo_struct frame_fifo; lwrb_t lwrb_ctx;
void by_frame_init(void) void by_frame_init(void)
{ {
fifo_init(&frame_fifo, FIFO_DATA_8BIT, frame_buffer_recv, (2 * (4 + 8))); lwrb_init(&lwrb_ctx, frame_buffer_recv, sizeof(frame_buffer_recv)); // lwrb 最大元素数量为 buff 大小减一
uart_init(BY_FRAME_UART_INDEX, BY_FRAME_UART_BAUDRATE, BY_FRAME_UART_TX_PIN, BY_FRAME_UART_RX_PIN); uart_init(BY_FRAME_UART_INDEX, BY_FRAME_UART_BAUDRATE, BY_FRAME_UART_TX_PIN, BY_FRAME_UART_RX_PIN);
uart_rx_interrupt(BY_FRAME_UART_INDEX, ENABLE); uart_rx_interrupt(BY_FRAME_UART_INDEX, ENABLE);
} }
@@ -34,15 +34,20 @@ void by_frame_send(uint8_t data_num, uint32_t *data_array)
uart_write_buffer(BY_FRAME_UART_INDEX, frame_buffer_send, 4 + data_num * sizeof(uint32_t)); uart_write_buffer(BY_FRAME_UART_INDEX, frame_buffer_send, 4 + data_num * sizeof(uint32_t));
} }
/**
* @brief
*
* @param data_num
* @param data_array
* @todo 将其中写死的数据长度按照宏定义给出
*/
void by_frame_parse(uint8_t data_num, uint32_t *data_array) void by_frame_parse(uint8_t data_num, uint32_t *data_array)
{ {
uint32_t len = lwrb_get_full(&lwrb_ctx); // 缓冲区大小
uint16_t len = (uint16_t)fifo_used(&frame_fifo); uint8_t status = 0; // 状态 0-未找到帧头 1-找到帧头 2-校验
uint16_t len_cnt = len; uint16_t frame_start = 0; // 帧起始位置
uint8_t status = 0; uint8_t frame_buf[4 + 8] = {0}; // 帧
uint16_t frame_start = 0; uint8_t buf[(4 + 8) * 2] = {0}; // 用于解析的数据块
uint8_t frame_buffer[4 + 8] = {0};
uint8_t buf[sizeof(frame_buffer)] = {0};
if (len < 2 * (4 + 4 * data_num)) { if (len < 2 * (4 + 4 * data_num)) {
// 当前要求缓冲区满 // 当前要求缓冲区满
@@ -55,39 +60,50 @@ void by_frame_parse(uint8_t data_num, uint32_t *data_array)
// 目前的解决办法大概是缓冲区开两帧长的大小,然后一次性读完 // 目前的解决办法大概是缓冲区开两帧长的大小,然后一次性读完
// 读取的时候不清除,等待新帧覆盖 // 读取的时候不清除,等待新帧覆盖
// 用 lwrb 的话就只能清除了
return; return;
} }
fifo_read_buffer(&frame_fifo, buf, &len, FIFO_READ_ONLY); // 从环形缓冲区里读取数据
lwrb_read(&lwrb_ctx, buf, len);
while (len_cnt--) { // 递归解析有效帧
while (1) {
if (0 == status) // 没找到帧头 if (0 == status) // 没找到帧头
{ {
printf("finding frame head, now frame_start %d\r\n", frame_start); // 读到最后一个元素还没找到帧头
uint16_t temp = *((uint16_t *)(buf + (frame_start++))); if (frame_start >= len - 2) {
printf("now find %02X\r\n", temp); return;
}
// printf("finding frame head, now frame_start %d\r\n", frame_start);
uint16_t temp = (buf[frame_start] | (buf[frame_start + 1] << 8));
frame_start++;
// printf("now find %02X\r\n", temp);
// 递归寻找帧头,直接俩拼起来找 注意比较的时候低位在前 // 递归寻找帧头,直接俩拼起来找 注意比较的时候低位在前
if ((BY_FRAME_HEAD_2 << 8 | BY_FRAME_HEAD_1) == temp) { if ((BY_FRAME_HEAD_2 << 8 | BY_FRAME_HEAD_1) == temp) {
status = 1; // 找到了好耶 status = 1; // 找到了好耶
printf("frame head found!!!!!!!!!\r\n"); // printf("frame head found!!!!!!!!!\r\n");
} }
continue; continue;
} }
if (1 == status) // 开始读数据 // 开始读数据
{ if (1 == status) {
if ((frame_start + 4 + 8) >= len) // 剩下的数据不够组成一帧 // 剩下的数据不够组成一帧
{ if ((frame_start + 4 + 8 - 1) > len) {
printf("failed! length not enough \r\n"); // printf("failed! length not enough \r\n");
return; // 解析出错,缓冲区中没有有效帧 // 解析出错,缓冲区中没有有效帧
return;
} else { } else {
memcpy(frame_buffer, buf + frame_start - 1, 4 + 8); // 复制到帧缓冲区,减一是因为之前多加了一次 // 复制到帧缓冲区,减一是因为之前多加了一次
for (uint8_t i = 0; i < 12; i++) { memcpy(frame_buf, buf + frame_start - 1, 4 + 8);
printf("%02X", frame_buffer[i]);
} // for (uint8_t i = 0; i < 12; i++) {
// printf("%02X", frame_buf[i]);
// }
// printf("\r\n");
printf("\r\n");
status = 2; status = 2;
} }
continue; continue;
@@ -95,86 +111,30 @@ void by_frame_parse(uint8_t data_num, uint32_t *data_array)
if (2 == status) // 校验 CRC if (2 == status) // 校验 CRC
{ {
// TODO 确认一下高低位 if ((frame_buf[2 + 8] << 8 | frame_buf[2 + 8 + 1]) == crc16_check(frame_buf, 2 + 4 * data_num)) {
if (*((uint16_t *)(frame_buffer + 2 + 8)) == crc16_check(frame_buffer, 2 + 4 * data_num)) // 暂时用 0xFF 替代 注意比较的时候字节序!!! // 解析成功了✌
{ // printf("parsed done!!!!!!!!\r\n");
printf("parsed done!!!!!!!!\r\n"); // 解析成功了✌ // 复制数据
memcpy(data_array, frame_buffer + 2, 4 * data_num); // 复制数据 memcpy(data_array, frame_buf + 2, 4 * data_num);
return; return;
} else { } else {
status = 0; status = 0;
// frame_start += (8 - 1); // 这样无法应对连续帧之间缺字节的的问题,但是减少了重新遍历寻找帧头的时间 // 这样无法应对连续帧之间缺字节的的问题,但是减少了重新遍历寻找帧头的时间
frame_start += (2 - 1); // 从上一个帧头之后开始解析 // frame_start += (8 - 1);
// 从上一个帧头之后开始解析
frame_start += (2 - 1);
continue; continue;
} }
} }
} }
return; return;
// uint8_t cnt = 0;
// uint8_t cnt_crc = 2;
// uint8_t cnt_ptr = 0;
// uint8_t data = 0;
// uint8_t data_array_temp[100] = {0};
// uint16_t crc_cal = 0;
// uint32_t read_length = 50;
// if (fifo_used(&frame_fifo) >= 4 + 4 * data_num) {
// fifo_read_buffer(&frame_fifo, frame_buffer_parse, &read_length, FIFO_READ_AND_CLEAN);
// while (1) {
// if (cnt_ptr < 50) {
// data = frame_buffer_parse[cnt_ptr];
// cnt_ptr++;
// }
// // printf("char : %0.2X\r\n", data);
// if ((0 == cnt) && (BY_FRAME_HEAD_1 == data)) {
// frame_parse_busy = 1; // 开始解析
// cnt = 1;
// data_array_temp[0] = data;
// continue;
// }
// if ((1 == cnt) && (BY_FRAME_HEAD_2 == data)) {
// cnt = 2;
// data_array_temp[1] = data;
// continue;
// }
// if ((2 <= cnt) && (cnt < 2 + data_num * sizeof(uint32_t))) {
// data_array_temp[cnt] = data;
// cnt++;
// continue;
// }
// if (cnt_crc) {
// crc_cal |= ((uint16_t)data << (--cnt_crc * 8));
// cnt++;
// continue;
// }
// // printf("GET CRC %0.4X\r\n", crc_cal);
// // printf("CAL CRC %0.4X\r\n", crc16_check((uint8_t *)data_array_temp, 2 + data_num * sizeof(uint32_t)));
// if (!cnt_crc) {
// if (crc_cal == crc16_check(data_array_temp, 2 + data_num * sizeof(uint32_t))) {
// memcpy(data_array, data_array_temp + 2, data_num * sizeof(uint32_t));
// fifo_clear(&frame_fifo); // TODO 确认是否有必要清除
// // lwrb_reset(&lwrb_struct); // 处理完直接清空缓冲区,避免堆积产生处理阻塞
// memset(data_array_temp, 0, sizeof(data_array_temp));
// }
// break;
// }
// }
// }
} }
void by_frame_parse_uart_handle(uint8_t data) void by_frame_parse_uart_handle(uint8_t data)
{ {
fifo_write_element(&frame_fifo, data); // fifo_write_element(&frame_fifo, data);
// lwrb_write(&lwrb_struct, &data, 1); lwrb_write(&lwrb_ctx, &data, 1);
} }
/** /**
@@ -183,8 +143,4 @@ void by_frame_parse_uart_handle(uint8_t data)
*/ */
void by_frame_parse_timer_handle(void) void by_frame_parse_timer_handle(void)
{ {
static uint8_t time_out = 0;
if (frame_parse_busy) {
time_out--;
}
} }