stm32 使用 rt-thread 引脚PIN中断设置边沿触发问题

一、PIN中断设置

1.1 RT-Thread的PIN中断简介

RT-Thread是一个开源的嵌入式实时操作系统,它提供了丰富的设备驱动和组件,方便开发者进行嵌入式系统开发。其中,PIN设备是RT-Thread对通用输入输出(GPIO)的抽象和封装,使得开发者可以更方便地管理GPIO,包括配置引脚模式、读写引脚状态、处理外部中断等。

PIN中断是RT-Thread中处理外部事件的一种重要机制。当GPIO引脚上的电平发生变化时,可以触发中断,进而执行相应的中断回调函数。这种机制对于按键检测、传感器信号采集等场景非常有用。

中断触发模式可配置,一般有下图所示 5 种中断触发模式:

输入输出模式可控制:

  • 输出模式一般包括:推挽、开漏、上拉、下拉。引脚为输出模式时,可以通过配置引脚输出的电平状态为高电平或低电平来控制连接的外围设备。
  • 输入模式一般包括:浮空、上拉、下拉、模拟。引脚为输入模式时,可以读取引脚的电平状态,即高电平或低电平。

1.2 RT-Thread的PIN中断使用步骤

1.获取GPIO编号

使用RT-Thread提供的GET_PIN宏来获取引脚编号。例如,获取编号为PA0的引脚,可以使用#define LED0_PIN GET_PIN(A, 0)。

2.设置引脚模式

根据硬件原理图和实际需求,将引脚设置为合适的模式,如输入模式或输出模式。在中断实验中,通常将引脚设置为下拉输入模式或上拉输入模式。

3.注册中断回调函数、配置中断触发模式、编写中断服务程序

3.1 使用rt_pin_attach_irq()函数将中断回调函数与引脚关联起来。这个回调函数会在引脚检测到指定电平变化时被触发。

3.2 根据实际的硬件需求,设置中断的触发模式,如上升沿触发、下降沿触发、边沿触发(上升沿和下降沿都触发)、高电平触发或低电平触发。

3.3 在中断回调函数中编写具体的处理逻辑,如切换LED灯的状态、记录按键事件等。

4.使能引脚中断

使用rt_pin_irq_enable()函数来使能之前注册的引脚中断。如果不使能中断,即使中断事件发生了,也不会触发回调函数。

RT-Thread 提供的 PIN 设备管理接口来访问 GPIO,相关接口如下所示:

二、问题描述

stm32单片机 使用引脚的外部中断,设置为下拉输入,当使能外中断时,引脚被拉高。

/* 按键1引脚为输入模式 */
rt_pin_mode(PIN_NUM, PIN_MODE_INPUT_PULLDOWN);// PB1为低

/*绑定中断,下降沿模式,回调函数名为beep on */
rt_pin_attach_irq(PIN_NUM, PIN_IRQ_MODE_FALLING, beep_On,RT NULL);//PB1为低

/*使能外中断 */
rt_pin_irq_enable(PIN_NUM, PIN_IRQ_ENABLE);//PB1被拉高 为什么会被拉高?

查看代码,发现配置上升沿触发时,又对引脚模式进行了配置,配置为了上拉。

