你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

转载:基于STM32F103VE标准库的串口接收不定长数据与源程序

[复制链接]
电子星辰 发布时间:2018-5-30 10:31
转载自:http://www.51hei.com/bbs/dpj-39885-1.html
  e4 z6 \+ L# i2 |我是瑞生,毫无保留的给大家透露电子设计经验,不定时分享实用的落地的电子设计技巧,希望能够帮助到大家。7 E& p3 {7 x( M/ c, u9 h& m
今天说一下STM32单片机的接收不定长度字节数据的方法。由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。
/ i0 ^" l& V7 k9 FIDLE中断什么时候发生?2 p( A) q) f* v4 y) i
IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。5 @5 D/ P$ X) ?1 ~1 I- a' s
如何判断一帧数据结束,就是我们今天讨论的问题。因为很多项目中都要用到这个,因为只有接收到一帧数据以后,你才可以判断这次收了几个字节和每个字节的内容是否符合协议要求。& B5 A+ h( ~" O( x7 H# K4 s' v) @
看了前面IDLE中断的定义,你就会明白了,一帧数据结束后,就会产生IDLE中断。这个中断真是太TMD有用了。省去了好多判断的麻烦。
3 Y% R- K$ G" `0 o如何配置好IDLE中断?) Q) H% q. `* Q. l( q
下面我们就配置好串口IDLE中断吧。
& K5 O) R8 i' _- Q# x! ^4 M1 b# {7 H+ P, O2 o! o+ I% g- m
这是串口CR1寄存器,其中,对bit4写1开启IDLE中断,对bit5写1开启接收数据中断。(注意:不同系列的STM32,对应的寄存器位可能不同)
4 f( g/ N6 x2 M2 \( q(RXNE中断和IDLE中断的区别?
+ b$ J5 i1 U" B. S% F当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。)
4 s: ^2 I% c8 @( e$ e8 M4 i# S
, |! x$ U0 u5 C, C
& C3 j. W3 Y$ j7 n
这是状态寄存器,当串口接收到数据时,bit5就会自动变成1,当接收完一帧数据后,bit4就会变成1.
, a' m) R. @$ E) Q  Q需要注意的是,在中断函数里面,需要把对应的位清0,否则会影响下一次数据的接收。比如RXNE接收数据中断,只要把接收到的一个字节读出来,就会清除这个中断。IDLE中断,如何是F0系列的单片机,需要用ICR寄存器来清除,如果是F1系列的单片机,清除方法是“先读SR寄存器,再读DR寄存器”。(我怎么知道?手册上写的)1 H: p1 c$ @/ M% K0 a9 q0 o# ~( m
下面以STM32F103为例给出源程序。, S7 X2 R; B7 o5 O1 Z
我们先来看程序中的主要部分。. x, M) c! N( r. o9 o. y
串口初始化函数片段
# W1 @' R0 l; Y

; ]# i* V1 F7 O- x* e6 s如果你原来的串口初始化函数具有打开串口接收中断的话,实际上就是在初始化函数中多了一条打开空闲中断的语句。. R1 m! C3 ]8 i' B" {1 M  d) u
串口中断函数, E7 l5 r$ `+ u0 |% T6 i0 g

5 v% t' k/ i( v  S; p% H
5 ~2 ~  v+ |# t; w
串口中断函数里面,最重要的两条语句,就是上图中圈出来的两条语句。第一条语句用来判断是否接收到1个字节,第二条语句用来判断是否接收到1帧数据。(是不是感觉超级方便?妈妈再也不用担心我如何判断是否接收完1帧数据了。)
- H+ C$ k# J. h  I( m  a7 `5 S9 O5 x0 d主函数
. C% u7 l1 w" h# E

1 p1 M7 d  n/ Z) P我写的这个主函数,是用来验证接收的正确性的。RxCounter表示的是这一帧数据有几个字节,接收完一帧数据,会在中断函数里面把ReceiveState置1,然后,通过串口把接收到的数据发送回串口。这样,既验证了接收了多少字节的正确性,又验证了接收到的数据是否正确。
' s- S% Y1 M: @. D
, i% [% i" ]% P  ]. m上图是结果验证
+ t* ~2 d2 ^1 J' R/ ]以下是部分源代码。
& k5 h* W% C* ~4 _/**1 F, J+ w9 M9 n' X' a! R4 y
  ******************************************************************************2 X; @' C; U! d9 B$ V" Z+ V
  * @file    串口接收不定长字节数据
0 q7 H+ f, ]6 x0 U: y4 t  * @author  瑞生- a: n  c, ~8 h- s1 t3 X
  * @version V1.0
3 _1 n5 }4 o7 p8 q5 ~: X  g: y( l) l  * @date    2015.10.23
! Z5 u6 v4 h9 ^1 e  * @brief   Main program body& A5 d: a8 U3 h1 L
  ******************************************************************************
+ a, r/ s1 [) S5 U" h, w  ******************************************************************************
: V4 e2 K# h- ^& H1 h/ }3 ]2 G  */  0 ]( }3 h+ {2 b# y5 n& [1 z( _
  Y6 L9 Z; G# J% M+ f* g
/* Includes ------------------------------------------------------------------*/* W: `, W- D4 j8 K/ ?6 G% \
#include "stm32f10x.h"# ~+ x. [; k2 d. A" Q2 M* T
#include "uart.h"/ B% z) p. O# u& [0 f

$ t# v  S' T: A3 T
/ s1 B. _  W5 b; I, G- ~0 L3 J4 Wvolatile uint8_t aRxBuffer[100]={0x00};
$ z: J; P$ v! D0 ^) T% lvolatile uint8_t RxCounter=0;
+ u  E; s' T# f" z- {3 s& @3 Xvolatile uint8_t ReceiveState=0;5 x9 O4 J7 _; F& B) }' }# P
/**
7 h( h) N1 t5 z3 [6 p. E  * @brief  Main program.
; d7 @8 Q+ s* k5 W  * @param  None* e( D4 `+ G' Z0 E; k- K: p9 q+ W
  * @retval None9 G1 [  r2 u& W2 ]
  */
8 n- d/ f* e/ L4 O6 |int main(void)% a4 Y. C: o/ J" @& x  c# P
{
" S- v( E6 d/ c. Q: P& V        uint8_t i=0;2 N. G5 r1 I5 R2 K# G; X1 l, f( M
        ) E, N8 K, q/ q- w6 d) F
        USART1_Init();% u* S1 Y$ F8 x' s4 e
        
0 I% x! |; l4 Y& R# j- L/ s+ C  while (1), n, R2 U+ O$ `# t" c: Y7 c
  {
4 v# q8 C+ p. K6 R1 V* w9 U                if(ReceiveState==1)//如果接收到1帧数据# ^, n7 N7 H! D0 p8 W
                {: l4 L& t2 U& H0 e" y
                        ReceiveState=0;
1 b$ Y* B# z  H! ]4 G% ?                        i=0;% `, h( G* k( M9 c

; h+ U% a# p, b6 a8 `2 R" h                        while(RxCounter--)// 把接收到数据发送回串口
- P" c( e) X- I7 J- n; [( T                        {
+ h8 n1 `0 n; Z3 Q( o0 g1 L, a                                USART_SendData(USART1, aRxBuffer[i++]);        2 ?$ \* e/ r6 w3 ~; O
                                while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);& a& I7 Q7 J/ z- }7 ^0 S8 l
                        }4 v/ J4 |  I$ Z- s7 H
                        RxCounter=0;
2 s. {: B. v  b, G+ I                }4 R8 \  d( T8 X& m- }
  }: E. [9 t8 W1 ~" N; i
}% {) X+ W: [- _0 l

, {( t0 m# S7 `( Q0 B9 D: u* n1 U% ?0 A, S

STM32串口接收不定长数据程序.rar

下载

1.72 MB, 下载次数: 74

赞 收藏 1 评论5 发布时间:2018-5-30 10:31

举报

5个回答
zero99 回答时间:2018-5-30 13:10:25
谢谢分享
xiaoouyang 回答时间:2018-7-11 17:17:46
谢谢分享 如果是接收16进制的数该怎么处理呢
电子星辰 回答时间:2018-7-12 09:26:27
xiaoouyang 发表于 2018-7-11 17:17
) w* T2 F8 U7 Y/ x3 c2 ^谢谢分享 如果是接收16进制的数该怎么处理呢
5 p, F# G& B; R  c2 U1 A
不用特别处理,这个例子本身就是发送接收的16进制
xushengg 回答时间:2019-4-18 10:29:39
受用了 谢谢
poweradc 回答时间:2019-5-31 14:55:10
谢谢分享                       

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版