STM32f429串口通信-基于HAL库

STM32f429串口通信接收-基于HAL库

串口接收

配置步骤

1.调用函数 HAL_UART_Init(UART_HandleTypeDef *huart) 。 通过定义结构体类型句柄 UART_HandleTypeDef 并初始化相关参数来配置串口通信的选用串口、字长、波特率、停止位、奇偶校验位、硬件流控、收发模式、DMA等。

UART_HandleTypeDef usart1_handler; //UART句柄

结构体UART_HandleTypeDef 定义如下

typedef struct
{
          
   
  USART_TypeDef                 *Instance;        /*!< UART registers base address        */
  
  UART_InitTypeDef              Init;             /*!< UART communication parameters      */
  
  uint8_t                       *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */
  
  uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */
  
  uint16_t                      TxXferCount;      /*!< UART Tx Transfer Counter           */
  
  uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */
  
  uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */
  
  uint16_t                      RxXferCount;      /*!< UART Rx Transfer Counter           */  
  
  DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      */
    
  DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */
  
  HAL_LockTypeDef               Lock;             /*!< Locking object                     */

  __IO HAL_UART_StateTypeDef    State;            /*!< UART communication state           */
  
  __IO uint32_t                 ErrorCode;        /*!< UART Error code                    */

}UART_HandleTypeDef;

初始化相关参数

usart1_handler.Instance=USART1;					    //USART1
	usart1_handler.Init.BaudRate=115200;				    //波特率
	usart1_handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	usart1_handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	usart1_handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	usart1_handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	usart1_handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	
	HAL_UART_Init(&usart1_handler);					    //HAL_UART_Init()会使能UART1
	HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//开启接收中断

调用函数 HAL_UART_Init(UART_HandleTypeDef *huart) 后会使能相应的串口(此处为UART1),就不用再使能相应的串口了,同时在函数内部会调用回调函数 。如果要使用串口接收中断,首先要使能相应的串口中断,并且设置此中断的类型的优先级,这两步可以在下面的回调函数中编写,另外还需要调用相应的HAL库函数来开启接收中断,即上面的最后一条语句。 以上两步可以封装在同一个函数下。

  1. void HAL_UART_MspInit(UART_HandleTypeDef *huart),它是一个弱函数需要自己定义
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
          
   
   
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
	{
          
   
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟
	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);		//初始化PA10
		
		HAL_NVIC_EnableIRQ(USART1_IRQn);//使能usart1中断通道
		HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);//抢占优先级3,子优先级3
		
	}
}

在调用HAL_UART_Init(UART_HandleTypeDef *huart) 时在函数内部会调用一个相同的外设回调函数 HAL_UART_MspInit(UART_HandleTypeDef *huart)(用户可以通过编写此回调函数来配置相应的外设),所以编写回调函数时需要约束判断条件,究竟是哪个串口的回调函数。 串口接收中断优先级配置和使能:

HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);

当我们开启了串口接收中断后,每收到一个字符就会产生一次中断,,进入中断服务函数USART1_IRQHandler,

DCD     I2C1_EV_IRQHandler                ; I2C1 Event                                             
                DCD     I2C1_ER_IRQHandler                ; I2C1 Error                                             
                DCD     I2C2_EV_IRQHandler                ; I2C2 Event                                             
                DCD     I2C2_ER_IRQHandler                ; I2C2 Error                                               
                DCD     SPI1_IRQHandler                   ; SPI1                                            
                DCD     SPI2_IRQHandler                   ; SPI2                                            
             DCD     USART1_IRQHandler                 ; USART1                                          
                DCD     USART2_IRQHandler                 ; USART2                                          
                DCD     USART3_IRQHandler                 ; USART3
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)

即每收到一个字符就调用一次中断服务函数USART1_IRQHandler,由HAL库中断处理函数判断中断类型,调用相应的接收中断处理函数

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart);

在这个接收中断处理函数中,当收到的数据满足了设置的大小时(开启串口接收中断函数设置的即函数 HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE)) 就会将相应的串口接收中断取消使能,所以要想继续使用串口接收中断。就要重新开启中断。这样设置的原因可能是因为上次中断处理完之后,用于存储串口接收数据的数组指针已经变化了,不能继续使用这个内存,所以需要重新设置串口接收的存储位置,而开启串口接收中断的HAL库函数正好有这个作用,所以才会在每次处理完接收中断后将相应的串口接收中断取消使能,所以在中断服务函数USART1_IRQHandler中除了调用HAL库的中断处理函数还要加上一个使能串口接收中断函数(因为此代码实现的功能是每接收一个字符就发送出去,所以设置的结束数据长度是一)。

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
void USART1_IRQHandler(void)
{
          
   
	HAL_UART_IRQHandler(&usart1_handler);
	HAL_UART_Receive_IT(&usart1_handler, (u8 *)buff, 1);

}

此外全部数据接收完成后HAL_UART_IRQHandler函数会调用相应的回调函数(接收中断处理函数调用的)

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

不管是处理完什么类型的中断,HAL_UART_IRQHandler函数会调用同一个回调函数,所以回调函数也需要判断条件是哪个类型的中断回调的

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
          
   
	if(huart->Instance==USART1)//如果是串口1
	{
          
   
		u8 rdata;
		rdata=*(--(huart->pRxBuffPtr));
		HAL_UART_Transmit(&usart1_handler, &rdata, 1, 1000);
	
	}
}

在最终的中断处理函数里写入想执行的操作

经验分享 程序员 微信小程序 职场和发展