【发布时间】:2015-12-15 06:02:50
【问题描述】:
我编写了一个小程序,它使用 STM32 Discovery 板上的按钮在二进制/十进制/十六进制模式下充当计数器(屏幕循环显示 3 个选项,一旦按下,每次按下最多计数 16在重置为循环选项之前)。
我遇到了一个让我有点困惑的小“错误”(阅读,不是真的)。如果我以十进制/十六进制计数,它会立即返回循环选项,但如果我以二进制计数,则需要大约 1 秒左右才能这样做(明显延迟)。
int main(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
lcd_init();
button_init();
while (1)
{
while (!counting) {
standard_output();
}
}
}
void standard_output(void) {
state = 0;
lcd_command(0x01);
delay_microsec(2000);
lcd_putstring("Binary");
for (i=0; i<40; i++) delay_microsec(50000); // keep display for 2 secs
if (counting) return; // if we have pressed the button, want to exit this loop
state = 1;
lcd_command(0x01);
delay_microsec(2000);
lcd_putstring("Decimal");
for (i=0; i<40; i++) delay_microsec(50000); // keep display for 2 secs
if (counting) return; // if we have pressed the button, want to exit this loop
state = 2;
lcd_command(0x01);
delay_microsec(2000);
lcd_putstring("Hexadecimal");
for (i=0; i<40; i++) delay_microsec(50000); // keep display for 2 secs
if (counting) return; // if we have pressed the button, want to exit this loop
}
void EXTI0_IRQHandler(void) {
if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
if (!stillBouncing) { // a button press is only registered if stillBouncing == 0
if (!counting) { // if we weren't already counting, a valid button press means we are now
counting = 1;
count = 0; // starting count from 0
}
else {
count++;
}
if (count < 16) {
lcd_command(0x01);
delay_microsec(2000);
format_int(count);
}
else {
counting = 0; // we are no longer counting if count >= 16
}
}
stillBouncing = 10; // every time a button press is registered, we set this to 10
while (stillBouncing > 0) { // and check that it hasn't been pressed for 10 consecutive 1000microsec intervals
if (!delay_millisec_or_user_pushed(1000)) {
stillBouncing--;
}
}
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
void format_int(unsigned int n) {
if (state == 0) { // if we selected binary
for (i=0;i<4;++i) {
num[i] = (n >> i) & 1; // generate array of bit values for the 4 least significant bits
}
i = 4;
while (i>0) {
i--;
lcd_putint(num[i]); // put ints from array to lcd in reverse order to display correctly
}
}
else if (state == 1) { // if we selected decimal
lcd_putint(n); // lcd_putint is enough for decimal
}
else { // if we selected hex
snprintf(hex, 4, "%x", n); // format string such that integer is represented as hex in string
lcd_putstring(hex); // put string to lcd
}
}
int delay_millisec_or_user_pushed(unsigned int n)
{
delay_microsec(n);
if (!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) {
return 0;
}
return 1;
}
我真的不知道它为什么会这样做,现在已经玩过了,但仍然无法弄清楚。这很好,但我想知道为什么它会这样做。
【问题讨论】:
-
中断处理程序内部的延迟是一个非常糟糕的主意。中断处理程序不应阻塞。不知道这是否是您的问题的原因,但它的设计真的很糟糕,所以我想我会指出它。
-
这是一个我们被告知我们需要处理开关弹跳的任务。到目前为止,我的经验是在 Java 和 Python 方面——应该如何处理?
-
可能 lcd_putint 需要很长时间来刷新显示。
format_int()在二进制情况下,它循环 4 次,然后是 Hex 和 Dec 情况的 4 倍。 -
使用定时器加中断。 @unwind 是对的:中断处理程序应尽可能短,因此永远不要阻塞忙等待(这通常是个坏主意,即使在线程模式下也是如此)。