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

【经验分享】STM32L031 HAL 串口收发例程(中断配合轮询)

[复制链接]
STMCU小助手 发布时间:2021-11-16 01:34
代码环境; K1 h. h- x. K; Z* e8 x. @
开发工具:STM32CUBEIDE2 N  t/ H; J7 Q. r& C$ k/ f
芯片:STM32L031K6T6
- L2 c9 \/ X' l+ z% x端口: UART21 f7 s; \% m1 z$ I
基本配置8 u4 Z1 L$ Y1 ]! r/ D

4 q$ V9 k# y  H
2019111911265218.png
5 K7 m1 Y# Z. d- R
2 v; F$ O$ ?( X  f( a5 A# d: V, F: Q
20191119112729252.png
; k- b6 g2 H9 Z2 O/ ]
& V  I' s" h# h% J
20191119112750442.png

+ ]- n3 c" b& q5 P4 v+ E4 g3 w% P8 d6 `0 ~1 N0 U5 L. m
其中,PA9 (RX)的输入上拉,在System Core的GPIO里配置。% W- I. F' F; v. W
5 d# c; M6 a! C
20191119112920480.png
* t, {' e/ D$ u  W  C- N; l

7 T! M# j- a  F" D9 Y3 _6 cTX(发送)设计* r/ z. g% H  T, T
TX部分增加bsp_usart.c和bsp_usart.h文件,以支持printf重载。* M" B4 V2 S1 q9 ]

4 Q$ A- n$ e" g. ?& c% A" z; tbsp_usart.h内容, r' [/ X, x5 z# l: A
6 u" v( T- n; H7 V
  1. #ifndef __BSP_USART_H/ x6 I. z, f! q- |
  2. #define __BSP_USART_H
    4 i  x1 H; m" x# j9 [
  3. + J3 ^/ ^) \6 L. P2 i
  4. #include "stm32l0xx_hal.h"4 I# C6 c7 @4 A. ?
  5. #include "stdio.h"                           " t! Y2 t6 k; K$ B8 s* @1 J

  6. & h; \4 c" T' u$ s/ u
  7. int fputc(int ch, FILE *f);* J( c# O5 m2 q8 X7 x

  8. 9 ?; ]4 Y5 \1 }" l& Y
  9. #endif
复制代码
, u$ J& G7 P" {8 i. `3 p; a6 j
bsp_usart.c内容
+ w( _( f+ C4 F! v2 @' D& ^0 [9 S4 w& n" N% ^
  1. #include <bsp_usart.h>0 m8 J" h" N8 T3 w8 |' C
  2. ) [+ r2 |( v* l& m" Y+ \
  3. extern UART_HandleTypeDef huart2;
    # u( Y% A9 w. T1 z$ ?2 o

  4. % t$ O9 Q9 h( Y- _9 O$ c
  5. /* USER CODE BEGIN 1 */
    0 [! }( \' s9 N: B$ N. m- t' n
  6. #ifdef __GNUC__" r, ~, R8 j4 x" O/ U. f! w
  7. /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf* d) I2 A& Z4 z' f) l9 Y6 E
  8. set to 'Yes') calls __io_putchar() */8 q' Y) B" @, z! {; a) a0 J
  9. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)9 g( S2 T" q8 _( F
  10. #else* ~4 T! V; V4 X  S" D% ^
  11. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)& J1 G4 [9 W0 t* r
  12. #endif /* __GNUC__ */
    " p: l, \3 o# U) s; L% t$ w& F$ l$ }
  13. /**
    . q- Z" b9 b: K* i! @: I
  14. * @brief  Retargets the C library printf function to the USART.
    9 I4 f: O/ j8 T) ~$ F
  15. * @param  None
    * B3 {5 J6 ?, e9 h
  16. * @retval None
    ) Z& K0 m* K4 D+ d! y, J
  17. */
    1 F$ p9 o5 n9 M
  18. PUTCHAR_PROTOTYPE {
    # V& P, U7 ?6 \% I( }% M! r
  19.         /* Place your implementation of fputc here */9 X8 L* K0 W8 y
  20.         /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */" E+ d# T. N, G$ _
  21.         HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF);
    & b! w) ]' `/ z  _- i  h! ~
  22.         return ch;
    $ {5 i" e! A/ _
  23. }0 f- ^" i/ o; U9 u- d; O
  24. /* USER CODE END 1 */
    % i' G6 u+ ^& z$ r
复制代码

, \; l/ f3 D& }2 q; P2 B. z在main.c文件里引入头文件
# I0 b3 k% e' C; a" z3 w' G! g9 {' X
  1. #include <stdbool.h>( P. c! _4 @5 E. h; `
  2. #include <string.h>1 q$ l7 r0 z1 B$ x7 @8 z/ [% B
  3. #include <stdio.h>
    4 |; S2 Y* q0 r
  4. #include "bsp_usart.h"
