标题: STM32串口接收不定长数据原理与源程序 [打印本页]

作者: piaolin    时间: 2015-10-29 23:09
标题: STM32串口接收不定长数据原理与源程序
今天说一下STM32单片机的接收不定长度字节数据的方法。由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。
IDLE中断什么时候发生?
IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。
如何判断一帧数据结束,就是我们今天讨论的问题。因为很多项目中都要用到这个,因为只有接收到一帧数据以后,你才可以判断这次收了几个字节和每个字节的内容是否符合协议要求。
看了前面IDLE中断的定义,你就会明白了,一帧数据结束后,就会产生IDLE中断。这个中断真是太TMD有用了。省去了好多判断的麻烦。
如何配置好IDLE中断?
下面我们就配置好串口IDLE中断吧。

这是串口CR1寄存器,其中,对bit4写1开启IDLE中断,对bit5写1开启接收数据中断。(注意:不同系列的STM32,对应的寄存器位可能不同)
(RXNE中断和IDLE中断的区别?
当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。)

这是状态寄存器,当串口接收到数据时,bit5就会自动变成1,当接收完一帧数据后,bit4就会变成1.
需要注意的是,在中断函数里面,需要把对应的位清0,否则会影响下一次数据的接收。比如RXNE接收数据中断,只要把接收到的一个字节读出来,就会清除这个中断。IDLE中断,如何是F0系列的单片机,需要用ICR寄存器来清除,如果是F1系列的单片机,清除方法是“先读SR寄存器,再读DR寄存器”。(我怎么知道?手册上写的)
下面以STM32F103为例给出源程序。
我们先来看程序中的主要部分。
串口初始化函数片段

如果你原来的串口初始化函数具有打开串口接收中断的话,实际上就是在初始化函数中多了一条打开空闲中断的语句。
串口中断函数

串口中断函数里面,最重要的两条语句,就是上图中圈出来的两条语句。第一条语句用来判断是否接收到1个字节,第二条语句用来判断是否接收到1帧数据。(是不是感觉超级方便?妈妈再也不用担心我如何判断是否接收完1帧数据了。)
主函数

我写的这个主函数,是用来验证接收的正确性的。RxCounter表示的是这一帧数据有几个字节,接收完一帧数据,会在中断函数里面把ReceiveState置1,然后,通过串口把接收到的数据发送回串口。这样,既验证了接收了多少字节的正确性,又验证了接收到的数据是否正确。

上图是结果验证。
点击下载源程序: STM32串口接收不定长数据程序.7z (207.13 KB, 下载次数: 1812)
                                       
                                我是瑞生,毫无保留的给大家透露电子设计经验,不定时分享实用的落地的电子设计技巧,希望能够帮助到大家。   

  1. /**
  2.   ******************************************************************************
  3.   * @file    串口接收不定长字节数据
  4.   * @author  瑞生
  5.   * @version V1.0
  6.   * @date    2015.10.23
  7.   * @brief   Main program body
  8.   ******************************************************************************
  9.   ******************************************************************************
  10.   */  

  11. /* Includes ------------------------------------------------------------------*/
  12. #include "stm32f10x.h"
  13. #include "uart.h"


  14. volatile uint8_t aRxBuffer[100]={0x00};
  15. volatile uint8_t RxCounter=0;
  16. volatile uint8_t ReceiveState=0;
  17. /**
  18.   * @brief  Main program.
  19.   * @param  None
  20.   * @retval None
  21.   */
  22. int main(void)
  23. {
  24.         uint8_t i=0;
  25.         
  26.         USART1_Init();
  27.         
  28.   while (1)
  29.   {
  30.                 if(ReceiveState==1)//如果接收到1帧数据
  31.                 {
  32.                         ReceiveState=0;
  33.                         i=0;

  34.                         while(RxCounter--)// 把接收到数据发送回串口
  35.                         {
  36.                                 USART_SendData(USART1, aRxBuffer[i++]);        
  37.                                 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  38.                         }
  39.                         RxCounter=0;
  40.                 }
  41.   }
  42. }


复制代码

   

作者: 0406445    时间: 2016-2-1 21:59
好详细的帖子,谢谢lz
作者: woodman100    时间: 2016-2-21 19:27
程序下来试了,IDLE进不了啊!

作者: My_Skity    时间: 2016-3-17 08:13
这两天正在琢磨STM32F103的串口中断处理程序,之前以为只能一个字节一个字节接收,多谢楼主提醒还有IDLE这个帧数据接收,大爱啊!
作者: My_Skity    时间: 2016-3-17 08:13
这两天正在琢磨STM32F103的串口中断处理程序,之前以为只能一个字节一个字节接收,多谢楼主提醒还有IDLE这个帧数据接收,大爱啊!
作者: duckfans    时间: 2016-3-23 17:50
好标记
作者: seu_zhang    时间: 2016-4-18 15:13
谢谢楼主的分享,太赞了,终于解决我这个不定长GPS信息的接收问题了,赞赞赞
作者: seu_zhang    时间: 2016-4-18 15:19
woodman100 发表于 2016-2-21 19:27
程序下来试了,IDLE进不了啊!

