外部中断实验

来源:互联网 发布:软件测试行业如何 编辑:程序博客网 时间:2024/06/14 00:24
外部中断实验
STM32F103 的中断控制器支持 19 个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。 STM32F103 的19 个外部中断为:
线 0~15:对应外部 IO 口的输入中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。
STM32 供 IO 口使用的中断线只有 16 个,GPIO口不止16个。 于是 STM32 就这样设计, GPIO 的管脚GPIOx.0~GPIOx.15(x=A,B,C,D,E, F,G)分别对应中断线 15~0。这样每个中断线对应了最多 7 个 IO 口,形成映射关系。以线 0 为例:它对应了 GPIOA.0、 GPIOB.0、 GPIOC.0、 GPIOD.0、
GPIOE.0、 GPIOF.0、 GPIOG.0。而中断线每次只能连接到 1 个 IO 口上,这样就需要通过配置来
决定对应的中断线配置到哪个 GPIO 上了。
决定对应的中断线配置到哪个 GPIO 上了。 下面我们看看 GPIO 跟中断线的映射关系图:

根据映射关系,就开始配置按键对应GPIO口和中断的映射了:

外部中断的步骤:
1:初始化 IO 口为输入。
2:开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。
 函数为void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
3:IO与中断线映射,中断线上中断的初始化,设置触发条件等。
 函数为:void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
 EXTI_InitTypeDef 的成员变量:
 typedef struct
 { uint32_t  EXTI_Line; (中断线的标号,取值范围为EXTI_Line0~EXTI_Line15)
EXTIMode_TypeDef  EXTI_Mode;(中断模式 EXTI_Mode_Interrupt,EXTI_Mode_Event)
EXTITrigger_TypeDef  EXTI_Trigger;触发方式EXTI_Trigger_Falling,EXTI_Trigger_Rising
FunctionalState  EXTI_LineCmd;(使能中断线)
 }EXTI_InitTypeDef
4:配置中断分组(NVIC),并使能中断。
typedef struct
{uint8_t NVIC_IRQChannel;//定义初始化的是哪个中断
uint8_t NVIC_IRQChannelPreemptionPriority;//定义这个中断的抢占优先级别
uint8_t NVIC_IRQChannelSubPriority;//定义这个中断的子优先级别。
FunctionalState NVIC_IRQChannelCmd;//该中断是否使能。
} NVIC_InitTypeDef;

5:编写中断服务函数,STM32 的 IO 口外部中断函数只有 6 个,分别为:
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler
 中断线 0-4 每个中断线对应一个中断函数, 中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中
 断线 10-15 共用中断函数 EXTI15_10_IRQHandler。
判断某个中断线上的中断是否发生:ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
清除某个中断线上的中断标志位:void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
中断服务函数格式:
void EXTI2_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生
{
中断逻辑…
EXTI_ClearITPendingBit(EXTI_Line3); //清除 LINE 上的中断标志位
}}

