Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

btnНа первом уроке мы научились подавать напряжение ножкой микроконтроллера. Теперь нужно научиться управлять микроконтроллером без перепрошивки.

Зачем это нужно? Например, вы сделали часы на микроконтроллере, нужно выставить время, но очень не удобно каждый раз перепрошивать, когда собьется время. Намного удобнее пользоваться кнопками, например, одной менять часы, другой минуты.

Помните в первом уроке мы настраивали ножку как выход, т.е. мы могли ей подавать напряжение. Так вот, ножку можно настроить как вход. В таком режиме можно проверить есть ли на ней напряжение или нет.

Пример: создаем проект при помощи мастера проектов. Первую ногу настраиваем как выход, вторую как вход. При создании мастером проектов указываем, что ножка PB1 будет входом, на ней же включаем подтягивающий резистор, реализуется это так:

После создания проекта приведем код к такому виду:

#include <mega8.h>
#include <delay.h>
 
void main(void)
{
 
PORTB=0x02;
DDRB=0x01;
 
while (1)
{
 
if(PINB.1==0)
{
PORTB.0=1;
delay_ms(100);
PORTB.0=0;
delay_ms(100);
}
 
};
}

Как мы видим, по сравнению с первым уроком изменилась настройка порта

PORTB=0x02;
DDRB=0x01;

Подробнее о том что значат данные строки можно почитать тут

Также появилась новая строчка

if(PINB.1==0)
{}

данную строчку нужно читать так — если на ножке 1 порта В подключили землю (0 потенциал), то выполнить код в фигурных скобках. В нашем примере это код из первого урока. Если кнопка не замкнута, то ничего не делать. Промоделировать можно в Proteuse.

Вместо кнопки можно поставить датчик, реле и т.п., вместо светодиода — пищалку, получится сигнализация.

Архив с прошивкой и файлом протеуса доступен тут

Update1: Зачем нужна подтяжка порта?
У входа мк большое сопротивление, если будут течь даже микротоки вызванные помехами, то по закону Ома U=R*I это может привести к тому, что на входе появится лог 1. Чтобы не было таких проблем в AVR микроконтроллерах можно подключить ножку к плюсу питания, через подтягивающий резистор. В этом случае даже, логика работы меняется наоборот — но если появится помеха, нам это не важно, ведь у нас на входе уже логическая единица.

Почему подключение через резистор? Допустим мы подключили вход к плюсу напрямую без резистора. Когда кнопка сработает, она притянет вход к земле, поэтому на входе будет короткое замыкание между + и землей. Если же стоит резистор, то при замыкании кнопки с одной стороны он так и останется подключен к +, а со второй стороны на нем появится земля от кнопки. Через резистор потечет ток, но его величина будет не такой большой.
btn_pup

Update2: Добавлен тест, в котором вы можете проверить на сколько хорошо вы усвоили материал урока

This movie requires Flash Player 9

