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

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

[复制链接]
STMCU小助手 发布时间:2021-11-16 01:34
代码环境) Z- H" |$ B. r
开发工具:STM32CUBEIDE& r) W! T  i$ Y, ?
芯片:STM32L031K6T6# c# C1 q& n9 w. B& [) G
端口: UART2( j% y& i8 l4 R# [$ a% \, L9 C
基本配置
* w" L/ q. S+ h9 m' Z6 h$ A3 j
% |2 G+ u, m5 S) M
2019111911265218.png

8 s5 `: i2 W' @2 B8 k* [
7 A7 T1 {2 U2 V+ N( j
20191119112729252.png
  m$ U" v- B/ _5 _: ?' o

1 W5 R1 b& M& j4 M$ w! M  ]7 o
20191119112750442.png

8 B5 C/ ]% |: Q
7 [0 f. Q* X0 b, V8 A6 y其中,PA9 (RX)的输入上拉,在System Core的GPIO里配置。
% l4 L/ v  G7 U" ], o/ Y
6 Z) \* z/ v4 J" v
20191119112920480.png
1 l- q' ~" e% s# C6 X
- ]1 ^3 n! S% o/ o0 b
TX(发送)设计
! O5 m/ Y( J6 h5 FTX部分增加bsp_usart.c和bsp_usart.h文件,以支持printf重载。
6 J1 Q, m0 I/ {- A8 R$ @. U! P6 c) n4 n/ G( T# J9 l
bsp_usart.h内容
+ O4 r% b+ l0 A; C' E; o  A. @8 Y3 p" W9 j- P* k
  1. #ifndef __BSP_USART_H
    1 z. u2 U" H4 }/ d, ]
  2. #define __BSP_USART_H
    & I; I3 `; I' \
  3. / ]( f5 q6 `  L3 T7 o
  4. #include "stm32l0xx_hal.h"9 y' Y) @# f& {8 a5 C5 r% F
  5. #include "stdio.h"                           2 Y$ v. ^9 r, R7 @; j5 O
  6. & y7 i0 l0 M7 a$ P" z" a
  7. int fputc(int ch, FILE *f);
    . \+ q# H$ F# w1 W* u

  8. + s" v6 u2 w, H* t' c* f
  9. #endif
复制代码
1 v: p# F1 s: u+ y+ s
bsp_usart.c内容* Z+ A: R5 K6 i1 p
5 Z$ w* y7 `! H( R
  1. #include <bsp_usart.h>
    1 }: _7 p  Y7 A: \) S. y  m

  2. % B* M! w9 ]7 Q$ L9 h1 {
  3. extern UART_HandleTypeDef huart2;8 ]9 k) `; Q/ c$ p. ]3 r$ R
  4. ) R% l& C* Y! L, W, @1 p: e/ h
  5. /* USER CODE BEGIN 1 */
    8 p, t9 l; ?; w/ g( ~- ], p( b2 d, T* A
  6. #ifdef __GNUC__
    0 `4 @8 ]& F1 L$ R- k
  7. /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
    7 C2 w; e' c3 p3 d3 B4 Y5 L
  8. set to 'Yes') calls __io_putchar() */
    , [* T, T6 W7 Y6 ?' L
  9. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    ) i  u8 E/ X8 J, X
  10. #else
    & S; l( c3 g- K* L
  11. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
      B/ G4 w/ u; @: k: o4 s
  12. #endif /* __GNUC__ */
    9 f/ x. N0 u% k
  13. /**7 e! ^8 |/ p7 E9 a& Y/ w
  14. * @brief  Retargets the C library printf function to the USART./ |4 u+ L) d2 D
  15. * @param  None& ]. I+ M' k( X" y5 p$ K7 j
  16. * @retval None
    - b$ J* V1 T1 n. E/ B& b$ L/ v" |
  17. */; L- w1 T) Q. T8 b1 x7 S8 N+ Q
  18. PUTCHAR_PROTOTYPE {
    1 w9 R9 a8 T; k2 r- X2 p
  19.         /* Place your implementation of fputc here */
      ^. {" l/ v# C
  20.         /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */0 k, f% h& |: q" B! ]: d
  21.         HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF);' |; U4 Y' m# w! S
  22.         return ch;6 `4 Y9 r% t* A  M9 ~4 @
  23. }
    8 O3 f$ j0 b0 V  `( d! |$ {7 V
  24. /* USER CODE END 1 */" v8 {! P# I+ h) |- A/ j3 `. E
