AVR Урок 8. Семисегментный индикатор. Статическая индикация



Урок 8

Семисегментный индикатор. Статическая индикация

 

Сегодня мы изучим, каким образом с помощью микроконтроллера Atmega8a можно управлять семисегментным светодиодным индикатором. Проект создадим также, как и обычно, назовём его Test05, удалим всё из main.c и скопируем туда содержимое одноименного файла из проекта прошлого занятия, также настроим симулятор в качестве программатора. Чтобы проверить, что в проекте всё нормально, попробуем его собрать. Также как и в прошлых занятиях, скопируем и переименуем файл протеуса, в свойствах контроллера там покажем путь к прошивке.

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

 

image04

 

Общий анод мы подключим к шине питания. И у нас сегменты будут светиться поэтому в том случае, когда на соответствующей ножке порта будет низкое напряжение, а когда высокое — не будут. Вот на этой основе мы и будем писать наш код. Подключаем вот так

 

image05

 

Ну и прежде, чем писать какой-то код, давайте посмотрим, что из себя данный индикатор представляет и где и какой у него сегмент находится (принято обозначать сегменты латинскими буквами)

 

image06

 

 

Поэтому, для того чтобы было легче данными сегментами управлять и выводить с помощью их свечения определённые цифры или символы, то мы соединим их по порядку — a с ножкой D0, b — с D1 и так далее по порядку и будем в уме постоянно себе представлять вот такое вот двоичное число

 

image07

 

Скопируем данную строку в буфер обмена и добавим в наш код как комментарий, например вот таким образом

 

DDRB = 0x00;

PORTD = 0b00000000;      // 1 2 3 4 5 6 7 8

PORTB = 0b00000001; //0b|dp|g|f|e|d|c|b|a|

 

Обработчик кнопки мы трогать пока не будем, она нам возможно ещё пригодится и не будем поэтому портить проект.

 

 

Добавим следующий код в бесконечный цикл, сделав возможным отображение новой цифры через 500 милисекунд, используя функцию задержки

 

while(1)