222 комментария: Урок 2. Управление кнопками в AVR

  • http://s009.radikal.ru/i310/1507/d5/9664ad6417b1.png
    вылетает такое окошко, при попитке нажать кнопку в режиме симуляции

  • так никакой ошибки нет

  • Супер! А как можно в условие запихать прочитанный пин порта В если он настроен на выход? Как можно выводить на третий пин порта В если он настроен на вход? Вы сначала разберитесь в настройках портов. Запомните! DDRx если 1 то вывод, если 0 то вход. Если вывод настроен на вход, то записав в порт единицу вы не выводите ее, а просто подтягиваете к питанию ножку внутренним резистором.

  • Добрый вечер, Админ, помоги пожалуйста готов отблагодарить хочу сделать устройство чтоб одной кнопкой менять режимы мигания светодиодов, я уже делал с помощью переменной увеличивал ее и по каждому значению ее менялись режимы но только чтоб с одного режима перейти на другой нужно было дождаться пока закончится первый режим. Как сделать что б переключение осуществлялось сразу?

  • через внешнее прерывание. читайте урок 13

  • Я понял что нужно это делать с выставлением флагов в обработчике прерывания но как выставить флаги?

  • Админ подскадешь

  • Админ подскажешь как с флагами действовать? Как их выставлять?

  • Хотим урок по созданию меню

  • Оникс, флаги это обыкновенные переменные, поэтому не понятен вопрос

  • Andrey, а самому попробовать не судьба? Или все за вас должны делать. Куда катится мир. Раньше пытались, а потом просили найти ошибку и направить на путь истинный. А сейчас. Хочу урок. Причем для создания меню тех уроков что здесь есть вполне достаточно. Надо лишь подумать головой и собрать все во едино.

  • Админ, я хочу сделать переключатель световых эффектов что б одной кнопкой менять режимы мигания светодиодов. Я знаю что можно создать переменную и нажатием кнопки увеличивать ее и в зависимости от ее значения соответственно менять режимы мигания,но в таком случае при переходе на следующий эффект приходится ждать окончания предыдущено эффекта и только потом происходит переход на следующий эффект. Как можно сделать что бы переход сразу происходил при нажатии на кнопку без ожидания окончания предыдущего эффекта? В устройстве 5 эффектов хочу реализовать.

  • Вешаешь кнопку на внешнее прерывание. В прерывании увеличиваешь переменную от 0 до 4 по кругу. Каждый световой эффект крутишь в цикле while(номер цикла от 0 до 4 == переменная) с условием совпадения своего номера. Как только номер эффекта поменяется, при нажатии на кнопку, эффект сразу перескочит на следующий цикл. И так по кругу. Пока давишь на кнопку, циклы перепрыгивают. Перестал давить, крутится текущий цикл.

  • Алексей, вот код
    interrupt
    {
    i++;
    }
    void main ()
    while (i ==1)
    {
    PORTB.0=1;
    delay _ms(500);
    PORTB.0=0;
    delay _ms(500);
    }
    while (i ==2)
    {
    PORTB.1=1;
    delay _ms(500);
    PORTB.1=0;
    delay _ms(500);
    }
    Не работает как должно быть, все равно когда и==2 то сначала доделается код при и ==1 а потом только перейдет на 2. То есть, если при и==1 будет гореть светодиод и когда увеличили и до 2 то сначала светодиод погАсент то есть код при и==1 дойдет до конца а потом только заработает код при и==2. Нужно что б при нажатии на кнопку сразу включался следующий эффект а не ждать окончания первого эффекта

  • Все верно, сначала выполняется тело цикла, а потом проверка при следующей итерации. Можно перед делеями написать так.

    if(i != 1) break;

    Тогда после каждого вывода значения в порт, программа будет сначала проверять на истинность i и если отличается, то принудительно выходить из цикла.

  • Алексей, заработало,большое благодарю за помощь !!! 🙂

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

  • Здрайствуйте админ. Делаю автоматику на котел.
    #include
    #include
    usigned int T, Verx=500, Nis=30;
    ISR (ADC_vect)
    { T=ADCW;
    if (T>=Verx)
    {PORTD=~(1«PD1);
    }
    if (T=<Niz)
    { PORTD=(1«PD1); }
    int main ()
    { DDRD=~(1«PD0);
    DDRB|=~((1«PB0)|(1«PB1));
    ADMUX=(1«REFS0);
    ADCSRA=(1«ADEN)|(1«ADSC)|(1«ADIE)|(1«ADPS1)|(1«ADPS0);
    sei();
    for(;;);
    // или через фунцию while(1)
    }
    .Думал двома кнопками изменять Nis i Verx, + i -. через преривания . Но может не так оформил или еще что то, не получилось. Вообще реальная такая затея ? Или надо 4 кнопки ставить?

    }

  • кнопки лучше опрашивать в основном цикле

  • что или как посоветуете, исплльзовать for(;;) или внести виполнения нажатия и запуск ADCSRA=(1«ADEN); в функции.while (1) ? в протеус не хочет работать.(

  • разницы использовать for(;;) или while(1) никакой нет, это просто бесконечный цикл, в нем нужно опрашивать кнопки и выполнять действия. Так как программа простая, то и использовать прерывания для АЦП тоже не обязательно, вы можеть запускать переодически АЦП и проверять результат там же в основном цикле.

  • Админ, накидал я для начала код что бы посмотреть работу кнопок. В общем почему то одну кнопку нажымаешь-светодиод загоряеться, вторую- не работает. уже все перепробывал, може у меня глючит протеус? хотя не похоже. От программа легкая до ужаса, а сделатьь что нужно не могу( именно с этими кнопками (
    #define F_CPU 1000000UL
    #include
    #include
    #include
    #include
    unsigned int T, Verx=300, Niz=50;

    int main(void)
    {

    DDRD=(1<<PD5)|(1<<PD6);
    DDRB&=(0<<PB0)|(0<<PB1)|(0<<PB2)|(0<<PB3);
    DDRC|=(0<<PC0);
    ADCSRA |=(1<<ADEN)|(1<<ADIE)|(1<<ADPS1)|(1<<ADPS0);
    ADMUX =(1<<REFS0);
    PORTB|=(1<<PB0)|(1<<PB3);

    while(1)
    {
    //ADCSRA|=(1<<ADSC);
    T=ADCW;

    if (!(PINB&0))
    { _delay_ms(20);
    PORTD|=(1<<PD5);

    }
    //else if {PORTD&=(0<<PD5);}

    if (!(PINB&3))
    { _delay_ms(20);
    PORTD|=(1<<PD6);
    }

    PORTD=(0<<PD6)|(0<<PD5);

    }

    }

  • Так вы сначала устанавливаете биты и тут же пытаетесь их сбросить

  • Что то я не пойму ничего. А как присвоить в авр 1 например ножке 0 PORTB? начинал с codevision, так там понятней , а в авр беда .

  • Portb |= (1< <6) вкл ножку 6

  • С новым Годом админ и всех! так я так и пишу PORTB |=(1<<6) или (1<<PB6) помоему это одно и тоже. А сбрасывать же тоже нада, вот и пишу PORTB |=(0<<6) или PORTB |=~(1<<6)

  • Админ еще раз с Новым гдом! )
    Написал я код который работает. Включения и выкл. светод. происходит в if. Преривания сделал так как автоматику хочу развивать до использования шима, передаче даных по wi-fi. Ми же люди, и не работаем со скоростью микроконтроллера, получаеться он зашол по условию, светодиод включил за тисячну секунду и вишел , а там у меня виключить светодиод. это все быстро происходит что глазу не заметно, нужно ставить задержки. Но еще один момент не ясен, почему когда нажымаю на кнопки (любые 4) светодиод которий по adc виключаеться, при отжатии включаеться обратно? может потому что я условия виполнения по преривани adc написал в обработке преривания? я не знаю как у вас происходил курс усвоения СИ и микроконтроллеров, но нужно постоянно практиковаться и перечитивать теорию снова и снова. я только спустя полгода понял как работает шим, от делаешь все как написано, работает. А сам не знаешь как настроить, как сделать регулировку шима. А оказываеться все просто, настраиваешь счетчик, присвоиваешь переменную к регистру сравнения и меняешь переменную кнопками . А за яблоки и велосипед интересно написано 😉

  • Проблема кнопок известна. Поищите в гугле про дребезг контактов

  • Админ, честтно, не пойму при чем сдесь дребезг если а) в протеусе нет дребезга как и не сгорит светодиод если подключить без резистора. и б) я сделал задержку в условии что бы убрать дребезг.

  • Может я не так написал, я для наглядности поставил светодиод на условия при нажатой кнопки он загоряеться при не нажатой off. И отдельно на условия температури, горит при такой температуре. Запускаю все норм, поставил малую температуру лаампочка включилась On . Но когда хочу увеличить или уменьшить значения, при нажатии светодиод светится , а тот что на температуре гасне,

  • Надо код смотреть так не понятно

  • Админ, ваш урок рассчитан только для программистов, или тем кто не знает язык программирования, и тока начинает осваивать язык программирования (Си) ❓

  • Уроки были написаны когда я изучал материал сам. Следовательно их в состоянии изучить человек с любым уровнем в том числе и нулевым. Я не акцентировал внимание на языке си. Его можно выучить по любой книге.

  • bili, я вот например еще не изучал си, но вполне успешно усваиваю микроконтроллер. Просто как сказать, можно написать по разному и на разных языках, но суть будет одна. Например преривания можно разрешить так SREG =(1«6). а можна и так sei (cli).

  • Админ, что то я неправильно оформил? вроде работает в реальной жизне, но например светодиод не горит при включении реле. Может сделать постоянно работу ацп?

  • там вторая if
    #define F_CPU 8000000UL

    #include

    #include
    #include

    unsigned int T, Verx=700, Niz=600;

    ISR(ADC_vect)
    {

    T = ADCW;

    if (T<=Niz)
    {
    PORTD =(1<<PD5);
    PORTC =(1<=Verx)
    {

    PORTC =(0<<PC3);
    PORTD =(0<<PD5);
    }

    }

    int main(void)

    { ADMUX |=(1<<REFS0);

    ADCSRA|=(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);

    DDRB |=(1<<0)|(1<<1)|(1<<7);
    PORTB &=(0<<0)|(0<<1);
    DDRC |=(0<<PC0)|(0<<PC5)|(0<<PC4)|(1<<PC3);

    DDRD |=(1<<PD5)|(0<<PD2)|(0<<PD3);
    PORTD &=(0<<3)|(0<<2);

    while(1)
    {
    ADCSRA |=(1<<ADSC);
    sei();
    if (PIND&(1<<PD3))
    {
    _delay_ms(20);
    Verx=Verx+25;

    }
    if (PIND&(1<<PD2))
    {
    _delay_ms(20);

    Verx=Verx-25;

    }

    if (PINC&(1<<PC5))
    {
    _delay_ms(20);
    Niz=Niz+25;
    }

    if (PINC&(1<<PC4))
    {
    _delay_ms(20);
    Niz=Niz-25;
    }

    }
    }

    или надо else писать? я в преривании два условия написал.

  • Удали админ 3 последних записи. КАкаято ерунда происходит. там там первое условия проверяет значения низа, тоесть если значения которое пришло с адс меньше заданого, то запускаем реле, а второе условия если значения которое пришло больше заданого верха, то выключить реле. но почему то светодиод не светит, и не стабильно как то работает…(

  • Еще нашол код для решения дребезга (решил сделать страховку)
    if (PIND & (1<<PD3))
    {
    _delay_ms (50);
    if (PIND &(1<<PD3))
    Verx=Verx+25;

    while (PIND & (1<<PD3)) //Все ждем отпускание кнопки
    {}
    }
    Надо сначала решить почему не включаеться светодиод с реле, что то я не так напсал в коде.

  • вы сначала проверьте заходит ли вообще программа в прерывание. в прерывании просто включите светодиод, без всяких условий

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Свежие записи
Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика