STM32
直播中

吴湛

10年用户 842经验值
擅长:33391
私信 关注
[问答]

如何利用keil软件去实现STM32L152的中断控制呢

如何利用keil软件去实现STM32L152的中断控制呢?

怎么实现STM32L152的按键优先级屏蔽呢?

回帖(1)

李勇

2021-11-18 15:47:16
  本文主要讲解用keil软件实现中断控制,默认读者keil环境已经配好,且头文件已正确引入,如出现编译错误以及st-link下载问题,请自行百度解决。
  前面我们讲了中断控制的简单应用,下面就让我们结合键盘输入和七色灯的知识,看看怎么实现按键优先级屏蔽吧!
  功能四:按键优先级屏蔽
  具体:使用主板蓝色按键作为一个低优先级中断源,键盘阵列选择其中的一个按键作为
  高优先级中断源,当蓝色按键按下一次时,亮红灯,红灯亮 5 秒后自动灭;键盘阵列
  的一个按键按下一次时亮绿灯,绿灯亮 10 秒后灭;尝试以下操作:
  ⚫ 按下键盘阵列的按键,绿灯亮,此时再按蓝色按键,观察红灯是否亮灭
  ⚫ 按下蓝色按键,红灯亮,此时再按键盘阵列按键,观察绿灯是否亮灭
  默认大家已经完成前面的实验,头文件等引用不再赘述,这里主要修改了几个函数里的参数。
  1.GPIO初始化函数
  由于用到了键盘输入,新激活了两个管脚PB9和PC5,分别代表键盘阵列的第一行和第一列,由于本实验只用到了键盘上的一个键,因此只激活这两个就够了。
  另外由于用到了七色灯,还需要激活七色灯的三个管脚,(其实只用到了两个)这里我用的是PA5,PA6,PA7。LED注意四个管脚的连线,有一个管脚要接GND。
  行输出低电平,列上拉并读取,未按键时会一直读高电平,按键按下之后将读到低电平。
  void GPIO_Configuration(void)
  {
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB|RCC_AHBPeriph_GPIOC,ENABLE);
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_40MHz;
  GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA,&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
  GPIO_Init(GPIOA,&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;
  GPIO_Init(GPIOA,&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC,&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
  GPIO_Init(GPIOB,&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC,&GPIO_InitStructure);
  GPIO_ResetBits(GPIOC,GPIO_Pin_5);
  }
  2.NVIC初始化函数
  这里两个按键需要激活两个通道,第二行设置了优先级组别,我们给主优先级和次优先级分别分配两个bit的储存空间。给蓝色按键分配的优先级为3,给键盘第一个按键的优先级为2,故键盘优先级靠前,有抢占的权利。(由于是列在读取,故中断通道判断的是PB9的电平)
  void NVIC_Configuration(void)
  {
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x03;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;;
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  }
  3.EXTI初始化函数
  为两个按键配置外部中断参数
  void EXTI_Configuration(void)
  {
  EXTI_InitTypeDef EXTI_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC,EXTI_PinSource13);
  EXTI_InitStructure.EXTI_Line=EXTI_Line13;
  EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd=ENABLE;
  EXTI_Init(&EXTI_InitStructure);
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource9);
  EXTI_InitStructure.EXTI_Line=EXTI_Line9;
  EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd=ENABLE;
  EXTI_Init(&EXTI_InitStructure);
  }
  4.main函数
  int main(void)
  {
  GPIO_Configuration();
  EXTI_Configuration();
  NVIC_Configuration();
  while(1);
  }
  5.stm32l1xx_it.c文件里的代码
  为了方便,将控制七色灯的管脚define一下
  #define PA5 GPIOA,GPIO_Pin_5
  #define PA6 GPIOA,GPIO_Pin_6
  #define PA7 GPIOA,GPIO_Pin_7
  下面是两个中断响应函数,分别响应键盘和蓝色按键,都是SetBits一个管脚delay一段时间再ResetBits,PB9控制绿灯,PC13控制红灯。
  如果按下蓝色按键,红灯亮5秒灭,如果按下键盘第一个键,绿灯亮10秒灭。
  如果按下蓝色按键紧接着按键盘,红灯变成黄灯(红灯绿灯同时亮)10秒后绿灯灭,灯又变为红色,经过不到5秒,红灯也灭了。
  如果先按键盘紧接着按蓝色按键,绿灯不变,10秒后,自动变成红灯,5秒后红灯灭。
  更多操作请大家自行实验。
  void EXTI9_5_IRQHandler(void)
  {
  if(EXTI_GetITStatus(EXTI_Line9) != RESET)
  {
  GPIO_SetBits(PA6);
  delay(20000000);
  GPIO_ResetBits(PA6);
  EXTI_ClearITPendingBit(EXTI_Line9);
  }
  }
  void EXTI15_10_IRQHandler(void)
  {
  if(EXTI_GetITStatus(EXTI_Line13) != RESET)
  {
  GPIO_SetBits(PA5);
  delay(10000000);
  GPIO_ResetBits(PA5);
  EXTI_ClearITPendingBit(EXTI_Line13);
  }
  }
  别忘了写上次用过的delay()函数啊!
  至此,拓展实验已经全部完成,如果代码或者讲解有错误欢迎指出,大家也可以讨论自己的思路,由于鄙人时间有限,细节的疑问请大家认真思考,自力更生
举报

更多回帖

发帖
×
20
完善资料,
赚取积分