stm32f103——外部中断和事件——检测按键按下点灯

中断与事件的区别

我们先来看中断/事件控制器的内部

注意:对某个通道的上升沿和下降沿检测,通过配置上升/下降沿选择寄存器来进行检测哪一种沿。但是,只能在上升沿和下降沿两者中二选一来进行检测。

中断/事件寄存器:选择最后输出的是中断还是事件。

如果选择的是事件寄存器:

路径如图所示:

        选择事件寄存器后,路径如图中红色箭头所示,我们由此可以知道事件路径最终输出的是脉冲信号。所以,事件的最终产物是指定频率的脉冲信号。可以输出脉冲信号给外设,使外设做出相应操作。

如果选择的是中断寄存器:

路径如图所示:

         选择中断寄存器后,路径如图中红色箭头所示,我们由此可以知道中断路径到达的是中断控制器NVIC,然后触发中断,MCU执行中断服务函数。

所以,中断与事件的区别:

        中断,是检测到外部上升或者下降沿,触发中断,进入中断服务函数。

        事件,是检测到外部上升或者下降沿,最终产生的是指定频率的脉冲信号    

外部中断/事件的线路映像

 

         由图可知,一共有19个输出,每一组GPIOx通过选择器,选择该GPIO组中的一个I/O口作为EXTI的外部中断/事件源

库函数:

一共19条外部中断线,选其中一个作为外部中断/事件。

 选择EXTI最后产生的是中断还是事件

 选择上升沿触发还是下降沿触发。

标志位:

         如果指定的线路检测到上升沿/下降沿,那么该标志位置SET。注意:它只检测上升沿/下降沿,至于后面发没发生中断它没有办法检测到。

 清除标志位

 如果指定的线路发生了 中断/事件,那么该标志位位置SET。它就可以检测到中断/事件是否发生。

  清除标志位。

         配置中断优先级。

         

上述库函数,可以实现将哪个引脚作为外部中断/事件源。

         我们现在用一个按键按下来模拟下降沿作为外部触发。实际上,要产生真正的上升沿/下降沿,需要用信号发生器来产生真正的上升沿/下降沿。

编程步骤:

外部中断-----EXTI
    按键模拟外部中断,编程步骤:

//注意:GPIO的时钟与EXTI的时钟是绑在一起的,所以只需要打开GPIO的时钟,EXTI的时钟就会自动被打开了(但是有些单片机需要单独打开,就看手册有没有单独打开EXTI时钟的参数就可以知道GPIO的时钟与EXTI的时钟是不是绑在一起的)
        1,打开时钟----GPIOA,EXTI,AFIO       
        2,初始化GPIO
            ----GPIO_Pin_0
            ----上拉输入(当没有下降沿时,输入检测到的是高电平)
        3,初始化EXTI
            ----外部中断线路0
            ----模式---中断模式
            ----触发方式---下降沿
            ----使能
        4,配置中断源---将GPIOA0作为外部线路0的中断源
        5,配置中断优先级----NVIC初始化
            ----中断通道号----stm32f10x.h中找
            ----主优先级
            ----次优先级
            ----使能 
        6,编写中断服务函数
        void EXTI0_IRQHandler(void)
        {
            if(SET==EXTI_GetITStatus( EXTI_Line0)){
                EXTI_ClearITPendingBit(EXTI_Line0);
                ledflag=~ledflag;
            }
        }

编写程序:

void EXTI0_Config(void)
{
     GPIO_InitTypeDef  GPIO_InitStruct;
     EXTI_InitTypeDef  EXTI_InitStruct;
     NVIC_InitTypeDef  NVIC_InitStruct;
  

    // 1,打开时钟----GPIOA,EXTI,AFIO
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

    // 2,初始化GPIO
    GPIO_InitStruct.GPIO_Pin   =GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Mode  =GPIO_Mode_IPU;
    GPIO_Init(GPIOA,&GPIO_InitStruct);

    // 3,初始化EXTI
    EXTI_InitStruct.EXTI_Line  =EXTI_Line0;
    EXTI_InitStruct.EXTI_LineCmd  =ENABLE;
    EXTI_InitStruct.EXTI_Mode     =EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger  =EXTI_Trigger_Falling;
    EXTI_Init(&EXTI_InitStruct);

    // 4,配置中断源---将GPIOA0作为外部线路0的中断源
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

    // 5,配置中断优先级----NVIC初始化
    NVIC_InitStruct.NVIC_IRQChannel   =EXTI0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority       =1;
    NVIC_Init(&NVIC_InitStruct);
    
}