你进不了吗?我就是参考了 这个思想,很棒啊!你看看是不是板子的型号不对,他这是F1的,修改程序,和你的板子相称
作者: 舞者0068    时间: 2016-4-21 14:09
感觉挺不错,之前还有个什么串口延时处理,要是这个能用的话都不用那么麻烦了
作者: hdfjg    时间: 2016-5-10 13:28
赞,解决了我的问题
作者: 打酱油+1    时间: 2016-5-19 21:05
太感谢楼主了
作者: 打酱油+1    时间: 2016-5-19 21:06
感谢楼主
作者: doer    时间: 2016-5-20 18:57
谢谢楼主分享,帮了大忙。。。。。。。
作者: MUCV    时间: 2016-5-21 00:22
正在学这个,给点赞楼主
作者: sqhua333    时间: 2016-5-30 10:49
为什么最后串口发送的数据总是有个别数据丢失了呢?
作者: sqhua333    时间: 2016-5-30 10:50
楼主,为什么最好发送的数据总是有个别的数据丢失了呢?

作者: sqhua333    时间: 2016-5-30 11:08
楼主,波特率为9600的时候数据是正确的,当波特率设置为115200时,数据就不正确了,为什么呢?
作者: mardin    时间: 2016-5-31 08:52
真心是太TMD有用了
作者: yaoyanyan    时间: 2016-6-14 10:40
大家好,我是新来的,就像楼主说的方法我也试了,只不过是用的UART4,在发送的时候也是有数据丢失,是什么原因呢
作者: lamdota    时间: 2016-6-15 16:05
zhichizhichi
作者: phantomplus    时间: 2016-6-30 17:21
非常谢谢。
作者: a7250658    时间: 2016-7-1 17:02
学习了

作者: 遗忘的心    时间: 2016-7-11 15:40
好东西,谢谢!
作者: 默默成长    时间: 2016-7-20 20:53
好东西,学习了。
作者: tanliang    时间: 2016-7-21 09:20
非常有用,modbus可以用上 前面说的9600可以有这个情况吗
作者: senzh01    时间: 2016-7-22 11:27
谢谢楼主的分享,太赞了
作者: 1321498219    时间: 2016-8-11 20:58

感谢楼主
作者: biyaoyzs    时间: 2016-8-16 11:13
很好,学习学习!
作者: faguoduifangui    时间: 2016-8-16 16:36
一直在找方法到底怎么做!!!!!!!!!!!!
作者: faguoduifangui    时间: 2016-8-17 16:55
真心的良心帖子
作者: qscdianzhi    时间: 2016-8-17 18:08
强!!!!为;楼主的态度点赞!!
作者: intersetings    时间: 2016-8-23 23:41
谢谢楼主的分享,太赞了
作者: tubage    时间: 2016-8-31 15:05
不错,支持
作者: vitasnokia    时间: 2016-9-25 21:56
继续顶,终于有黑币可以下载了
作者: 单片机初始化    时间: 2016-10-12 13:30