static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
                                     rt_uint8_t enabled)
{
    const struct pin_irq_map *irqmap;
    rt_base_t level;
    rt_int32_t irqindex = -1;
    GPIO_InitTypeDef GPIO_InitStruct;

    if (PIN_PORT(pin) >= PIN_STPORT_MAX)
    {
        return -RT_ENOSYS;
    }

    if (enabled == PIN_IRQ_ENABLE)
    {
        irqindex = bit2bitno(PIN_STPIN(pin));
        if (irqindex < 0 || irqindex >= (rt_int32_t)ITEM_NUM(pin_irq_map))
        {
            return -RT_ENOSYS;
        }

        level = rt_hw_interrupt_disable();

        if (pin_irq_hdr_tab[irqindex].pin == -1)
        {
            rt_hw_interrupt_enable(level);
            return -RT_ENOSYS;
        }

        irqmap = &pin_irq_map[irqindex];

        /* Configure GPIO_InitStructure */
        GPIO_InitStruct.Pin = PIN_STPIN(pin);
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        switch (pin_irq_hdr_tab[irqindex].mode)
        {
        case PIN_IRQ_MODE_RISING:
            GPIO_InitStruct.Pull = GPIO_PULLDOWN;
            GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
            break;
        case PIN_IRQ_MODE_FALLING:
            GPIO_InitStruct.Pull = GPIO_PULLUP;
            GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
            break;
        case PIN_IRQ_MODE_RISING_FALLING:
            GPIO_InitStruct.Pull = GPIO_NOPULL;
            GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
            break;
        }
        HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct);

        HAL_NVIC_SetPriority(irqmap->irqno, 5, 0);
        HAL_NVIC_EnableIRQ(irqmap->irqno);
        pin_irq_enable_mask |= irqmap->pinbit;

        rt_hw_interrupt_enable(level);
    }
    else if (enabled == PIN_IRQ_DISABLE)
    {
        irqmap = get_pin_irq_map(PIN_STPIN(pin));
        if (irqmap == RT_NULL)
        {
            return -RT_ENOSYS;
        }

        level = rt_hw_interrupt_disable();

        HAL_GPIO_DeInit(PIN_STPORT(pin), PIN_STPIN(pin));

        pin_irq_enable_mask &= ~irqmap->pinbit;
#if defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)
        if ((irqmap->pinbit >= GPIO_PIN_0) && (irqmap->pinbit <= GPIO_PIN_1))
        {
            if (!(pin_irq_enable_mask & (GPIO_PIN_0 | GPIO_PIN_1)))
            {
                HAL_NVIC_DisableIRQ(irqmap->irqno);
            }
        }
        else if ((irqmap->pinbit >= GPIO_PIN_2) && (irqmap->pinbit <= GPIO_PIN_3))
        {
            if (!(pin_irq_enable_mask & (GPIO_PIN_2 | GPIO_PIN_3)))
            {
                HAL_NVIC_DisableIRQ(irqmap->irqno);
            }
        }
        else if ((irqmap->pinbit >= GPIO_PIN_4) && (irqmap->pinbit <= GPIO_PIN_15))
        {
            if (!(pin_irq_enable_mask & (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
                                         GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)))
            {
                HAL_NVIC_DisableIRQ(irqmap->irqno);
            }
        }
        else
        {
            HAL_NVIC_DisableIRQ(irqmap->irqno);
        }
#else
        if ((irqmap->pinbit >= GPIO_PIN_5) && (irqmap->pinbit <= GPIO_PIN_9))
        {
            if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9)))
            {
                HAL_NVIC_DisableIRQ(irqmap->irqno);
            }
        }
        else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15))
        {
            if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)))
            {
                HAL_NVIC_DisableIRQ(irqmap->irqno);
            }
        }
        else
        {
            HAL_NVIC_DisableIRQ(irqmap->irqno);
        }
#endif
        rt_hw_interrupt_enable(level);
    }
    else
    {
        return -RT_ENOSYS;
    }

    return RT_EOK;
}

当配置下降沿触发时,将配置的下拉引脚改为了上拉导致的。

解决办法:

根据需求自行修改此处的代码,或者使用stm32的HAL库进行操作。

参考:

https://club.rt-thread.org/ask/question/f157b3d17b168c24.html

https://club.rt-thread.org/ask/question/921e2288c7c5c7ba.html

https://club.rt-thread.org/ask/question/abff83df48655f40.html

相关推荐
网易独家音乐人Mike Zhou4 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
PegasusYu7 小时前
STM32CUBEIDE FreeRTOS操作教程(九):eventgroup事件标志组
stm32·教程·rtos·stm32cubeide·free-rtos·eventgroup·时间标志组
lantiandianzi12 小时前
基于单片机的多功能跑步机控制系统
单片机·嵌入式硬件
文弱书生65612 小时前
输出比较简介
stm32
哔哥哔特商务网12 小时前
高集成的MCU方案已成电机应用趋势?
单片机·嵌入式硬件
跟着杰哥学嵌入式12 小时前
单片机进阶硬件部分_day2_项目实践
单片机·嵌入式硬件
东芝、铠侠总代1361006839313 小时前
浅谈TLP184小型平面光耦
单片机·嵌入式硬件·物联网·平面
lantiandianzi13 小时前
基于单片机中医药柜管理系统的设计
单片机·嵌入式硬件
嵌入式知识大讲堂13 小时前
HDMI数据传输三种使用场景
单片机
黑客呀14 小时前
[系统安全]Rootkit基础
stm32·单片机·系统安全