Blog the XELFAER

Заметки *NIX

Подключение семисегментного индикатора к AVR. Динамическая индикация. —

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

Итак, что же из себя представляет динамическая индикация. Представим ситуацию что нам необходимо в нашем устройстве сделать вывод данных на 7-ми сегментный индикатор. Хорошо если у микроконтроллера много ног свободных, то можно себе позволить подключить и статический индикатор, а вот если ног мало да и используется не один такой индикатор, то тут нас спасает динамическая индикация. Конечно для уменьшения количества занимаемых выводов можно использовать и сдвиговые регистры, но это уже отдельная тема разговора.
Индикаторы есть как с общим анодом, так и с общим катодом. Возьмем для примера индикатор из предыдущей статьи:
E40561-L-O-8-W
Данный индикатор с общим катодом на 4 разряда. Заглянув в datasheet увидим распиновку данного индикатора:
E40561-LI
Как видим у него 4 вывода отвечают за разряды, а 8 выводов отвечают за сегменты (7 сегментов для формирования значений + одна точка для каждого разряда из 4).
И как все же это работает? Все достаточно просто. При динамической индикации у нас загорается каждый разряд по очереди с определенной частотой, которая создает иллюзию что все сегменты горят одновременно по причине того что человеческий глаз не успевает заметить этого:
dynamic_indication_low_speed
Если немного ускорить процесс, то смысл становиться более понятен:
dynamic_indication_fast_speed
После небольшой вводной теории приступим к практике.
Проект будем делать на микроконтроллере ATtiny2313 и семисегментном индикаторе с общим катодом E40561-L-O-8-W.
Схема устройства:
scheme_led_segment_dynamic_indication
Из радиодеталей потребуется:
1) IC1 — Микроконтроллер ATtiny2313;
2) R1-R4 — резисторы 1 кОм;
3) R5-R12 — резисторы 120 Ом;
4) R13 — резистор 10 кОм;
5) Т1-T4 — транзисторы BC337;
6) HL1 — семисегментный индикатор с общим катодом E40561-L-O-8-W;
7) C1,C2 — конденсаторы керамические 24 пФ;
8) С3 — конденсатор керамический 100 нФ;
9) С4 — конденсатор электролитический 100 мкФ;
10) Q1 — кварцевый резонатор 12 МГц.
Источник питания для схемы: 5B.

Далее пишем прошивку. Для ознакомления возьмем простую задачу: вывести значение «1234» на наш индикатор.
Для удобства будем использовать 8-ми битный Таймер/Счетчик0 (8-bit Timer/Counter0). Смену разрядов будем производить при переполнении с помощью вектора TIMER0_OVF_vect.
Вот собственно код самой прошивки:

//MCU ATtiny2313; 12 MHz; Fuses: H:DF, L:7F
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

//функция инициализации регистров и портов МК
void init_port()
{
    DDRD |= (1 << PD5)|(1 << PD4)|(1 << PD3)|(1 << PD2);        //устанавливаем выводы регистра DDRD на выход
        PORTD = 0x00;       //устанавливаем логический 0 на портах регистра DDRD
        DDRB |= (1 << PB7)|(1 << PB6)|(1 << PB5)|(1 << PB4)|(1 << PB3)|(1 << PB2)|(1 << PB1)|(1 << PB0);        //устанавливаем выводы регистра DDRB на выход
        PORTB = 0x00;       //устанавливаем логический 0 на портах регистра DDRB
   
}

//функция инициализации таймера: TIMER0
void init_timer(void)
{
    TIMSK = (1 << TOIE0);       //разрешить прерывание таймера по переполнению
    TCCR0B = (1 << CS01);       //предделитель равен 8
}
 
unsigned char codes[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
volatile int dig = 0;       //номер разряда
volatile int data = 0;      //выводимые данные

//обработчик прерывания по TIMER0
ISR (TIMER0_OVF_vect)
{
    PORTB = 0x00;       //выключаем все сегменты
    PORTD = (1 << dig);
    switch(dig)
    {
        case 2: PORTB = (codes[data % 10]); break;      //раскладываем число на разряды
        case 3: PORTB = (codes[data % 100 / 10]); break;
        case 4: PORTB = (codes[data % 1000 / 100]); break;
        case 5: PORTB = (codes[data % 10000 / 1000]); break;
    }
    if ((dig++) > 4) dig = 0;
}

// Главная функция
int main (void)
{
    init_port();
    init_timer();
    sei();
    while(1)
    {
        data = 1234;
    };
}

Компилируем наш получившийся файл дабы получить прошивку в hex:

avr-gcc -mmcu=attiny2313 -I. -gdwarf-2 -DF_CPU=12000000UL -Os -o main.o main.c
avr-objcopy -O ihex main.o main.hex

Заливаем получившуюся прошивку в наш микроконтроллер и выставляем fuse:
hfuse: DF
lfuse: 7F

Вот что получилось у меня в итоге:
led_segment_dynamic_indication
Скачать архив прошивки: firmware

© 2015, XELFAER. Все права защищены. Использование материалов блога разрешается только при указании активной ссылки на статью.

Print Friendly, PDF & Email

Рубрики: Linux | Microcontrollers | Radioelectronica



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