exit.c
  1. <pre name="code" class="csharp"><pre name="code" class="html">void EXTIX_Init(void)  
  2. {  
  3.    
  4.     EXTI_InitTypeDef EXTI_InitStructure;  
  5.     NVIC_InitTypeDef NVIC_InitStructure;  
  6.   
  7.     KEY_Init();  // 按键端口初始化 IO设置为输入 
  8.   
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟  
  10.   
  11.   //GPIOE.2 中断线以及中断初始化配置   下降沿触发  
  12.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);//GPIO端口与中断线映射起来    
  13.     EXTI_InitStructure.EXTI_Line=EXTI_Line2;    //KEY2  
  14.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;   
  15.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
  16.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;  
  17.     EXTI_Init(&EXTI_InitStructure);//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器  
  18.   
  19.  //GPIOE.3    中断线以及中断初始化配置 下降沿触发 //KEY1  
  20.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);  
  21.     EXTI_InitStructure.EXTI_Line=EXTI_Line3;  
  22.     EXTI_Init(&EXTI_InitStructure);//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器  
  23.   
  24.  //GPIOE.4    中断线以及中断初始化配置  下降沿触发   //KEY0  
  25.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);  
  26.     EXTI_InitStructure.EXTI_Line=EXTI_Line4;  
  27.     EXTI_Init(&EXTI_InitStructure);//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器  
  28.   
  29.   
  30.   //GPIOA.0   中断线以及中断初始化配置 上升沿触发 PA0  WK_UP  
  31.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);   
  32.   
  33.     EXTI_InitStructure.EXTI_Line=EXTI_Line0;  
  34.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
  35.     EXTI_Init(&EXTI_InitStructure);//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器  
  36.   
  37.   
  38.     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能按键WK_UP的外部中断通道  
  39.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,  
  40.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;    //子优先级3  
  41.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //使能外部中断通道  
  42.     NVIC_Init(&NVIC_InitStructure);   
  43.   
  44.     NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//使能按键KEY2在的外部中断通道  
  45.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2,   
  46.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;  //子优先级2  
  47.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //使能外部中断通道  
  48.     NVIC_Init(&NVIC_InitStructure);  
  49.   
  50.   
  51.     NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//使能按键KEY1在的外部中断通道  
  52.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2   
  53.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;  //子优先级1   
  54.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     //使能外部中断通道  
  55.     NVIC_Init(&NVIC_InitStructure);//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器  
  56.     NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//使能按键KEY0在的外部中断通道  
  57.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2   
  58.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;  //子优先级0   
  59.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //使能外部中断通道  
  60.     NVIC_Init(&NVIC_InitStructure);//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器     
  61. }  
  62.   
  63. //外部中断0服务程序   
  64. void EXTI0_IRQHandler(void)  
  65. {  
  66.     delay_ms(10);//消抖  
  67.     if(KEY3==1)  //WK_UP按键  
  68.     {                  
  69.         BEEP=!BEEP;   
  70.     }  
  71.     EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位    
  72. }  
  73.    
  74. //外部中断2服务程序  
  75. void EXTI2_IRQHandler(void)  
  76. {  
  77.     delay_ms(10);//消抖  
  78.     if(KEY2==0)   //按键KEY2  
  79.     {  
  80.         LED0=!LED0;  
  81.     }          
  82.     EXTI_ClearITPendingBit(EXTI_Line2);  //清除LINE2上的中断标志位    
  83. }  
  84. //外部中断3服务程序  
  85. void EXTI3_IRQHandler(void)  
  86. {  
  87.     delay_ms(10);//消抖  
  88.     if(KEY1==0)  //按键KEY1  
  89.     {                  
  90.         LED1=!LED1;  
  91.     }          
  92.     EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位    
  93. }  
  94.   
  95. void EXTI4_IRQHandler(void)  
  96. {  
  97.     delay_ms(10);//消抖  
  98.     if(KEY0==0)  //按键KEY0  
  99.     {  
  100.         LED0=!LED0;  
  101.         LED1=!LED1;   
  102.     }          
  103.     EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中断标志位    
  104. }  
exit.h
  1. #ifndef __EXTI_H
  2. #define __EXIT_H
  3. #include "sys.h"   
  4. void EXTIX_Init(void);//外部中断初始化
  5. #endif  

main.c 
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "key.h"
  4. #include "sys.h"
  5. #include "usart.h"
  6. #include "exti.h"
  7. #include "beep.h" 
  8. #include "led.h"
  9. #include "delay.h"
  10. #include "key.h"
  11. #include "sys.h"
  12. #include "usart.h"
  13. #include "exti.h"
  14. #include "beep.h"  
  15. int main(void)
  16. {
  17. delay_init(); //延时函数初始化
  18. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  19. uart_init(115200); //串口初始化为115200
  20. LED_Init(); //初始化与LED连接的硬件接口
  21. BEEP_Init(); //初始化蜂鸣器端口
  22. KEY_Init(); //初始化与按键连接的硬件接口
  23. EXTIX_Init(); //外部中断初始化
  24. LED0=0; //点亮LED0
  25. while(1)
  26. {
  27. printf("OK\r\n");
  28. delay_ms(1000);
  29. }
  30.