HAL库_串口接收/发送_阻塞+中断
标准库中打开串口的函数:
USART_Cmd(USART1, ENABLE);
标准库中打开中断的函数:需要单独设置被打开的中断的类型
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
在HAL中,打开串口和中断合并成了一个函数:发送就打开发送中断,接收就打开接收中断
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
标准库和HAL库中都有阻塞式发送接收和非阻塞式发送接收(中断或DMA)
标准库中阻塞式发送和接收函数
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
HAL库中阻塞式发送和接收
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
阻塞式发送和接收在使用上都没有太大的差别,发送就等着发送完,HAL中阻塞式发送函数的第4个参数Timeout,可以设置一个超时时间,超时后没发完就不再阻塞。
接收没有差别。超时时间根据systic的计数频率和计数值确定
中断式发送和接收
先说接收
标准库中接收的话需要自己在中断函数里面判断中断类型,清标志位
在HAL中void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);这个库函数帮我们完成了中断类型判断和清除标志位,我们只需要在具体的函数中写逻辑即可。
上面这个库函数判断出不同的类型,然后调用不同的回调函数,我们处理接收中断回调函数HAL_UART_TxCpltCallback即可。
全部回调函数如下:
1 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); 2 void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); 3 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); 4 void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart); 5 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart); 6 void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart); 7 void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart); 8 void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart);
发送和接收中断的一些问题:
HAL_UART_Transmit_IT(huart11,datass,2 ); HAL_UART_Receive_IT(&huart1,recivedatass,3);
关于中断式发送和接收,可以看到这两个函数的第3个参数,是设置要接收多少个、发送多少个字节。发送的中断就不用说了,有个全部发送完成和发送一半。
接收的话,每接收到一个字节就会产生一个接收中断,但是我们可能需要接收完3个字节的数据才想处理一次。HAL_UART_IRQHandler内部做了判断,当接收到3个字节后才会调用一个回调函数 HAL_UART_RxCpltCallback
实验:使用串口中断每接收到3个字节后,在中断回调函数中使用串口中断式发送2个字节的字符串“TR”,当发送完成后,在发送完成中断中翻转LED。
main.c :打开串口并开启接收中断
uint8_t datass[100] ="TR";
uint8_t recivedatass[100]="";
HAL_UART_Receive_IT(&huart1,recivedatass,3); HAL_Delay(2000);
接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart11) { HAL_UART_Transmit_IT(huart11,datass,2 ); HAL_UART_Receive_IT(&huart1,recivedatass,3);//再次打开接收中断,以便下次继续接收 }
发送完成中断回调函数
void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart11) { HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_5); HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5); //HAL_UART_Transmit_IT(&huart1,datass,2); }
遇到的问题:
接到几次就会卡死,后来发现是HAL_UART_IRQHandler函数内部每接收到一个字节就会关闭接收中断,如果我们还要继续接收,则需要在接收中断回调函数中打开接收中断。
而在发送完成中断中不用打开发送中断。打开了会死循环发送。
CUbeMx配置串口
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步