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

相关推荐
析木不会编程18 分钟前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉4 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名6775 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普5 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣5 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室5 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费5 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
qq_397562317 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
艺术家天选8 小时前
STM32点亮LED灯
stm32·单片机·嵌入式硬件
向阳逐梦8 小时前
基于STM32F4单片机实现ROS机器人主板
stm32·单片机·机器人