感谢楼主
作者: johnsonxjq    时间: 2016-10-12 15:11
感谢楼主教诲
作者: g753388438    时间: 2016-10-13 16:48
好贴  推荐
作者: whole_hope    时间: 2016-10-20 10:26
正好需要串口传速大量的数据,不知道速度跟不跟得上
作者: tangquan    时间: 2016-10-20 11:08
嗯,不错不错,我之前还是使用流控制界定帧的,移植性好一点,但是既然STM32自带这个功能那为何不用呢,
作者: jackouy    时间: 2016-11-5 09:37
兄弟,为什么我参考你的这个程序,串口助手发送11 22 33 44 55时,单片机接收出现FF 11 22 33 44 55
作者: dmgy343    时间: 2016-11-14 15:34
好办法,下次尝试使用这种方法
作者: jzxiecl    时间: 2016-11-15 17:28
果然是良心贴,顶。。。。。。。。
作者: 709360416    时间: 2016-11-17 14:16
我用的是串口2,但是不通
作者: bing20138    时间: 2016-11-22 13:15
这个方式很赞!!!!
作者: 1725591298    时间: 2016-12-12 16:11
8错~~~
作者: ljy773945726    时间: 2016-12-12 18:40
谢谢楼主分享,先收藏下!!!
作者: ljy773945726    时间: 2016-12-12 18:40
谢谢楼主分享!!!
作者: 520sky    时间: 2017-2-6 17:27
试了好多网上的idle+dma的都不行
作者: 520sky    时间: 2017-2-7 15:31
不知道怎么回事就是进不了 IDLE
作者: 332052001    时间: 2017-2-26 12:36
我曹这个功能太有用了,以前做51的时候都是定了长度的
作者: jasonyu    时间: 2017-2-27 09:51
楼主你好,为什么我按照你的程序这样改的,那个idle中断每个字节都进呢
作者: zhang135789    时间: 2017-3-4 09:23
良心贴,很有用处,只是修改
作者: xiangyang123    时间: 2017-3-4 14:57
好贴必须顶上去,赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞赞
作者: splendid    时间: 2017-3-4 16:03
大兄弟,用了五黑币下下来,连中断程序都没有是怎么回事??
作者: museum    时间: 2017-3-27 13:56
谁下载了给我一份  qq  1952488652
我积分不够,谢谢
作者: cm7626    时间: 2017-4-8 11:14
讲解的很详细 大家需要你这样的高手
作者: jdm2005    时间: 2017-4-26 13:22
高手,谢谢知道
作者: 落雁秋莎    时间: 2017-4-27 10:59
很好,希望有所帮助
作者: hongqintin    时间: 2017-5-18 11:36
好贴,谢谢楼主
作者: xiaoyue92    时间: 2017-5-19 18:16
我遇到和上面同志一样的问题  有数据丢失现象  楼主能解下祸吗
作者: 树叶的人生    时间: 2017-5-20 10:36
这个真的很有用啊,谢谢分享,很有帮助的
作者: worinidege    时间: 2017-5-23 14:08
就是不知道后面的abuffer是怎么处理的
作者: victor6611    时间: 2017-6-12 09:40
不错,下载学习,学习
作者: dzfree    时间: 2017-6-30 15:56
很详细很经典的帖子,苦无头绪的串口终于搞定了  谢谢谢谢谢谢谢谢 谢谢谢谢
作者: sfd123    时间: 2017-7-1 10:28
什么原理呢?单片机根据波特率自己得到一个帧超时时间?
作者: cqh757128    时间: 2017-7-4 08:28
很棒,正好需要这一块的东西,谢谢楼主
作者: 君临天下尹成    时间: 2017-8-4 16:33
很实用                  
作者: Allaneil    时间: 2017-9-13 10:40
感谢楼之分享
作者: 穿山跃海    时间: 2017-11-23 23:34
下来试试,借鉴一下,最近正在调这个东西
作者: www76307a    时间: 2017-12-5 16:45
好详细的帖子,谢谢lz
作者: 竹轩2018    时间: 2018-1-2 23:27
给力楼主!谢谢分享!
作者: fan5572283    时间: 2018-1-7 15:22
感谢楼主
作者: xjjwws    时间: 2018-1-16 17:01
好东西,值得大家下载。原楼主多多奉献,不慎感激
作者: whj4674672    时间: 2018-3-19 11:06
好东西,正好有用
作者: 278821852    时间: 2018-3-27 19:51
好东西,谢谢楼主分享!
作者: 564646546465    时间: 2018-3-29 16:34
赞赞赞!!!!!!程序试过了,没问题
作者: gaojian218    时间: 2018-4-3 22:32
好详细的帖子,谢谢lz
作者: wutuobangs    时间: 2018-4-8 14:02
感谢楼主分享
作者: fly_confidence    时间: 2018-5-22 22:14
好详细的帖子,谢谢lz
作者: ljjmust    时间: 2018-5-25 09:36
真的很方便,非常感谢。
作者: caosongze    时间: 2018-6-2 17:04
收益匪浅
作者: user5448    时间: 2018-6-4 12:50
長知識了 感謝無私分享
作者: Jesus    时间: 2018-7-7 13:42
新手签到,谢谢
作者: 一世界    时间: 2018-7-11 11:15
  牛逼  简直学到了  
作者: 小欧阳    时间: 2018-7-12 17:31
我也用了出了一些问题
作者: kaneky    时间: 2018-7-31 14:09
学习了,谢谢楼主!
作者: 离落城    时间: 2018-10-12 13:10
很给力!
作者: hwasun    时间: 2018-11-6 10:29
感觉挺不错,之前还有个什么串口延时处理,要是这个能用的话都不用那么麻烦了
作者: wdliming    时间: 2018-11-13 08:44
标记一下~~~~~
作者: guguren    时间: 2018-11-19 15:32
学习下,新手
作者: 离落城    时间: 2018-12-2 15:13
先收藏了,有空一定试试
作者: SKYlink    时间: 2018-12-3 09:15
厉害厉害   
作者: Xchonger    时间: 2018-12-4 11:01
不错 ,学习到了
作者: Adey杨    时间: 2018-12-17 13:35
有没有库函数版本的代码呢,寄存器不会
作者: bucker    时间: 2018-12-21 21:54
虽然已经用过,确实非常好用,还是为楼主点赞。
作者: 天风情    时间: 2018-12-24 16:43
正学习中断呢,看了好多程序,目前看到的只有这个比较好
作者: 天风情    时间: 2018-12-24 16:44
jackouy 发表于 2016-11-5 09:37
**** 作者被禁止或删除 内容自动屏蔽 ****

是不是上电的时候多发的?你上电稳定后把接收数据清除一下,再发送试试看
作者: amesim2019    时间: 2019-4-17 13:52
太感谢楼主了
作者: jiaxiangqi    时间: 2019-5-14 20:53
非常感谢楼主分享
作者: Caramel2    时间: 2019-6-30 19:43
谢谢楼主分享!




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1