Печать

Занятие №2. Переключение светодиода

Автор: AntonChip Опубликовано . Опубликовано в Программирование на Си

Рейтинг:   / 23
ПлохоОтлично 

Задача: Разработаем устройство управления светодиодом при помощи одной кнопки. При каждом нажатии на кнопку выход порта к которому подключен светодиод должен менять свое состояние на противоположное. Эта задача легко решается при помощи D-триггера, но все же рассмотрим как ее можно решить при помощи микроконтроллера.

Схема устройства такая же как в занятии 1. Алгоритм программы прост. Сначала настраиваем порты ввода-вывода. Проверяем состояние младшего разряда порта D(PD0) к которому подключена кнопка, а затем выполняем операцию сравнения, где PD0 проверяется на равенстве единице. Если условие выполняется программа переходит к началу цикла, если нет то выполняется еще одна операция сравнения, но уже линии PB0. Сначала оператор сравнения проверяет PB0 на равенство нулю, если результат истина(PB0=0), то разряд сбрасывается в единицу (PB0=1). Если ложно, устанавливается в ноль (PB0=0). Далее в программу вносим процедуру ожидания, без нее наш светодиод будет так часто мигать, что наш глаз не заметит этого. Основной цикл программы будет приостанавливается как только произойдет переключение светодиода и будет возобновляться как только будет отпущена кнопка.

Настраиваем порты ввода вывода как в задании 1:

DDRD = 0x00; //порт D - вход

PORTD = 0xFF; //подключаем нагрузочные резисторы

DDRB = 0xFF; //порт B - выход

PORTB = 0x00; //устанавливаем 0 на выходе

Пишем основной цикл программы. Здесь мы будем использовать условный оператор if else. Этот оператор выполняет различные операции в зависимости от некоторого условия и записывается так:

If (условие)

{набор операторов A;}

else

{набор операторов B;}

Условие это любое логическое выражение. Если результат этого выражения истина, то выполняется «набор операторов А», в противном случае выполняется «набор операторов В»

Процедура ожидания нажатия кнопки представляет собой пустой цикл while, и этот цикл будет выполняться до тех пор когда условие истинно. Условием будет равенство линии PD0 единице, т.е до тех пор пока кнопка не нажата.

while ((PIND&(1 << PD0)) == 1){}

Проверяем состояние линии PB0 следующим выражением

if ((PINB&(1 << PB0)) == 0) //если PB0 равен нулю

Переключаем состояние PB0 на противоположное

PORTB |= (1 << PB0); //устанавливаем в PB0 единицу

В противном случае оставляем в PB0 ноль

PORTB &= ~(1 << PB0); //устанавливаем в PB0 ноль

Далее снова проверяем состояние кнопки

while ((PIND&(1<< PD0)) == 0){}
//если кнопка нажата будет выполняться пустой цикл

Так же в этой программе можно решить проблему дребезга контактов. Самый простой способ внедрение в программу специальных задержек. Дребезг приводит к тому, что на соответствующем разряде порта D вместо простого перехода с единицы в ноль мы получаем серию импульсов. Чтобы избавиться от этого программе нужно перейти в режим ожидания как только она обнаружит первый нулевой уровень на входе. В режиме ожидания программа приостанавливает все свои действия и просто отрабатывает задержку. Для того чтобы ввести задержку воспользуемся стандартной библиотекой процедуры задержки util/delay.h.

Воспользуемся функцией которая реализует задержку:

_delay_ms(200); //задержка на 200 миллисекунд

Она обеспечивает задержку в любое целое количество микросекунд. Далее эту функцию просто вставляем после каждого цикла while.

Код программы будет таким:

#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRD = 0x00; // Порт D вход
PORTD = 0xFF; // Подключаем подтягивающие резисторы
DDRB = 0xFF; // Порт B выход
PORTB = 0x00; // Лог. 0 на выходе
while(1)
{
while ((PIND&(1 << PD0)) == 1){} // Ждем пока на выводе PDO лог. 1
_delay_ms(200); // Задержка 200мс
if ((PINB&(1 << PB0)) == 0) // Если на выводе PB0 лог. 0
{
PORTB |= (1 << PB0); // Лог. 1 на выводе PB0
}
else
{
PORTB &= ~(1 << PB0); // Лог. 0 на выводе PB0
}
while ((PIND&(1 << PD0)) == 0){} // Ждем пока на выводе PDO лог. 0
_delay_ms(200); // Задержка 200мс
}
} 

