金华做网站建设公司,网站推广和优化系统,做农家乐农产品旅游的网站,广州网站百度排名推广Bug
使用标准库配置STM32F103C8T6的串口1开启接收中断和空闲中断#xff0c;通过空闲中断来判断数据发送是否结束#xff0c;收到数据后切换板载LED灯所接引脚电平#xff0c;发现LED出现三种情况#xff0c;熄灭、微亮、正常亮#xff0c;但是LED灯所接的GPIO引脚为PC13…Bug
使用标准库配置STM32F103C8T6的串口1开启接收中断和空闲中断通过空闲中断来判断数据发送是否结束收到数据后切换板载LED灯所接引脚电平发现LED出现三种情况熄灭、微亮、正常亮但是LED灯所接的GPIO引脚为PC13配置PC13时为推挽输出模式应该只有高低也就是亮灭两种情况却出现了微亮的现象具体串口代码配置如下
static void USART1_NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 6; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0;NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_Init(NVIC_InitStructure);
}void USART1_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);GPIO_InitStructure.GPIO_Pin GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, GPIO_InitStructure);USART_InitStructure.USART_BaudRate 115200;USART_InitStructure.USART_WordLength USART_WordLength_8b;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(USART1, USART_InitStructure);USART1_NVIC_Configuration();USART_ITConfig(USART1, USART_IT_RXNE | USART_IT_IDLE, ENABLE); USART_Cmd(USART1, ENABLE);
}volatile u8 USART1_BUF[200] {0};
volatile u8 USART1_BUF_LEN 0;
volatile u8 USART1_REC_FLAG 0;
void USART1_IRQHandler(void)
{static u8 res 0;if(USART_GetITStatus(USART1,USART_IT_RXNE) ! RESET){res USART_ReceiveData(USART1);if(USART1_BUF_LEN 200)USART1_BUF[USART1_BUF_LEN] res;USART_ClearITPendingBit(USART1,USART_IT_RXNE); } if(USART_GetITStatus(USART1,USART_IT_IDLE) ! RESET){LED_Trig(); //切换LED灯电平状态函数memset((void*)USART1_BUF,0,USART1_BUF_LEN);USART_ClearITPendingBit(USART1,USART_IT_IDLE); }
}LED灯所接GPIO引脚配置函数
void LED_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);GPIO_InitStructure.GPIO_Pin GPIO_Pin_13;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOC, GPIO_InitStructure);
}void LED_Trig(void)
{static u8 led 0;if(led 0){GPIO_ResetBits(GPIOC,GPIO_Pin_13);led 1;}else{ GPIO_SetBits(GPIOC,GPIO_Pin_13);led 0;}
}Reason 1
通过Debug发现空闲中断并未进去查看了串口1的配置寄存器发现空闲中断并未使能而空闲中断的使能只有一条函数 USART_ITConfig(USART1, USART_IT_RXNE | USART_IT_IDLE, ENABLE); 在仔细查看了该函数后发现不能通过与运算来同时开启两个中断使能因为该宏并不是以往像GPIO驱动一样通过每个位来控制就能直接通过与运算包含进去直接配置每个宏的值都是单独的
#define USART_IT_PE ((uint16_t)0x0028)
#define USART_IT_TXE ((uint16_t)0x0727)
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_IT_RXNE ((uint16_t)0x0525)
#define USART_IT_ORE_RX ((uint16_t)0x0325) /* In case interrupt is generated if the RXNEIE bit is set */
#define USART_IT_IDLE ((uint16_t)0x0424)
#define USART_IT_LBD ((uint16_t)0x0846)
#define USART_IT_CTS ((uint16_t)0x096A)
#define USART_IT_ERR ((uint16_t)0x0060)
#define USART_IT_ORE_ER ((uint16_t)0x0360) /* In case interrupt is generated if the EIE bit is set */
#define USART_IT_NE ((uint16_t)0x0260)
#define USART_IT_FE ((uint16_t)0x0160)Resolution 1
因此需要分开进行中断使能正确的中断使能应该是分开调用使能函数进行 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); Reason 2
第二个情况LED灯出现三种亮灭状态的异常情况明明只是配置成普通的GPIO引脚却出现微亮的情况说明程序出现了异常现象然后再网上偶然看到一个空闲中断中读取串口数据的在空闲中断中也加入了串口的接收数据读取程序就又正常了一开始以为空闲中断没有数据需要读取所以就没有调用读取函数了没想到会异常在这里具体的原因还未知怀疑是因为没有去读取数据导致中断异常同时我也发现了串口中断中必须去读取数据不管数据有用无用或者是担心保存数据的缓冲区溢出而加入了长度限制或者是其他操作标志位限制而不去读取数据都会导致这种情况所以无论什么情况都要去读取串口接收数据也就是调用USART_ReceiveData()函数。 Resolution 2
在串口中断中无论是接收中断还是空闲中断都要去读取串口数据 volatile u8 USART1_BUF[200] {0};
volatile u8 USART1_BUF_LEN 0;
volatile u8 USART1_REC_FLAG 0;
void USART1_IRQHandler(void)
{static u8 res 0;if(USART_GetITStatus(USART1,USART_IT_RXNE) ! RESET){res USART_ReceiveData(USART1);if(USART1_BUF_LEN 200)USART1_BUF[USART1_BUF_LEN] res;USART_ClearITPendingBit(USART1,USART_IT_RXNE); } if(USART_GetITStatus(USART1,USART_IT_IDLE) ! RESET){USART_ReceiveData(USART1); //一定要读LED_Trig();memset((void*)USART1_BUF,0,USART1_BUF_LEN);USART_ClearITPendingBit(USART1,USART_IT_IDLE); }
} 同时程序也验证了串口的空闲中断能够接收数据不定长的情况至于如何判断数据是否结束主要通过起始位后如果全是1说明没有数据进入那么在差不多两三个字节都是全1就会认为数据已经发送结束产生空闲中断。