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_Init(UART_HandleTypeDef *huart) 后会使能相应的串口(此处为UART1),就不用再使能相应的串口了,同时在函数内部会调用回调函数
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
这个函数需要自己编写,并在这个函数里面调用HAL库的中断处理函数(该函数会对相应的中断来源进行分析,调用相应函数)。
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
即每收到一个字符就调用一次中断服务函数USART1_IRQHandler,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);
}
}
在最终的中断处理函数里写入想执行的操作