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

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

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

7 {* r) e  L) m- t& O7 r
硬件准备
    首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:    ; F* Z4 d" Y( [4 r8 X! S

& w2 C3 D' g1 R4 T6 H8 \
微信图片_20230415164627.jpg
5 j, p. t1 N1 h/ ^5 ^! P/ x3 ^
选择芯片型号
       使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
  j& t% p( j2 a4 a8 z+ S- n
微信图片_20230415164623.png

( G- F! Z4 g. [7 J5 \, P配置时钟源
    HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:; V: E3 N$ k% [1 u4 C, e( v

7 n  F' _" F. T& s0 }7 ]4 P
微信图片_20230415164620.png
6 J$ U( V1 E4 v- c% V8 k; ], y8 A
配置时钟树
    STM32F0的最高主频到48M,所以配置48即可:$ E! j; W5 T5 K  E9 t8 E
5 z( P3 _4 k$ q" N
微信图片_20230415164614.png

- @4 E- W- k8 v% N! p1 E8 h$ X串口配置
    本次实验使用的串口1进行串口通信,波特率配置为115200。* U+ C- b6 Z8 q& Z( u" t' H

3 D& E( Q" r" D( I, y8 y
微信图片_20230415164611.png

' L' B* V3 ?+ a
    中断. O* h4 z9 ~7 ~
/ P( h) y. U& e; j$ `( ^8 E$ k
微信图片_20230415164607.png

& r! @, G9 a6 V( V5 \) cGPIO配置
    板子上led为PA5端口,故设置PA5闪烁来验证是否正确。4 e8 e) K9 ^3 b2 f( Q0 z3 R, v
( \6 }* [3 @4 b4 ~  J: r) k8 K/ x
微信图片_20230415164604.png
& d2 p/ M+ Z0 a0 p- g8 X
定时器配置
    本次实验使用的是TIM3来进行计数。
. n" b/ `" `7 A
+ {. k- n6 R; W- v. b0 Q$ a+ O4 n
微信图片_20230415164601.png

: I3 b3 }0 f/ [: R1 l
    PWM频率计算如下所示。

+ j/ J" u0 m7 d% v: G6 X$ V
微信图片_20230415164558.png
9 S: A; p3 ^* e& [0 R" o
    在上面配置TIM3参数,预分频系数设置为480-1, 自动重载值设置为10000-1,那么PWM频率为48,000,000/((480-1+1)*(10000-1+1))=10Hz,即 100ms一个周期。1 ?* C: N. r3 v0 \& G3 ?
# ~5 Y! U$ G- A- o. ]
生成工程设置
    注意在生产工程设置中不能出现中文,不然会报错。+ y4 a# _1 I3 _  m+ `0 r
( X8 {7 P! W+ |! ?0 P
微信图片_20230415164553.png

6 W. N" h+ |: L$ Q( @" o代码生成设置
    最后设置生成独立的初始化文件:
+ x: F6 O9 y6 c8 H* I- R9 S: i' G) Q

3 M+ O) {+ @9 x+ \9 T" |
微信图片_20230415164550.png

  ^  \8 g0 {' `0 f3 W生成代码- n' L0 O6 J0 U
0 S' k5 [6 F! E( Z) ~
微信图片_20230415164541.png
( w; h% Q; y) U6 ?  R  g% n% A
配置keil
微信图片_20230415164538.png

7 f( t; S! Z8 R- u" y
微信图片_20230415164511.png
$ w! ^* \8 [1 G- N4 Y' D3 L5 |
  Q1 B& t' a: T6 Z# u4 A
代码
    在main.c中,先加入头文件。
  1. /* USER CODE BEGIN Includes */
    5 E6 Q7 g6 `  h- P4 a. p3 n
  2. #include "stdio.h"//printf头文件
    $ A4 J  |( F0 z
  3. #include "string.h"//memset头文件
    . n/ r. m- s& G4 }
  4. /* USER CODE END Includes */
复制代码
' n/ J0 G) z8 M! d- y
    定义变量存储。
  1. /* USER CODE BEGIN PV */
    7 @5 U- I1 l2 F: M. _
  2. uint8_t RxBuff[1];      //进入中断接收数据的数组
    ; I2 t# H3 {- p  M
  3. uint8_t DataBuff[5000]; //保存接收到的数据的数组" h8 |0 T: [% l( f3 }
  4. int RxLine=0;           //接收到的数据长度
    0 U3 y) P# @1 ]) @
  5. int Rx_flag=0;          //接受到数据标志; ?1 X. l4 k$ D" z4 V3 b5 ~
  6. /* USER CODE END PV */
复制代码

' y2 y% @0 {3 B6 s* N) j
    定义printf的重定向函数fputc。
  1. /* USER CODE BEGIN 0 */
    : l" x( h. @' I+ _
  2. void printf_usart(void);//输出内容
    # x" ]" L; R, q% K; B
  3. int fputc(int ch, FILE* file)//定义printf的重定向函数fputc,满足串口调试打印& Z1 e$ q  L4 L
  4. {
    , }5 e) h" s% {2 n% W
  5.     return HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 100);
    0 a6 R5 b% m. m5 D( [9 Y
  6. }, J+ s6 G9 e- q2 ^0 @
  7. /* USER CODE END 0 */
复制代码
   
打开串口和定时器。
  1.   /* USER CODE BEGIN 2 */$ {3 ]0 o9 v# A
  2.   HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //打开串口中断接收
    $ j/ e) h. n- e8 x& |0 a
  3.   HAL_TIM_Base_Start_IT(&htim3);//开启定时器
    ! @* [5 {  H. R. ^
  4.   /* USER CODE END 2 */
复制代码
( S9 F4 E) L6 m7 C$ Y  p* w2 p
    串口接受代码,当接受到最后数据为FF时候,直接打印,否则等待100ms打印。
  1. /* USER CODE BEGIN 4 */8 F1 B) \. A% q
  2. void printf_usart(void)
    $ z, F4 P1 }7 h: ~6 v3 f; s
  3. {( }) g& f, w2 Y6 A$ z
  4.   printf("数据长度=%d\r\n",RxLine);
    " l8 N* v$ b+ V  @/ A$ V
  5.   for(int i=0;i<RxLine;i++)3 N; K  c6 k7 k$ }3 Q; p
  6.     printf("数据:[%d] = 0x%x\r\n",i,DataBuff[i]);                           
    + i$ X9 {8 L; T" G
  7.   memset(DataBuff,0,sizeof(DataBuff));  //清空缓存数组
    # M, g. K, a5 n- Y& s
  8.   //memset()作用:可以方便的清空一个结构类型的变量或数组。
    $ X5 q  f/ c4 P4 E
  9.   //例句:memset(aTxbuffer,0,sizeof(aTxbuffer))  用memset清空aTxbuffer。) ^* |2 B  x2 X' s
  10.   RxLine=0;  //清空接收长度4 _! ^6 n$ [" \) u. S
  11. }8 w6 r2 _  X# `- H% m
  12. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    ' d; F* E% U/ q- Y
  13. {
    ( X4 K3 E7 H6 b  {0 [
  14.     if (htim->Instance == htim3.Instance)) O8 N( M- |3 u( K( }
  15.     {9 n+ ?/ i" u# S. Z# ]- P9 v" b, S
  16.       HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);9 k+ y. |7 q  }- s4 X3 L! R" }( ?3 k
  17.         /* Toggle LED */
    , P* ?8 `* u3 F
  18.       if(Rx_flag==1)
    2 u; d& X$ v) V6 l2 |9 l
  19.       {
    6 N8 q+ Q2 Y* \9 X8 e# e
  20.         printf_usart();, U7 m$ F. k$ P) S. e
  21.         Rx_flag=0;+ w; A# x) W  A7 L. n+ }
  22.       }
    3 m" n1 F+ j. K  E$ S( _8 W4 f
  23.     }  & y, l" \. |7 i" k5 p  f  t* S
  24. }
    $ w% q5 x/ J* j; L, ]+ R3 r
  25. // 捕获中断回调函数,每次捕获到信号就会进入这个回调函数
    9 o# Z  ?9 R9 U3 _
  26. void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)
    0 }8 t7 |$ _3 _) \# Y
  27. {) Z: S9 B3 L! i; J, j- d. d
  28.     RxLine++;                      //每接收到一个数据,进入回调数据长度加1
    ! m: y" E! a0 D+ Y8 o0 E% F
  29.     DataBuff[RxLine-1]=RxBuff[0];  //把每次接收到的数据保存到缓存数组
    + \) N) I( F+ `
  30.     Rx_flag=1;& H& c3 e4 Y# e5 R# g
  31.     if(RxBuff[0]==0xff)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff
    7 k! m/ ]% U4 n- V/ t
  32.     {. }" a, E' T! w! a* k
  33.       printf_usart();
    7 s' M- O' [# b9 u. e1 k/ f2 r
  34.     }   6 N, |" g/ J) h* e! t! m0 Y
  35.     RxBuff[0]=0;
    ; H  c) Y5 N) ^; b% r# O
  36.     HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //每接收一个数据,就打开一次串口中断接收,否则只会接收一个数据就停止接收# M! m4 }7 L5 @/ s2 e% {
  37.     __HAL_TIM_SET_COUNTER(&htim3, 1); // 计数清零,从头开始计( {9 u/ T( N" N3 h( N7 l. F# ^
  38. }
    $ o  \6 {2 ~" T1 P
  39. /* USER CODE END 4 */
复制代码
% H( L* ^- X7 O1 x& y
: c+ K" X9 G4 A* K
演示效果
    可以看到  发送11 12 13需要等待100ms左右才能发送,如果最后加上ff直接发送。

0 `- t% U7 D  y2 \6 A! ~- A
微信图片_20230415164508.png

1 _; N  e6 ~- q" m0 F. m
转载自:记帖
如有侵权请联系删除
* Q$ a) f8 L$ t& M  a( `

0 w) t* d- b+ a% g" {7 x
9 p+ K& X; i; u! Q$ B* N7 J
赞 收藏 评论0 发布时间:2023-4-15 16:48

举报

0个回答

所属标签

相似技术帖

官网相关资源

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