实现您的目标最简单的方法可能是轮询LED环路中的按钮,因为您已经在按钮循环中。然而,作为一个通用的解决方案,它的内聚性差,不能扩展到更复杂的应用程序。
a 通用实现并发性的方法,不借助中断或多任务调度程序就是使用状态机进行LED控制。
与其调用led()
并要求它在返回之前完成整个闪存序列,状态机将简单地确定按钮是否被按下以及是否是时间更改LED状态,然后立即返回。它会记录时间和状态,但不会在一次通话中执行完整的LED指示灯序列。
这将在下面执行,但是请注意,时机是原油和使用你已经使用了延时功能实现的 - 因为我不能告诉其他的服务提供给您。如果任何处理需要很长时间,这可能会影响闪光时间。它依靠每10ms调用一次LED状态机,并且它只是对通话进行计数。如果状态机使用独立的时钟源(例如标准函数库clock()
)会更好,那么它是否被称为非周期性并不重要 - 而不是计算调用次数,它会切换状态实际时间已过。
注意使用static
变量来维护状态。 A static
在调用该函数之间保持其值。
#define TICK 10 // milliseconds
#define FLASH_ON_TICKS 25 // 250ms
#define FLASH_OFF_TICKS 25 // 250ms
#define FLASH_COUNT 10
static void ledUpdate(int start_flashing) ;
int main(void)
{
for(;;)
{
// Perform loop on each tick (10ms)
// Assumes loop processing time is not significant!
_delay_ms(TICK) ;
if (!(PINB & (1<<PB7)))
{
PORTB |= (1 << PB1); // Piezo on
ledUpdate(1) ;
}
else
{
PORTB &= ~(1 << PB1); // Piezo off
ledUpdate(0) ;
}
}
return 0 ;
}
void ledUpdate(int start_flashing)
{
static enum
{
LED_IDLE,
LED_FLASH_ON,
LED_FLASH_OFF
} led_state = LED_IDLE ;
static int led_tick = 0 ;
static int flash_count = 0 ;
switch(led_state)
{
case LED_IDLE :
{
if(start_flashing)
{
led_state = LED_FLASH_ON ;
PORTB |= (1 << PB0); //LED on
}
}
break ;
case LED_FLASH_ON :
{
led_tick++ ;
flash_count++ ;
if(led_tick >= FLASH_ON_TICKS)
{
led_state = LED_FLASH_OFF ;
led_tick = 0 ;
PORTB &= ~(1 << PB0); //LED off
}
}
break ;
case LED_FLASH_OFF :
{
if(flash_count >= FLASH_COUNT)
{
led_state = LED_IDLE ;
}
else
{
led_tick++ ;
if(led_tick >= FLASH_ON_TICKS)
{
led_state = LED_FLASH_ON ;
led_tick = 0 ;
PORTB |= (1 << PB0); //LED on
}
}
break ;
}
}
注意,按钮的状态只影响LED如果尚未闪烁,完成十个周期,即使松开按钮。如果您希望释放按钮时闪烁停止,则必须在LED_FLASH_OFF
和可能的LED_FLASH_ON
状态中测试start_flashing
,并且会导致提早返回到LED IDLE
。例如:
的方法,可以很容易地适合于在一个定时器中断运行LED状态机。可以将按钮状态作为参数而不是ledUpdate()
,这可以通过共享变量传递给中断处理程序。状态机代码的其余部分将保持不变。然后主循环会在按钮关闭时简单地设置共享变量。
个人身份证主张分离和封装所述压电控制,按钮轮询和LED控制,使得主回路看起来像:
int main()
{
for(;;)
{
int button_state = getButtonState() ;
upodatePiezo(button_state) ;
updateLed(button_state) ;
}
}
这将对桁条的凝聚力和更松散的耦合。软件设计中两个有用的目标是实现代码的可维护性和可重用性。
简单但破坏组织,您可以在led功能内添加按钮状态的检查,并在那里只用四分之一秒延迟关闭压电,或者如果您将延迟分成较小的时间段并在两者之间检查,则更少。或者为了更有组织的解决方案,使用有状态事件驱动的设计并将领先的时间移至中断。或者保持原样并将压电元件移动到引脚电平变化中断。 – 2014-10-12 14:02:36