这里我用的开发板时正点原子的MiniSTM32,芯片型号为STM32F103RCT6. This is easy, so you can do that very easily!
***REMENBER STM32 is you! :)
我们在这里进行通俗的讲解,详细的内容,可以在以后再去看STM32手册。
这里我们先介绍中断的概念,中断举个例子就是,我现在正在吃饭,这时有人敲门,那我不得不去放下碗筷去开门,然后再回来继续吃饭。那为什么需要中断呢?因为我们肯定不想吃饭的时候,总是去看下门口有没有人,这样就占用了我吃饭的时间!这点在程序中的意义是重大的!
那么我们就想如果有很多中断怎么办呢?就像我在吃饭的时候,有人敲门,但是水又开了,这两者差不多同时出现,我到底改做什么呢?这时就有优先级的概念,谁重要,我就先去做谁!
这里我们采用开关控制LED这个例子来说明GPIO EXTI NVIC这三个内容的一些使用方法!
我们用到的LED灯接口是PA8, 我们用到的开关是PC5, 为上拉的模式
这里的例子是开关使用 EXTI 中断控制灯的亮灭(注意这里我们这里的代码是连续的):
//@Time:2018/2/16
//@author:junwencui
//@wether: sun
//@location: yunnan
void key_Config(void){
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //这里最好还是打开复用
以上是配置函数的开头,首先我们定义了结构体,然后我们就需要打开时钟,这里需要注意在KEIL中,打开时钟需要放在定义结构体的后面,不然会报错!
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //这里采用上拉输入模式
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化结构体定义
这里的模式 GPIO_Mode_IPU 是在使用上拉输入的时候使用,当然也可以使用
GPIO_Mode_IPD 下拉输入
这里的区别是你的电路硬件!
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5); //这里将EXTI映射到PC5
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
这里因为定义的为PC5所以相应的EXTI_Line5,我们简单采用中断模式,因为PC5 接的是上拉电阻,所以这里当然是电平下降的时候触发了!就使用EXTI_Trigger_Falling
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //这里指定外部中断 为EXTI5~9
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //设置抢占优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; //设置响应优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE; //使能NVIC
NVIC_Init(&NVIC_InitStructure); //初始化结构体
}
这里的外部中断,用的是EXTI_Line5, 但是stm32库函数定义了 中断线5到9 ,都用EXTI9_5_IRQn,这里其实并无大碍,因为后面的中断函数内部我们还是要进行判断的! 中断的优先级 服从的规则是: 先看抢占优先级,后看响应优先级,当抢占优先级一样时,又是同时发生,就看响应优先级。他们都是数值越小,等级越高!所以当有多个中断的时候我们需要仔细安排这些有先级。
当然我们也可以定义我们的优先级组,例子:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//抢占优先级可选0~3,响应优先级可选0~3;
这是优先级组选择范围,千万不可以超出范围!
以上就是EXTI中断配置的内容!接下来看中断函数:
static u8 led_red_flag =0; //此为标志位
void EXTI9_5_IRQHandler(void){
delay_ms(8); //消抖
if(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) && !led_red_flag){ //读取Pin_5的状态
GPIO_ResetBits(GPIOA,GPIO_Pin_8);
led_red_flag =1;
}else if(!GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) && led_red_flag){
GPIO_SetBits(GPIOA,GPIO_Pin_8);
led_red_flag =0;
}
EXTI_ClearITPendingBit(EXTI_Line5);
}
这里中断函数是固定的,我们可以在stm32f10x_it.h里面去查看,EXTI9_5_IRQHandler 从这个名字看就是中断线5~9,和我们上面的内容保持一致! 这里的消抖是常用操作,防止干扰! 在中断函数内,都会有消除中断标志位的语句, 就是EXTI_ClearITPendingBit(EXTI_Line5);
这里是至关重要的,每次都不会少!
void led_Congfig(void){
GPIO_InitTypeDef GPIO_InitStructure; //PA8
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //采用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
}
这里是配置 led 的函数,采用推挽输出,50Mhz的工作速度!
int main(){
led_Congfig();
key_Config();
while(1){
}
return 0;
}
这里是我们的主函数!注意这里的 while(1{}, 不可以省略,否则程序直接退出,不会运行中断!!!
上一篇: stm32初学之LED按键中断
下一篇:STM32实战3.定时器控制LED灯闪烁(定时器1)
推荐阅读最新更新时间:2024-03-16 16:27