1

我正在使用 Atmel SAM3x8E 微控制器,并在按下按钮时尝试进行简单的 LED 切换。我正在使用上拉配置按钮来触发中断程序。

这是中断的初始化:

// Set button pins as pull-up inputs 
pio_set_input(PIOC, BUTTON_1, PIO_PULLUP);
pio_set_input(PIOC, BUTTON_2, PIO_PULLUP); 

// Configure button input pin interrupt mode and handler (Rising Edge)
pio_handler_set(PIOC, ID_PIOC, BUTTON_1,  PIO_IT_RISE_EDGE, button_press_handler);
pio_handler_set(PIOC, ID_PIOC, BUTTON_2,  PIO_IT_RISE_EDGE, button_press_handler);

// Enable the interrupts
pio_enable_interrupt(PIOC, BUTTON_1); 
pio_enable_interrupt(PIOC, BUTTON_2); 
NVIC_EnableIRQ(PIOC_IRQn); 
NVIC_EnableIRQ(PIOC_IRQn); 

然后这是中断程序:

// Interrupt handler for button press
void button_press_handler(uint32_t a, uint32_t b)
{
   pio_toggle_pin_group(PIOC, BLUE_LED4); // NOT TOGGLING LED (ONLY TURNS IT ON)
}

然而,当我运行它时,我无法让 LED 切换。它只是打开并保持打开状态。pio_toggle_pin_group 调用的函数如下:

 * \param p_pio Pointer to a PIO instance.
 * \param ul_mask Bitmask of one or more pin(s) to configure.
 */
void pio_toggle_pin_group(Pio *p_pio, uint32_t ul_mask)
{
    if (p_pio->PIO_ODSR & ul_mask) {
        /* Value to be driven on the I/O line: 0. */
        p_pio->PIO_CODR = ul_mask;
    } else {
        /* Value to be driven on the I/O line: 1. */
        p_pio->PIO_SODR = ul_mask;
    }
}

关于为什么我的 LED 没有按照我想要的方式切换的任何想法?我已经参考了Atmel ASF 文档,但我仍然无法弄清楚这一点。

4

3 回答 3

1

我无法帮助您进行实际的函数调用,但假设您使用边缘中断。据我所知,您为每个上升沿调用一个中断处理程序。但是,在第一个上升沿之后,您需要在按钮释放时触发,这将是一个下降沿,因此您需要在中断处理程序中更改沿。

但是您必须考虑到机械按钮在按下或释放时不会产生干净的单边。相反,它会反弹。对于带有上拉(或下拉)电阻器的普通瞬时接触按钮,这会导致每个事件产生多个脉冲,因此 LED 可能会多次打开/关闭并保持在任意状态,该状态可能 - 偶然 - 远“开启”大多数时候。如果可用,请使用示波器检查。

这可以通过一个电容器在硬件中规避,或者在软件中使用一个定时器来规避,该定时器在相关边沿之后具有死区时间,然后再对任何其他按钮事件做出反应。死区时间取决于按钮的类型,但典型值为 5 到 20ms,应在按钮的数据表中提及。如有疑问,请使用可接受的最高值。

于 2015-04-25T23:53:06.723 回答
0

这最终为我工作:

// Interrupt handler for button press
void button_press_handler(uint32_t a, uint32_t b)
{
    // Turn the LED's on or off
        if (pio_get(PIOC, PIO_TYPE_PIO_OUTPUT_0, BLUE_LED4))
        pio_clear(PIOC, BLUE_LED4);
        else
        pio_set(PIOC, BLUE_LED4);
}

这是用于打开 LED 的所谓“设置”功能:

void pio_set(Pio *p_pio, const uint32_t ul_mask)
{
    p_pio->PIO_SODR = ul_mask;
}
于 2015-04-26T01:04:21.957 回答
0

为避免由弹跳按钮产生的随机尖峰,请尝试使用去抖输入过滤器。在 sam3x8e 上,您可以通过将寄存器设置PIO?->PIO_DIFSR为 BUTTON_1 或 BUTTON_2 来启用此功能。

还可以通过读取清除 PIO 中断的状态寄存器PIO?->PIO_ISR。这将清除所有输入更改并允许多次输入中断。

于 2016-12-30T14:09:09.923 回答