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

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

[复制链接]
STMCU小助手 发布时间:2021-11-16 01:34
代码环境
开发工具:STM32CUBEIDE
芯片:STM32L031K6T6
端口: UART2
基本配置

2019111911265218.png


20191119112729252.png


20191119112750442.png


其中,PA9 (RX)的输入上拉,在System Core的GPIO里配置。

20191119112920480.png


TX(发送)设计
TX部分增加bsp_usart.c和bsp_usart.h文件,以支持printf重载。

bsp_usart.h内容

  1. #ifndef __BSP_USART_H
  2. #define __BSP_USART_H

  3. #include "stm32l0xx_hal.h"
  4. #include "stdio.h"                           

  5. int fputc(int ch, FILE *f);

  6. #endif
复制代码

bsp_usart.c内容

  1. #include <bsp_usart.h>

  2. extern UART_HandleTypeDef huart2;

  3. /* USER CODE BEGIN 1 */
  4. #ifdef __GNUC__
  5. /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
  6. set to 'Yes') calls __io_putchar() */
  7. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  8. #else
  9. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  10. #endif /* __GNUC__ */
  11. /**
  12. * @brief  Retargets the C library printf function to the USART.
  13. * @param  None
  14. * @retval None
  15. */
  16. PUTCHAR_PROTOTYPE {
  17.         /* Place your implementation of fputc here */
  18.         /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  19.         HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF);
  20.         return ch;
  21. }
  22. /* USER CODE END 1 */
复制代码

在main.c文件里引入头文件
  1. #include <stdbool.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include "bsp_usart.h"
复制代码

然后,就可以使用printf(“uart2 output data = %d \r\n”, data);了。

RX(接收)设计
常规的串口接收设计,都需要设计当前接收字节后的超时识别,如果出现超时,认为接收结束。即使是固定字节长度的传输,也需要为异常情况下设计超时识别作为传输结束。
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)),因此考虑将两种方式结合使用,以简化超时判断的设计。
主要的设计思路是:1.通过中断接收第一个字节;2. 通过轮询接收后续字节。

main()函数前初始化相关代码,部分代码由STM32CUBEIDE自动生成:

  1. /* Private macro -------------------------------------------------------------*/
  2. /* USER CODE BEGIN PM */
  3. #define UART2_RX_STOP 0
  4. #define UART2_RX_START 1
  5. /* USER CODE END PM */
  6. /* Private variables ---------------------------------------------------------*/
  7. UART_HandleTypeDef huart2;
  8. /* USER CODE BEGIN PV */
  9. uint8_t aRxBuffer;                        //RX int buffer, 1 byte
  10. uint8_t Uart2_RxBuff[10] = {0};                //Rx buffer,should be adjusted according to Rx max byte length per communication.
  11. uint8_t uart2_rx_flag = UART2_RX_STOP;
  12. HAL_StatusTypeDef uart2_status_rx;
  13. /* Private function prototypes -----------------------------------------------*/
  14. void SystemClock_Config(void);
  15. static void MX_USART2_UART_Init(void);
复制代码

main()函数相关代码,部分代码由STM32CUBEIDE自动生成:

  1. int main(void)
  2. {
  3.   /* USER CODE BEGIN 1 */
  4.   /* USER CODE END 1 */
  5.   /* MCU Configuration--------------------------------------------------------*/
  6.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  7.   HAL_Init();
  8.   /* USER CODE BEGIN Init */
  9.   /* USER CODE END Init */
  10.   /* Configure the system clock */
  11.   SystemClock_Config();
  12.   /* USER CODE BEGIN SysInit */
  13.   /* USER CODE END SysInit */
  14.   /* Initialize all configured peripherals */
  15.   MX_USART2_UART_Init();
  16.   /* USER CODE BEGIN 2 */
  17.   /* USER CODE END 2 */
  18.   /* Infinite loop */
  19.   /* USER CODE BEGIN WHILE */
  20.   if (HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1)!=HAL_OK) printf("UART2 IT FAILED! \r\n");
  21.   while (1)
  22.   {
  23.     /* USER CODE END WHILE */
  24.     /* USER CODE BEGIN 3 */
  25.      if (uart2_rx_flag == UART2_RX_START)
  26.      {
  27.              uart2_status_rx = HAL_UART_Receive(&huart2, Uart2_RxBuff+1, 9, 100);
  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]);
  29.              uart2_rx_flag = UART2_RX_STOP;
  30.              memset(Uart2_RxBuff, 0, sizeof(Uart2_RxBuff));
  31.              MX_USART2_UART_Init();
  32.              HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);

  33.      }
  34.           HAL_Delay(1);   //must for timing
  35.   }
  36.   /* USER CODE END 3 */
  37. }
复制代码

中断响应通过函数HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)的重载实现。

  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
  2. {

  3.         Uart2_RxBuff[0] = aRxBuffer;
  4.         uart2_rx_flag = UART2_RX_START;

  5.           //printf("uart2 get rx interrupt!\r\n");
  6.       return;
  7. }
复制代码

注意事项
HAL_UART_Receive()不能放在HAL_UART_RxCpltCallback()函数里处理,HAL_UART_Receive()的Timeout会失效。这是因为SysTick的中断优先级低于了外设UART的中断优先级,在UART的中断处理过程中无法响应SysTick中断。(如果一定要把HAL_UART_Receive()放在HAL_UART_RxCpltCallback()函数里,就需要调整SysTick中断的优先级)。
main()里的while(1)循环,需要延时HAL_Delay(1), 时序才正常。
-End-


收藏 评论0 发布时间:2021-11-16 01:34

举报

0个回答

所属标签

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