复制代码

8 A; T; c' C4 u2 K/ L8 R* V' e( w然后,就可以使用printf(“uart2 output data = %d \r\n”, data);了。
2 ^" _" S4 ]9 {
3 Y$ \1 }% w7 M( gRX(接收)设计
4 Z/ B% i* S2 h$ k4 E常规的串口接收设计,都需要设计当前接收字节后的超时识别,如果出现超时,认为接收结束。即使是固定字节长度的传输,也需要为异常情况下设计超时识别作为传输结束。
8 P/ |, o5 s# z8 {STM32 HAL库支持轮询超时的方式接收串口数据(HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)),也支持中断的方式接收串口数据(HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)),因此考虑将两种方式结合使用,以简化超时判断的设计。, n. i3 K. A. w; O1 t4 n
主要的设计思路是:1.通过中断接收第一个字节;2. 通过轮询接收后续字节。
8 s) A2 J2 [; q6 y; q7 O0 N  O9 a& e" K6 }, b2 |
main()函数前初始化相关代码,部分代码由STM32CUBEIDE自动生成:
- |8 K9 _0 L: h0 k! b: }1 G) h' p: D  A! A6 v* a* y6 g( N
  1. /* Private macro -------------------------------------------------------------*/9 N$ t" e* \% {4 V* E
  2. /* USER CODE BEGIN PM */
      Q! H6 N( d$ G' \- h
  3. #define UART2_RX_STOP 0
    / n& p0 m& [% T3 N4 T6 R/ W
  4. #define UART2_RX_START 1; n% V+ ~' r2 w/ L. K% V
  5. /* USER CODE END PM */
    3 n% C* s1 D9 Z- `
  6. /* Private variables ---------------------------------------------------------*/
    1 z* Q  j* `2 v" [4 M( i1 ~
  7. UART_HandleTypeDef huart2;: J0 f$ R: z; [5 j( X
  8. /* USER CODE BEGIN PV */
    7 R% B5 F% t7 j
  9. uint8_t aRxBuffer;                        //RX int buffer, 1 byte  s, Y) A; t/ z; p
  10. uint8_t Uart2_RxBuff[10] = {0};                //Rx buffer,should be adjusted according to Rx max byte length per communication.! |5 {9 C4 \1 e/ d% Q1 q
  11. uint8_t uart2_rx_flag = UART2_RX_STOP;
    2 j% {8 s# h: R5 n7 R
  12. HAL_StatusTypeDef uart2_status_rx;5 s8 r4 T! l9 [5 z
  13. /* Private function prototypes -----------------------------------------------*/
    , _1 @* m+ }+ n) Q
  14. void SystemClock_Config(void);
    ; D  L! z! l- s8 r: j0 U
  15. static void MX_USART2_UART_Init(void);
复制代码

" r  n6 r1 I- Omain()函数相关代码,部分代码由STM32CUBEIDE自动生成:" l! P+ z" P+ \! d( w- r) ]

" |4 ^7 R3 S: y4 [3 u( p( e/ c
  1. int main(void)
    + f7 t$ [: g* Q4 I# a% g
  2. {5 O. `6 {, a/ z& l9 \& R
  3.   /* USER CODE BEGIN 1 */
    : I% i6 x! {2 s1 \
  4.   /* USER CODE END 1 */0 R; |( @# R1 a3 @
  5.   /* MCU Configuration--------------------------------------------------------*// p* b( X9 {/ D% T2 u& J
  6.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    - S% j7 ~# R- v0 w) R5 Y
  7.   HAL_Init();
    ! E% c6 v- w' O3 }8 Q& `
  8.   /* USER CODE BEGIN Init */* c1 a* k: d: C' r
  9.   /* USER CODE END Init */$ h$ k. Y/ F: Z& a) y" n
  10.   /* Configure the system clock */( i: b- O$ A% k! o6 j4 g& |
  11.   SystemClock_Config();
    # g: [! D1 w4 @3 q2 z9 }( G
  12.   /* USER CODE BEGIN SysInit */
    : R. i; r0 _" B: d# J/ e
  13.   /* USER CODE END SysInit */: t" V3 K5 x  [' y' u& E$ X" D
  14.   /* Initialize all configured peripherals */; u" @% X* d$ E  z. ^) P7 ~6 q$ T
  15.   MX_USART2_UART_Init();
    4 c6 Y9 G: u) C* f( L0 s- U
  16.   /* USER CODE BEGIN 2 */
    2 ]4 r0 u8 n4 f2 W6 o
  17.   /* USER CODE END 2 */
    $ U7 c* b0 d0 h6 d: q; z' l" s
  18.   /* Infinite loop */
    / a, _+ r7 {, r# {
  19.   /* USER CODE BEGIN WHILE */( E9 H, S5 E  \
  20.   if (HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1)!=HAL_OK) printf("UART2 IT FAILED! \r\n");
    / O( H0 a$ `) m  C
  21.   while (1)( X/ I% o  j3 T, S' n0 t/ V
  22.   {$ r9 k+ J! i4 c! i  v7 ~
  23.     /* USER CODE END WHILE */0 E" H1 ?( _4 t0 ?
  24.     /* USER CODE BEGIN 3 */
    3 u) Z  [$ M: P. ^6 j, G) T
  25.      if (uart2_rx_flag == UART2_RX_START)
    6 M. K: s! n1 M" A& O
  26.      {
    + J" L( a7 r4 O( }; ~
  27.              uart2_status_rx = HAL_UART_Receive(&huart2, Uart2_RxBuff+1, 9, 100);
    ( ]4 V! G7 R7 L% B6 N
  28.              printf("uart2 got rx data: %d  %d %d %d %d %d %d %d %d %d\r\n", Uart2_RxBuff[0], Uart2_RxBuff[1], Uart2_RxBuff[2], Uart2_RxBuff[3], Uart2_RxBuff[4], Uart2_RxBuff[5], Uart2_RxBuff[6], Uart2_RxBuff[7], Uart2_RxBuff[8], Uart2_RxBuff[9]);$ N8 K% i- `3 L" ]4 z0 a  K) Q% W
  29.              uart2_rx_flag = UART2_RX_STOP;
    " L) d- h1 Y. U1 ^
  30.              memset(Uart2_RxBuff, 0, sizeof(Uart2_RxBuff));
    4 _/ q) i  r8 A
  31.              MX_USART2_UART_Init();
    ) i- B. r1 }- {" y
  32.              HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);
    , K% ?* x) @! l

  33. 0 b" m6 L2 Q( s4 r$ d
  34.      }3 b* w5 C& x; f5 z" N
  35.           HAL_Delay(1);   //must for timing
    7 E$ N! Q  p& f8 n; H! i
  36.   }0 h2 F9 z0 I) [1 J  E; i  P" X9 `
  37.   /* USER CODE END 3 */
    ) }4 R( f/ W& E- @
  38. }
