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

相关推荐
智商偏低2 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen3 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森5 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白5 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D5 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术8 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt9 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘9 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang9 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n11 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件