STM32L031 HAL 串口收发例程(中断配合轮询)

STM32L031 HAL 串口收发例程(中断配合轮询)

代码环境

  1. 开发工具:STM32CUBEIDE
  2. 芯片:STM32L031K6T6
  3. 端口: UART2

基本配置

在这里插入图片描述

在这里插入图片描述
其中,PA9 (RX)的输入上拉,在System Core的GPIO里配置。
在这里插入图片描述

TX(发送)设计

TX部分增加bsp_usart.c和bsp_usart.h文件,以支持printf重载。

bsp_usart.h内容

#ifndef __BSP_USART_H
#define __BSP_USART_H

#include "stm32l0xx_hal.h"
#include "stdio.h"	 	  	

int fputc(int ch, FILE *f);

#endif

bsp_usart.c内容

#include <bsp_usart.h>

extern UART_HandleTypeDef huart2;

/* USER CODE BEGIN 1 */
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
 set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
 * @brief  Retargets the C library printf function to the USART.
 * @param  None
 * @retval None
 */
PUTCHAR_PROTOTYPE {
    
    
	/* Place your implementation of fputc here */
	/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
	HAL_UART_Transmit(&huart2, (uint8_t*) &ch, 1, 0xFFFF);
	return ch;
}
/* USER CODE END 1 */


在main.c文件里引入头文件

#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#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自动生成:

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
#define UART2_RX_STOP 0
#define UART2_RX_START 1
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
uint8_t aRxBuffer;			//RX int buffer, 1 byte
uint8_t Uart2_RxBuff[10] = {
    
    0};		//Rx buffer,should be adjusted according to Rx max byte length per communication.
uint8_t uart2_rx_flag = UART2_RX_STOP;
HAL_StatusTypeDef uart2_status_rx;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_USART2_UART_Init(void);

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

int main(void)
{
    
    
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  if (HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1)!=HAL_OK) printf("UART2 IT FAILED! \r\n");
  while (1)
  {
    
    
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
     if (uart2_rx_flag == UART2_RX_START)
     {
    
    
    	 uart2_status_rx = HAL_UART_Receive(&huart2, Uart2_RxBuff+1, 9, 100); 
    	 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]);
    	 uart2_rx_flag = UART2_RX_STOP;
    	 memset(Uart2_RxBuff, 0, sizeof(Uart2_RxBuff));
    	 MX_USART2_UART_Init(); 
    	 HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);

     }
	  HAL_Delay(1);   //must for timing
  }
  /* USER CODE END 3 */
}

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

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
    
    

	Uart2_RxBuff[0] = aRxBuffer;
	uart2_rx_flag = UART2_RX_START;

	  //printf("uart2 get rx interrupt!\r\n");
      return;
}

注意事项

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

-End-

扫描二维码关注公众号,回复: 11675686 查看本文章

猜你喜欢

转载自blog.csdn.net/hwytree/article/details/103138655