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

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

[复制链接]
STMCU小助手 发布时间:2021-11-16 01:34
代码环境
0 Y( K8 [# t$ s) H8 _开发工具:STM32CUBEIDE
+ @/ y3 e( s- k! ^" R" G, a芯片:STM32L031K6T6
9 t. R3 d( _% b) e. F+ V0 D% l端口: UART2* U; k& L& \! W% _( G: [
基本配置  r! n# a0 j9 x$ I

" V7 E1 {) @: ^! E7 ]; {) b# v
2019111911265218.png
" e7 J% B+ Y0 B$ X! v  J7 H  j

( r! _9 `- V' s$ |# i
20191119112729252.png
& e2 X0 z1 U8 R1 N
. M9 I) ^. e* @
20191119112750442.png

5 [6 h0 b5 k, o$ f+ v- W# E) x0 \: V8 _4 l6 H5 d
其中,PA9 (RX)的输入上拉,在System Core的GPIO里配置。
. e2 M+ L9 Q5 J& e( v  a: k( V9 A$ G* A7 z7 S5 P$ O) U( q
20191119112920480.png

7 W" I$ M( r: n3 H5 |/ N( k: ^5 ?4 |; E
TX(发送)设计
' g( d; O4 I; KTX部分增加bsp_usart.c和bsp_usart.h文件,以支持printf重载。
9 h4 [; q$ v2 P: O$ t8 R" H
9 c, T) y- `5 l: }: M; {bsp_usart.h内容
$ D, U' i" m" \; q# O, Y) M% _) L
  1. #ifndef __BSP_USART_H1 Y5 Y) V) g1 C9 g; t6 N
  2. #define __BSP_USART_H
    ! _1 H5 i6 C6 r2 u1 U. g. n
  3. . C, z2 i  u! d* k$ F
  4. #include "stm32l0xx_hal.h"
    $ I+ q) m2 c) b% v7 e; G
  5. #include "stdio.h"                           
      Q" F$ Z* Y2 g4 s* I" r

  6. : P  L/ E/ k* G8 b4 ?+ ~0 M
  7. int fputc(int ch, FILE *f);
    7 N8 k! z; @3 S9 a+ i) \; f, }# N
  8. # _' Z/ D3 f2 u# T: s. E
  9. #endif
复制代码

# |, b; J# U" E( Z  x' ^bsp_usart.c内容4 w# c9 b6 C6 C7 Q& S5 A- U
; l+ c/ @" h0 C5 Z* A8 ^) |
  1. #include <bsp_usart.h>
    5 C- r* x( K0 K# w

  2. ! w7 n0 K+ d4 M. c, x
  3. extern UART_HandleTypeDef huart2;- r7 {" Y) O! E3 H& K+ S
  4. ; _, P. |) B7 C: }5 V: m
  5. /* USER CODE BEGIN 1 */
    7 f- q. x1 Z: N. t/ ~7 D
  6. #ifdef __GNUC__
      j% N4 c0 N- B% Z0 j. Q) ~: _9 q: G
  7. /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf; c0 K( P+ e; {$ \4 b4 c# ^9 c
  8. set to 'Yes') calls __io_putchar() */
    ' k. B0 z, A# w" K) c/ s
  9. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    1 }2 x4 r; {+ N$ |8 O
  10. #else4 e1 I) v! X( y" l" `4 y
  11. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    + Q. H& f" f9 Z0 {- I" t
  12. #endif /* __GNUC__ */0 W5 t  ~9 x) A( W/ x
  13. /**
    8 ~0 U8 U- W% O) w# r
  14. * @brief  Retargets the C library printf function to the USART., Z# n6 l6 }! W8 @& I
  15. * @param  None0 w! r1 I7 z$ d" X. |
  16. * @retval None
    - O: S  `0 J5 j7 u! Y: ]5 J
  17. */
    # Y' k2 @3 E* c, @9 [
  18. PUTCHAR_PROTOTYPE {
    - _0 A9 |1 g7 D. h7 D; q
  19.         /* Place your implementation of fputc here */* c7 `0 a" i$ g! y8 z
  20.         /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
    ! Z6 L* a  ^. T4 e
  21.         HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF);
    5 v/ O! J/ f8 F" j0 H
  22.         return ch;6 B+ s8 f- ^' q1 f1 J: S; w1 g. F
  23. }
    & g& x" X+ N0 N& z
  24. /* USER CODE END 1 */
    + N4 L& o" E" k0 R/ c
复制代码

: [: n$ e; K9 K2 ^8 r3 W4 F/ q! ]在main.c文件里引入头文件, r2 q$ q5 f- M: l
  1. #include <stdbool.h>
    6 a- [1 h& P, L" v/ E
  2. #include <string.h>
    2 ?$ ]& e3 _2 {# C, r9 v
  3. #include <stdio.h>. E# d4 K5 I6 f7 `4 u# x5 U8 m. p
  4. #include "bsp_usart.h"
复制代码

& d" s% j' V  h$ o9 w( {0 j2 s; |然后,就可以使用printf(“uart2 output data = %d \r\n”, data);了。
% q- [5 H" }7 n5 H' G) b4 b2 `% K# `) k0 ?3 f
RX(接收)设计) o9 v7 b$ {  [0 j% y
常规的串口接收设计,都需要设计当前接收字节后的超时识别,如果出现超时,认为接收结束。即使是固定字节长度的传输,也需要为异常情况下设计超时识别作为传输结束。, W6 ~% ?6 i* R: S0 c1 X& |
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)),因此考虑将两种方式结合使用,以简化超时判断的设计。% P) C/ x# n! ]( e: S% k- Z
主要的设计思路是:1.通过中断接收第一个字节;2. 通过轮询接收后续字节。
7 j6 Q, S  B& j- y) k1 U! F! s6 t! z; O+ e# k" {$ E0 P) J
main()函数前初始化相关代码,部分代码由STM32CUBEIDE自动生成:
9 ]0 k" x! B# U) `/ ?
' u$ X0 X# a* [6 y
  1. /* Private macro -------------------------------------------------------------*/+ f' m  {9 L! G, {7 S& K
  2. /* USER CODE BEGIN PM */
    8 ~3 ]* b: o2 D3 o. j& n$ B
  3. #define UART2_RX_STOP 0# v; ?* n  a/ D/ p) t8 X+ X5 U/ e
  4. #define UART2_RX_START 1
    6 B9 ^- x5 Z' {  L3 Q7 o
  5. /* USER CODE END PM */* a! a& p0 F, \, T1 f# V
  6. /* Private variables ---------------------------------------------------------*/: p- X+ y& {- G8 Z' ]+ y  a7 p
  7. UART_HandleTypeDef huart2;
    ) N3 l7 {' h) `3 |6 x2 b! W
  8. /* USER CODE BEGIN PV */
    ! y; d2 s6 k% O9 c6 Q$ z3 {' N& f
  9. uint8_t aRxBuffer;                        //RX int buffer, 1 byte7 w/ j) o% i9 y: }% I7 c- K
  10. uint8_t Uart2_RxBuff[10] = {0};                //Rx buffer,should be adjusted according to Rx max byte length per communication.: c1 g9 }8 b" ?
  11. uint8_t uart2_rx_flag = UART2_RX_STOP;
    2 [* ^: w& i) `
  12. HAL_StatusTypeDef uart2_status_rx;. }. ^5 x( G# Z$ ]2 m! @
  13. /* Private function prototypes -----------------------------------------------*/
      W5 [+ C& y8 D2 r. M8 W
  14. void SystemClock_Config(void);
    * B7 r7 O- l9 |' M7 o
  15. static void MX_USART2_UART_Init(void);
复制代码
) k6 i  ]; [0 B9 T# U- B4 ?
main()函数相关代码,部分代码由STM32CUBEIDE自动生成:' b; W: H3 v; s% ?+ ]. C2 D

& k9 D$ m5 L: D) h/ N# X0 o) G
  1. int main(void)
    * ], V4 @. C! f/ G: m" A7 Z
  2. {. b) {* O5 ]! S* b- v# \
  3.   /* USER CODE BEGIN 1 */
    - }7 E3 q: X8 `2 i2 l3 n6 `0 [
  4.   /* USER CODE END 1 */
    $ ~5 Z( y" F# [. L
  5.   /* MCU Configuration--------------------------------------------------------*/
    7 |3 v* l7 B3 \7 b4 }  b7 _/ K; f; P
  6.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */8 M+ j* i, `# N9 S/ C/ u! j
  7.   HAL_Init();5 E) e4 P0 a8 @7 Q" J
  8.   /* USER CODE BEGIN Init */
    3 T6 A+ P4 A( C, m
  9.   /* USER CODE END Init */
    ) K5 q3 ~+ W) s9 x% o' W' x
  10.   /* Configure the system clock */
    5 @3 c  ^- h2 v5 `  V  B
  11.   SystemClock_Config();1 O% }& Q5 R' @6 N6 p, u
  12.   /* USER CODE BEGIN SysInit */
    . {" ~: o: `8 Z0 a8 f
  13.   /* USER CODE END SysInit */
    3 ^% J2 v9 U( @7 ^& K( B* G
  14.   /* Initialize all configured peripherals */3 n! Q! J  f8 A3 B: P1 @9 t
  15.   MX_USART2_UART_Init();& X: G  P" \1 @& @
  16.   /* USER CODE BEGIN 2 */; l2 j' F( P4 H) g+ X
  17.   /* USER CODE END 2 */
    ) r7 d1 b: n' Z8 y
  18.   /* Infinite loop */
    3 S3 v2 U) {) M) {  J- ^  _
  19.   /* USER CODE BEGIN WHILE */
    ( j; y$ W$ b( d; M. R
  20.   if (HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1)!=HAL_OK) printf("UART2 IT FAILED! \r\n");; `3 `' s  c3 o. i1 y9 h& I
  21.   while (1)
    + r* W% Y* b# B6 A) x: \9 E
  22.   {
    . T: D; w+ [: S) e2 b& g
  23.     /* USER CODE END WHILE */, d- K! t6 J7 t5 N( |6 t5 J
  24.     /* USER CODE BEGIN 3 */
    0 M1 Z5 p- {! g9 r- A2 _( o% l& M3 _
  25.      if (uart2_rx_flag == UART2_RX_START)! J" ?. G( k* n( W- |2 i* ^, s' Z
  26.      {
    # g" w, {* Q7 f4 ~; S0 n4 N
  27.              uart2_status_rx = HAL_UART_Receive(&huart2, Uart2_RxBuff+1, 9, 100); + \8 @3 f) z, p/ k7 n" _4 O
  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]);: G2 f$ X# ]' \! x6 l$ W( Q8 s5 |
  29.              uart2_rx_flag = UART2_RX_STOP;& |& x" h* n3 \
  30.              memset(Uart2_RxBuff, 0, sizeof(Uart2_RxBuff));
    8 g& U0 B* }8 F' s' }( I$ `
  31.              MX_USART2_UART_Init(); 9 y- t9 y: a) g3 q* ?
  32.              HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);/ Z$ a- n0 c$ i. S( `& K& F

  33. % S4 A6 s8 G$ K1 o7 F8 M
  34.      }
    6 ^& m, X- N# y$ p( D& ?1 `) \6 |
  35.           HAL_Delay(1);   //must for timing
    0 q4 P) \0 J4 i8 L$ v. ?- z1 K
  36.   }% S) N- R/ v! a
  37.   /* USER CODE END 3 */4 Z- b6 C$ E4 d5 V5 U: M5 Y
  38. }
