赞
踩
1、Connectivity选择USART1
2、Mode选择Asynchronous
3、Parameter Settings:
Baud Rate 115200 Bit/s
Word Length 8 Bits
Parity None
Stop Bits 1
Data Direction Receive and Transmit
Over Sampling 16 Samples
4、NVIC Settings:
USART1 global interrupt 打√
5、生成代码
6、找到usart.c文件,定义接收数组,位置和代码如下:
/* USER CODE BEGIN 0 */
uint8_t RecvBuffer[1];
/* USER CODE END 0 */
打开usart.h文件,增加接收数组声明代码,位置和代码如下:
/* USER CODE BEGIN Includes */
extern uint8_t RecvBuffer[];
/* USER CODE END Includes */
7、找到main.c文件中的MX_USART1_UART_Init(); 在其后的/* USER CODE BEGIN 2 */之后添加以下代码:
HAL_UART_Receive_IT(&huart1,RecvBuffer,1);//使能串口1接收中断
8、接下来写串口接收中断回调函数,首先对其来龙去脉进行介绍。
串口中断函数在stm32f4xx_it.c文件中,打开此文件,找到 void USART1_IRQHandler(void)函数内,找到 HAL_UART_IRQHandler(&huart1)函数,右键点击函数并选择GO TO Definition Of,定位到stm32f4xx_hal_uart.c文件的 HAL_UART_IRQHandler函数体,关于所有UART的中断,都由此函数统一管理。
函数开始处:
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
if (errorflags == RESET)
{
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
即若无任何错误,进入UART_Receive_IT函数,找到此函数体,为static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart),然后找到函数中的此处:
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx complete callback*/
huart->RxCpltCallback(huart);
#else
/*Call legacy weak Rx complete callback*/
HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
可以看到回调函数HAL_UART_RxCpltCallback的调用处。 在回调函数名上右键选择GO TO Definition Of,定位到回调函数 体,发现此回调函数中的一段话:
/* NOTE: This function should not be modified, when the callback is needed,the HAL_UART_RxCpltCallback could be implemented in the user file */
意为当需要回调时,不应修改此函数,可以在用户文件中实现,即不建议在HAL库文件中实现此回调函数。
仔细看此处的回调函数定义,前面有__weak修饰符,同其意,称其为“弱函数”,加上了__weak 修饰符的函数,编译时会首 先查看是否有用户重复定义的同名函数,若有则首先选择用户定义的函数,若没有重新定义才就会执行__weak 声明的函数。
所以建议找到usart.c文件,拉到最底部,
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
在此处去重新实现回调函数。
9、实现串口中断回调函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == huart1.Instance)
{
HAL_UART_Transmit(&huart1, RecvBuffer, 1, 0xFFFF);// 将收到的数据在发回去
HAL_UART_Receive_IT(&huart1, RecvBuffer, 1);// 再次使能接收中断
}
}
此处注意:函数名一定书写正确,建议之间使用__weak同名函数进行复制,否则不能正确回调。
此处需要再次使能接收中断的原因为:找到stm32f4xx_hal_uart.c中的UART_Receive_IT函数体,在if (--huart->RxXferCount == 0U)代码之后可以看到,接收完成后会关闭中断,所以若想下次继续接收,需要重新使能接收中断。
10、下载代码进行测试。
注意。此种单个字符的发送和接收方式,当UART波特率较高时,串口中断优先级较其他中断优先级低,或因为未知代码造成接收中断进入慢,容易产生溢出错误。所以建议使用总线空闲中断来减少串口接收中断的进入次数。
下面展示通过在中断中清除溢出错误,来提高接收准确性的方法,但此方式治标不治本。
if(((READ_REG(huart->Instance->SR))& USART_SR_ORE) != RESET)
{
CLEAR_BIT(huart->Instance->SR, USART_SR_ORE);//及时清除溢出中断
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。