前题:
前面,通过分析中断的那几个库函数实现过程,加上对各种资料的阅读,于是自己也用寄存器实现了按键输入中断,呵呵~~~
首先,外部事件/中断过程如下:
A) 配置输入线: I/O口的模式,特性等等;
B) 配置外部事件,并使能外部事件;
C) 给该外部事件所带来的中断分组,分级<优先级>;
D) 中断服务程序:当中断触发后,将跳到该程序中。
按部就班,先说说我的硬件连接:
按键1 PD^11;
按键2 PD^12;
LED1 PD^2;
LED2 PD^3;
软件实现:
按键1 按下:led 1、led2 循环亮、灭;按键2按下,led2 独亮。
直接上代码:
1:头文件exit.h
1 #ifndef _EXIT_H_ 2 #define _EXIT_H_ 3 4 #include <stm32f10x.h> 5 6 void ExitInit(void); 7 void Button_Init(void); 8 void EXTI_Configuration(void); 9 void NVIC_Configuration(void); 10 void EXTI15_10_IRQHandler(void); 11 12 #endif /*_EXIT_H_*/
2 exit.c
1 #include "exit.h" 2 3 volatile unsigned char Flag = 0; 4 5 /******************************** 6 Name: Exit_Init 7 Parameters: Null 8 Retural Value: NULL 9 Function: Initialization of interrupt 10 ********************************/ 11 12 void ExitInit(void) 13 { 14 Button_Init(); 15 EXTI_Configuration(); 16 NVIC_Configuration(); 17 } 18 19 20 /************************ 21 Name: Button_Init 22 Parameters: Null 23 Retural Value: NULL 24 Function: Initialization of interrupt 25 *************************/ 26 27 void Button_Init(void) 28 { 29 RCC->APB2ENR |= 0x01; //AFIO clock enable 30 RCC->APB2ENR |= 0x01 << 5; // I/O port D clock enable 31 32 GPIOD->CRH &= ~(0x0F << 12); //PD^11 input 33 GPIOD->CRH |= 0x02 << 14; //PD^11 up/down input 34 GPIOD->ODR |= 0x01 << 11; //up 35 GPIOD->CRH &= ~(0x0F << 16); // PD^12 input 36 GPIOD->CRH |= 0x02 << 18; //PD^12 up/down input 37 GPIOD->ODR |= 0x01 << 12; //up 38 39 AFIO->EXTICR[2] &= ~(0x0F << 12); 40 AFIO->EXTICR[2] |= 0x03 << 12; //mapping pD^11 to EXTI 11 41 AFIO->EXTICR[3] &= ~(0x0F << 0); 42 AFIO->EXTICR[3] |= 0x03 << 0; //mapping pD^12 to EXTI 12 43 } 44 45 #define ExTI_ADDR_BASE EXTI_BASE 46 #define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) 47 48 /********************************************************** 49 50 ***********************************************************/ 51 52 void EXTI_Configuration() 53 { 54 unsigned long tmp = 0; 55 // tmp = (unsigned long)ExTI_ADDR_BASE; 56 EXTI->IMR &= ~(0x03 << 11); //clear interrupt 11,12 57 EXTI->EMR &= ~(0x03 << 11); //clear exti 11,12 58 // *(volatile unsigned long*)tmp |= 0x1800; 59 EXTI->IMR |= 0x03 << 11; 60 61 EXTI->RTSR &= ~(0x03 << 11); //clear rings 62 EXTI->FTSR &= ~(0x03 << 11); //clear rings 63 // tmp = (unsigned long)ExTI_ADDR_BASE; 64 // tmp += 0x0C; //Falling addr offset 65 // *(volatile unsigned long*)tmp |= 0x1800; 66 EXTI->FTSR |= 0x03 << 11; 67 } 68 69 /****************************************************** 70 71 *******************************************************/ 72 73 74 void NVIC_Configuration(void) 75 { 76 SCB->AIRCR = AIRCR_VECTKEY_MASK | 0x500; //PriorityGroup_2 77 NVIC->IP[40] = 0x10; // PriorityGroup_2 \ EXTI15_10_IRQn 78 NVIC->ISER[1] = 0x01 << 8; 79 } 80 81 82 /******************************************************** 83 84 *********************************************************/ 85 86 87 void EXTI15_10_IRQHandler(void) 88 { 89 90 if((EXTI->PR & 0x0800) && (EXTI->IMR & 0x0800)) 91 { 92 Flag = 0; 93 EXTI->PR |= 0x0800; 94 } 95 96 if ((EXTI->PR & 0x1000) && (EXTI->IMR & 0x1000)) 97 { 98 Flag = 1; 99 EXTI->PR |= 0x1000; 100 } 101 102 }
Button_Init()函数是对PD^11,PD^12两个I/O的配置:包括模式等等;并将它们作为外部事件中断来使用<开启AFIO时钟和映射中断线>
EXTI_Configuration()外部事件配置:包括触发方式、事件/中断屏蔽的设置。
NVIC_Configuration()配置中断:包括中断分组、优先级、使能/失能。
EXTI15_10_IRQHandler()中断服务例程:如果按键1按下,则Flag = 0; 如果按键2按下,则Flag = 1;Flag为全局变量,后面其他函数可以使用它。另外注意清中断。
3 main.h
1 #ifndef _MAIN_H_ 2 #define _MAIN_H_ 3 4 #include <stm32f10x.h> 5 #include "led.h" 6 #include "exit.h" 7 #include "gpio.h" 8 9 #endif /*_MAIN_H_*/
4 main.c
1 #include "main.h" 2 extern volatile unsigned char Flag; 3 4 5 int main(void) 6 { 7 unsigned long time; 8 LedInit(); 9 ExitInit(); 10 while(1) 11 { 12 if(Flag == 0) 13 { 14 LedOnOff(); 15 16 }else 17 GPIOD->ODR |= 1 << 2; 18 } 19 }
以上过程原理在前一篇中断函数分析中已经记述了,这里不再赘述。下面附上LED和GPIO的代码配置<其实前面也有了>
1 #include "led.h" 2 /****************************************** 3 Name: LedInit 4 Parameters: Null 5 Retural Value: NULL 6 Function: Initialization of Led 7 ******************************************/ 8 void LedInit(void) 9 { 10 GPIO_Configuration(); 11 } 12 13 14 /****************************************** 15 Name: LedRecyc 16 Parameters: Null 17 Retural Value: NULL 18 Function: On and Off the Led 19 ******************************************/ 20 void LedOnOff(void) 21 { 22 volatile unsigned long delay = 2000000;; 23 GPIOD->ODR |= 1 << 2; 24 while(delay--); 25 GPIOD->ODR &= ~(1 << 2); 26 delay = 2000000;; 27 while(delay--); 28 GPIOD->ODR &= 0x0; 29 GPIOD->ODR |= 1 << 3; 30 delay = 2000000;; 31 while(delay--); 32 GPIOD->ODR &= ~(1 << 3); 33 delay = 2000000;; 34 while(delay--); 35 }
1 #include "gpio.h" 2 3 4 /****************************************** 5 Name: GPIO_Configuration 6 Parameters: Null 7 Retural Value: NULL 8 Function: Initialization of GPIO; 9 Detailed description: GPIOD.2: push-pull output,50MHz output rate, high level 10 ******************************************/ 11 void GPIO_Configuration(void) 12 { 13 RCC->APB2ENR |= 1 << 5; 14 GPIOD->CRL &= 0xFFFFF0FF; 15 GPIOD->CRL |= 0x3 << 8; 16 GPIOD->ODR &= ~(1 << 2); 17 18 GPIOD->CRL &= ~(0x0F << 12); 19 GPIOD->CRL |= 0x03 << 12; 20 GPIOD->ODR &= ~(1 << 3); 21 }
其余参考前面<stm32 中断库函数分析>