您的位置 首页 技术

调试 ARM STM32 外部中止 遇到的一个问题

问题背景:STM32f103zet6的PB9和PE0脚分别外接一个按键,希望通过这两个按键可以产生外部中断,点亮该按键对应的LED。使用EXTI[9:5]通道…

问题布景: STM32f103zet6的PB9和PE0脚别离外接一个按键,期望通过这两个按键能够发生外部中止,点亮该按键对应的LED。运用EXTI[9:5]通道。

首要装备RCC:
void RCC_Configuration() {     ErrorStatus HSEStartUpStatus;     RCC_DeInit(); //将外设RCC寄存器设为缺省值     RCC_HSEConfig(RCC_HSE_ON); //使能HSE     HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等候HSE安排妥当     if(HSEStartUpStatus == SUCCESS) //判别HSE是否起振成功     {                                          RCC_HCLKConfig(RCC_SYSCLK_Div1);  //设置AHB时钟(HCLK) = 体系时钟         RCC_PCLK2Config(RCC_HCLK_Div2);  //设置高速APB2时钟(PCLK2)= 体系时钟          RCC_PCLK1Config(RCC_HCLK_Div2);  //设置低速APB1时钟(PCLK1)= 体系时钟/2           /*****确保在将PLL切换时钟源之前使能Flash预取缓存*****/         FLASH_SetLatency(FLASH_Latency_2); //设置等候时刻 = 2个周期         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能预取指缓存                             /*                     这儿刺进设置需求舱位的外设的时钟,比方                     RCC_ADCCLKConfig(RCC_PCLK2_Div4); //设置ADC时钟=PCLK/4 =9MHz                     */          //设置PLL的输入时钟 = HSE时钟频率;倍频系数 = PLL输入时钟×9         RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);          RCC_PLLCmd(ENABLE); //使能PLL          //查看指定的RCC标志位(PLL安排妥当位)设置与否,若为否, 则等候         while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)         {/*NULL*/ }          RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //设置体系时钟(SYSCLK)为PLL          //0x00:HSI作为体系时钟; 0x04:HSE作为体系时钟;0x08:PLL作为体系时钟         while(RCC_GetSYSCLKSource() != 0x08) //等候直到PLL作为体系时钟源         {/*NULL*/ }           }            /*****这儿依据详细需求舱位相应的时钟*****/           // PB9: WORK PE0: ALARM           RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);           RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //舱位功用复用I/O时钟            }

然后装备GPIO:
void GPIO_Configuration(void) //设置GPIO {           GPIO_InitTypeDef GPIO_InitStructure;                      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        GPIO_Init(GPIOB, &GPIO_InitStructure);                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        GPIO_Init(GPIOE, &GPIO_InitStructure);                      }
再然后装备NVIC
void NVIC_Configuration(void) {           NVIC_InitTypeDef NVIC_InitStructure; //界说中止参数结构体变量 #ifdef  VECT_TAB_RAM             NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);//设置向量表的方位和偏移(0x20000000)  #else             NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//设置向量表的方位和偏移(0x20000000)    #endif            NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //挑选运用优先级分组第0组                     /*使能EXTI[9:5]通道,0级先占优先级,0级次占优先级*/     NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&NVIC_InitStructure);      } 
最终装备EXTI:
void EXTI_Configuration(void) //装备外部中止/事情控制器 {     EXTI_InitTypeDef EXTI_InitStructure;      GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5|GPIO_PinSource6);           EXTI_InitStructure.EXTI_Line = EXTI_Line5|EXTI_Line6;     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;     EXTI_InitStructure.EXTI_LineCmd = ENABLE;     EXTI_Init(&EXTI_InitStructure);  } 
main函数如下:
int main(void) {      RCC_Configuration();      GPIO_Configuration();      NVIC_Configuration();      EXTI_Configuration();              while (1)   { } } 
中止服务函数如下:
void EXTI9_5_IRQHandler(void) {      if (EXTI_GetITStatus(EXTI_Line5) != RESET)      {           if(led_bit3)           {                GPIO_SetBits(GPIOB,GPIO_Pin_9);                led_bit3=0;           }           else           {                GPIO_ResetBits(GPIOB,GPIO_Pin_9);                led_bit3=1;           }                EXTI_ClearFlag(EXTI_Line5);      }            if(EXTI_GetITStatus(EXTI_Line6) != RESET)      {           if(led_bit1)           {                GPIO_SetBits(GPIOE,GPIO_Pin_0);                led_bit1=0;           }           else           {                GPIO_ResetBits(GPIOE,GPIO_Pin_0);                led_bit1=1;           }           EXTI_ClearFlag(EXTI_Line6);      } }
问题描绘:1. 按两个按键中的随意一个,都没反响,原因是没进入中止服务函数。
2. 只运用其间一个按键发生中止,屏蔽另一个按键,成果正常,LED能够被点亮。
也就是说,只开其间一个按键中止是能够的,一起翻开两个按键中止,则不可。
问题处理:通过必定时刻的纠结与手足无措,为何一个就能够,两个一起就不能够。看到EXTI_Configuration()中:

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5|GPIO_PinSource6);  EXTI_InitStructure.EXTI_Line = EXTI_Line5|EXTI_Line6;
干脆不运用那个或,每个都独自装备一下。于是乎:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);  EXTI_InitStructure.EXTI_Line = EXTI_Line5; EXTI_InitStructure.EXTI_Line = EXTI_Line6;
仍是不可,通过若干次的组合测验:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);  EXTI_InitStructure.EXTI_Line = EXTI_Line6; EXTI_InitStructure.EXTI_Line = EXTI_Line5;  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);  EXTI_InitStructure.EXTI_Line = EXTI_Line5; EXTI_InitStructure.EXTI_Line = EXTI_Line6;  ...  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);  EXTI_InitStructure.EXTI_Line = EXTI_Line5|EXTI_Line6; 

