component/examples/simple_data_analysis.c

180 lines
7.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../inc/data_type_def.h"
#include "../inc/log.h"
#include "../inc/osel_arch.h"
#include "../inc/data_analysis.h"
#define UART_RXSIZE (254U)
#define UART_DATA_ANALYSIS_PORT_1 DATA_1
#define UART_DATA_ANALYSIS_PORT_2 DATA_2
static data_interupt_cb_t uart_data_analysis_cb = NULL; // 数据源中断回调函数
static void data_analysis_event1(void)
{
uint8_t frame[UART_RXSIZE];
uint8_t data_head[3];
uint8_t crc[2];
uint16_t frame_len, out_frame_len;
data_read(UART_DATA_ANALYSIS_PORT_1, &data_head[0], 3);
osel_memcpy((uint8_t *)&frame_len, &data_head[1], 2);
frame_len = B2S_UINT16(frame_len) - 2; // 报文长度包含帧长这里需要减2
if (frame_len > UART_RXSIZE)
{
lock_data(UART_DATA_ANALYSIS_PORT_1);
unlock_data(UART_DATA_ANALYSIS_PORT_1);
return;
}
out_frame_len = data_read(UART_DATA_ANALYSIS_PORT_1, frame, (uint16_t)frame_len);
if (out_frame_len != frame_len)
{
return;
}
out_frame_len = out_frame_len - 1; // 报文中包含帧尾这里需要减1
// 校验CRC_16
uint16_t crc_16 = 0;
uint16_t crc16 = crc16_compute(&frame[0], out_frame_len - 2);
osel_memcpy(&crc[0], &frame[out_frame_len - 2], 2);
crc_16 = BUILD_UINT16(crc[1], crc[0]);
if (crc16 != crc_16)
{
return;
}
// CRC校验通过后将数据长度-2
out_frame_len -= 2;
LOG_PRINT("data_analysis_event1 ok:");
LOG_HEX(frame, out_frame_len);
}
static void data_analysis_event2(void)
{
uint8_t frame[UART_RXSIZE];
uint8_t data_head[4];
uint8_t crc[2];
uint16_t frame_len, out_frame_len;
data_read(UART_DATA_ANALYSIS_PORT_2, &data_head[0], 4);
osel_memcpy((uint8_t *)&frame_len, &data_head[2], 2);
frame_len = B2S_UINT16(frame_len);
if (frame_len > UART_RXSIZE)
{
lock_data(UART_DATA_ANALYSIS_PORT_2);
unlock_data(UART_DATA_ANALYSIS_PORT_2);
return;
}
out_frame_len = data_read(UART_DATA_ANALYSIS_PORT_2, frame, (uint16_t)frame_len);
if (out_frame_len != frame_len)
{
printf("out_frame_len:%d, frame_len:%d\n", out_frame_len, frame_len);
return;
}
// 校验CRC_16
uint16_t crc_16 = 0;
uint16_t crc16 = crc16_compute(&frame[0], out_frame_len - 2);
osel_memcpy(&crc[0], &frame[out_frame_len - 2], 2);
crc_16 = BUILD_UINT16(crc[1], crc[0]);
if (crc16 != crc_16)
{
LOG_PRINT("crc error crc16:%x, crc_16:%x\n");
return;
}
out_frame_len -= 2; // 去掉CRC_16
LOG_PRINT("data_analysis_event2 ok:");
LOG_HEX(frame, out_frame_len);
}
/**
* @brief 需要识别帧头和帧尾的数据协议
* @return {*}
* @note
*/
static void data_register1(void)
{
/**
* 帧头 帧长度 源地址 目标地址 报文类型 报文体 校验 帧尾
1 2 2 2 1 n 2 1
*/
#define FRAME_HEAD 0x05 // 帧头
#define FRAME_TAIL 0x1b // 帧尾
// 注册数据解析
data_reg_t reg;
reg.sd.valid = TRUE; // 数据头部验证有效标志位
reg.sd.len = 1; // 数据头部长度
reg.sd.pos = 0; // 数据头部偏移量
reg.sd.data[0] = FRAME_HEAD; // 数据头部数据
reg.ld.len = 2; // 数据长度
reg.ld.pos = 2; // 报文长度包含帧长这里需要设置偏移2
reg.ld.valid = TRUE; // 数据长度有效标志位
reg.ld.little_endian = FALSE; // 数据长度是否小端模式
reg.argu.len_max = UART_RXSIZE; // 数据最大长度
reg.argu.len_min = 2; // 数据最小长度
reg.ed.valid = TRUE; // 数据尾部有效标志位
reg.ed.len = 1; // 数据尾部长度
reg.ed.data[0] = FRAME_TAIL; // 数据尾部数据
reg.echo_en = FALSE; // 是否回显
reg.func_ptr = data_analysis_event1; // 数据解析回调函数 data_analysis模块处理完数据后会调用这个函数继续数据协议的处理
uart_data_analysis_cb = data_fsm_init(UART_DATA_ANALYSIS_PORT_1); // 注册数据处理函数 data_analysis模块会调用这个函数将数据写入到data_analysis模块
data_reg(UART_DATA_ANALYSIS_PORT_1, reg); // 注册数据解析
}
/**
* @brief 需要识别帧头和没有帧尾的数据协议
* @return {*}
* @note
*/
static void data_register2(void)
{
/**
* 帧头 帧长度 源地址 目标地址 报文类型 报文体 校验
2 2 2 2 1 n 2
*/
#define FRAME_HEAD1 0xD5 // 帧头
#define FRAME_HEAD2 0xC8 // 帧尾
// 注册数据解析
data_reg_t reg;
reg.sd.valid = TRUE; // 数据头部验证有效标志位
reg.sd.len = 2; // 数据头部长度
reg.sd.pos = 0; // 数据头部偏移量
reg.sd.data[0] = FRAME_HEAD1; // 数据头部数据
reg.sd.data[1] = FRAME_HEAD2; // 数据头部数据
reg.ld.len = 2; // 数据长度
reg.ld.pos = 0; // 报文长度不包含帧长
reg.ld.valid = TRUE; // 数据长度有效标志位
reg.ld.little_endian = FALSE; // 数据长度是否小端模式
reg.argu.len_max = UART_RXSIZE; // 数据最大长度
reg.argu.len_min = 2; // 数据最小长度
reg.ed.valid = FALSE; // 数据尾部有效标志位
reg.echo_en = FALSE; // 是否回显
reg.func_ptr = data_analysis_event2; // 数据解析回调函数 data_analysis模块处理完数据后会调用这个函数继续数据协议的处理
uart_data_analysis_cb = data_fsm_init(UART_DATA_ANALYSIS_PORT_2); // 注册数据处理函数 data_analysis模块会调用这个函数将数据写入到data_analysis模块
data_reg(UART_DATA_ANALYSIS_PORT_2, reg); // 注册数据解析
}
int32_t main(void)
{
data_register1();
data_register2();
// 模拟串口数据
uint8_t data1[] = {0x05, 0x00, 0x0a, 0xff, 0xff, 0x00, 0x01, 0x00, 0x55, 0x40, 0x1b};
for (uint16_t i = 0; i < ARRAY_LEN(data1); i++)
{
uart_data_analysis_cb(UART_DATA_ANALYSIS_PORT_1, *(data1 + i));
}
// 模拟串口数据
uint8_t data2[] = {0xD5, 0xC8, 0x00, 0x07, 0xff, 0xff, 0x00, 0x01, 0x00, 0x55, 0x40};
for (uint16_t i = 0; i < ARRAY_LEN(data2); i++)
{
uart_data_analysis_cb(UART_DATA_ANALYSIS_PORT_2, *(data2 + i));
}
return 0;
}