STM32F10X EXTI控制 LED 亮灭小教程

前言(可绕开):

       今天是大年初一,忽然发现我开学还要去参加蓝桥杯的嵌入式比赛,觉得是时候去温习一波以前的学习内容,说到STM32那还是在我大一进入西科大机器人小组的时候,那是的我是多么单纯,怀着一股向前学习的心,控制机器人什么的,那时每天都在小组待到寝室快熄灯的半小时,然后才从新区的科技园走到老区的寝室,那时路上没有人,听着歌! 那时的学习,一穷二白,就算是使用STM32库函数,有很多还是不知道,寄存器就更是如此了,虽然有教程,但是也只是片面的。这里我就想总结一些清晰例子,给以后的伙伴们学习参考!

这里我用的开发板时正点原子的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{}, 不可以省略,否则程序直接退出,不会运行中断!!

大致内容就是这样,我觉得跟多的还是要我们自己去掌握!!


欢迎大家指点,互相学习!!!
最后预祝 我校机器人小组在2018Robocn中举得佳绩!!!

这里献上一首歌 Coldplay - 酷玩Coldplay联手烟鬼-首演新单Something Just Like This:点击打开链接

猜你喜欢

转载自blog.csdn.net/qq_37389133/article/details/79330635
今日推荐