找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 66152|回复: 146
打印 上一主题 下一主题
收起左侧

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, 下载次数: 1781)
                                       
                                我是瑞生,毫无保留的给大家透露电子设计经验,不定时分享实用的落地的电子设计技巧,希望能够帮助到大家。   

  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. }


复制代码

   

评分

参与人数 14黑币 +99 收起 理由
黑夜问白天-YEJ + 12 绝世好帖!
wzb1003 + 30
Tony不吃辣 + 24 回帖助人的奖励!
菜鸡一只314159 + 5 绝世好帖!
tangchenfei + 5 很给力!
kqk123 + 1 很给力!
电子星辰 + 1 赞一个!
JULIS + 5 很给力!
Zeuphoria + 4 赞一个!
1111_1111 + 5 共享资料的黑币奖励!
kkkMill + 2 很棒,正好需要这一块的东西,谢谢楼主
xiaoguaishou + 1 很给力!
panx + 2 很给力!
jsnjzhw + 2 赞一个!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏42 分享淘帖 顶23 踩
回复

使用道具 举报

沙发
ID:91390 发表于 2016-2-1 21:59 | 只看该作者
好详细的帖子,谢谢lz
回复

使用道具 举报

板凳
ID:105982 发表于 2016-2-21 19:27 | 只看该作者
程序下来试了,IDLE进不了啊!
回复

使用道具 举报

地板
ID:109266 发表于 2016-3-17 08:13 | 只看该作者
这两天正在琢磨STM32F103的串口中断处理程序,之前以为只能一个字节一个字节接收,多谢楼主提醒还有IDLE这个帧数据接收,大爱啊!
回复

使用道具 举报

5#
ID:109266 发表于 2016-3-17 08:13 | 只看该作者
这两天正在琢磨STM32F103的串口中断处理程序,之前以为只能一个字节一个字节接收,多谢楼主提醒还有IDLE这个帧数据接收,大爱啊!
回复

使用道具 举报

6#
ID:110407 发表于 2016-3-23 17:50 | 只看该作者
好标记
回复

使用道具 举报

7#
ID:114928 发表于 2016-4-18 15:13 | 只看该作者
谢谢楼主的分享,太赞了,终于解决我这个不定长GPS信息的接收问题了,赞赞赞
回复

使用道具 举报

8#
ID:114928 发表于 2016-4-18 15:19 | 只看该作者
woodman100 发表于 2016-2-21 19:27
程序下来试了,IDLE进不了啊!

你进不了吗?我就是参考了 这个思想,很棒啊!你看看是不是板子的型号不对,他这是F1的,修改程序,和你的板子相称
回复

使用道具 举报

9#
ID:115692 发表于 2016-4-21 14:09 | 只看该作者
感觉挺不错,之前还有个什么串口延时处理,要是这个能用的话都不用那么麻烦了
回复

使用道具 举报

10#
ID:119763 发表于 2016-5-10 13:28 | 只看该作者
赞,解决了我的问题
回复

使用道具 举报

11#
ID:122041 发表于 2016-5-19 21:05 | 只看该作者
太感谢楼主了
回复

使用道具 举报

12#
ID:122041 发表于 2016-5-19 21:06 | 只看该作者
感谢楼主
回复

使用道具 举报

13#
ID:122221 发表于 2016-5-20 18:57 | 只看该作者
谢谢楼主分享,帮了大忙。。。。。。。
回复

使用道具 举报

14#
ID:117525 发表于 2016-5-21 00:22 来自手机 | 只看该作者
正在学这个,给点赞楼主
回复

使用道具 举报

15#
ID:120530 发表于 2016-5-30 10:49 | 只看该作者
为什么最后串口发送的数据总是有个别数据丢失了呢?
回复

使用道具 举报

16#
ID:120530 发表于 2016-5-30 10:50 | 只看该作者
楼主,为什么最好发送的数据总是有个别的数据丢失了呢?
回复

使用道具 举报

17#
ID:120530 发表于 2016-5-30 11:08 | 只看该作者
楼主,波特率为9600的时候数据是正确的,当波特率设置为115200时,数据就不正确了,为什么呢?
回复

使用道具 举报

18#
ID:124166 发表于 2016-5-31 08:52 | 只看该作者
真心是太TMD有用了
回复

使用道具 举报

19#
ID:126634 发表于 2016-6-14 10:40 | 只看该作者
大家好,我是新来的,就像楼主说的方法我也试了,只不过是用的UART4,在发送的时候也是有数据丢失,是什么原因呢
回复

使用道具 举报

20#
ID:126864 发表于 2016-6-15 16:05 | 只看该作者
zhichizhichi
回复

使用道具 举报

21#
ID:103617 发表于 2016-6-30 17:21 | 只看该作者
非常谢谢。
回复

使用道具 举报

22#
ID:128839 发表于 2016-7-1 17:02 | 只看该作者
学习了
回复

使用道具 举报

23#
ID:130030 发表于 2016-7-11 15:40 来自手机 | 只看该作者
好东西,谢谢!
回复

使用道具 举报

24#
ID:134419 发表于 2016-7-20 20:53 | 只看该作者
好东西,学习了。
回复

使用道具 举报

25#
ID:123377 发表于 2016-7-21 09:20 | 只看该作者
非常有用,modbus可以用上 前面说的9600可以有这个情况吗
回复

使用道具 举报

26#
ID:6553 发表于 2016-7-22 11:27 | 只看该作者
谢谢楼主的分享,太赞了
回复

使用道具 举报

27#
ID:136557 发表于 2016-8-11 20:58 | 只看该作者

感谢楼主
回复

使用道具 举报

28#
ID:136869 发表于 2016-8-16 11:13 | 只看该作者
很好,学习学习!
回复

使用道具 举报

29#
ID:136903 发表于 2016-8-16 16:36 | 只看该作者
一直在找方法到底怎么做!!!!!!!!!!!!
回复

使用道具 举报

30#
ID:136903 发表于 2016-8-17 16:55 | 只看该作者
真心的良心帖子
回复

使用道具 举报

31#
ID:136987 发表于 2016-8-17 18:08 | 只看该作者
强!!!!为;楼主的态度点赞!!
回复

使用道具 举报

32#
ID:137439 发表于 2016-8-23 23:41 来自手机 | 只看该作者
谢谢楼主的分享,太赞了
回复

使用道具 举报

33#
ID:138053 发表于 2016-8-31 15:05 | 只看该作者
不错,支持
回复

使用道具 举报

34#
ID:136553 发表于 2016-9-25 21:56 | 只看该作者
继续顶,终于有黑币可以下载了
回复

使用道具 举报

35#
ID:142422 发表于 2016-10-12 13:30 | 只看该作者

感谢楼主
回复

使用道具 举报

36#
ID:75390 发表于 2016-10-12 15:11 | 只看该作者
感谢楼主教诲
回复

使用道具 举报

37#
ID:61002 发表于 2016-10-13 16:48 | 只看该作者
好贴  推荐
回复

使用道具 举报

38#
ID:143545 发表于 2016-10-20 10:26 | 只看该作者
正好需要串口传速大量的数据,不知道速度跟不跟得上
回复

使用道具 举报

39#
ID:143559 发表于 2016-10-20 11:08 | 只看该作者
嗯,不错不错,我之前还是使用流控制界定帧的,移植性好一点,但是既然STM32自带这个功能那为何不用呢,
回复

使用道具 举报

40#
ID:146174 发表于 2016-11-5 09:37 | 只看该作者
兄弟,为什么我参考你的这个程序,串口助手发送11 22 33 44 55时,单片机接收出现FF 11 22 33 44 55
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表