我正在使用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 documentation进行了审核,但我仍然无法弄清楚这一点。
答案 0 :(得分:1)
我无法帮助您进行实际的函数调用,但假设您使用了边缘中断。据我所知,你为每个上升沿调用一个中断处理程序。但是,在第一个上升沿之后,您需要触发按钮释放,这将是下降沿,因此您需要更改中断处理程序中的边缘。
但是你必须考虑到按下或释放机械按钮时不会产生干净的单边。它确实反弹了。对于带有上拉(或下拉)电阻的正常瞬时接触按钮,这会导致每个事件产生多个脉冲,因此LED可能会多次打开/关闭并保持任意状态,这可能 - 偶然 - " on& #34;大多数时候。如果可用,请使用示波器进行检查。
这可以通过电容器或硬件使用定时器在相关边沿之后具有死区时间,然后对任何其他按钮事件作出反应来规避。 死区时间取决于按钮的类型,但典型值为5到20ms,应在按钮的数据表中提及。如有疑问,请使用可接受的最高值。
答案 1 :(得分: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);
}
这里是被叫" set"有助于打开LED的功能:
void pio_set(Pio *p_pio, const uint32_t ul_mask)
{
p_pio->PIO_SODR = ul_mask;
}
答案 2 :(得分:0)
为避免弹跳按钮产生的随机尖峰,请尝试使用去抖动输入过滤器。在sam3x8e上,您可以通过在您的情况下将寄存器PIO?->PIO_DIFSR
设置为BUTTON_1或BUTTON_2来启用此功能。
同时通过读取PIO?->PIO_ISR
清除PIO中断的状态寄存器。这将清除所有输入更改并允许多次输入中断。