本帖最后由 gjianw217 于 2016-10-5 18:31 编辑
本帖子利用外部中断,实现与实验2类似的效果,即:通过开发板上载有的3个按钮(KEY_UP、KEY0 、KEY1),来控制板上的2个LED(DS0和DS1),其中KEY0控制DS0,按一次亮,再按一次,就灭。 KEY1控制DS1,效果同KEY0。KEY_UP则同时控制 DS0和DS1,按一次,他们的状态就翻转一次。
1 MM32F103的外部中断
外部中断和时间控制器(EXTI)管理外部和内部异步事件/中断,并生成相应的事件请求到CPU/中断控制器和到电源管理的唤醒请求。有21个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。MM32F103所有的中断事件如下图所示:
MM32F103的每个IO口都可以作为中断输入,这点类似STM32,如下图所示:
要把IO口作为外部中断输入,有以下几个步骤:
1)初始化IO口为输入。
这一步设置要作为外部中断输入的IO口的状态,可以设置为上拉/下拉输入,也可以设置为浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触发。在干扰较大的地方,就算使用了上拉/下拉,也建议使用外部上拉/下拉电阻,这样可以一定程度防止外部干扰带来的影响。
2)开启IO口复用时钟,设置IO口与中断线的映射关系。
MM32的IO口与中断线的对应关系需要配置外部中断配置寄存器EXTI_SWIER,这样我们要先开启复用时钟,然后配置IO口与中断线的对应关系。才能把外部中断与中断线连接起来。
3)开启与该IO口相对的线上中断/事件,设置触发条件。
这一步,要配置中断产生的条件,MM32可以配置成上升沿触发,下降沿触发,主要通过两个寄存器来设置:
4)配置中断分组(NVIC),并使能中断。
配置中断的分组,以及使能,对MM32的中断来说,只有配置了NVIC的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。
5)编写中断服务函数。
这是中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断,但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃。
6)另外,还有两个寄存器,必须说明,一个是中断屏蔽寄存器和软件中断事件寄存器
2 硬件电路
如下电路所示,其中KEY0接在了PC5上,KEY1接在了PC1上,WKUP接在PA0上,故外接中断分别会用到EXIT5、EXIT1和EXIT0。
3 代码实现
(1)中断初始化
void EXTI_Init(void)
{
KEY_Init();
Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发
Ex_NVIC_Config(GPIO_C,1,FTIR); //下降沿触发
Ex_NVIC_Config(GPIO_C,5,FTIR); //下降沿触发
MY_NVIC_Init(2,2,EXTI0_IRQn,2); //抢占2,子优先级2,组2
MY_NVIC_Init(2,0,EXTI1_IRQn,2); //抢占2,子优先级0,组2
MY_NVIC_Init(2,1,EXTI9_5_IRQn,2); //抢占2,子优先级1,组2
}
(2)中断函数
void EXTI0_IRQHandler(void)
{
delay_ms(10); //消抖
if(WK_UP==1) //WK_UP按键
{
LED0=!LED0;
LED1=!LED1;
}
EXTI->PR=1<<0; //消除中断标志
}
void EXTI9_5_IRQHandler(void)
{
delay_ms(10);
if(KEY0==0)
{
LED0=!LED0;
}
EXTI->PR=1<<5;
}
void EXTI1_IRQHandler(void)
{
delay_ms(10);
if(KEY1==0)
{
LED1=!LED1;
}
EXTI->PR=1<<1;
}
(3)主函数
int main(void)
{
delay_init(72);
uart_init(72,9600);
LED_Init();
EXTI_Init(); // 外部中断初始化
LED0=0; /点亮LED
while(1)
{
printf("OK\r\n"); //指示工作状态
delay_ms(1000);
}
}
4 实验效果
本帖最后由 gjianw217 于 2016-10-5 18:31 编辑
本帖子利用外部中断,实现与实验2类似的效果,即:通过开发板上载有的3个按钮(KEY_UP、KEY0 、KEY1),来控制板上的2个LED(DS0和DS1),其中KEY0控制DS0,按一次亮,再按一次,就灭。 KEY1控制DS1,效果同KEY0。KEY_UP则同时控制 DS0和DS1,按一次,他们的状态就翻转一次。
1 MM32F103的外部中断
外部中断和时间控制器(EXTI)管理外部和内部异步事件/中断,并生成相应的事件请求到CPU/中断控制器和到电源管理的唤醒请求。有21个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。MM32F103所有的中断事件如下图所示:
MM32F103的每个IO口都可以作为中断输入,这点类似STM32,如下图所示:
要把IO口作为外部中断输入,有以下几个步骤:
1)初始化IO口为输入。
这一步设置要作为外部中断输入的IO口的状态,可以设置为上拉/下拉输入,也可以设置为浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触发。在干扰较大的地方,就算使用了上拉/下拉,也建议使用外部上拉/下拉电阻,这样可以一定程度防止外部干扰带来的影响。
2)开启IO口复用时钟,设置IO口与中断线的映射关系。
MM32的IO口与中断线的对应关系需要配置外部中断配置寄存器EXTI_SWIER,这样我们要先开启复用时钟,然后配置IO口与中断线的对应关系。才能把外部中断与中断线连接起来。
3)开启与该IO口相对的线上中断/事件,设置触发条件。
这一步,要配置中断产生的条件,MM32可以配置成上升沿触发,下降沿触发,主要通过两个寄存器来设置:
4)配置中断分组(NVIC),并使能中断。
配置中断的分组,以及使能,对MM32的中断来说,只有配置了NVIC的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。
5)编写中断服务函数。
这是中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断,但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃。
6)另外,还有两个寄存器,必须说明,一个是中断屏蔽寄存器和软件中断事件寄存器
2 硬件电路
如下电路所示,其中KEY0接在了PC5上,KEY1接在了PC1上,WKUP接在PA0上,故外接中断分别会用到EXIT5、EXIT1和EXIT0。
3 代码实现
(1)中断初始化
void EXTI_Init(void)
{
KEY_Init();
Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发
Ex_NVIC_Config(GPIO_C,1,FTIR); //下降沿触发
Ex_NVIC_Config(GPIO_C,5,FTIR); //下降沿触发
MY_NVIC_Init(2,2,EXTI0_IRQn,2); //抢占2,子优先级2,组2
MY_NVIC_Init(2,0,EXTI1_IRQn,2); //抢占2,子优先级0,组2
MY_NVIC_Init(2,1,EXTI9_5_IRQn,2); //抢占2,子优先级1,组2
}
(2)中断函数
void EXTI0_IRQHandler(void)
{
delay_ms(10); //消抖
if(WK_UP==1) //WK_UP按键
{
LED0=!LED0;
LED1=!LED1;
}
EXTI->PR=1<<0; //消除中断标志
}
void EXTI9_5_IRQHandler(void)
{
delay_ms(10);
if(KEY0==0)
{
LED0=!LED0;
}
EXTI->PR=1<<5;
}
void EXTI1_IRQHandler(void)
{
delay_ms(10);
if(KEY1==0)
{
LED1=!LED1;
}
EXTI->PR=1<<1;
}
(3)主函数
int main(void)
{
delay_init(72);
uart_init(72,9600);
LED_Init();
EXTI_Init(); // 外部中断初始化
LED0=0; /点亮LED
while(1)
{
printf("OK\r\n"); //指示工作状态
delay_ms(1000);
}
}
4 实验效果