串口接收中断程序配置过程(HAL)
- 初始化相关参数,使能串口:
HAL_UART_Init();
该函数的参数是串口的基址,在stm32f429xx.h文件中,定义了8个UART_HandleTypeDef的值,分别是USART1、USART2、USART3、UART4、UART5、USART6、UART7、UART8,可以用HAL_UART_Init对这8个串口进行初始化,我们要用USART1,就填USART1
-
串口相关IO口配置,复用配置。在HAL_UART_MspInit中调用HAL_GPIO_Init函数
-
串口接收中断优先级配置和使能
HAL_NVIC_EnableIRQ();
HAL_NVIC_SetPriority();
- 使能串口接收中断
所有的串口都使用HAL_UART_Receive_IT使能接收中断
HAL_UART_Receive_IT();
- 编写中断服务函数:USARTx_IRQHandler
这个函数在startup_stm32f429xx.s中可以找到。
不同的串口有不同的中断服务函数
void USARTx_IRQHandler(void) ;//(x=1~3,6)
void USARTx_IRQHandler(void) ;//(x=4,5,7,8)
具体配置过程
我们通过电脑把数据发送给STM32,STM32收到数据之后再把数据发送给电脑
- 初始化相关参数,使能串口
UART_HandleTypeDef usart_handler; //定义为全局变量
void usart1_init(void)
{usart_handler.Instance = USART1; //指定用哪个串口usart_handler.Init.BaudRate = 115200; //波特率设置usart_handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //硬件流控制usart_handler.Init.Mode = UART_MODE_TX_RX; //接收or发送or接收发送//usart_handler.Init.OverSampling = usart_handler.Init.Parity = UART_PARITY_NONE; //奇偶校验usart_handler.Init.StopBits = UART_STOPBITS_1; //停止位usart_handler.Init.WordLength = UART_WORDLENGTH_8B; //字长HAL_UART_Init(&usart_handler);}
- 串口相关IO口配置,复用配置。在HAL_UART_MspInit中调用HAL_GPIO_Init函数
//HAL_UART_Init会自动调用HAL_UART_MspInitvoid HAL_UART_MspInit(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_USART1_CLK_ENABLE();//GPIO口初始化就配置好了复用功能GPIO_Initure.Pin=GPIO_PIN_9; //PA9GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_FAST; //高速GPIO_Initure.Alternate=GPIO_AF7_USART1; //复用为USART1HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9GPIO_Initure.Pin=GPIO_PIN_10; //PA10HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10HAL_NVIC_EnableIRQ(USART1_IRQn);HAL_NVIC_SetPriority(USART1_IRQn,3,3);}
}
HAL_UART_Init初始化串口后,会自动调用HAL_UART_MspInit,我们在HAL_UART_MspInit里面初始化相关GPIO、设置中断优先级以及使能中断。
-
串口接收中断优先级配置和使能,在步骤2实现了
-
使能接收中断,我们在main函数里面加入一行代码来使能接收中断,该中断对所有的UART中断都产生影响。
HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));
第一个参数usart_handler是UART_HandleTypeDef类型的句柄,第二个参数是接收数据存放的位置,第三个是位置大小。经过这四个步骤,我们就配置好了接收中断。
- 编写中断服务函数:USARTx_IRQHandler
void USART1_IRQHandler(void)
{HAL_UART_IRQHandler(&usart_handler);HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));
}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){HAL_UART_Transmit(huart,rdata,sizeof(rdata),1000);}}
HAL提供了中断处理函数HAL_UART_IRQHandler,具体流程如下:
前面四个步骤是配置接收中断的,那么什么时候产生中断呢?
我们使能接收中断函数是:
HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));
当接收的数据为sizeof(rdate)字节时,就会产生中断,进入USART1_IRQHandler函数,USART1_IRQHandler调用HAL库提供的中断处理函数HAL_UART_IRQHandler来判断中断类型,进而调用不同的处理函数。我们这里是接收中断,所以会进入UART_Receive_IT函数,把数据放到rdata,处理完毕后,UART_Receive_IT会自动调用HAL_UART_RxCpltCallback回调函数,这个函数我们是可以重写的,我们可以写出我们想要的逻辑处理功能函数,在这里调用HAL_UART_Transmit发送数据。
当接收完数据之后,系统会关闭中断,所以我们还需要打开中断,接收下一位数据,USART1_IRQHandler中调用HAL_UART_Receive_IT开启中断
具体main函数代码:
int main(void)
{//u8 buff[] = "send to rec";HAL_Init();Stm32_Clock_Init(360,25,2,8);delay_init(180);usart1_init();HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));while(1){}}