Задача: разработаем устройство которое должно обеспечивать движение огня в двух разных направлениях. Переключение направления движения будет осуществляться с помощью переключателя S1. В соответствие с поставленной задачей наше устройство должно управлять восемью светодиодами HL1-HL8. Подключим восемь светодиодов к порту D микроконтроллера через токоограничительные резисторы по 220 Ом. Переключатель подключим к младшему разряду порта C.
Алгоритм программы будет такой:
1. Читаем состояние переключателя управления;
2. Если контакты разомкнуты переходим к процедуре сдвига вправо;
3. Если контакты замкнуты переходим к сдвигу влево;
4. После окончания полного цикла сдвига (8 шагов) переходим к началу алгоритма.
Алгоритм сдвига:
1. Записываем в рабочий регистр начальное значение, это будет двоичное число, у которого один из разрядов равен единице. Для сдвига вправо нам нужно число с единицей в старшем самом разряде(0b10000000). Для сдвига влево в единицу устанавливаем младший разряд(0b00000001);
2. Выводим значение рабочего регистра в порт D;
3. Вызываем подпрограмму задержки, чтобы скорость бега огней была нормальная т.е. видима человеческим глазом;
4. Сдвигаем содержимое рабочего регистра вправо(влево на один разряд);
5. Проверка конца полного цикла сдвига (8 шагов);
6. Если полный цикл сдвига не закончен переходим к пункту 2 данного алгоритма.
В этой программе мы впервые будем использовать переменную. Так как сдвигаемых битов должно быть 8 используем тип переменной – unsigned char. Переменная такого типа имеет длину в 1 байт. Второй однобайтовый тип (char) в данном случае не подходит, т. к. представляет собой число со знаком, у которого старший разряд интерпретируется как знак, остальные разряды используются для хранения значений. Записывается так:
unsigned char temp; //вводим переменную temp
Настроим порты ввода-вывода:
DDRC = 0x00; //порт С на вход
PORTC |= (1 << PC0); //подключаем нагрузочный резистор к PC0
DDRD = 0xFF; //порт D на выход
PORTD = 0x00; //устанавливаем нули на выходе
Телом основного цикла является оператор сравнения (if-else), проверяющий состояние бита к которому подключен переключатель. Бит PC0 проверяется на равенстве единице. Если он равен единице то выполняется сдвиг вправо, если не равен то выполняется сдвиг влево.
while(1)
{
if ((PINC&(1 << PC0)) == 0) //проверяем нажатие кнопки
{ //сдвиг вправо
temp = 0x80; //записываем начальное значение 0b10000000
while (temp != 0)
{
PORTD = temp; //запишем temp в порт D
temp = temp >> 1; //сдвигаем разряды
_delay_ms(200); //задержка 200 мс
}
}
Для того чтобы цикл повторялся только 8 раз, используется оператор цикла while (temp!=0) , в качестве условия, при котором цикл выполняется, используется выражение temp!=0 . Выражение “!=” на языке Си означает неравно.
Для сдвига разрядов используется оператор “>>”. Результатом выражения temp >> 1 является число, полученное путем сдвига всех разрядов переменной temp на одну позицию вправо. Число 1 справа от оператора сдвига означает количество разрядов, на которое нужно сдвинуть число.
temp = temp >> 1;
Выражение означает: присвоить переменной temp значение этой же переменной сдвинутое на один разряд вправо. Можно записать и так:
temp >> = 1;
Процедура сдвига влево работает точно так же, как процедура сдвига вправо. Вот код нашей программы полностью:
/***************Занятие №4. Бегущие огни*****************/
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
unsigned char temp;
DDRC = 0x00;
PORTC |= (1 << PC0); // подключаем нагрузочный резистор к PC0
DDRD = 0xFF;
PORTD = 0x00;
while(1){
if ((PINC&(1 << PC0)) == 0) // проверяем нажатие кнопки
{
// сдвиг вправо
temp = 0x80; // записываем начальное значение 0b10000000
while (temp != 0) // пока temp не равно нулю
{
PORTD = temp; // запишем temp в порт D
temp = temp >> 1; // сдвигаем разряды
_delay_ms(100); // задержка 100 мс
}
}
else
{
//сдвиг влево
temp = 0x01; // записываем начальное значение 0b00000001
while (temp != 0) // пока temp не равно нулю
{
PORTD = temp; // запишем temp в порт D
temp = temp << 1; // сдвигаем разряды
_delay_ms(100); // задержка 100 мс
}
}
}
}
В статье были использованы материалы из книги Белова А.В. "Самоучитель разработчика устройств на AVR"
условие работает наоборот
Эта программа на "Си", на ассемблере нету
Спасибо, исправил
Заменить имя переменной TEMP другим... это слово уже используется в *.H -- файле.
Например так:
Чтоб одним нажатием была бегущиен огни ,со вторым мигающие огни??? Мигающие не идёт что то
Изучал урок 4 бегущие огни на языке си
программа не реагирует на кнопку и виснит где ошибка,?
с уважением.
Почему в строке 13 ==0,а не ==1?
код выделяйте тегом code