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

基于STM32CUBEME接收不定长数据之USART定时器经验分享

[复制链接]
攻城狮Melo 发布时间:2023-4-15 16:48
概述
   本文利用中断实现串口不定长接收(非DMA),使用HAL库,将接受的数据打印出去。

* q( D* p# y. W  |" R
硬件准备
    首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:   
. o8 j) k. i7 b) k- |0 p1 w
5 y2 k% u+ `! e$ `8 U$ X; x$ n% |1 n
微信图片_20230415164627.jpg

+ t; c4 ]& s* X+ C( S" ^选择芯片型号
       使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
8 x( u+ D4 {: p" g  Y( k
微信图片_20230415164623.png
7 z& L$ o7 r5 Z8 t4 u3 E8 E% b
配置时钟源
    HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:# i% s2 h/ \8 h1 P

/ N) R, T8 n- K1 U8 J4 s
微信图片_20230415164620.png

7 A5 S! H+ u/ D  C' B2 M
配置时钟树
    STM32F0的最高主频到48M,所以配置48即可:
5 Q: k9 i; u$ t: E
1 j5 W- Z# w' V3 X0 q
微信图片_20230415164614.png
$ a/ a, H. }& g" O% O
串口配置
    本次实验使用的串口1进行串口通信,波特率配置为115200。9 ~+ f7 D' c, i/ t/ i( h2 _# k. C
" W6 `" l# O8 b7 w# Q
微信图片_20230415164611.png

+ }' S: h* p6 U% {9 `- _
    中断