复制代码
: a  y* @6 y% z  X: E' d$ _
中断响应通过函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)的重载实现。
/ K+ N9 |' t6 o7 s* X! g
" Z1 Q% N' W2 ?0 K7 T4 E4 z
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
    ' }( A2 d! I, J7 G
  2. {
    ! d) W0 ?; X$ O: ~9 {; g) K

  3. ) K! `$ k% O" D, U! U
  4.         Uart2_RxBuff[0] = aRxBuffer;
    - t  G% o$ d3 r! w& S9 R
  5.         uart2_rx_flag = UART2_RX_START;4 G$ u8 F' x, N

  6. # Y# F$ t6 V6 U4 s# h% M& |
  7.           //printf("uart2 get rx interrupt!\r\n");
    7 z$ [8 `+ r7 c1 b& U  |5 P
  8.       return;
    ' e0 W9 E: j3 B- s  @3 _2 z1 Y- Q; g
  9. }
复制代码

1 n/ d0 i3 t- c6 z注意事项" g1 Z4 ^& y! N  U. j: G# y, r
HAL_UART_Receive()不能放在HAL_UART_RxCpltCallback()函数里处理,HAL_UART_Receive()的Timeout会失效。这是因为SysTick的中断优先级低于了外设UART的中断优先级,在UART的中断处理过程中无法响应SysTick中断。(如果一定要把HAL_UART_Receive()放在HAL_UART_RxCpltCallback()函数里,就需要调整SysTick中断的优先级)。
9 B" Z, M/ N# mmain()里的while(1)循环,需要延时HAL_Delay(1), 时序才正常。6 N  `9 \- w7 f: X
-End-. }4 a$ h. B; c6 \% w3 M

$ T% J4 U, E: X; ]8 V) M* ]; s; U
收藏 评论0 发布时间:2021-11-16 01:34

举报

0个回答

所属标签

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