USART初始化部分就不介绍了,直接看官方给的例程就能知道,现在主要将自己在学习过程中遇到的问题以及解决方法记录一下。
首先,如果使用了串口接收中断,就需要在初始化中打开中断以及设定中断优先级等常规操作。
HAL_UART_Init(&UartHandle) -> HAL_UART_MspInit(huart)-> /* Set Interrupt Group Priority */ HAL_NVIC_SetPriority(USARTx_IRQn, 0, 1);/* Enable the TIMx global Interrupt */
HAL_NVIC_EnableIRQ(USARTx_IRQn); 然后需要调用串口接收终端初始化函数: /** * @brief Receives an amount of data in non blocking mode * @param huart: UART handle * @param pData: Pointer to data buffer * @param Size: Amount of data to be received * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)各个参数都有英文解释。
根据网上资料显示,这个函数只能对串口中断接收进行一次接收,而且接收的字节大小是固定的uint16_t Size,但是在实际使用中,不可能完全满足每次接收到的字节数都是一样的,而且是确定的。所以大家采用的方法都是令uint16_t Size = 1;这样的话,每接收到一个字节就中断一次。那么中断处理函数处理的规则应该是
1、关闭此接收中断 2、将接收到的数据转移至缓存器 3、再次打开中断根据Cube库函数给的函数以及示例,中断处理函数是:
void USARTx_IRQHandler(void) { HAL_UART_IRQHandler(&UartHandle); } 其中void USARTx_IRQHandler(void)对应的是不同的中断处理函数,但是终端中调用的都是HAL_UART_IRQHandler(&UartHandle); 因为HAL_UART_IRQHandler(&UartHandle);函数的参数不同,所以不会产生异常。大家仔细看HAL_UART_IRQHandler(&UartHandle)这个函数,应该能发现两个问题:
1、用户自己的中断处理函数在哪里不会影响库函数的完整性 2、中断如何再次打开 自己是新手,最初急于求成,没有认真学习函数中每一步,导致自己一直在纠结第一个问题:用户中断处理函数放在什么地方不影响库函数的完整性,后来详细阅读了源代码,发现库函数提供了一个可供用户重新定义的弱定义函数__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 可以供用户重新定义函数内容,用户直接将自己的中断缓存数据部分放在此函数中,用户只需要在stm32f2xx_hal_msp_.c中重新定义此函数即可。 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { UART1RxBuff[UART1RxBuffCount++] = aRxBuffer; } 同理,用户可以在 HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 中再次调用 HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) 这样的话,就可以实现连续中断接收USART数据。而且当需要多个串口中断接收的时候,上述中断处理函数如何进行中断缓存数据,如何区别时哪一个串口发送过来的数据。这里可以利用中断初始化中的UartHandle.Instance 这个成员变量,加上判断就能实现串口区别,最后产生的HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)函数应该如下:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { UART1RxBuff[UART1RxBuffCount++] = aRxBuffer; } HAL_UART_Receive_IT(huart, (uint8_t *)&aRxBuffer, 1) ; }