{

  PORTD = ~0b00000110;

  _delay_ms(500);

  PORTD = ~0b01011011;

  _delay_ms(500);

  PORTD = ~0b01001111;

  _delay_ms(500);

  PORTD = ~0b01100110;

  _delay_ms(500);

  PORTD = ~0b01101101;

  _delay_ms(500);

  PORTD = ~0b01111101;

  _delay_ms(500);

  PORTD = ~0b00000111;

  _delay_ms(500);

  PORTD = ~0b01111111;

  _delay_ms(500);

  PORTD = ~0b01101111;

  _delay_ms(500);

  PORTD = ~0b00111111;

  _delay_ms(500);

 

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

А у нас-то наоборот — будут светиться единицы. Всё это достигается засчет операции инверсии. С точки зрения оптимизации лучше сделать всё-таки по первому варианту, но так как нам тут спешить некуда, то мы немного заодно повторим лишний раз пройденный материал по логическим операциям ибо они нам постоянно будут нужны.

Соберём код и проверим его сначала в протеусе

 

image08

 

Код наш отлично работает. Давайте теперь посмотрим на живом контроллере и индикаторе. Для этого я взял ту же макетницу и собрал всё на ней, соединив с отладочной платой. У каждого отдельно-взятого индикатора схема распиновки своя. У моего она вот такая:

 

image09

 

Прошьём контроллер и увидим, что всё у нас нормально работает (нагляднее конечно на видео, которое приложено внизу)

 

image10

 

 

Предыдущий урок Программирование МК AVR Следующий урок

 

 

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

Программатор (продавец надёжный) USBASP USBISP 2.0

Семисегментный одноразрядный индикатор красный с общим анодом 10 шт

 

Смотреть ВИДЕОУРОК

 

AVR Семисегментный индикатор. Статическая индикация

 

19 комментариев на “AVR Урок 8. Семисегментный индикатор. Статическая индикация
  1. Al:

    Спасибо! Отличный урок! Повторил, все рабоет.

  2. Сергей:

    Не могли бы подсказать по созданию счётчика событий?Нужно использовать прерывания или опросы кнопки?долго уже голову ломаю,а в интернете нет ничего похожего(((

  3. Александр:

    Простите, а где ссылка на исходный код?

  4. Алексей:

    Повторил-не работает. Может где то накосячил?

    #define F_CPU 8000000
    #include <avr/io.h>
    #include <util/delay.h>

    int main(void)
    {
        
        DDRB = 0x00;
        PORTD = 0b00000000;
        PORTB = 0b00000001;
        while(1)
        {
           PORTD = ~0b00000110;
           _delay_ms(500);
           PORTD = ~0b01011011;
           _delay_ms(500);
           PORTD = ~0b01001111;
           _delay_ms(500);
           PORTD = ~0b01100110;
           _delay_ms(500);
           PORTD = ~0b01101101;
           _delay_ms(500);
           PORTD = ~0b01111101;
           _delay_ms(500);
           PORTD = ~0b00000111;
           _delay_ms(500);
           PORTD = ~0b01111111;
           _delay_ms(500);
           PORTD = ~0b01101111;
           _delay_ms(500);
           PORTD = ~0b00111111;
           _delay_ms(500);
        }
    }

  5. Алексей:

    Заменил DDRB=0x00 на DDRD=0xFF и все пошло

  6. Анигилирую:

    Кароче дядя, твои уроки шик, ты объясняешь как препод для даунов, но это работает, спасибо

  7. morpheus:

    Что-то я не понял смысла оператора » ~ » в операции присвоения порту D значения для вывода цифры. Разве не проще сразу нужное значение присваивать ? Инвертирование ведь тоже занимает определенное время на выполнение . Т.е вместо PORTD=~0b00000110 можно сразу записать PORTD=0b11111001 .

    • Можно, но спешить нам здесь некуда и так получилось нагляднее. Сделано для того, чтобы показать, что светиться сегменты именно с единичками. А с точки зрения оптимизации конечно по-Вашему лучше.

  8. Николай:

    Вообще красавчик.
    С ~(тильдой) классно придумал. Если пишешь на С/С++, то компиляторы такие выверты рассчитывают в момент сбора проекта и в прошивке не будет лишних операций, а читабельность кода на порядок выше. Сомневающимся рекомендую глянуть на файлик *.lss в папке «Debug» Эта строка на С «PORTD = ~0b01011011;» и эта PORTD = 0b10100100; в итоге даст ldi r31, 0xA4;

  9. ежовая_рукавица:

    Если взять индикатор с общим катодом, нужно просто избавиться от инверсии.
    Буквально два дня назад работа с семисегментным индикатором казалась чем-то невозможной и архисложной, и вот же на — полчаса на изучение и я уже могу зажигать требуемые символы)
    Спасибо за труды, товарищ автор!

  10. sergi:

    Здравствуйте. почему не работает код .

    #define F_CPU 100000L
    #include
    #include
    //#include
    #define t 500
    unsigned int cif [10]={0b0000110,0b1011011,0b1001111,0b1100110,0b1101101,
    0b1111101,0b0100111,0b1111111,0b1101111,0b0111111};

    int main(void)
    {
    unsigned int np=0;
    DDRC=0b00000011;
    PORTC |= (2<10;np++)
    {
    PORTD=cif[np];
    _delay_ms(500);
    }

    if (np>=10); np=0;
    }
    }

    • Vladimir:

      В первую очередь подключите библиотеки:
      #include
      #include
      Если в коде используется микроконтроллер с тактовой частотой 1МГц, а не 10000 Гц, то нужно записать #define F_CPU 1000000UL, а не #define F_CPU 100000L
      Далее в тексте используется команда «PORTD=cif[np];», при этом назначения порта D нет, следует перед ней записать:
      DDRD=0xFF;
      Команда «PORTC |= (2=10); np=0; нужно убрать «;», получится:
      if (np>=10) np=0; Также можно записать
      if (np>=10)
      {
      np=0;
      }
      В конце функции int main(void) желательно (необязательно) добавить перед последними скобками
      return 0; Это нужно чтобы функция int main(void) завершилась.

  11. Александр:

    Добрый день!
    Создатель этих уроков вообще огонь, объясняет всё так доходчиво что даже не отпадает желания углубляться в знания программирования дальше,спасибо огромное!!!

  12. Александр:

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

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

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

*