我做这个串口数据接收 dma+空闲中断 加fifo 实现串口的高效收发 ,主要是串口接收的数据长度不定长,时间超时也不好做,还要串口收发的效率要高,采用串口数据的接收 dma+空闲中断+fifo的方式 速度快和效率高,占用cpu的时间短
对比了其他几种方式
1:采用串口中断的话,每接收1byte就得中断一次。这样太消耗CPU资源! 频繁进中断,占用中断,特别是对时间和时序要求比较严格的时候 串口频繁进入中断导致其他中断时序有影响
2:采用DMA方式接收数据,接收的数据长度必须是固定的 对于接收数据长度不固定就不怎么好弄了,特别像gprs通信,接收长度不固定,这些都是困扰我
3:采用dma方式接收数据+定时器超时中断,这样来确定一帧数据完成,需要开关定时器,操作比较复杂,超时时间还不太好设置,stm32f1和f4 没有超时中断还只能采用定时器或者把rxd引脚接到stm32定时器触发引脚上来实现超时,
4:stm32串口dma方式接收数据+空闲中断或者超时中断+fifo 这种分内事来实现不定长的数据和高效的串口数据接收 效率比其他的方式要快,消耗cpu的时间比较少,这样应用可以做数据超时
所以我采用了stm32串口dma方式接收数据+空闲中断或者超时中断+fifo方式来实现
像stm32f103和stm32f407芯片没有时间超时中断 需要定时器来做超时 比较麻烦,nxp的部分芯片串口有超时中断,atmel的部分芯片串口有超时中断,stm32的h7和f7系列才有超时中断
要实现stm32串口dma方式接收数据+空闲中断或者超时中断+fifo方式来实现
第一步 stm32的串口dma配置 ,串口的初始化,还有串口的空闲中断
1,通过stm32的cubemx软件来生成串口+dma配置的初始化
cubemx生成代码都是HAL库的模式,我就以stm32f4的HAL库的方式实现
dma的配置可以通过cubemx软件串口+dma方式来生成代码
2,stm32生成的代码是不支持空闲中断的,需要自己增加空闲中断和空闲中断的处理
串口中断的处理
第二步 了解环形fifo的buff特点,通过分析环形buff的特点,其实串口的dma接收 dma模式设置循环模式 就是环形buff
环形buff的说明讲 站:https://blog.csdn.net/jiejiemcu/article/details/80563422
以下内容是引用了原文的内容
实现的原理:初始化的时候,列队头与列队尾都指向0,当有数据存储的时候,数据存储在‘0’的地址空间,列队尾指向下一个可以存储数据的地方‘1’,再有数据来的时候,存储数据到地址‘1’,然后队列尾指向下一个地址‘2’。当数据要进行处理的时候,肯定是先处理‘0’空间的数据,也就是列队头的数据,处理完了数据,‘0’地址空间的数据进行释放掉,列队头指向下一个可以处理数据的地址‘1’。从而实现整个环形缓冲区的数据读写。
看图,队列头就是指向已经存储的数据,并且这个数据是待处理的。下一个CPU处理的数据就是1;而队列尾则指向可以进行写数据的地址。当1处理了,就会把1释放掉。并且把队列头指向2。当写入了一个数据6,那么队列尾的指针就会指向下一个可以写的地址。
如果你懂了环形队列,那就跟着一步步用代码实现吧:
是不是跟dma的circular的模式跟这个环形队列非常相似呢
第3步就开始写串口dma+空闲中断或超时中断+fifo的代码啦
重要的代码 串口dma的fifo的数据长度的处理
但是这种方式会2个问题:
1,串口一直有数据接收 不产生空闲中断 这个时候会有问题 解决的方法采用超时方法来解决 或者采用一个一个的数据处理方式采用每来一个数据产生一个中断方式
2, 一个数据包超过dma的最大buff长度 已经越界 导致了部分数据被覆盖啦 解决方法就是把DMA的接收buff定义更大一点 最好定义为2倍的一个最大数据包 考虑资源也可以考虑1.5或1倍的一个最大数据包 或者采用一个一个的数据处理方式 采用每来一个数据产生一个中断方式
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!