外部中断通道号:

中断服务函数:

按一下按键,EXTI就会检测到下降沿,那么 ledflag=~ledflag;

void EXTI0_IRQHandler(void)
{
    if(SET==EXTI_GetITStatus( EXTI_Line0)){
        EXTI_ClearITPendingBit(EXTI_Line0);
        ledflag=~ledflag;
    }
}

//功能:按一下按键,此时main中小灯进行亮/灭替换

uint8_t ledflag=0;

int main(void)
{
    LED_Config();
    RCC_ConfigTo72M();//将系统时钟配置成72MHZ 
    Systick_Config(72);

    EXTI0_Config();
    // 4,如果是程序的第一个中断,需要设置优先级分钟
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    
    while(1){

        if(0==ledflag){
            LED_CTRL(LEDR,LED_OPEN);        //开灯
        }else{
            LED_CTRL(LEDR,LED_CLOSE);       //关灯
        }

    }
}

        注意:用外部中断去检测按键是否按下,依然会存在按键抖动导致产生多个下降沿,多次触发外部中断的问题。所以我们需要在中断中加延时,进行按键消抖处理。但是,外部中断触发是会叠加的,上一次的中断触发没有执行完,那么这一次的中断就会等它执行完后立马再执行。而且中断中最好不要使用延时,如果使用了较长的延时(ms级),又恰好main中需要输出PWM波,那么由于进入中断执行时间过长,会导致main中的PWM波无法正常输出。

我们可以使用硬件消抖的方法。

硬件消抖:

        方法一:RS触发器为常用的硬件去抖。下图中两个“与非”门构成一个RS触发器。当按键未按下时(开关位于A),输出为0;当键按下时,输出为1。此时即使用按键的机械性能,使按键因弹性抖动而产生瞬时断开(抖动跳开B),只要按键不返回原始状态A,双稳态电路的状态不改变,输出保持为0,不会产生抖动的波形。也就是说,即使B点的电压波形是抖动的,但经双稳态电路之后,其输出为正规的矩形波。

​​​​​​​

1.当R端无效(1),S端有效时(0),则Q=1,Q非=0,触发器置1。

2.当R端有效(0)、S端无效时(1),则Q=0,Q非=1,触发器置0。

3.当RS端均无效时(0),触发器状态保持不变。

4.当RS端均有效时(1),触发器状态不确定。

        

        方法二:就是在按键上并联一个电容,如下图所示,利用电容的充放电特性来对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。

STM32F103是一款常用的单片机芯片,它具有丰富的外设资源,包括GPIO(通用输入输出)引脚。在STM32F103中,可以通过配置GPIO引脚为中断模式来实现按键检测。通过中断方式检测按键的状态可以提高效率,避免了轮询方式的资源浪费。 在使用STM32F103进行按键检测时,可以按照以下步骤进行操作: 1. 配置GPIO引脚:使用GPIO初始化函数将按键引脚配置为输入模式。 2. 设置外部中断(EXTI):通过配置外部中断触发方式(上升沿、下降沿、上下都触发)来确定按键触发的条件。 3. 设置中断优先级(NVIC):通过设置中断优先级来确定中断的响应顺序。 4. 编写中断服务函数:在中断服务函数中编写按键触发后的处理逻辑。 具体的代码实现可以参考引用\[2\]和引用\[3\]中提供的示例代码。这些示例代码演示了不同的按键检测方式,包括不带锁存和带锁存的方式。你可以根据自己的需求选择适合的方式进行按键检测。 总结来说,通过配置GPIO引脚为中断模式,结合外部中断中断服务函数的编写,可以实现在STM32F103上进行按键检测。这种方式相比轮询方式更高效,可以提高系统的响应速度。 #### 引用[.reference_title] - *1* [STM32F103入门 | 11.按键实验(下)](https://blog.csdn.net/Chen_rr/article/details/89457944)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [基于STM32F103入门2——按键点灯](https://blog.csdn.net/weixin_47457689/article/details/120196469)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值