В статье были использованы материалы из книги Белова А.В. "Самоучитель разработчика устройств на AVR"

Комментарии  

+3 #81 AntonChip 17.07.2014 06:11
Попробуй написать так
Код:
while (PIND&(1 << PD1)) {}
Сообщить модератору
+3 #82 Scroodge 26.07.2014 15:15
Антон, спасибо за уроки, реально помогают чайникам, вроде меня. Такой вопрос- при нажатии на кнопку светодиод моргает с одной частотой, при каждом последующем нажатии кнопки частота морганий увеличивается, а при последнем нажатии выключается. Как реализовать это в АВР студии? Спасибо!
Сообщить модератору
+2 #83 AlexVenture 03.06.2015 21:29
не понятно изначальное равенство PD0 нулю в этом условии:

Код:((PIND&(1 << PD0)) == 1)

насколько я узнал из даташита есть 3 регистра отвечающие за каждый порт:
1. DDRxn - регистр направления;
2. PORTxn - регистр данных;
3. PINxn - регистр состояния.

Так вот, не понятно, что такое PD0, PB0?
это ячейки какого-то регистра?
если ячейки регистра PORTxn, то почему мы считаем, что PD0 равен 0? (ведь записали вначале Код:PORTD = 0xFF;)
Сообщить модератору
0 #84 AntonChip 03.06.2015 21:48
Перед while(1) обычно предварительно настраиваются регистры микроконтроллер а. Этой записью
DDRD = 0x00; // Порт D Настраиваем на вход
PORTD = 0xFF; // Подключаем подтягивающие резисторы к выводам порта D
В бесконечном цикле, настройки регистров могут много раз меняться
Сообщить модератору
0 #85 ПАВЛИК 03.09.2015 23:24
ПРИВЕТ ВСЕМ!!! РЕБЯТА ПОМОГИТЕ СТАРОМУ ЧАЙНИКУ Я СТАРЫЙ РАДИОЛЮБИТЕЛЬ И ЭЛЕКТРОНШИК НА ПЕНСИИ РЕШИЛ ВЗЯТЬСЯ ЗА СТАРОЕ РЕМЕСЛО. Я выписал из КИТАЯ программаторы. Один СН341а другой АТМЕГА 8 ТЕПЕРЬ надо найти программы для них. посаветуйте какой из них лутче и легче и какую программу вы пасаветуетhttp: //radioparty.ru /components/com _jcomments/imag es/smilies//lol .gifе? Спасибо!!! НЕ СМЕЙТЕСЬ СИЛЬНО ЗА МОИ ОШИБКИ :lol:
Сообщить модератору
0 #86 AntonChip 04.09.2015 20:03
Программаторами такими не пользовался, думаю что программы прошивальщики должны идти в комплекте. Сами же программы пишу в avrstudio 4 или 6, другими пользуюсь редко.
Сообщить модератору
0 #87 SANYA 11.11.2015 21:15
А на CV уроки есть? А то как то не понятные все выражения которые вы не раскрываете. Например:
if ((PINB&(1
Сообщить модератору
0 #88 Alex_och 07.12.2015 17:30
Здравствуйте. Решил себе сделать триггер или одновибратор (ждущий мультивибратор) такого плана:
-нажал на кнопку - светодиод моргнул 1 раз, даже если кнопка продолжает быть нажата;
-отпустил кнопку - ни чего не происходит.
А у меня получается, что при нажатой кнопке постоянно моргает светодиод, а нужно чтоб один раз.
Код: / ТРИГГЕР /

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

int main(void)
{
DDRB = 0b00001111;
PORTB = 0b00010000;
while (1) {
if ((PINB&(1 << PB4)) == 0)
{
PORTB |= _BV(PB3);
_delay_ms(100);
PORTB &= ~_BV(PB3);
_delay_ms(100);
} } }

Правда это для Attiny13.
Понимаю, что можно сделать через прерывания, но может можно и без них?
Сообщить модератору

Рекомендуем посмотреть