复制代码

, k" ^4 n5 C* @在main.c文件里引入头文件
2 g+ I3 i% H8 T% |7 u
  1. #include <stdbool.h>
    " }% x; W( F4 I2 u! P0 L. k1 t
  2. #include <string.h>* b  q" h( T+ q9 Q
  3. #include <stdio.h>
    8 F" ~* V: \# H: T
  4. #include "bsp_usart.h"
复制代码

0 S) F8 w/ t2 C然后,就可以使用printf(“uart2 output data = %d \r\n”, data);了。3 b# q* B, r6 _. ?% c8 g

+ I$ O) N9 L! t: M! KRX(接收)设计
* T: [% M7 D5 D5 Y常规的串口接收设计,都需要设计当前接收字节后的超时识别,如果出现超时,认为接收结束。即使是固定字节长度的传输,也需要为异常情况下设计超时识别作为传输结束。
5 Z9 c' ]. |! x  `! p( vSTM32 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)),因此考虑将两种方式结合使用,以简化超时判断的设计。9 A: l. i0 t* M" o
主要的设计思路是:1.通过中断接收第一个字节;2. 通过轮询接收后续字节。
% H- u- o+ p' t  |! j* J
' O( I3 T- H) R+ \# J" Y3 }main()函数前初始化相关代码,部分代码由STM32CUBEIDE自动生成:
- N0 d0 Y' S, R' }7 y8 q8 J4 K  t: y; t( Z0 S& W
  1. /* Private macro -------------------------------------------------------------*/
    ; Z+ h3 r5 `2 `7 V* n: T& J& w
  2. /* USER CODE BEGIN PM */
    9 E: n$ u& n' _( Q3 ]: z; G( ^! e
  3. #define UART2_RX_STOP 0
    ; ?5 t# E* G* E. @: X2 X
  4. #define UART2_RX_START 1
    ! d3 @) U8 {$ I( J* ]3 ~
  5. /* USER CODE END PM */
    0 P% g, r% _% R8 ~" K: T
  6. /* Private variables ---------------------------------------------------------*/
    $ ]+ O. {1 n8 X$ E. w" s$ X
  7. UART_HandleTypeDef huart2;
    # ~2 M/ G* q/ N, T
  8. /* USER CODE BEGIN PV */
    . B' B  h  Z( h2 m
  9. uint8_t aRxBuffer;                        //RX int buffer, 1 byte7 l5 [* E9 |6 o3 h$ y
  10. uint8_t Uart2_RxBuff[10] = {0};                //Rx buffer,should be adjusted according to Rx max byte length per communication.
    ( A. \) K: g" Q
  11. uint8_t uart2_rx_flag = UART2_RX_STOP;
    - ?! u* ~: W. _& u$ h
  12. HAL_StatusTypeDef uart2_status_rx;
    ; A) K" }% K. _$ |3 l
  13. /* Private function prototypes -----------------------------------------------*/
    1 J4 E, ?5 _/ U9 L$ x5 [9 l
  14. void SystemClock_Config(void);: P6 t& Y/ D" \# P# p  c
  15. static void MX_USART2_UART_Init(void);
复制代码

! t, y% e! _5 dmain()函数相关代码,部分代码由STM32CUBEIDE自动生成:8 z/ e0 `( T1 w( D6 q7 W& P

7 I' D8 J" X, f2 U6 S- e. d1 h
  1. int main(void)" |. Q8 K% X7 q
  2. {
    6 j( ?5 B5 A, q$ W# W; z9 i0 V5 g
  3.   /* USER CODE BEGIN 1 */
    ! h% t/ i2 o6 j/ G% S
  4.   /* USER CODE END 1 */0 _- Y( e3 ^8 E+ F9 j+ _( [3 \
  5.   /* MCU Configuration--------------------------------------------------------*/; ?: U) R. e6 `6 W% D8 v
  6.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */+ x; c9 w. W- G
  7.   HAL_Init();
    & ]9 j- k9 ?6 i7 P3 {3 F
  8.   /* USER CODE BEGIN Init */
    2 x; [, l4 }  v2 E" K( g" s, \) K1 ^
  9.   /* USER CODE END Init */8 ?* {+ G/ P" j) v
  10.   /* Configure the system clock */
    0 y9 T1 G* S9 u0 Y; e/ H6 O' r' L
  11.   SystemClock_Config();( B+ E0 h- w6 m/ O0 {7 s
  12.   /* USER CODE BEGIN SysInit */( r. M3 r: o. Y  P4 p
  13.   /* USER CODE END SysInit */( g/ s$ E# U" v. ^) i) g4 |5 w
  14.   /* Initialize all configured peripherals */( K/ _" v& A( }
  15.   MX_USART2_UART_Init();
    : f# l2 F" |9 Q! o: P5 \
  16.   /* USER CODE BEGIN 2 */
    + M* ^1 I+ E1 k( q4 z
  17.   /* USER CODE END 2 */# }2 S/ E4 ~) n1 H
  18.   /* Infinite loop */
    / J* v1 c' i! q! h8 T0 F
  19.   /* USER CODE BEGIN WHILE */5 k. e' g  _- H
  20.   if (HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1)!=HAL_OK) printf("UART2 IT FAILED! \r\n");
    . Q( l8 [/ e& M
  21.   while (1)
    4 M. h! H+ Z) j8 n' W( I' w
  22.   {7 ~+ H) F9 [. H( l: ~1 H0 u
  23.     /* USER CODE END WHILE */
    0 J4 R* F' p+ h6 ?
  24.     /* USER CODE BEGIN 3 */
    . I2 W* W8 I$ z  j& g
  25.      if (uart2_rx_flag == UART2_RX_START)* b2 F- P" x, f" C9 g% B1 k( X3 a
  26.      {0 k5 Z% ?+ S& [8 t% ^8 R' B& G! N
  27.              uart2_status_rx = HAL_UART_Receive(&huart2, Uart2_RxBuff+1, 9, 100); & H. O: B4 l/ M) n# G
  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]);% T( _! H! E& V; _$ p4 O8 O
  29.              uart2_rx_flag = UART2_RX_STOP;
    & L. B! f4 y1 E& g, z- S, c
  30.              memset(Uart2_RxBuff, 0, sizeof(Uart2_RxBuff));3 ^' C$ V2 b2 {5 ^. c
  31.              MX_USART2_UART_Init();
    0 p3 f: S/ R- g/ F$ ^# Y
  32.              HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);9 @0 |8 z+ w1 i$ d+ v9 S

  33. 4 a& o* z  }0 V' }: a6 w
  34.      }! B9 U# L1 y7 _' |
  35.           HAL_Delay(1);   //must for timing2 X" A3 E* _3 V$ Z
  36.   }! S  E" A, U8 m  R
  37.   /* USER CODE END 3 */5 [. T1 A7 @9 ?, E; I
  38. }
复制代码
! W; A6 x! `7 o. k) Q7 v/ t+ `
中断响应通过函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)的重载实现。0 i0 ?' \- ?- A: t* p" z

( ]9 f- Z2 M2 F, @. ?& `+ C5 X
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
    * s) ?0 o3 D* w  ~
  2. {
      b- S; z: |4 _3 K4 T& k
  3. * t$ i. P1 J6 n; f
  4.         Uart2_RxBuff[0] = aRxBuffer;
    . \; a5 J  w" N4 D
  5.         uart2_rx_flag = UART2_RX_START;& @& F* ^% }- i3 c
  6.   D7 q4 H+ G1 L7 M+ w+ M2 A
  7.           //printf("uart2 get rx interrupt!\r\n");1 S3 o/ H9 H, o
  8.       return;# {5 R& f- g1 i2 w4 w! b. ~6 o
  9. }
复制代码
1 n  G9 Q, i( F' b
注意事项
! l2 o' o2 F, L& }HAL_UART_Receive()不能放在HAL_UART_RxCpltCallback()函数里处理,HAL_UART_Receive()的Timeout会失效。这是因为SysTick的中断优先级低于了外设UART的中断优先级,在UART的中断处理过程中无法响应SysTick中断。(如果一定要把HAL_UART_Receive()放在HAL_UART_RxCpltCallback()函数里,就需要调整SysTick中断的优先级)。7 c- `& e( K1 ~" M) E' x1 G5 f
main()里的while(1)循环,需要延时HAL_Delay(1), 时序才正常。
) q2 }5 L% a* u; A-End-8 g  b; A8 }* {& F: d  t* M

8 K" o( z2 o5 c: [: x/ X# H* |7 c5 p; }% l; W
收藏 评论0 发布时间:2021-11-16 01:34

举报

0个回答

所属标签

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