完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
最近遇到一个问题,系统采用rtthread系统 ,主控(stm32f103vc)通过串口转485 连接到X设备。从X设备接收485数据,波特率4800 ,X设备发送数据长度在16-64个字节之间(有固定包头和长度 无包尾标识并且复杂加密),平时大概30S一次数据(一次数据有三帧,每帧时间间隔50ms),现在由于特殊情况,X设备发送了大量垃圾数据(我不需要的数据),每秒大概20帧垃圾数据,4800波特率,我看了收400多个字节,几乎是全速在在发。 这是时候我要准确的把我要的包识别并取出来(解密算法也很复杂),并且保证其他6-7个任务正常运行,如何做才能比较高效和稳定? 我现在的办法是串口中断接收一个字节一个字节判断,但是偶尔会丢包。请各位大神能给点建议! |
|
相关推荐
6个回答
|
|
|
|
|
|
|
|
|
是的 我现在就是这样处理的,但是效率有点低,偶尔有丢包
|
|
|
|
|
|
用代码说话,项目中用的,有包头包尾,数据长度,数据类型,数据域等等,数据完整性判断
rt_uint8_t *recvbuf = RT_NULL; static struct serial_configure uart_conf = RT_SERIAL_CONFIG_USER; rt_uint8_t *datbuf = RT_NULL; rt_size_t rcv_off = 0, recv_sz = 1024, tmp = 0; rt_size_t dat_off = 0, dat_len = 0, i; rt_tick_t _speed_ctrl = 0; recvbuf = rt_malloc(128); rt_memset(recvbuf, 0, 128); datbuf = rt_malloc(32); rt_memset(datbuf, 0, 32); busif_speed_ctrl = rt_tick_get(); rt_sem_init(&rx_sem, "bifrx", 0, 0); dev_busif = rt_device_find("uart1"); if (dev_busif == RT_NULL) { rt_kprintf("Can not find device: %sn", "uart1"); return; } if (rt_device_open(dev_busif, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM) == RT_EOK) { rt_device_set_rx_indicate(dev_busif, busif_rx_ind); } rt_device_control(dev_busif, RT_DEVICE_CTRL_CONFIG, &uart_conf); while(1) { rt_sem_take(&rx_sem, RT_WAITING_FOREVER); recv_sz = rt_device_read(dev_busif, -1, &recvbuf[rcv_off], 128-rcv_off); if (recv_sz > 0) { rt_kprintf("data: %dn", recv_sz); if (rcv_off == 0) { i = 0; while ((recvbuf[i] != 0x1A) && (i < recv_sz)) i++; // find header if (i == 0) { rcv_off = recv_sz; } else if (i < recv_sz) { rcv_off = recv_sz-i; rt_memcpy(recvbuf, &recvbuf[i], recv_sz-i); } else { // no header rcv_off = 0; continue; } } else { rcv_off += recv_sz; } if (rcv_off < 2) { // data not enough continue; } dat_len = recvbuf[1]; if (dat_len > 16) { // error length rcv_off = 0; dat_len = 0; continue; } if (rcv_off >= (dat_len + 3)) { // len enough float val = 0; AdcVal adc_val; if (recvbuf[9+2] != 0x1B) { // find tailer error dat_len = 0; rcv_off = 0; continue; } tmp = rcv_off-(dat_len + 3); _speed_ctrl = rt_tick_get(); if (/*busif_busy > 0 || */(_speed_ctrl - busif_speed_ctrl < 100)) { busif_busy--; if (tmp > 0) { rt_memcpy(recvbuf, &recvbuf[dat_len + 3], tmp); rcv_off = tmp; } else { rcv_off = 0; } dat_len = 0; continue; } switch(recvbuf[2]){ // map function type id case 1: adc_val.type = FUNC_DCV; break; case 2: adc_val.type = FUNC_DCI; break; default: // unsupport type id if (tmp > 0) { rt_memcpy(recvbuf, &recvbuf[dat_len + 3], tmp); rcv_off = tmp; } else { rcv_off = 0; } dat_len = 0; rt_kprintf("error type: %dn", adc_val.type); continue; break; } rt_memcpy(datbuf, recvbuf+4, 7); // change str 2 float datbuf[7] = 0; rt_kprintf("%sn", datbuf); // 数据域 ,可以是字符串,可以是十六进制数据 // 其它数据处理 .... // prepare next package 准备下一包 if (tmp > 0) { rt_memcpy(recvbuf, &recvbuf[dat_len + 3], tmp); rcv_off = tmp; } else { rcv_off = 0; } dat_len = 0; } } } |
|
|
|
|
|
可以根据这个修改,先把完整包处理出来,然后解密的工作当前线程处理也行,交给其它线程也行。
|
|
|
|
|
|
我用的波特率 115200 虽然包长不大,但是你的波特率低,不至于会丢数据。
|
|
|
|
|
|
里面有注释,去掉包尾判断,剩下的和你的基本是一样的。虽然我的数据是定长的,有数据长度域在,处理变长数据没一点儿压力
|
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1033 浏览 0 评论
2877 浏览 0 评论
图腾柱PFC无法上升至400V,且电感电流为正弦波形,但是幅值极小
9386 浏览 0 评论
飞凌嵌入式ElfBoard-Vim编辑器之静态链接和动态链接
2898 浏览 0 评论
使用 LinkBoy 将程序导出为 C 语言代码并烧录至 Arduino ESP32 开发板
2302 浏览 1 评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 06:51 , Processed in 0.744809 second(s), Total 84, Slave 67 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
4212