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

继续谈STM32串口通信时自定义协议问题(二)

[复制链接]
只取一瓢 发布时间:2020-10-23 11:01
上一篇我已经给大家介绍过了,不知道有没有人验证过我在上一篇文章中的程序,因为当时没有搭建硬件环境进行试验,程序在实际的板子上是跑不起来的,这篇文章就是来填坑的。
) l: V4 c2 E0 r; V; H) [1 K8 k  K4 n5 p2 x# G0 X. H
我想明白一个问题:其实具体的代码怎么写是不太重要的,重要的是我实现该功能的思路。只要把思路理顺,代码自然而然就出来了,这可能也是在逛论坛的时候,大家更喜欢分享自己的想法,而不愿意直接贴代码的原因。
0 `( [' s- d9 [2 c4 G; u% X
1 `. S  T9 |5 O8 L: U; _$ r1 j说回我们的主题,自定义协议说白了就是协议的格式不同于其他的一些标准协议,但差别也仅仅体现在协议的内容上。在进行串口通信的时候,数据是一个字节一个字节的进行发送和接收的,理论上只要能实现一个字节的发送和接收,这个问题就已经解决了。但是很多人和我刚开始接触这个问题的时候一样,脑子转不过来,想不明白怎么从接收一个数据怎么扩展到接收一帧数据,下面给大家说一下我的思路:9 ?* Q2 f1 z* r- j1 q

6 ^  V3 S, D3 |! j* a/ b我们先来说数据的接收,要实现这一功能显然离不了串口中断,既然要用到中断自然少不了对STM32进行配置;大致可以分为以下几个步骤:
+ _. J( G  T+ o: [  h# A串口时钟使能,GPIO时钟使能;
6 X' c. W/ @# f3 ~1 H1 K设置引脚复用映射;
0 c' i4 k4 w7 NGPIO初始化设置;# Y( F" T6 \, w# E& K9 q/ i
串口参数初始化;
7 x4 Z7 o7 ?( ?& ^6 C开启中断;
* J5 X1 Y0 O4 p% ]2 D8 h: l使能串口;
- ~  \' [7 c! D1 O  y4 V/ a' C编写中断处理函数;
3 n& ~& V+ G( O0 E! D$ I5 v4 Z9 P) ^9 P; H7 N8 P5 l
以上这几个步骤都是些程式化的东西,只需要按照其要求按部就班的配置就可以了。编写中断处理函数是我们的重中之重,因为从这里开始才真正与我们要接受的数据有了联系。7 Q" l# ?! `5 b6 Q6 q0 t# S
11.png 7 j0 s, M6 c% a
我们要接收AA 01 01 02 BB这么一帧数据,我们可以按照下面这个流程图的方法来编写中断处理函数.
7 O( N6 F4 x- |+ U  G0 o# S6 l2 ]! ]3 ]1 k3 B$ m1 c
代码实现如下:, m) c6 x1 V. S: G& |" e, l
  1. void USART1_IRQHandler(void)                  
    * z, u; I* ^3 C/ `8 G5 G: V
  2. {
    # E4 t1 M: f  l5 l8 c
  3.   u8 Res;//临时变量,存放串口接收的数据1 R( M' [3 f# k( x7 p. }
  4.   if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
    . E) f" F  o( }, E
  5.   {& w9 J0 ]% n# \
  6.     Res =USART_ReceiveData(USART1);//(USART1->DR);  //读取接收到的数据
    $ }: C: R& y6 N* n4 d- o/ {
  7.     if(rx_stack.head_flag==1)//收到了帧头$ n& m9 M, J/ k2 K) e0 V9 P+ m
  8.     {' i& ?8 J; `( Q( D
  9.         if(Res==rx_stack.tail)//判断当前值是不是帧尾
    # e6 j, P: m8 [8 n
  10.         {1 r4 c, P) k0 w! V! S. ~
  11.           rx_stack.finish_flag = 1;' c5 x0 r, ?1 }1 {
  12.           rx_stack.tail_flag=1;" B" r( H! H- u9 f$ x9 E
  13.           rx_stack.head_flag=0;
    5 O! v: y- D" \$ l3 K# s
  14.         }, ~4 t: {+ L& V$ Q: o2 o/ q
  15.         else. [( }, ?' L+ K( V, j+ f
  16.         {- G" x, `( @5 k, o8 A
  17.           rx_stack.recevie_data[rx_stack.data_pt] = Res;  [8 @; Y4 M- K, |0 D  Y- F2 ^6 E3 p
  18.           rx_stack.data_pt++;
    # t( h8 }9 w! r) I! S4 J0 V; q
  19.           if(rx_stack.data_pt > 9); j* O% H. W. w
  20.           {8 b6 U3 X3 D  |& u! e
  21.             rx_stack.data_pt = 0;0 `  f) b: i6 w- O  n
  22.           }; i& E0 D7 ^8 P* H/ b
  23.         }                  
    8 Y3 B7 z% ^* n
  24.     }
    3 a) z* S  @9 w$ g
  25.     else//没有收到帧头
    ; b/ T2 g& O  g( ]; P( K
  26.     {
    * L5 i# F! v: q
  27.       if(Res==rx_stack.head)- E6 g7 Z& d- U
  28.         rx_stack.head_flag=1;
    ! e% M7 e! W* {8 j( p# t. p3 r
  29.       else
    1 B. h( R% _$ l# I8 f/ ~
  30.       {
    % {; O/ G5 D! A. D2 u9 i2 @
  31.         CommClr();; E9 x/ k% W0 _0 f2 H# C! ~0 P
  32.         return;  8 V. W" Y' q) Z
  33.       }  
    8 g0 p$ c. Y4 K' l( i
  34.     }   
    5 A. t6 g! t% D+ V! @
  35.   }
    + |# v% `, m/ t. ~* S( t7 D
  36.     USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除接受中断标志5 k7 r! `3 @/ r& M; j
  37. }
复制代码

6 o3 t! Y! m9 A通过以上操作我们就可以将AA 01 01 02 7B这一帧数据存放到数组中了。那么我们怎么将控制字解析出来呢?这就要用到解包函数。解包函数怎么写相信大家应该有思路了吧!定义一个解包函数,先判断数据接收完成功能的标志位是不是已经置位,如果已经置位就直接把数组里相应位置的数据取出来就完成了。
; l% e& F! s8 n' j1 I5 S3 `" f7 \* }( D+ V3 l

0 Y2 h8 s; B& C! h当然,这种方法是可以实现我们最初制定的目标的,但是如果数据传输过程中出错该怎么办呢?会不会出现取出来的控制字和预期的不一样呢?这个问题小伙伴们可以自己去摸索。当然大家如果有更好的实现方法,也可以给我留言,一起交流一下。. G4 R2 x+ T# `* i7 h& z
! M% m6 g$ n. u* R* O" y0 {' d
上一篇传送:https://www.stmcu.org.cn/module/forum/thread-627440-1-1.html4 I0 r& Q8 k7 v! C

9 q5 D3 l( [+ Y8 v
收藏 评论0 发布时间:2020-10-23 11:01

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版