В прошлой статье мы рассмотрели простейшую программу для МК. Сейчас же усложним задачу: Усовершенствуем программу для МК, а, следовательно, и схему, так что бы выполнялись два условия:
->Возможность отключать бегущий огонь, и включать «дежурный» светодиод.
->Добавим возможность регулировки скорости «бега» бегущего огня.
Первым делом изменим схему, включив в нее две кнопки: одна с фиксатором, вторая без. Одним контактом кнопки включены через резистор на «+», тем самым формируя на RA0 и RA1 логическую единицу. При нажатии на выключатель SW1 (SW2), RA0 (RA1) замыкается на «землю» - теперь есть логический ноль.
Займемся кодом. В конце статьи есть полный исходник на С. Сейчас же разберем полученную свистопляску символов.
Начнем с команды Delay_ms() – пауза в мс (задаются в скобках). При выполнении данной команды, МК как будто «замирает» на время паузы, тем самым не дает возможности наблюдать за портами ввода RA0 и RA1 – не сможем видеть нажат ли SW1 или SW2. Заменим данную команду циклом и вынесем его в отдельную функцию, которую можно будет вызывать при необходимости в любом месте программы:
/*------------------------------------------- Функция паузы ---------------------------------------------*/
void pause()
{
int i; // Вводим целое i для счета пробега по циклу
for (i=0;i<=t;i++) // цикл будет выполнятся пока i<t t-время паузы
{
Delay_ms(1); //Пауза в 1 мс
if (knopka1 == 1 || knopka2 == 0 ) break; //Проверка переключателей
} //если кнопки нажимались, пауза прерывается
}
/*--------------------------------------- Конец функции паузы -----------------------------------------*/
|
Далее запишем сам процесс «бегущего огня» тоже в виде функции, заменяя Delay_ms() написанной функцией pause().
/*----------------------------------------- Функция бегущего огня -------------------------------------*/ void begogon () { while(knopka1==0 && knopka2 == 1 )// Цикл будет выполятя пока SW1 вкл и { // SW2 отпущена PORTB.F4=1; //Устанавливаем на выводе RB4 1 - LED1 загорается pause(); //Пауза PORTB.F4=0; //Устанавливаем на выводе RB4 0 - LED1 гаснет PORTB.F5=1; //Устанавливаем на выводе RB4 1 - LED2 загорается pause(); //Пауза PORTB.F5=0; //Устанавливаем на выводе RB4 0 - LED2 гаснет PORTB.F6=1; //Устанавливаем на выводе RB4 1 - LED3 загорается pause(); //Пауза PORTB.F6=0; //Устанавливаем на выводе RB4 0 - LED3 гаснет PORTB.F7=1; //Устанавливаем на выводе RB4 1 - LED4 загорается pause(); //Пауза PORTB.F7=0; //Устанавливаем на выводе RB4 0 - LED4 гаснет } } /*--------------------------------------- Конец функции бегущего огня --------------------------------*/ |
Данные функции можно вызвать при необходимости в процессе исполнения программы.
C кнопкой SW1 все понятно:
/*------------------------------- Обработка кнопки SW1 ------------------------------*/
if (knopka1==0) begogon(); // Если SW1 вкл, то будет бегущий огонь else PORTB.F4=1; // Иначе (если SW1 не вкл) - дежурный LED /*------------------------------- Конец обработки кнопки SW1* ---------------------*/ |
В начале исполнения первой функции программы main(), переменной t присваивается максимальное значение паузы maxtime. Таким образом t = 510 мс (выбрано наугад). Если кнопка SW2 нажата, то отнимаем от текущего значения t величину в 60 мс (так же подобрана и может изменятся, как нужно). Pначение уже t =450 мс и т.д.
Выражение if (t<30) t=maxtime; необходимо, для контроля времени паузы t. Если оно будет меньше 30 мс (так же можно изменить на нужное), то переменной t присваивается значение maxtime.
Так как МК достаточно быстрый и может обработать состояние кнопки несколько раз, пока мы ее единожды нажали, значит, что операция разности может быть произведена несколько раз за одно нажатие. Что бы этого не допустить, вводится команда паузы Delay_ms(100) между последующими обработками SW2.
Ну и на последок как это работает.
Ну и на последок как это работает.
Симуляция в Proteus Professional |
Так же любые вопросы можно обсудить на форуме.