Задача: разработаем устройство которое должно обеспечивать движение огня в двух разных направлениях. Переключение направления движения будет осуществляться с помощью переключателя 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"
Комментарии
((PINC&(1 << PC0)) == 0)
условие работает наоборот
Код:
((PINC&(1 << PC0)) == 1)
Эта программа на "Си", на ассемблере нету
Спасибо, исправил
Заменить имя переменной TEMP другим... это слово уже используется в *.H -- файле.
Например так:
Код:
if ((PINC&(1 << PC0)) == 0) //проверяем нажатие кнопки
{ //сдвиг вправо
temp = 0x80; //записываем начальное значение 0b10000000
while (temp != 0) //пока temp не равно нулю
{
PORTB = 0;
PORTD = temp; // запишем temp в порт D
temp = temp >> 1; // сдвигаем разряды
_delay_ms(100); // задержка 100 мс
if(PIND&(1 << PD0)) // Если PD0 = 1
{
PORTD = 0;
temp = 0x80;
while (temp != 0) // пока temp не равно нулю
{
PORTB = temp; // запишем temp в порт D
temp = temp >> 1; // сдвигаем разряды
_delay_ms(100); // задержка 100 мс
}
}
}
}
else
{
// аналогично
}
Чтоб одним нажатием была бегущиен огни ,со вторым мигающие огни??? Мигающие не идёт что то
Изучал урок 4 бегущие огни на языке си
программа не реагирует на кнопку и виснит где ошибка,?
с уважением.
Почему в строке 13 ==0,а не ==1?
код выделяйте тегом code