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

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

[复制链接]
STMCU小助手 发布时间:2021-11-16 01:34
代码环境7 f; \, e" V# m( q- L; B
开发工具:STM32CUBEIDE/ |; z" _* @2 L' v$ J5 a
芯片:STM32L031K6T6
5 I) `/ I- E# }端口: UART2- i- R- a+ k1 I5 z% V. {) S
基本配置
  B; W4 @9 o: P/ z( P
0 Y* c+ S' S+ M7 n9 Y9 X4 q
2019111911265218.png

* j3 Q) h, j# L5 j5 _* N) Z! @# V- t- g; i& o
20191119112729252.png

) {. m( d# d# B; U* l7 q1 h1 Q9 J; m+ ^
20191119112750442.png
: `0 h( v6 `2 Y* W" m! o

$ s- `, `% B* `其中,PA9 (RX)的输入上拉,在System Core的GPIO里配置。
- k& s; Q# t1 e3 I/ U, G5 B$ T3 b# X' F2 L
20191119112920480.png

! t4 c% d0 W2 w" q  K. d0 S2 I+ |# J, o$ ]/ P! D7 H5 w/ I0 K
TX(发送)设计
% r" \( V5 d6 j4 u- j' ZTX部分增加bsp_usart.c和bsp_usart.h文件,以支持printf重载。
  k4 s7 N1 E# K6 p" g: s2 T8 `  E7 p# S9 w
bsp_usart.h内容4 c$ w- t' \" H/ k9 N0 v. j' j

/ S) X( {; Z$ c1 J" ^
  1. #ifndef __BSP_USART_H: B4 A1 a- @8 [9 ]' u, Z0 V# s& j
  2. #define __BSP_USART_H
    + N6 I/ L5 C& T& q* ~( S3 N
  3. $ e/ a6 G1 J4 [2 l' U: ^8 E' T
  4. #include "stm32l0xx_hal.h"
    2 n1 I0 [5 G5 j) g
  5. #include "stdio.h"                           
    & b- ?$ Q6 H8 {& L* Z5 N  `; z

  6. ; g6 j. M# j- v% U6 z3 ?; W
  7. int fputc(int ch, FILE *f);' Y& M8 ]% h! @2 o& [$ F1 i

  8. 4 G) W4 J9 r7 T9 n# |& ]
  9. #endif
复制代码
4 z: t, ^5 @* r
bsp_usart.c内容$ m9 Z% V3 W( B8 `
  E3 {. z3 Y, i7 [
  1. #include <bsp_usart.h>
    . a! Y$ d* z  F& ?: \  ]) W" n  D
  2. ; m- `) Z- l- p9 O4 g8 H  Q& G
  3. extern UART_HandleTypeDef huart2;1 P; ^( J$ A  j; ?9 X4 \9 {
  4. 7 \, h! V) I9 q4 d) m  T4 y
  5. /* USER CODE BEGIN 1 */% I1 i4 c8 e; e6 h, B
  6. #ifdef __GNUC__0 p$ R2 ~4 }( ?+ g
  7. /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf9 t- z' ^& D" j0 Z
  8. set to 'Yes') calls __io_putchar() */3 Y" D+ x( o& n, b* D, t
  9. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)" E. y0 ]1 W6 s7 Q; I3 u' O
  10. #else
    # ]; v) ^$ `  f0 P8 J( U2 w
  11. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
      Q( ]( N; L  F7 L" ]
  12. #endif /* __GNUC__ */  m/ G4 f$ |8 f* p8 B
  13. /**
    * j* E0 F5 p6 L: ]5 _& d0 {+ k
  14. * @brief  Retargets the C library printf function to the USART.1 z( R# ^  \/ y
  15. * @param  None
    . t& ?# D, \& k; ~# p( }
  16. * @retval None
    & T! w9 L* J* v9 M/ ]2 N; a
  17. */
    1 d3 k- D: U9 ^- z# M  N2 P
  18. PUTCHAR_PROTOTYPE {
    ' M. t! ~+ N. ~7 y+ F6 ^
  19.         /* Place your implementation of fputc here */
    1 ]: D/ R; x7 U5 E) @
  20.         /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */- b. R. Y( n8 O9 n5 z
  21.         HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF);2 K0 R' V1 A8 I/ u& p( N5 J
  22.         return ch;
    0 H4 T! u0 H4 v
  23. }( M! `; i% e0 I+ K
  24. /* USER CODE END 1 */& k$ `! o/ x) G$ D: x5 Z
复制代码

5 L. @2 b4 m/ v4 J在main.c文件里引入头文件+ T$ y: ~5 \& k, f
  1. #include <stdbool.h>
    ; u/ G! O5 W3 r( q; d: w
  2. #include <string.h>
    % \) s$ ]$ j/ s/ k0 d6 A
  3. #include <stdio.h>- K. u/ U! ?' O5 J# u2 u( S
  4. #include "bsp_usart.h"
复制代码

! Y2 H( f$ T( R3 L2 z0 @3 c% D然后,就可以使用printf(“uart2 output data = %d \r\n”, data);了。
5 e5 q5 E# D) C! G' k1 u; D, g0 a( W# w. ?, V4 T
RX(接收)设计
( @+ s1 h6 ^% g# Z- H2 u常规的串口接收设计,都需要设计当前接收字节后的超时识别,如果出现超时,认为接收结束。即使是固定字节长度的传输,也需要为异常情况下设计超时识别作为传输结束。
+ [4 [6 M7 M& ]' w$ M" iSTM32 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)),因此考虑将两种方式结合使用,以简化超时判断的设计。2 r) ]) t: E' j# j! h
主要的设计思路是:1.通过中断接收第一个字节;2. 通过轮询接收后续字节。5 S3 x4 u; y6 x- s
2 g) y6 {# p$ i) J* ]4 C; s- i
main()函数前初始化相关代码,部分代码由STM32CUBEIDE自动生成:
# c7 j" G9 T: I8 {6 y, a/ h) M" W" z1 J0 p# R. o* H+ W$ I
  1. /* Private macro -------------------------------------------------------------*/
    % |) A# H4 w5 A- d& M, r4 s
  2. /* USER CODE BEGIN PM */( l* L* X3 a5 g8 t, p; ^, ?
  3. #define UART2_RX_STOP 0" W+ P. ]2 k) t! @
  4. #define UART2_RX_START 1  d% w8 [% e7 T
  5. /* USER CODE END PM */
    5 Y* |" U1 k; V. e, X8 Z
  6. /* Private variables ---------------------------------------------------------*/3 _$ k, d2 E4 s* ?3 T, y: j3 n
  7. UART_HandleTypeDef huart2;6 s1 U7 F+ t* _9 p
  8. /* USER CODE BEGIN PV */
    2 g% d3 F/ C: x( W' v0 H  u: l7 v
  9. uint8_t aRxBuffer;                        //RX int buffer, 1 byte" q! T& X7 H& ?# J# X0 z. a7 X
  10. uint8_t Uart2_RxBuff[10] = {0};                //Rx buffer,should be adjusted according to Rx max byte length per communication., v5 t8 Z2 x, H9 Q7 @% r+ ?
  11. uint8_t uart2_rx_flag = UART2_RX_STOP;6 {* z/ v' l& _6 b0 Y
  12. HAL_StatusTypeDef uart2_status_rx;
    $ V, K0 c4 d! K* `+ q
  13. /* Private function prototypes -----------------------------------------------*/8 `9 T; J& `/ Y) |( m
  14. void SystemClock_Config(void);% u8 d8 O- c( V) Y
  15. static void MX_USART2_UART_Init(void);
复制代码

% p6 N. x0 F0 d+ u- r+ F! w" b" Vmain()函数相关代码,部分代码由STM32CUBEIDE自动生成:( a3 @' V- z2 s$ e
# V. |& y( z+ }' D/ b& D0 X
  1. int main(void)
    8 D' m" _+ X- y0 k/ @
  2. {
    0 _! T/ T# J3 Q& S; ^/ E
  3.   /* USER CODE BEGIN 1 */9 x3 w6 s- s& l; s
  4.   /* USER CODE END 1 */
    7 z& P/ \9 r; I* V% }
  5.   /* MCU Configuration--------------------------------------------------------*/: O4 ]3 \- g3 G- [7 ?) c
  6.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    6 ^- _3 Z. ?  w* z; a! @: S1 _
  7.   HAL_Init();) D6 ]2 u# y* ?% @. W( d/ S/ u
  8.   /* USER CODE BEGIN Init */* J9 }* S4 u, V2 z* l1 {
  9.   /* USER CODE END Init */6 j& {4 z# m' O0 G
  10.   /* Configure the system clock */7 a, R  l$ a6 ]( m, z1 }) f
  11.   SystemClock_Config();0 p# j0 {, {" l% H2 ~4 I% a. `* d
  12.   /* USER CODE BEGIN SysInit */
    5 A( X% j. Z/ R0 ?0 I
  13.   /* USER CODE END SysInit */
    , ^/ @1 Z. q4 H2 o
  14.   /* Initialize all configured peripherals */5 {7 I- P0 s( m& t: }
  15.   MX_USART2_UART_Init();
    . I. F0 _- W# u4 g8 f, b& a
  16.   /* USER CODE BEGIN 2 */3 k6 [6 P; T; N3 k6 y4 A) v
  17.   /* USER CODE END 2 */2 o0 `0 {5 D. s7 U) M) k% p  Y, z
  18.   /* Infinite loop */
    9 g9 m) E2 s7 f" u( K5 m  D! C5 O
  19.   /* USER CODE BEGIN WHILE */
    ' e/ g9 g6 |+ p- S5 ^+ V7 V8 s
  20.   if (HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1)!=HAL_OK) printf("UART2 IT FAILED! \r\n");
    % x  U  W8 y. n
  21.   while (1)* J- e. K) X- H
  22.   {
    + B+ G. y5 E8 ]4 j/ m( g
  23.     /* USER CODE END WHILE */
    7 p+ s6 M! o, Y7 k+ F
  24.     /* USER CODE BEGIN 3 */
    2 o6 N/ Y/ v3 Q; u- L4 O
  25.      if (uart2_rx_flag == UART2_RX_START)
    8 }0 C* ?* c- w$ s
  26.      {
    ' \$ g+ F/ k% j/ i  _3 u( O
  27.              uart2_status_rx = HAL_UART_Receive(&huart2, Uart2_RxBuff+1, 9, 100); ( J! Y2 t# j- w; @. i% B5 \5 l2 \
  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]);
    ( _" Y; o  P+ L: M; U
  29.              uart2_rx_flag = UART2_RX_STOP;
    8 Q, }( j. }" {; x$ S4 [0 w" O# V0 R- M
  30.              memset(Uart2_RxBuff, 0, sizeof(Uart2_RxBuff));2 v2 [5 w1 Y) Q5 G3 |& L+ ^0 }6 v
  31.              MX_USART2_UART_Init();
    & E7 w+ Z5 s( h. v2 ~
  32.              HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);" k( J* L2 M# \( ^/ a

  33. 5 U, `# \& @9 J$ ^! |, t
  34.      }
    5 X5 U& p( y! s5 S
  35.           HAL_Delay(1);   //must for timing- t9 y; _  {3 Q: E) I3 G
  36.   }& f5 T8 W4 f" U, @; K- I
  37.   /* USER CODE END 3 */
    & K8 z7 ^7 i) d
  38. }
复制代码
6 @; ^1 j  R* h3 d/ o
中断响应通过函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)的重载实现。( m2 s5 t& K- X4 }" r: z6 V

9 u% U* l0 E; ?3 l& r
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
    . l5 e+ i' x* @7 Z0 M3 k; ?  t3 B; O% c+ M
  2. {: b9 n! ^. u) v( _: M" o; Q) l

  3. 7 f1 h( z+ |; i$ f- {' P5 X0 ?) S8 N
  4.         Uart2_RxBuff[0] = aRxBuffer;
    $ d4 P- y* j! @' M; Z
  5.         uart2_rx_flag = UART2_RX_START;
    4 V% G+ C  o0 }" `4 I/ E4 @
  6. ; I, q3 _# i/ c# D
  7.           //printf("uart2 get rx interrupt!\r\n");# j( W, M, j8 u% o: h8 K
  8.       return;1 `1 I1 I6 n. l6 P6 ]
  9. }
复制代码

6 P1 G, Z1 D, E2 _! d! H注意事项
+ c9 K/ M4 S. x' T4 Z8 ?3 g8 \! aHAL_UART_Receive()不能放在HAL_UART_RxCpltCallback()函数里处理,HAL_UART_Receive()的Timeout会失效。这是因为SysTick的中断优先级低于了外设UART的中断优先级,在UART的中断处理过程中无法响应SysTick中断。(如果一定要把HAL_UART_Receive()放在HAL_UART_RxCpltCallback()函数里,就需要调整SysTick中断的优先级)。
* F+ ^' r( K) W( t5 Q5 Ymain()里的while(1)循环,需要延时HAL_Delay(1), 时序才正常。8 e4 j0 Q8 E- D3 c* a1 D
-End-
. V6 d% v7 g# _1 x' x7 F9 f, g" g. k  c1 E& B

  z4 e; c& F" }! h5 j7 U9 {
收藏 评论0 发布时间:2021-11-16 01:34

举报

0个回答

所属标签

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