需求:用两个按键控制两个LED灯循环点亮,要按键2的按键中断能够中断按键1的按键中断。
我的想法是两个按键控制进入中断程序,在各自的中断程序中写入5秒的循环点亮灯(循环用的滴答定时器)。把按键2的优先级设置高于按键1。
现象:初始化是两个灯都灭的状态,按键1按了之后就一直亮不闪,按键2按了也是。但过一会之后两个灯都灭了。
灯的引脚是PB0和PB5,按键引脚是PA0和PC13。
delay.c#include "delay.h"
static u8 fac_us = 0;
static u16 fac_ms = 0;
void delay_init(){
//((SysTick_Type*)(0xE000E010))->CTRL &= ~(1<<2); //系统时钟的8分频
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us = SystemCoreClock / 8000000;
fac_ms = (u16)fac_us*1000;
}
void delay_ms(u16 nms){
u32 temp;
SysTick->LOAD = nms*fac_ms;//重装数值
SysTick->VAL = 0x00; //清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //启动计数器
do{
temp = SysTick->CTRL; //查询状态
}while((temp&0x01) && !(temp&(1<<16)));
SysTick->CTRL &= ~(1<<0); //关闭计数器
SysTick->VAL = 0x00; //清空计数器
}
exti_key.c#include "exti_key.h"
#include "misc.h"
void EXTI_Key_Init(void)
{
//初始化按键PA0、PC13的引脚为浮空输入,开启时钟复用功能,并使能
GPIO_InitTypeDef GPIO_InitStructure_PA;
GPIO_InitTypeDef GPIO_InitStructure_PC;
//开启PA0、PC13的时钟,并开启复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);
//设置PA0、PC13引脚为下拉输入,速度可以不用配置
GPIO_InitStructure_PA.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure_PC.GPIO_Pin = GPIO_Pin_13;
//配置输入引脚功能为下拉输入
GPIO_InitStructure_PA.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure_PC.GPIO_Mode = GPIO_Mode_IPD;
//使能PA、PC端口
GPIO_Init(GPIOA,&GPIO_InitStructure_PA);
GPIO_Init(GPIOC,&GPIO_InitStructure_PC);
//初始化NVIC,
NVIC_InitTypeDef NVIC_InitStructure;
//选择中断优先级分组2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
//初始化EXTI
EXTI_InitTypeDef EXTI_InitStructure;
//清空中断标志
EXTI_ClearITPendingBit(EXTI_Line0);
EXTI_ClearITPendingBit(EXTI_Line13);
//设置中断线工作模式
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
//设置GPIO相应的PA0引脚和中断线连接起来
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_Init(&EXTI_InitStructure);
//设置GPIO相应的PC13引脚和中断线连接起来
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource13);
EXTI_InitStructure.EXTI_Line = EXTI_Line13;
EXTI_Init(&EXTI_InitStructure);
}
main.c#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "exti_key.h"
void flicker(u8 n, GPIO_TypeDef * GPIO, uint16_t GPIO_Pin){
u8 i;
for(i=0; i<n; i++){
GPIO_WriteBit(GPIO,GPIO_Pin,(BitAction)((1-GPIO_ReadOutputDataBit(GPIO,GPIO_Pin))));
delay_ms(500);
GPIO_WriteBit(GPIO,GPIO_Pin,(BitAction)((1-GPIO_ReadOutputDataBit(GPIO,GPIO_Pin))));
delay_ms(500);
}
}
int main(void)
{
LED_Init();
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOB,GPIO_Pin_0);
EXTI_Key_Init();
while(1)
{
}
}
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
flicker(5, GPIOB, GPIO_Pin_5);
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line13) != RESET)
{
flicker(5, GPIOB, GPIO_Pin_0);
EXTI_ClearITPendingBit(EXTI_Line13);
}
}
|