STM32L031 HAL serial port transceiver routine (interrupt with polling)

STM32L031 HAL serial port transceiver routine (interrupt with polling)

Code environment

  1. Development tools: STM32CUBEIDE
  2. Chip: STM32L031K6T6
  3. Port: UART2

basic configuration

Insert picture description here

Insert picture description here
Among them, the input of PA9 (RX) is pulled up and configured in the GPIO of System Core.
Insert picture description here

TX (transmit) design

TX part adds bsp_usart.c and bsp_usart.h files to support printf overload.

bsp_usart.h content

#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 content

#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 */


Introduce the header file in the main.c file

#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "bsp_usart.h"

Then, you can use printf("uart2 output data = %d \r\n", data);.

RX (receive) design

Conventional serial port receiving design needs to design the timeout recognition after the current received byte. If there is a timeout, the reception is considered to be over. Even if it is a fixed byte length transmission, it is necessary to design timeout recognition as the end of transmission for abnormal situations.
The STM32 HAL library supports the polling timeout method to receive serial port data (HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)), and also supports the interrupt method to receive serial data (HAL_StatusTypeDefType HAL_UART_Receive_Receive_T pData, uint16_t Size)), so consider combining the two methods to simplify the design of timeout judgment.
The main design ideas are: 1. Receive the first byte through interrupt; 2. Receive subsequent bytes through polling.

Initialize the relevant code before the main() function, and part of the code is automatically generated by 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() function related code, part of the code is automatically generated by 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 */
}

The interrupt response is realized by reloading the function 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;
}

Precautions

  1. HAL_UART_Receive() cannot be processed in the HAL_UART_RxCpltCallback() function, and the Timeout of HAL_UART_Receive() will be invalid. This is because the interrupt priority of SysTick is lower than that of the peripheral UART, and the SysTick interrupt cannot be responded to during the interrupt processing of the UART. (If you must put HAL_UART_Receive() in the HAL_UART_RxCpltCallback() function, you need to adjust the priority of the SysTick interrupt).
  2. The while(1) loop in main() needs to delay HAL_Delay(1), and the timing is normal.

-End-

Guess you like

Origin blog.csdn.net/hwytree/article/details/103138655
Recommended