Простейший способ достижения вашей цели - это, возможно, опрос кнопки в светодиодной петле, поскольку вы уже находитесь в петле кнопки. Однако, как общее решение, оно имеет плохую сплоченность и не является расширяемым для более сложных приложений.
A общего назначения метод достижения параллелизма, не прибегая к прерываниям или многозадачному планировщику, заключается в использовании государственной машины для управления светодиодами.
Для того, Он отслеживает время и состояние, но не выполняет полную последовательность светодиодов в одном вызове.
Это реализуется ниже, однако обратите внимание, что время является сырым и реализуется с помощью функции задержки вы уже использовали - потому что я не могу сказать, что другие услуги доступны для вас. Если какая-либо обработка займет какое-то значительное время, это может повлиять на время вспышки. Он полагается на вызов светодиодного состояния машины каждые 10 мс, и он просто подсчитывает вызовы. Было бы лучше, если бы устройство состояния использовало независимый источник синхронизации (например, стандартная библиотека 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 ;
}
}
Обратите внимание, что состояние кнопка действует только светодиод, если он уже не мигает, а десять циклов полный, даже если кнопка отпущена. Если вы хотите, чтобы мигание остановилось, когда кнопка была отпущена, то start_flashing
необходимо протестировать в состоянии LED_FLASH_OFF
и, возможно, в состоянии LED_FLASH_ON
и вызвать раннее возвращение до LED IDLE
. Например:
Способ может быть легко адаптирована к управлению СИД состояния-машины на прерывание таймера.Вместо ledUpdate()
, принимая состояние кнопки в качестве параметра, это может быть передано обработчику прерываний через общую переменную. Остальная часть кода конечного автомата останется прежней. Основной цикл затем просто установил общую переменную, пока кнопка не была нажата.
Лично я бы выступать разделения и герметизирующего элемента управления пьезо, кнопка опроса, и светодиод управления таким образом, что основной цикл был похож:
int main()
{
for(;;)
{
int button_state = getButtonState() ;
upodatePiezo(button_state) ;
updateLed(button_state) ;
}
}
Это будет иметь стрингера сплоченность и рыхлую связь. Две полезные цели в разработке программного обеспечения для обеспечения ремонтопригодности и повторного использования кода.
Просто, но нарушая организацию, вы можете добавить проверки состояния кнопки внутри светодиодной функции и выключить пьезометр с задержкой в четверть секунды или меньше, если вы разделите задержку на меньшие периоды и проверите. Или для более организованного решения используйте конструкцию, ориентированную на состояние событий, и переместите время синхронизации на прерывание. Или держите светодиод как есть и переместите пьезо на прерывание смены выводов. –