上一篇我已经给大家介绍过了,不知道有没有人验证过我在上一篇文章中的程序,因为当时没有搭建硬件环境进行试验,程序在实际的板子上是跑不起来的,这篇文章就是来填坑的。
) 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
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
- void USART1_IRQHandler(void)
* z, u; I* ^3 C/ `8 G5 G: V - {
# E4 t1 M: f l5 l8 c - u8 Res;//临时变量,存放串口接收的数据1 R( M' [3 f# k( x7 p. }
- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
. E) f" F o( }, E - {& w9 J0 ]% n# \
- Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
$ }: C: R& y6 N* n4 d- o/ { - if(rx_stack.head_flag==1)//收到了帧头$ n& m9 M, J/ k2 K) e0 V9 P+ m
- {' i& ?8 J; `( Q( D
- if(Res==rx_stack.tail)//判断当前值是不是帧尾
# e6 j, P: m8 [8 n - {1 r4 c, P) k0 w! V! S. ~
- rx_stack.finish_flag = 1;' c5 x0 r, ?1 }1 {
- rx_stack.tail_flag=1;" B" r( H! H- u9 f$ x9 E
- rx_stack.head_flag=0;
5 O! v: y- D" \$ l3 K# s - }, ~4 t: {+ L& V$ Q: o2 o/ q
- else. [( }, ?' L+ K( V, j+ f
- {- G" x, `( @5 k, o8 A
- rx_stack.recevie_data[rx_stack.data_pt] = Res; [8 @; Y4 M- K, |0 D Y- F2 ^6 E3 p
- rx_stack.data_pt++;
# t( h8 }9 w! r) I! S4 J0 V; q - if(rx_stack.data_pt > 9); j* O% H. W. w
- {8 b6 U3 X3 D |& u! e
- rx_stack.data_pt = 0;0 ` f) b: i6 w- O n
- }; i& E0 D7 ^8 P* H/ b
- }
8 Y3 B7 z% ^* n - }
3 a) z* S @9 w$ g - else//没有收到帧头
; b/ T2 g& O g( ]; P( K - {
* L5 i# F! v: q - if(Res==rx_stack.head)- E6 g7 Z& d- U
- rx_stack.head_flag=1;
! e% M7 e! W* {8 j( p# t. p3 r - else
1 B. h( R% _$ l# I8 f/ ~ - {
% {; O/ G5 D! A. D2 u9 i2 @ - CommClr();; E9 x/ k% W0 _0 f2 H# C! ~0 P
- return; 8 V. W" Y' q) Z
- }
8 g0 p$ c. Y4 K' l( i - }
5 A. t6 g! t% D+ V! @ - }
+ |# v% `, m/ t. ~* S( t7 D - USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除接受中断标志5 k7 r! `3 @/ r& M; j
- }
复制代码
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 |