复制代码

  C+ W5 a# _3 `0 e$ S0 l中断响应通过函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)的重载实现。3 i, K6 v3 D# t& U, G6 F  d# k& ]) C

. o( ?1 {  F# y, L
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
    0 C: `: b8 E/ Y( h
  2. {6 b7 W% v) M( m% \3 B1 S

  3. . J5 N; Z0 w6 {
  4.         Uart2_RxBuff[0] = aRxBuffer;
    6 h+ H4 ~) A' U9 t
  5.         uart2_rx_flag = UART2_RX_START;$ a3 {- z6 K; Y

  6. 1 h7 R/ W+ K6 {: _* P' ^0 I
  7.           //printf("uart2 get rx interrupt!\r\n");$ `6 V2 d) I$ p: j# {4 t$ k
  8.       return;
    : T: m  H+ L- y
  9. }
复制代码

- A! ]+ x7 y- B$ N注意事项1 q7 l; ^1 K7 {/ E& U3 C$ W
HAL_UART_Receive()不能放在HAL_UART_RxCpltCallback()函数里处理,HAL_UART_Receive()的Timeout会失效。这是因为SysTick的中断优先级低于了外设UART的中断优先级,在UART的中断处理过程中无法响应SysTick中断。(如果一定要把HAL_UART_Receive()放在HAL_UART_RxCpltCallback()函数里,就需要调整SysTick中断的优先级)。
8 v/ A5 C& R7 x, M5 V, f6 Imain()里的while(1)循环,需要延时HAL_Delay(1), 时序才正常。0 U3 t" t  R7 u) f! Y! d  q
-End-! S5 @; E; z9 j: s8 Z$ f
; R. ?) W$ I0 h! Z9 f( m  E
+ v3 t! E0 A, x
收藏 评论0 发布时间:2021-11-16 01:34

举报

0个回答

所属标签

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