STM32 串口中断接收原理与实战详解:从配置到中断服务函数全流程解析
大家可以从下面主函数推测这是关于什么的代码,其实可以从题目中就可以看到了,没错是串口的中断接收程序,那就在底下评论区把这个代码描述出来
现在具体这个项目快要正式开始了,前面的GPIO我们简单过了一遍,接下来就要过一下串口的内容。
因为我觉得串口这节带了挺多基础的东西,比如端口复用,中断配置,中断服务函数
int main(){u8 key;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);key_Init();LED_Init();Init_USART1();while(1){if(usart1_buf.flag == 1){usart1_buf.flag = 0;if(strcmp((char*)(usart1_buf.buff),"open")){LED_R_ON;}else if(strcmp((char*)(usart1_buf.buff),"close")){LED_R_OFF;}}}}
那么接下来就将串口配置的细节都展示出来,这里我主要将串口的中断服务函数进行解释,其他不懂的,来评论区聊聊。
#include "main.h"void Init_USART1(){//RCC_InitRCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_StructInit(&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStruct.GPIO_Speed = GPIO_Medium_Speed;GPIO_Init(GPIOA, &GPIO_InitStruct);USART_InitTypeDef USART_InitStruct = {0};USART_StructInit(&USART_InitStruct);USART_InitStruct.USART_BaudRate = 115200;// USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;// USART_InitStruct.USART_Parity = USART_Parity_No;// USART_InitStruct.USART_StopBits = USART_StopBits_1;// USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStruct);NVIC_InitTypeDef NVIC_InitStruct = {0};NVIC_InitStruct.NVIC_IRQChannel =USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);USART_Cmd(USART1, ENABLE);}void SendByte(u8 a){while(!USART_GetFlagStatus(USART1,USART_FLAG_TXE))USART_SendData(USART1,a);}void SendString(u8 *str){u8 i = 0;while(*str != '\0'){USART_SendData(USART1,*str);str++;}}
在中断函数里
typedef struct usart{u8 buff[1024];u8 len;u8 flag;}Usart_ReData;#include"stm32f4xx_it.h"Usart_ReData usart1_buf ;void USART1_IRQHandler(){if(USART_GetITStatus(USART1,USART_IT_RXNE)){USART_ClearITPendingBit(USART1,USART_IT_RXNE);usart1_buf.buff[usart1_buf.len++] = USART_ReceiveData(USART1);}if(USART_GetITStatus(USART1,USART_IT_IDLE)){USART1->SR;USART1->DR;usart1_buf.buff[usart1_buf.len] = '\0';usart1_buf.len = 0;usart1_buf.flag = 1;}}
代码解释
typedef struct usart{u8 buff[1024]; // 缓冲区:用于存放接收到的一帧数据,最大 1024 字节u8 len; // 当前接收到的字节数(长度)u8 flag; // 数据接收完成标志位(1 表示接收完成)} Usart_ReData;
中断服务函数解释
void USART1_IRQHandler(){// 1. 接收非空中断(每接收一个字节触发一次)if(USART_GetITStatus(USART1, USART_IT_RXNE)){USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除中断标志位// 将接收到的一个字节存入缓冲区usart1_buf.buff[usart1_buf.len++] = USART_ReceiveData(USART1);}// 2. 空闲中断(接收一帧数据后,串口线空闲会触发)if(USART_GetITStatus(USART1, USART_IT_IDLE)){USART1->SR; // 清除 IDLE 中断标志:读 SR 和 DRUSART1->DR;// 在缓冲区尾部加 '\0' 作为字符串结束符(便于后续处理)usart1_buf.buff[usart1_buf.len] = '\0';// 接收长度归零,为下一帧做准备usart1_buf.len = 0;// 设置标志位,通知主程序有新数据usart1_buf.flag = 1;}}
