void USART1_IRQHandler(void) //´®¿Ú1ÖжϷþÎñ³ÌÐò { u8 Res; #if SYSTEM_SUPPORT_OS //Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS. OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ) { Res =USART_ReceiveData(USART1); //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý if((USART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É { if(USART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d { if(Res!=0x0a)USART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼ else USART_RX_STA|=0x8000; //½ÓÊÕÍê³ÉÁË } else //»¹Ã»ÊÕµ½0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ } } } }
这段代码是 USART1 中断的处理函数。当收到 USART1 的 RXNE(接收寄存器非空)中断信号时,会执行以下操作:
- 通过 USART_ReceiveData 函数获取接收到的数据。
- 检查 USART_RX_STA 的最高位(第 15 位),如果为 0 表示接收未完成。
- 如果 USART_RX_STA 的第 14 位为 1,表示已经接收到了 0x0d(回车符)。
- 如果接收到的数据不是 0x0a(换行符),则将 USART_RX_STA 置为 0,表示接收错误。
- 如果接收到的数据是 0x0a(换行符),则将 USART_RX_STA 的最高位(第 15 位)置为 1,表示接收完成。
- 如果 USART_RX_STA 的第 14 位为 0,表示还未接收到 0x0d(回车符):
- 如果接收到的数据是 0x0d(回车符),则将 USART_RX_STA 的第 14 位置为 1。
- 否则,将接收到的数据存入 USART_RX_BUF 缓冲区中,并将 USART_RX_STA 加一。
- 如果 USART_RX_STA 大于等于 USART_REC_LEN-1,则表示接收数据溢出,将 USART_RX_STA 置为 0,重新开始接收。
解释一下void USART1_IRQHandler(void) //´®¿Ú1ÖжϷþÎñ³ÌÐò { u8 Res; #if SYSTEM_SUPPORT_OS //Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS. OSIntEnter(); #endif if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ) { Res =USART_ReceiveData(USART1); //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý if((USART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É { if(USART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d { if(Res!=0x0a)USART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼ else USART_RX_STA|=0x8000; //½ÓÊÕÍê³ÉÁË } else //»¹Ã»ÊÕµ½0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ } } } } #if SYSTEM_SUPPORT_OS //Èç¹ûSYSTEM_SUPPORT_OSΪÕ棬ÔòÐèÒªÖ§³ÖOS. OSIntExit(); #endif } #endif
这是一个 USART1_IRQHandler() 函数的定义,用于处理 USART1 的中断事件。下面是对该函数的解释:
首先,在支持操作系统的情况下,调用 OSIntEnter() 函数进入中断。
然后,通过 USART_GetITStatus() 函数检查是否发生了 USART1 接收中断(USART_IT_RXNE)。如果接收到了数据,则执行下面的代码块。
通过 USART_ReceiveData() 函数读取接收到的数据,并将结果保存在变量 Res 中。
接下来,检查 USART_RX_STA 寄存器的值,用于判断当前是否已经接收到完整的数据。
如果 USART_RX_STA 的最高位(bit 15)为 0,表示接收未完成。
a. 如果 USART_RX_STA 的第 14 位(bit 14)为 1,表示已经接收到了换行符(0x0a)。这意味着之前已经接收到了回车符(0x0d),因此将 USART_RX_STA 置为 0,重新开始接收新的数据。
b. 如果 USART_RX_STA 的第 14 位(bit 14)为 0,表示还未接收到换行符。
如果接收到的数据为回车符(0x0d),则将 USART_RX_STA 的第 14 位(bit 14)置为 1,表示已接收到回车符。
否则,将接收到的数据存储在 USART_RX_BUF 缓冲区中,并将 USART_RX_STA 自增 1。如果接收到的数据超过了 USART_REC_LEN 的长度限制,则将 USART_RX_STA 置为 0,重新开始接收。
如果不支持操作系统,则直接退出中断。
以上就是该函数的主要逻辑。它用于处理 USART1 接收中断,并将接收到的数据存储在缓冲区中供后续处理使用。
unsigned char Usart3RecBuf[USART3_RXBUFF_SIZE];//´®¿Ú2½ÓÊÕÊý¾Ý»º´æ unsigned int Rx3Counter = 0; //´®¿Ú2ÊÕµ½Êý¾Ý±ê־λ bool rev_start = 0; //½ÓÊÕ¿ªÊ¼±êÖ¾ bool rev_stop = 0; //½ÓÊÕÍ£Ö¹±êÖ¾ void USART3_Config(void){ //GPIO¶Ë¿ÚÉèÖà GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //ʹÄÜUSART3£¬GPIOAʱÖÓ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //ʹÄÜGPIOBʱÖÓ //USART3_TX GPIOB.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯GPIOB.10 //USART3_RX GPIOB.11³õʼ»¯ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//¸¡¿ÕÊäÈë GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯GPIOB.11 //Usart3 NVIC ÅäÖà NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//ÇÀÕ¼ÓÅÏȼ¶ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; //×ÓÓÅÏȼ¶4 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀʹÄÜ NVIC_Init(&NVIC_InitStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷ //USART ³õʼ»¯ÉèÖà USART_InitStructure.USART_BaudRate = 9600;//´®¿Ú²¨ÌØÂÊ USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×Ö³¤Îª8λÊý¾Ý¸ñʽ USART_InitStructure.USART_StopBits = USART_StopBits_1;//Ò»¸öֹͣλ USART_InitStructure.USART_Parity = USART_Parity_No;//ÎÞÆæżУÑéλ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//ÎÞÓ²¼þÊý¾ÝÁ÷¿ØÖÆ USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //ÊÕ·¢Ä£Ê½ USART_Init(USART3, &USART_InitStructure); //³õʼ»¯´®¿Ú3 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//¿ªÆô´®¿Ú½ÓÊÜÖÐ¶Ï USART_Cmd(USART3, ENABLE); 把这些代码改为hal库可以使用的
用户提供的参考代码里有启用USART3和GPIOD的时钟,配置GPIO引脚为复用功能,设置UART参数,以及中断配置。在HAL库中,这些步骤大致相同,但具体函数和结构体可能不同。比如,时钟使现在HAL库中通常使用__HAL_RCC_USART3_CLK_ENABLE(),而GPIO的初始化可能需要使用HAL_GPIO_Init,并且需要配置GPIO的复用功能。
接下来,用户需要设置UART参数,比如波特率、字长、停止位等。在HAL库中,这需要通过UART_HandleTypeDef结构体来配置,例如huart3.Instance = USART3; 然后设置Init结构体的各个字段,如BaudRate、WordLength、StopBits等,最后调用HAL_UART_Init()函数。
中断配置部分,标准库可能直接操作NVIC寄存器,而HAL库提供了HAL_NVIC_SetPriority()和HAL_NVIC_EnableIRQ()函数。需要确保中断服务函数的名字正确,比如USART3_IRQHandler,并且在其中调用HAL_UART_IRQHandler()。另外,使能接收中断可能需要使用__HAL_UART_ENABLE_IT()宏,或者在初始化后调用HAL_UART_Receive_IT()函数来启动接收中断。
还要注意HAL库中的MSP初始化回调函数,比如HAL_UART_MspInit(),这个函数会被HAL_UART_Init()自动调用,用于配置GPIO和时钟等底层设置。因此用户需要在这个函数里放置GPIO和时钟的初始化代码。
可能存在的一些问题需要检查,例如是否正确处理了中断优先级,是否启用了全局中断,以及是否正确实现了接收中断的回调函数。HAL库使用回调机制,用户需要重写HAL_UART_RxCpltCallback()函数来处理接收完成事件。
最后,生成相关问题时要涵盖常见的转换问题、HAL库的使用技巧、调试方法以及DMA应用等,帮助用户全面理解迁移过程中的关键点。### 步骤说明:使用HAL库实现USART3初始化及中断配置
1. GPIO设置与时钟使能
在HAL库中,时钟使能和GPIO配置通常在HAL_UART_MspInit
回调函数中实现(该函数由HAL_UART_Init
自动调用):
void HAL_UART_MspInit(UART_HandleTypeDef *huart) {
if (huart->Instance == USART3) {
// 1. 使能时钟
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
// 2. 配置GPIO引脚
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; // 假设PD8=TX, PD9=RX
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出(TX)
GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉模式(RX)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3; // 复用功能选择USART3
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
}
2. UART参数配置
定义UART句柄并配置参数:
UART_HandleTypeDef huart3;
void USART3_Init(void) {
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200; // 波特率
huart3.Init.WordLength = UART_WORDLENGTH_8B; // 8位数据位
huart3.Init.StopBits = UART_STOPBITS_1; // 1位停止位
huart3.Init.Parity = UART_PARITY_NONE; // 无校验
huart3.Init.Mode = UART_MODE_TX_RX; // 收发模式
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 无硬件流控
HAL_UART_Init(&huart3); // 调用初始化
}
3. 中断优先级配置与使能
在HAL_UART_MspInit
中添加中断配置:
// 接续步骤1的代码
// 3. 配置中断优先级
HAL_NVIC_SetPriority(USART3_IRQn, 1, 0); // 设置优先级组
HAL_NVIC_EnableIRQ(USART3_IRQn); // 使能USART3中断
// 4. 使能接收中断
__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE); // 使能接收非空中断
4. 中断服务函数实现
在stm32xxxx_it.c
中添加中断处理:
void USART3_IRQHandler(void) {
HAL_UART_IRQHandler(&huart3); // HAL库统一中断处理函数
}
// 接收完成回调函数(需用户实现)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART3) {
// 处理接收到的数据
uint8_t data = huart->Instance->DR; // 读取数据寄存器
// ...用户自定义逻辑...
// 重新使能接收中断
HAL_UART_Receive_IT(&huart3, &data, 1);
}
}
关键差异说明
- 结构体封装:HAL库通过
UART_HandleTypeDef
集中管理配置参数[^2]; - 中断处理流程:HAL库要求使用统一中断入口
HAL_UART_IRQHandler
,并通过回调函数HAL_UART_RxCpltCallback
处理具体逻辑; - GPIO复用功能:需明确指定
Alternate
字段选择正确的复用功能编号(如GPIO_AF7_USART3
)。
相关推荐













