Содержание
Урок 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

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

  • Привет всем!
    Возникли трудности в обработке переменной с плавающей точкой Float
    есть простая менюшка в которой надо увиличивать-уменшать переменною но по непонятным причинам условия не работают(не уменш_не увил) прошу помощи у знающих

    float VBmin;
    ////////////////////////////////////////////////////////////////////
    void show_3()
    {

    //////////////////////////////////////////////////////////
    if(PIND.6==0)
    {
    esc++;
    delay_ms(200);
    }
    //////////////////////////////////////////////////////////
    if(esc>>2)
    {
    esc=0;
    lcd_gotoxy(0,1);
    lcd_putsf(» «);
    }
    ////////////////////////////////////////////////////////////
    if(esc==1)
    {
    lcd_gotoxy(0,0);
    lcd_putsf(«>»);

    if(PIND.4==0)
    {
    VBmin++;
    delay_ms(200);
    }
    if(VBmin>30) VBmin=0;

    }
    /////////////////////////////////////////////////////////////
    if(esc==2)
    {
    lcd_gotoxy(0,0);
    lcd_putsf(» «);

    lcd_gotoxy(0,1);
    lcd_putsf(«>»);

    }

  • не понятно esc>>2 это у вас опечатка или ошибка в коде

  • Добрый день.
    Помогите подправить код что бы работал 🙁
    Уже 3 день ничего не получается (

    1 кнопкам вкл. светодиод. а другвя выключает
    При повторном нажатии например на кнопку включения.ничего не должно происходить

    #include
    #include
    unsigned char blink = 0;
    void main(void)
    {
    PORTB=0x02;
    DDRB=0x01;
    while (1)
    if (PINB.1==1)
    { blink=1; }
    if (PINB.3==1)
    { blink=0; }
    if (blink)
    {PORTB.0=1;
    }
    else { PORTB.0=0;

    }
    }

  • для такого кода ноги мк, которые идут к кнопке должны быть физически подтянуты к 0, через резистор.

  • Кстати говоря…
    Если нога порта сконфигурирована как вход и подтянута к питанию, то вместо
    if (PINB.1==0)
    годнее писать просто
    if (!PINB.1)
    По сути ничего не меняется, но компилятор под такую конструкцию отжирает меньше памяти контроллера, иногда бывает критично, особенно при low level optimization.

  • А как сделать чтобы после отпускание кнопки светодиод горел еще минуту?

  • запустить таймер

  • Как подключить несколько независимых кнопок ?

  • Владимир От чего независимы Каждую кнопку можно настроить индеведуально

  • admin а как на Attiny 13 это сделать

  • абсолютно так же

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

    void menuChislo (void)
    {
    Max=alertMax;
    Min=alertMin;
    Hig=alertHig;
    Low=alertLow;
    Out1=alertOut1;
    Out2=alertOut2;
    Out3=alertOut3;
    while(menu)
    {
    switch (editCount)
    {
    //——————OUT 1————————-
    //—————-МАКСИМАЛЬНОЕ ЧИСЛО——————-

    case 0:

    if(PINC.2==0)
    {
    while
    (PINC.2==0)
    delay_ms(40);
    Max++;
    }

    if(Max > 9)
    {
    Max = 9;
    }

    if(PINC.3==0)
    {
    while
    (PINC.3==0)
    delay_ms(40);
    Max—;
    }

    if(Max = Max)
    {
    Min =Max-1;
    }

    if(PINC.3==0)
    {
    while
    (PINC.3==0)
    delay_ms(40);
    Min—;
    }

    if(Min < 0)
    {
    Min = 0;
    }

    if(PINC.1==0)
    {
    while
    (PINC.1==0)
    delay_ms(40);
    editCount++;
    alertMin=Min;
    chislo=1;
    }

    lcd_gotoxy(2,0);
    lcd_puts("OUT1 LOW PRES");

    lcd_gotoxy(5,1);
    lcd_putchar((Min/1)%10+0x30);
    lcd_putsf(" BAR");
    chislo=1;
    break;

  • если используется форматированный вывод, то в настройках проекта нужно выбрать, sprintf features float

  • добрый день
    а можно по подробней пожалуйста

  • if(PINC.3==0)
    {
    while
    (PINC.3==0)
    delay_ms(40);
    Max++
    }
    прибавляет целое число, а для проекта, для более точного контроля, желательно прибавлять и отнимать с десятыми

  • вопрос в том чтобы сделать это Max += 0.1?

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

  • Добрый день! Подскажите как реализовать например я портом ADC PORTС.0 измеряю напряжение 0-50в через делитель подходит минус к порту постоянно, как сделать чтобы при подачи минуса на порт PORTС.0 например выполнялся код? if(PINС.0==0)
    {
    PORTB.0=1;
    delay_ms(100);
    PORTB.0=0;
    delay_ms(100);
    }
    Заранее благодарю!

  • #define OUT1 PORTB.0
    #define OUT2 PORTA.0
    #define OUT3 PORTA.1
    #define IN1 PINB.1
    #define IN2 PINB.2
    #define IN3 PINA.7
    unsigned char a, b, q=0;

    void main(void)
    {

    #pragma optsize-
    CLKPR=(1<<CLKPCE);
    CLKPR=(0<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<5&&q==0)
    {
    q=1;
    OUT1=1;
    delay_ms(1000);
    OUT1=0;
    b=0;
    }
    if(IN1==1) b++;
    if(IN1==1&&b>5&&q==1)
    {
    q=0;
    b=0;
    }

    if(IN2==0) a++;
    if(IN2==0&&a>5&&q==0)
    {
    q=1;
    OUT1=1;
    delay_ms(1000);
    OUT1=0;
    delay_ms(1000);
    OUT1=1;
    delay_ms(1000);
    OUT1=0;
    b=0;
    }
    if(IN2==1) b++;
    if(IN2==1&&b>5&&q==1)
    {
    q=0;
    b=0;
    }
    }

    }
    А как сделать, чтоб при нажатии и удержании кнопки IN1 светодиод моргнул один раз OUT1.При нажатии и кнопки IN2 светодиод моргнул два раза OUT1. Сильно не пинайте если что не так , только учусь.

  • Начало не скопировалось вот исправил.
    while(1)
    {

    if(IN1==0) a++;
    if(IN1==0&&a>5&&q==0)
    {
    q=1;
    OUT1=1;
    delay_ms(1000);
    OUT1=0;
    b=0;
    }
    if(IN1==1) b++;
    if(IN1==1&&b>5&&q==1)
    {
    q=0;
    b=0;
    }

    if(IN2==0) a++;
    if(IN2==0&&a>5&&q==0)
    {
    q=1;
    OUT1=1;
    delay_ms(1000);
    OUT1=0;
    delay_ms(1000);
    OUT1=1;
    delay_ms(1000);
    OUT1=0;
    b=0;
    }
    if(IN2==1) b++;
    if(IN2==1&&b>5&&q==1)
    {
    q=0;
    b=0;
    }
    }

    }

  • Здравствуйте нашел ваш ответ на вопрос подобный моему но не разобрал его
    OldState=NewState;
    {
    TCNT1H=0×00;
    TCNT1L=0×00;
    }
    мне тоже необходимо что бы i увеличивалось на 1 при каждом нажатии независимо от длительности импульса нажатия

  • всем привет подскажите как обрабатовать нажатие 8ми кнопок по очереди чтобы включались светодиоды например кнопка 1 вкл порт 2 и 3, кнопка 2 вкл порт 1 -3-4 ,кнопка 3 вкл порт 2и4
    и тогда когда например 1-3-4 порты активны то остальные отключены и.т.п
    пробовал через условие if две кнопки работают прекрасно как только добавляю остальные кнопки то прога работает не так как должно например какой нибудь из выходов может мигать или быть в 1 хотя должен быть в 0

  • А вообще лучше немного по другому подключать кнопку.Кроме резистора ёмкость нужно подключать.Пускай автор меня подправит.

  • с тюнькой 2313 Штотто не ппАлучается….
    в чём может быть причина?

  • помогите !
    как будет выглядеть код
    1 вариант : нажал — включилось, ещё раз нажал — выключилось
    2 вариант : 1 кнопкой жмём переключает в одну сторону, жмём вторую — переключает в другую?

  • Доброго времени суток! Уважаемый Админ подскажите пожалуйста. К примеру в какой не будь регистр записано 0b00001100 как из этого байта вытащить только один нужный бит, к примеру 3 тик ? с регистров портов получилось а как с других регистров или с переменной?
    Спасибо за помощь!

  • Так же как и с другим числом. Сдвигаем число вправо, на нужное количество бит. Далее делаем логическое И с единицей, чтобы отсечь остальные разряды. Полученное число проверяем на ноль или единицу.

  • Спасибо за внимание к моему вопросу, а можно маленький пример? Нужно и переменной I которая содержит число 0b01001101 вытащить все биты по порядку и засунуть в 8 других переменных a ,s,d,f,g,h,f,z,x. Очень буду признателен за помощь, Спасибо. У вас отличный материал для обучения.

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

    #include
    #include
    unsigned char i,data;

    // Timer2 overflow interrupt service routine
    interrupt [TIM2_OVF] void timer2_ovf_isr(void)
    {
    // Reinitialize Timer2 value
    TCNT2=0x5F;
    // Place your code here

    ADCW=data;

    PORTB.0=0;
    i=ADCW.7;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.0=0;
    i=ADCW.6;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.0=0;
    i=ADCW.5;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.0=0;
    i=ADCW.4;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.0=0;
    i=ADCW.3;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.0=0;
    i=ADCW.2;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.0=0;
    i=ADCW.1;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.0=0;
    i=ADCW.0;
    PORTB.1=i;
    PORTB.0=1;
    delay_ms(10);

    PORTB.2=1;
    delay_ms(10);
    PORTB.2=0;

    }

    // Declare your global variables here

    void main(void)
    {
    // Declare your local variables here

    // Input/Output Ports initialization
    // Port B initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTB=0x00;
    DDRB=0xFF;

    // Port C initialization
    // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTC=0x00;
    DDRC=0x00;

    // Port D initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
    PORTD=0x00;
    DDRD=0x00;

    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: Timer 0 Stopped
    TCCR0=0x00;
    TCNT0=0x00;

    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: Timer1 Stopped
    // Mode: Normal top=0xFFFF
    // OC1A output: Discon.
    // OC1B output: Discon.
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A=0x00;
    TCCR1B=0x00;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;

    // Timer/Counter 2 initialization
    // Clock source: System Clock
    // Clock value: 31,250 kHz
    // Mode: Normal top=0xFF
    // OC2 output: Disconnected
    ASSR=0x00;
    TCCR2=0x06;
    TCNT2=0x5F;
    OCR2=0x00;

    // External Interrupt(s) initialization
    // INT0: Off
    // INT1: Off
    MCUCR=0x00;

    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x40;

    // USART initialization
    // USART disabled
    UCSRB=0x00;

    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;

    // ADC initialization
    // ADC disabled
    ADCSRA=0x00;

    // SPI initialization
    // SPI disabled
    SPCR=0x00;

    // TWI initialization
    // TWI disabled
    TWCR=0x00;

    // Global enable interrupts
    #asm(«sei»)

    while (1)
    {
    // Place your code here
    int v;
    for(v=0;v<255;v++)
    {
    delay_ms(100);
    data++;
    }
    }
    }

  • int v = 0b1000;
    int bit_n = 2;
    int bit = (v >> bit_n) & 1;

  • Спасибо огромное!

  • все работает, но компилятор ругается на 2 строку
    Error: C:\MK\mega8\test.c(23): invalid combination of type specifiers
    версия 2.05

  • Все, разобрался Спасибо!

  • Друг подскажи пожалуйста а в codevisionavr есть библиотека для работы с st7735

  • не знаю, я codevision не пользовался очень давно

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

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

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