主要遇到的问题: 1)按下按键之后多次触发中断,导致LED灯多次亮灭 原因:野火指南者开发板上的按键有并联电容,可以完成消抖,但是普中这款开发板上面并没有并联电容,导致按下按键之后又纹波,多次触发中断, 解决办法:用延时函数进行松手检测
移植步骤: 1)新建配置LED灯,指定为端口C的第五个引脚,代码如下
/** * @brief 初始化控制LED的IO * @param 无 * @retval 无 */ void LED_GPIO_Config(void) { /*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; /*开启LED相关的GPIO外设时钟*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5; /*设置引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*设置引脚速率为50MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化GPIO*/ GPIO_Init(GPIOC, &GPIO_InitStructure); }第二步:配置NVIC,代码如下:
/** * @brief 配置嵌套向量中断控制器NVIC * @param 无 * @retval 无 */ void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 配置NVIC为优先级组1 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* 配置中断源:按键K3 */ NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //EXTI Line4 Interrupt /* 配置抢占优先级 */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 配置子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断通道 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }第三步:配置IO为EXTI中断口,并且设置中断优先级,连线 代码如下:
/** * @brief 配置 IO为EXTI中断口,并设置中断优先级 * @param 无 * @retval 无 */ void EXTI_Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; /*开启按键GPIO口的时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE); /* 配置 NVIC 中断*/ NVIC_Configuration(); /*--------------------------KEY3配置-----------------------------*/ /* 选择按键用到的GPIO */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; /* 配置为浮空输入 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOE, &GPIO_InitStructure); /* 选择EXTI的信号源 */ GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4); EXTI_InitStructure.EXTI_Line = EXTI_Line4; /* EXTI为中断模式 */ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* 上升沿中断 */ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; /* 使能中断 */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }第四步:在stm32f10x_it.c中写中断处理函数,因为.s文件已经设置好了中断向量,所以在stm32f10x_it.c中写的中断处理函数,遇到中断时会自动调用,中断处理函数如下:
/** * @brief This function handles EXTI4_IRQHandler interrupt request. * @param None * @retval None */ void EXTI4_IRQHandler(void) { //确保是否产生了EXTI Line中断 if(EXTI_GetITStatus(EXTI_Line4) != RESET) { delay(5000); if(EXTI_GetITStatus(EXTI_Line4) != RESET) { // LED5 取反 GPIO_WriteBit(GPIOC,GPIO_Pin_4,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_4)))); GPIO_WriteBit(GPIOC,GPIO_Pin_5,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_5)))); //清除中断标志位 EXTI_ClearITPendingBit(EXTI_Line4); } } }随便写了个延时函数,如下:
//简单的延时函数 void delay(u16 num) { u16 i,j; for(i=0;i<num;i++) for(j=0;j<0x800;j++); }但是最稳妥的办法是调用SYSTICK ,写一个精确的延时函数,这样就不会导致纹波多次触发中断了