實現您的目標最簡單的方法可能是輪詢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