发现只拆开GPIO_EXTILineConfig()中的或,即可。
问题剖析:就这样,问题被瞎猫碰到死耗子地处理了。可是仍是得找找为何这样能够。
找到GPIO_EXTILineConfig()函数的界说:
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) {   uint32_t tmp = 0x00;   /* Check the parameters */   assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));   assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));      tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));   AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;   AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03))); }
咱们两种情况下的不同就在于GPIO_EXTILineConfig()函数的第二个参数。所以首要剖析assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); 再找到IS_GPIO_PIN_SOURCE():
#define IS_GPIO_PIN_SOURCE(PINSOURCE) (((PINSOURCE) == GPIO_PinSource0) ||                                         ((PINSOURCE) == GPIO_PinSource1) ||                                         ((PINSOURCE) == GPIO_PinSource2) ||                                         ((PINSOURCE) == GPIO_PinSource3) ||                                         ((PINSOURCE) == GPIO_PinSource4) ||                                         ((PINSOURCE) == GPIO_PinSource5) ||                                         ((PINSOURCE) == GPIO_PinSource6) ||                                         ((PINSOURCE) == GPIO_PinSource7) ||                                         ((PINSOURCE) == GPIO_PinSource8) ||                                         ((PINSOURCE) == GPIO_PinSource9) ||                                         ((PINSOURCE) == GPIO_PinSource10) ||                                         ((PINSOURCE) == GPIO_PinSource11) ||                                         ((PINSOURCE) == GPIO_PinSource12) ||                                         ((PINSOURCE) == GPIO_PinSource13) ||                                         ((PINSOURCE) == GPIO_PinSource14) ||                                         ((PINSOURCE) == GPIO_PinSource15))

其间:

#define GPIO_PinSource0            ((uint8_t)0x00) #define GPIO_PinSource1            ((uint8_t)0x01) #define GPIO_PinSource2            ((uint8_t)0x02) #define GPIO_PinSource3            ((uint8_t)0x03) #define GPIO_PinSource4            ((uint8_t)0x04) #define GPIO_PinSource5            ((uint8_t)0x05) #define GPIO_PinSource6            ((uint8_t)0x06) #define GPIO_PinSource7            ((uint8_t)0x07) #define GPIO_PinSource8            ((uint8_t)0x08) #define GPIO_PinSource9            ((uint8_t)0x09) #define GPIO_PinSource10           ((uint8_t)0x0A) #define GPIO_PinSource11           ((uint8_t)0x0B) #define GPIO_PinSource12           ((uint8_t)0x0C) #define GPIO_PinSource13           ((uint8_t)0x0D) #define GPIO_PinSource14           ((uint8_t)0x0E) #define GPIO_PinSource15           ((uint8_t)0x0F)

这样,全部就明亮了。
GPIO_PinSource5|GPIO_PinSource6 等价于0x05|0x06,即0x07。而这个当然与咱们要用的两个按键无关。
总结:GPIO_EXTILineConfig()的第二参数只能是GPIO_PinSource0~15中的一个,若要需求装备多个,只能独自装备,不能运用”或”。这种写法可能是受EXTI_InitStructure.EXTI_Line = EXTI_Line5|EXTI_Line6;这种写法的影响。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/jishu/263906.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部