
由此图可知:
采用HAL库,中断方式接收串口,只有当RxXferCount == 0 时,也就是调用这个函数,接收指定量的数据大小完成时,才会调用回调函数HAL_UART_RxCpltCallback()。
而且,RxXferCount == 0 后,也会使得中断退出,此时需要从新设置 HAL_UART_Receive_IT() 开启中断。
这里还需要注意下面两个函数的区别,HAL_UART_Receive_IT()HAL_UART_Receive()
分别为为非阻塞模式下接受数据,和阻塞模式下接受数据。
- void uart_init()
- {
- UART_HandleTypeDef usart1_handler;
- //UART 初始化设置
- 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
- }
无需解释,只是 UART 的初始配置。
- void HAL_UART_MspInit(UART_HandleTypeDef *huart)
- {
- //GPIO端口设置
- 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_FAST; //高速
- 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_SetPriority(USART1_IRQn,3,3); //设置中断优先级
- HAL_NVIC_EnableIRQ(USART1_IRQn); //使能中断
- }
- }
上一段代码最后一行 HAL_UART_Init() 会自动调用这个端口初始化函数。因为 UART1 依赖于PA9 和 PA10 所以需要初始化这两个 GPIO 的配置,在最后两行中,为UART1 设置了中断优先级并使能。
void USART1_IRQHandler (void) 函数是串口1的中断响应函数,当串口1 发生了相应的中断后,就会跳到该函数执行。
- void USART1_IRQHandler(void){
- HAL_UART_IRQHandler(&usart1_handler);
- HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata)); //开启中断
- }
值得注意的是,每次相应中断后,就会关闭之后的相应。
需要调用 HAL_UART_Receive_IT() 从新注册这个相应中断。
当 huart->RxXferCount 等于0时,HAL 就会帮我们调用 HAL_UART_RxCpltCallback 此函数才是真正的实现逻辑的地方。在下列函数中,会在读缓存区中取一个字符,并且通过串口回传给电脑。
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
- u8 rec;
- if(huart->Instance == USART1){
- rec = *((huart->pRxBuffPtr)-1);
- HAL_UART_Transmit(&usart1_handler,&rec,1,1000);
- }
- }
- #include "sys.h"
- #include "delay.h"
-
- //初始化IO 串口1
- //bound:波特率
- UART_HandleTypeDef usart1_handler;
- u8 rdata[1];
-
- void uart_init()
- {
- //UART 初始化设置
- 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
- }
-
- void HAL_UART_MspInit(UART_HandleTypeDef *huart)
- {
- //GPIO端口设置
- 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_FAST; //高速
- 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_SetPriority(USART1_IRQn,3,3); //设置中断优先级
- HAL_NVIC_EnableIRQ(USART1_IRQn); //使能中断
- }
- }
-
- void USART1_IRQHandler(void){
- HAL_UART_IRQHandler(&usart1_handler);
- HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata)); //开启中断
- }
-
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ //huart->RxXferCount 等于0 也就是读满rdata就执行这个回调函数
- u8 rec;
- if(huart->Instance == USART1){
- rec = *((huart->pRxBuffPtr)-1);
- HAL_UART_Transmit(&usart1_handler,&rec,1,1000);
- }
- }
-
-
- int main(void)
- {
- HAL_Init(); //初始化HAL库
- Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
- delay_init(180);
-
- uart_init();
-
-
- HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata)); //开启中断
-
- while(1){ //必须卡在死循环中,程序执行完毕就不能相应中断了
- delay_ms(3000);
- }
- }
-
