一、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