8 декабря 2012 г.

AVR Бегущий огонёк на C

Сейчас начал изучать AVR микроконтроллеры ( на СИ ) и ради практики делаю гирлянду с различными функциями. Заметил что некоторые делают бегущий огонь таким образом :

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

int main()
{
        DDRB=0xFF; //Порт B как выход

        while(1)
        {
                PORTB = 0b00000001; // Зажигаем 1 светодиод
                _delay_ms(100); // Задержка
                PORTB = 0b00000010; // 2
                _delay_ms(100);
                PORTB = 0b00000100;
                _delay_ms(100);
                // И так далее
         }
}


И так по очереди зажигается каждый светодиод. Это первое что может прийти в голову, но всё же есть более "красивые" методы.

Здесь я хочу привести несколько способов последовательного включения светодиодов.

1) Который использовал я в первый раз ( не разобравшись еще с побитовым сдвигом )
int n = 1;
_delay_ms( 160 ); // Пауза между зижиганием следующего светодиода в миллисекундах
PORTB = n;
n = n * 2;
if ( n >= 128)
{
        n = 1;
}

Двочиное значение       шестнадцатеричное        десятичное
0b11111111                    0xFF                                  256
0b01010101                    0xA5                                  165

Т.к 1 = 0b00000001( 2 в 0 степени) то мы зажигаем первый светодиод.
домножаем n на 2, значит n = 2 ( 2 в 1 степени ) или 0b00000010, загорается 2 светодиод, 1 тухнет.

дальше проверка если n больше 128 делаем его снова единичкой 1.
128 = 0b100000000 то есть горит последний светодиод.
Здесь мы всё время домножаем n на 2 или по другому увеличиваем степень 2.
Тогда в двоичном коде у нас сдвигается 1 бит в сторону.
0b00000001 => 0b00000010 => 0b00000100 => 0b00001000

2) Через for
for (i=0; i <= 5; i++)
{
     PORTC = (1 << i); // so PORTC = 0,1,2,4
     delay_ms(50);
}

Здесь используется битовый сдвиг влево.
То есть, вначале задаем i значение 0. PORTC = 0b00000001 сдвинутом влево 0 раз
повтор for: PORTC = 0b00000001 сдвинутом влево 1 раз тоесть уже 0b00000010;
и т.д
Это плохо тем что программа ничего не начнёт делать пока не пройдет весь цикл for.
Значит пока не загорелись все светодиоды по очереди вы ничего не можете сделать ( помигать другим светодиодом, проверить значения других ног и т.п )

3) он похож на предыдущий, но всё же


PORTB = 0x01 << n;;
_delay_ms( speed );

n++;
if ( n >= 8 )
{
        n = 0;
}


Здесь тот же сдвиг, но теперь мы увеличиваем значение на которое нужно сдвинуть сразу после его использования, затем проверяем не привысило ли оно допустимое если нет идём дальше выполняем что нам нужно и после выполнения всей программы возвращаемся сюда и зажигаем следующий светодиод

Комментариев нет :

Отправить комментарий