5 O9 o5 n6 u) m$ n
( [( X' K3 i: t8 Z
微信图片_20230415164607.png

3 C1 K% M7 B0 p% OGPIO配置
    板子上led为PA5端口,故设置PA5闪烁来验证是否正确。
4 o# ]' o" |% h, Y/ P5 w+ U: b1 s5 B

$ N9 E4 E, J. a, c: }1 @
微信图片_20230415164604.png

- H9 Q, `4 [! n" X- B9 ~4 z; g
定时器配置
    本次实验使用的是TIM3来进行计数。
8 N; T# l6 `  z. a
& |4 c3 c$ ~8 _0 L4 N6 ^* c, K- b
微信图片_20230415164601.png
6 b+ `9 C& L8 ~5 Y, i
    PWM频率计算如下所示。
# m, G! s: W% M! e
微信图片_20230415164558.png
' [0 U2 o( M5 E' D# Y* @
    在上面配置TIM3参数,预分频系数设置为480-1, 自动重载值设置为10000-1,那么PWM频率为48,000,000/((480-1+1)*(10000-1+1))=10Hz,即 100ms一个周期。
% h' g$ @  I# k& K; z8 u% X! }
  m9 R" q1 L6 e2 y
生成工程设置
    注意在生产工程设置中不能出现中文,不然会报错。# L" ^1 h1 y, R0 w. D( w" Q: |

' P( M" h# G) q$ n
微信图片_20230415164553.png

/ z9 ]0 f, A; @: F7 n+ o, l* H代码生成设置
    最后设置生成独立的初始化文件:
* ~9 u5 \: O/ c0 l" Y: }# s

) j# Z" u# ?% h( L) G# m0 _$ k9 q
微信图片_20230415164550.png
& G: Y! T4 h7 p- b6 ^5 G
生成代码2 s4 L& M" T, c- z+ X
& D* s; V1 k9 Z& E/ X0 h( E$ u! ]
微信图片_20230415164541.png
1 h# f! x- L; g
配置keil
微信图片_20230415164538.png
0 T4 i, k: L3 y3 G1 I/ F5 C
微信图片_20230415164511.png
0 D9 h9 i3 p% u+ L; m' y

- W+ g( R- ?0 p; C3 r1 p6 i2 F7 @代码
    在main.c中,先加入头文件。
  1. /* USER CODE BEGIN Includes */
    / r" Q/ @3 J' O9 U4 U$ O
  2. #include "stdio.h"//printf头文件
    : P9 I8 L0 j( }" u2 r" W" F( l
  3. #include "string.h"//memset头文件
    3 @1 v  o( n1 i4 I3 \
  4. /* USER CODE END Includes */
复制代码

- s/ ^: C; K6 U' S8 L. q. x3 x! b
    定义变量存储。
  1. /* USER CODE BEGIN PV */: j' Q' A( H7 Q4 o
  2. uint8_t RxBuff[1];      //进入中断接收数据的数组
    5 f  l) M  Q8 ]# |0 p
  3. uint8_t DataBuff[5000]; //保存接收到的数据的数组
    0 T) z/ w2 y4 y6 \
  4. int RxLine=0;           //接收到的数据长度
    . p& V% F& ^4 d# J  u' r$ l1 I+ H
  5. int Rx_flag=0;          //接受到数据标志
    1 a4 j; `1 n( z: j  e
  6. /* USER CODE END PV */
复制代码
( n- A1 H( M( U' E
    定义printf的重定向函数fputc。
  1. /* USER CODE BEGIN 0 */
    ) z4 l; B# k' T" I. }4 W
  2. void printf_usart(void);//输出内容
    5 x9 l* @! X( Y1 }" Z+ e) _
  3. int fputc(int ch, FILE* file)//定义printf的重定向函数fputc,满足串口调试打印# n  M% P6 C7 r7 F
  4. {  _! I4 q; b& b5 x& d
  5.     return HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 100);
    . q" o- }  ?. w- ^7 p
  6. }
    $ K9 T5 k- K3 F! Z
  7. /* USER CODE END 0 */
复制代码
   
打开串口和定时器。
  1.   /* USER CODE BEGIN 2 */  K- {7 [3 K8 {
  2.   HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //打开串口中断接收
    " u9 b: i% e) J
  3.   HAL_TIM_Base_Start_IT(&htim3);//开启定时器
    ) |8 q8 R0 A; R) d1 K( b& k
  4.   /* USER CODE END 2 */
复制代码

# Q6 ~0 v8 Q. |+ X
    串口接受代码,当接受到最后数据为FF时候,直接打印,否则等待100ms打印。
  1. /* USER CODE BEGIN 4 */- H2 d4 \8 H8 j/ z  m
  2. void printf_usart(void)) U$ I. k. @% V' [, B7 T
  3. {
    ! Y! }. K' b& g' F6 n
  4.   printf("数据长度=%d\r\n",RxLine);
    : i+ c6 y" c' I
  5.   for(int i=0;i<RxLine;i++)
    $ f4 J8 L( ]- D# D
  6.     printf("数据:[%d] = 0x%x\r\n",i,DataBuff[i]);                           
    & Q4 O& c' X+ e1 g, g9 F& L
  7.   memset(DataBuff,0,sizeof(DataBuff));  //清空缓存数组
    / J" k/ i2 w' D! N, {! H
  8.   //memset()作用:可以方便的清空一个结构类型的变量或数组。
    " z* p1 D1 \; {+ m  g
  9.   //例句:memset(aTxbuffer,0,sizeof(aTxbuffer))  用memset清空aTxbuffer。1 f% O9 g3 K; n1 X0 G' T7 d: t
  10.   RxLine=0;  //清空接收长度) S, e# Y4 d- o: t! \, [* F+ h8 z
  11. }2 k6 u4 k2 m- ]( a: i8 X$ k
  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim): o8 y$ o0 I2 N# F& _
  13. {
    $ x6 j1 U6 a" N% I
  14.     if (htim->Instance == htim3.Instance)' m- Y. |" x9 @, H: i
  15.     {% S& S) ~0 ]8 C7 p1 I- e
  16.       HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);$ f  V9 U( E1 G! W' E+ \7 J
  17.         /* Toggle LED */7 K# y+ {# \9 `
  18.       if(Rx_flag==1)
    ; C% \8 R: Q0 U! D2 ~
  19.       {
    ) J/ Y2 w, r) D$ x. D$ q
  20.         printf_usart();
    3 Y# V+ s( P+ p0 Y
  21.         Rx_flag=0;
    * l0 d4 k: U& v$ Y% U- k" |
  22.       }
    6 R/ F+ B' b7 t6 f
  23.     }  
    1 u% B  X: ]5 ^7 ~4 S$ r
  24. }5 I. i! @5 W% n) L
  25. // 捕获中断回调函数,每次捕获到信号就会进入这个回调函数; j8 a: g% P, A" w* G
  26. void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)
    3 w" [) r1 ^6 [, j0 O# ?; k+ S' \0 v
  27. {6 D9 t; i: i' {' u
  28.     RxLine++;                      //每接收到一个数据,进入回调数据长度加1
    ( R8 D/ R( v0 v$ w
  29.     DataBuff[RxLine-1]=RxBuff[0];  //把每次接收到的数据保存到缓存数组
    * ?* V. m3 u, D$ n( P! d4 h) M) L
  30.     Rx_flag=1;
    , a* e$ |1 i( S% m" s- |* o' ~
  31.     if(RxBuff[0]==0xff)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff" C0 R6 @. n3 C' `1 M2 y
  32.     {2 Q! ~& N- r( j& V( h9 @6 M
  33.       printf_usart();
    $ y' y* b7 t& [/ P
  34.     }   
    $ r/ u* B, d: k: T, M) n
  35.     RxBuff[0]=0;
    0 f- P# L- Q+ k) a" c) ?3 ]+ a+ e
  36.     HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //每接收一个数据,就打开一次串口中断接收,否则只会接收一个数据就停止接收& `3 o/ s) ~/ b; n
  37.     __HAL_TIM_SET_COUNTER(&htim3, 1); // 计数清零,从头开始计
    + P0 J5 y' r& O/ \
  38. }/ O. M6 ?$ q2 w1 b
  39. /* USER CODE END 4 */
复制代码
9 w0 r9 _, V' s7 s

# i- A/ @: Z; K2 u演示效果
    可以看到  发送11 12 13需要等待100ms左右才能发送,如果最后加上ff直接发送。

, c) X- Y4 b0 r( ~6 q* a; v4 I
微信图片_20230415164508.png
2 M- u- b5 n; W& n: D. o  s0 f* e+ N
转载自:记帖
如有侵权请联系删除

; V7 P) t6 n6 B8 [" k; b
! T! s+ T! m# o' ]
- R( s" h8 ^! U* ?( h% p( F
赞 收藏 评论0 发布时间:2023-4-15 16:48

举报

0个回答

所属标签

相似技术帖

官网相关资源

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