Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
DMA
串口
串口数据分段收到,这种情况如何用DMA方式接收?
发布于 2022-06-21 16:33:42 浏览:956
订阅该版
大家好!我的串口是用的RT_DEVICE_FLAG_DMA_RX方式接收数据, 现在遇到这样一个情况,我接收一个设备传来的数据,本来完整的一帧数据应该是“5A A5 07 82 11 12 00 02 78 E6”,但是偶尔会出现先收到“5A A5 07 82 11”,隔一会才收到“12 00 02 78 E6”这种情况, 因为每次都会对收到的数据做校验,当数据被分段收到后,就通不过,只能被放弃掉。 请问大家在使用串口DMA接收的时候,怎么处理这种一帧数据分两次收到的情况呢? ps.这个设备只定义了帧头,没有定义帧尾。
查看更多
lqwuliang
2022-06-21
天下没有解决不了的bug,只有发现不了的bug.
DMA空闲接收+定时器超时计时接收,然后再拼包处理。
7
个回答
默认排序
按发布时间排序
红枫
认证专家
2022-06-21
这家伙很懒,什么也没写!
DMA接收通过字节间隔分帧不太可靠,如果你的速率不是特别高,可以使用中断方式接收,使用RS485软件包,配置合适的字节超时时间,可以可靠分帧。
出出啊
2022-06-21
恃人不如自恃,人之为己者不如己之自为也
传数据一定加数据协议啊,要么固定字节数,要么带包头带长度域,要么包头包尾 没有协议格式的通信都是耍流氓。 具体处理可以看我写的文章 https://club.rt-thread.org/ask/article/2460fcd7db4821ae.html
lchnu
2022-06-21
Witness, Understand, Skill
dma中写ringbuffer,线程中读ringbuffer,并配合状态机做协议解析,同时也可以引入超时判断。 让中断做最少的事情,线程中对业务数据进行处理。
swet123
2022-06-22
ztlchina@foxmail.com
这个看来是串口屏的吧?直接给你代码 ``` enum lcdCMDProcessStatus { LCDPSTATUS_FINDHEAD1 = 0, LCDPSTATUS_FINDHEAD2 = 1, LCDPSTATUS_LEN, LCDPSTATUS_CMD, LCDPSTATUS_DATA, }; typedef struct { rt_device_t dev; struct rt_semaphore r_tx; rt_uint8_t buff[Screen_BUFF_SIZE]; rt_uint8_t buff_len; rt_uint8_t r_sta; rt_uint8_t errtime; } Screen_DEV ; static Screen_DEV ScreenDev; ALIGN(RT_ALIGN_SIZE) static rt_uint8_t sc_read_stack[ 1024 ]; static struct rt_thread sc_read_thread; void Screen_process(void* s) { RT_ASSERT(ScreenDev.dev); u8 ch = 0; rt_kprintf("scree process thread running...\r\n"); /* 清空接收参数.,做接收准备 */ ScreenDev.r_sta = LCDPSTATUS_FINDHEAD1; ScreenDev.buff_len = 0; rt_memset(ScreenDev.buff, 0, Screen_BUFF_SIZE); while (1) { if ((rt_sem_take(&ScreenDev.r_tx, 50)) != RT_EOK) { continue; } /* read one character from device */ while (rt_device_read(ScreenDev.dev, 0, &ch, 1) == 1) { lcd_cmd_analyse(ch); } rt_thread_delay(40); } } void lcd_cmd_analyse(u8 c) { static u8 len = 0; static u8 index = 0; switch (ScreenDev.r_sta) { case LCDPSTATUS_FINDHEAD1: if (c != 0x5A) break; len = 0; ScreenDev.buff_len = 0; ScreenDev.buff[ScreenDev.buff_len++] = c; ScreenDev.r_sta = LCDPSTATUS_FINDHEAD2; break; case LCDPSTATUS_FINDHEAD2: if (c != 0xA5) { ScreenDev.r_sta = LCDPSTATUS_FINDHEAD1; break; } ScreenDev.buff[ScreenDev.buff_len++] = c; ScreenDev.r_sta = LCDPSTATUS_LEN; break; case LCDPSTATUS_LEN: len = c; index = 0; ScreenDev.buff[ScreenDev.buff_len++] = len; ScreenDev.r_sta = LCDPSTATUS_CMD; if (len < 3) ScreenDev.r_sta = LCDPSTATUS_FINDHEAD1; break; case LCDPSTATUS_CMD: if (c != 0x80 && c != 0x81 && c != 0x82 && c != 0x83 && c != 0x84) { ScreenDev.r_sta = LCDPSTATUS_FINDHEAD1; break; } ScreenDev.buff[ScreenDev.buff_len++] = c; index++; ScreenDev.r_sta = LCDPSTATUS_DATA; break; case LCDPSTATUS_DATA: ScreenDev.buff[3 + index] = c; ScreenDev.buff_len++; index++; if (index == len) { #ifdef USING_LCD_CRC if (CRC16(ScreenDev.buff + 3, index) == 0) { Screen_Analyze(ScreenDev.buff); } else rt_kprintf("[LCD]: Recv from lcd, but crc error.\n"); #else rt_kprintf("get one screen cmd.\r\n"); debug_sendbuff(ScreenDev.buff, len + 3); Screen_Analyze(ScreenDev.buff); #endif } else { break; } ScreenDev.r_sta = LCDPSTATUS_FINDHEAD1; break; default: ScreenDev.r_sta = LCDPSTATUS_FINDHEAD1; break; } } typedef struct _LCD_COMMU_PARA { rt_uint8_t begain[2]; //5a a5 rt_uint8_t len; //长度 rt_uint8_t cmd; //命令 union { rt_uint8_t data[256]; struct { rt_uint8_t reg; word len; rt_uint8_t year; rt_uint8_t month; rt_uint8_t day; rt_uint8_t week; rt_uint8_t hour; rt_uint8_t min; rt_uint8_t sec; } lcd_time; struct { rt_uint16_t reg; rt_uint8_t regnum; rt_uint8_t regdata[1]; } txt_regvalue; struct { rt_uint16_t reg; rt_uint8_t regnum; rt_uint16_t regdata[1]; } num_regvalue; struct { rt_uint16_t reg; rt_uint8_t regnum; rt_uint32_t regdata[1]; } num_regLongvalue; struct cmd82 { rt_uint8_t begainreg1; rt_uint8_t begainreg2; union { rt_uint8_t dat[250]; PP_HeadLine1 page_HeadLine1; }cmd82dat; } cmd82; } data_area; } LCD_COMMU_PARA; void Screen_Analyze(u8* _buf) { #if 1 static SCREEN_PAGE_CHOSE oldpage = SCREEN_PAGE_Logo; uint16_t presskeyid = 0; //按键返回的按键ID uint16_t getvalue = 0; LCD_COMMU_PARA* reply = (LCD_COMMU_PARA*)_buf; // if (reply->cmd == 0x81) //只有时间设置才返回81,因为使用的是屏幕上的RTC // { // switch (reply->data_area.lcd_time.reg) { // case 0x20: //// analyse_lcd_time(reply); // break; // default: // break; // } // } // else if (reply->cmd == 0x83) { } } ```
jizhongbiao
2022-06-24
这家伙很懒,什么也没写!
做一个缓冲队列,或者直接用消息队列也可以。在串口中断中入队。开一个线程,在线程中出队。
伊森亨特
2022-12-07
这家伙很懒,什么也没写!
你好,你写的超时判断,超时是多久?
撰写答案
登录
注册新账号
关注者
0
被浏览
956
关于作者
DuBaojun
这家伙很懒,什么也没写!
提问
58
回答
14
被采纳
2
关注TA
发私信
相关问题
1
串口DMA发送数据时,数据被覆盖
2
关于串口DMA模式下rt_device_close问题
3
利用stm32f427实现usb转串口,电脑端什么也没有识别到
4
finsh 控制台 适配 RS 485请大神指点????
5
uart_sample.c 中,读串口设备时偏移量pos要设置为-1而不是0?
6
【结贴】at_device软件包中对串口接收数据缺少判断导致数据接收异常
7
串口无法接受数据,但可以发送
8
串口如何有效的清除掉接收缓冲,而不必一个一个的去读取
9
串口接收使用方式问题
10
雅特力FINSH问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
简单两步配置RTT源码阅读环境 vsc+clangd
2
恩智浦[FRDM-MCXN947]初探 之 ADC与DAC
3
LVGL使用字库IC芯片显示中文
4
基于STM32H750和Rt-Thread的CANFD通信实现的记录(一)
5
freemodbus主机在freertos的适配,参考rtthread例程
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部