你的位置:首页 > 操作系统

[操作系统]外部中断实验


实验4 外部中断实验

一、实验目的

理解中断的基本概念。

掌握STM32的中断源及中断优先级。

掌握STM32外部中断技术的基本使用方法。

掌握STM32中断处理程序的编程方法。

二、实验内容

硬件设计原理图如下图1所示:LED的连接在上一节已经介绍过了,在STM32开发板上的按键KEY0是接在PE4上,KEY1是接在PE3上的,KEY2是连在PE2上,WK_UP接在PA0上。

                       

 

 

三、实验预备知识

中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口中断,但是在STM32中,中断数量大大增加,而且中断的设置也更加复杂。今天就将来探讨一下关于STM32中的中断系统。

ARM Coetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。

STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。

STM32的每个IO口都可以作为中断输入,这点很好用。要把IO口作为外部中断输入,有以下几个步骤:

1)初始化IO口为输入。

这一步设置你要作为外部中断输入的IO口的状态,可以设置为上拉/下拉输入,也可以设置为浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触发。在干扰较大的地方,就算使用了上拉/下拉,也建议使用外部上拉/下拉电阻,这样可以一定程度防止外部干扰带来的影响。

2)开启IO口复用时钟,设置IO口与中断线的映射关系。

STM32的IO口与中断线的对应关系需要配置外部中断配置寄存器EXTICR,这样我们要先开启复用时钟,然后配置IO口与中断线的对应关系。才能把外部中断与中断线连接起来。

3)开启与该IO口相对的线上中断/事件,设置触发条件。

这一步,我们要配置中断产生的条件,STM32可以配置成上升沿触发,下降沿触发,或者任意电平变化触发,但是不能配置成高电平触发和低电平触发。这里根据自己的实际情况来配置。同时要开启中断线上的中断,这里需要注意的是:如果使用外部中断,并设置该中断的EMR位的话,会引起软件仿真不能跳到中断,而硬件上是可以的。而不设置EMR,软件仿真就可以进入中断服务函数,并且硬件上也是可以的。建议不要配置EMR位。

4)配置中断分组(NVIC),并使能中断。

这一步,我们就是配置中断的分组,以及使能,对STM32的中断来说,只有配置了NVIC的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。关于NVIC的详细介绍,请参考前面章节。

5)编写中断服务函数。

这是中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断,但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃!所以在开启了某个中断后,一定要记得为该中断编写服务函数。在中断服务函数里面编写你要执行的中断后的操作。

通过以上几个步骤的设置,我们就可以正常使用外部中断了。

四、实验步骤

  1. 课下完成作业

按照教材42页-55页,新建工程,命名为“INT+你的学号”,文件夹名和工程名都为“INT+你的学号”(所需的“库函数、HARDWARE和SYSTEM文件夹”在本次实验文件夹中,自已添加即可)。工程建好后,按照教材153页,编写好main()主函数,之后编译。

  1. 2.         实验室完成

(1)           在课下完成的工程中修改代码,让串口向PC机打印你的“学号姓名”,之后编译、下载到开发板,看现象。

 

(2)           修改代码实现如下功能

  • 系统开机后,LED0,LED1闪两次,蜂鸣器响一声后停止;
  • 设置中断优先级分组为组3;
  • 按键KEY0抢占优先级为2,响应优先级为0,控制蜂鸣器,按一次,叫一声;
  • 按键KEY1抢占优先级为3,响应优先级为1,控制LED0,按一次,LED0亮一次,再按一次LED0灭;
  • 按键KEY2抢占优先级为3,响应优先级为1,控制LED1,按一次,LED1闪一次;
  • 按键WK_UP抢占优先级为2,响应优先级为1,控制LED0和LED1反转一次;
  • 问KEY0、KEY1、KEY2、WK_UP的中断优先级顺序为?

KEY0>WK_UP>KEY1=KEY2  (KEY2 KEY2看谁先按下谁优先)

  • KEY0、KEY1、KEY2、WK_UP分别对应的外部中断线为?

KEY0对于外部中断线 EXTI4

KEY1对于外部中断线 EXTI3

KEY2对于外部中断线 EXTI2

WK_UP 对于外部中断线 EXTI0

(3)           完成下列问题

假设KEY3接在PE6上,KEY4接在PE7上,输入方式配置成上拉输入,并分别控制LED0和LED1,每按一次各反转一次。

  • 按键初始化代码KEY_Init(void):

答:

 

   void  KEY_Init(void)

{

GPIO_InitTypeDef   GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);

           GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;

           GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

           GPIO_Init(GPIOE,&GPIO_InitStructure);

}

 

  • 中断初始化代码EXTIX_Init(void):

答:

           void EXTIX_Init(void)

          {

           KEY_Init();

           EXTI_InitTypeDef   EXTI_InitStructure;

           NVIC_InitTypeDef   NVIC_InitStructure;

          

           RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

          

       //GPIOE.6  KEY3

           GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource6);

                EXTI_InitStructure.EXTI_Line=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);     

 

             NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;                

  //优先级

          

                 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        

               NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;                                          

              NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                    

              NVIC_Init(&NVIC_InitStructure);    

 

  

       //GPIOE.7  KEY3

           GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource6);

                EXTI_InitStructure.EXTI_Line=EXTI_Line7;    

                         EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;      

                         EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

                         EXTI_InitStructure.EXTI_LineCmd = ENABLE;

                         EXTI_Init(&EXTI_InitStructure);     

 

             NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;                

  //优先级

                 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        

               NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;                                          

               NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                  

               NVIC_Init(&NVIC_InitStructure);   

 

  • 中断服务程序函数名为?

答:

void EXTI9_5_IRQHandler(void)

 

  • 编写中断服务程序:

答:

void EXTI9_5_IRQHandler(void)

{

   If (EXTI_GetITstatus(EXTI_Line6)==Set)

 {

delay_ms(10);

  if(KEY6==1)

   {

   LED0 =!LED1;

}

                    EXTI_ClearITPendingBit(EXTI_Line6);

}

 

If (EXTI_GetITstatus(EXTI_Line7)==Set)

 {

  delay_ms(10);

if(KEY7===1)

{

   LED1 =!LED1;

}

                   EXTI_ClearITPendingBit(EXTI_Line7);

}

}

 

  • 查看“STM32中文参考手册.pdf”第132-134页,根据“其它STM32F10XXX产品向量表”。

ü     说明STM32F10xxx有多少个中断源?

答:  73

 

ü     EXTI9_5、和EXTI15_10的中断入口地址是多少?

答: 0x0000_009C

     0x0000_00E0