В продолжение темы о 7-ми сегментных индикаторах — время разобраться с динамической индикацией. Статическую индикацию смысла особого нет разбирать, так как более используемая все же динамическая.
Итак, что же из себя представляет динамическая индикация. Представим ситуацию что нам необходимо в нашем устройстве сделать вывод данных на 7-ми сегментный индикатор. Хорошо если у микроконтроллера много ног свободных, то можно себе позволить подключить и статический индикатор, а вот если ног мало да и используется не один такой индикатор, то тут нас спасает динамическая индикация. Конечно для уменьшения количества занимаемых выводов можно использовать и сдвиговые регистры, но это уже отдельная тема разговора.
Индикаторы есть как с общим анодом, так и с общим катодом. Возьмем для примера индикатор из предыдущей статьи:
Данный индикатор с общим катодом на 4 разряда. Заглянув в datasheet увидим распиновку данного индикатора:
Как видим у него 4 вывода отвечают за разряды, а 8 выводов отвечают за сегменты (7 сегментов для формирования значений + одна точка для каждого разряда из 4).
И как все же это работает? Все достаточно просто. При динамической индикации у нас загорается каждый разряд по очереди с определенной частотой, которая создает иллюзию что все сегменты горят одновременно по причине того что человеческий глаз не успевает заметить этого:
Если немного ускорить процесс, то смысл становиться более понятен:
После небольшой вводной теории приступим к практике.
Проект будем делать на микроконтроллере ATtiny2313 и семисегментном индикаторе с общим катодом E40561-L-O-8-W.
Схема устройства:
Из радиодеталей потребуется:
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
#include
#include
//функция инициализации регистров и портов МК
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:
Заливаем получившуюся прошивку в наш микроконтроллер и выставляем fuse:
hfuse: DF
lfuse: 7F
Вот что получилось у меня в итоге:
Скачать архив прошивки: firmware
© 2015, XELFAER. Все права защищены.
Добавить комментарий Отменить ответ
Для отправки комментария вам необходимо авторизоваться.
В продолжение темы о 7-ми сегментных индикаторах — время разобраться с динамической индикацией. Статическую индикацию смысла особого нет разбирать, так как более используемая все же динамическая.
Итак, что же из себя представляет динамическая индикация. Представим ситуацию что нам необходимо в нашем устройстве сделать вывод данных на 7-ми сегментный индикатор. Хорошо если у микроконтроллера много ног свободных, то можно себе позволить подключить и статический индикатор, а вот если ног мало да и используется не один такой индикатор, то тут нас спасает динамическая индикация. Конечно для уменьшения количества занимаемых выводов можно использовать и сдвиговые регистры, но это уже отдельная тема разговора.
Индикаторы есть как с общим анодом, так и с общим катодом. Возьмем для примера индикатор из предыдущей статьи:
Данный индикатор с общим катодом на 4 разряда. Заглянув в datasheet увидим распиновку данного индикатора:
Как видим у него 4 вывода отвечают за разряды, а 8 выводов отвечают за сегменты (7 сегментов для формирования значений + одна точка для каждого разряда из 4).
И как все же это работает? Все достаточно просто. При динамической индикации у нас загорается каждый разряд по очереди с определенной частотой, которая создает иллюзию что все сегменты горят одновременно по причине того что человеческий глаз не успевает заметить этого:
Если немного ускорить процесс, то смысл становиться более понятен:
После небольшой вводной теории приступим к практике.
Проект будем делать на микроконтроллере ATtiny2313 и семисегментном индикаторе с общим катодом E40561-L-O-8-W.
Схема устройства:
Из радиодеталей потребуется:
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
#include
#include
//функция инициализации регистров и портов МК
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:
Заливаем получившуюся прошивку в наш микроконтроллер и выставляем fuse:
hfuse: DF
lfuse: 7F
Вот что получилось у меня в итоге:
Скачать архив прошивки: firmware
© 2015, XELFAER. Все права защищены.
Добавить комментарий Отменить ответ
Для отправки комментария вам необходимо авторизоваться.
Урок 8
Сегодня мы изучим, каким образом с помощью микроконтроллера Atmega8a можно управлять семисегментным светодиодным индикатором. Проект создадим также, как и обычно, назовём его Test05, удалим всё из main.c и скопируем туда содержимое одноименного файла из проекта прошлого занятия, также настроим симулятор в качестве программатора. Чтобы проверить, что в проекте всё нормально, попробуем его собрать. Также как и в прошлых занятиях, скопируем и переименуем файл протеуса, в свойствах контроллера там покажем путь к прошивке.
Удалим все светодиоды, так как они будут нам не нужны и найдём в библиотеке семисегментный светодиодный индикатор с общим анаодом. А с общим анодом мы возьмём из-за того, что они чаще встречаются, а также потому, что он у меня есть
Общий анод мы подключим к шине питания. И у нас сегменты будут светиться поэтому в том случае, когда на соответствующей ножке порта будет низкое напряжение, а когда высокое — не будут. Вот на этой основе мы и будем писать наш код. Подключаем вот так
Ну и прежде, чем писать какой-то код, давайте посмотрим, что из себя данный индикатор представляет и где и какой у него сегмент находится (принято обозначать сегменты латинскими буквами)
Поэтому, для того чтобы было легче данными сегментами управлять и выводить с помощью их свечения определённые цифры или символы, то мы соединим их по порядку — a с ножкой D0, b — с D1 и так далее по порядку и будем в уме постоянно себе представлять вот такое вот двоичное число
Скопируем данную строку в буфер обмена и добавим в наш код как комментарий, например вот таким образом
PORTD = 0b00000000; // 1 2 3 4 5 6 7 8
PORTB = 0b00000001; //0b|dp|g|f|e|d|c|b|a|
Обработчик кнопки мы трогать пока не будем, она нам возможно ещё пригодится и не будем поэтому портить проект.
Добавим следующий код в бесконечный цикл, сделав возможным отображение новой цифры через 500 милисекунд, используя функцию задержки
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
_delay_ms (500);
В коде мы видим что каждый раз мы заносим в порт новые значения, соответствующие определённой комбинации светящихся сегментов. Где ноль — там сегмент светится, где единица — нет.
А у нас-то наоборот — будут светиться единицы. Всё это достигается засчет операции инверсии. С точки зрения оптимизации лучше сделать всё-таки по первому варианту, но так как нам тут спешить некуда, то мы немного заодно повторим лишний раз пройденный материал по логическим операциям ибо они нам постоянно будут нужны.
Соберём код и проверим его сначала в протеусе
Код наш отлично работает. Давайте теперь посмотрим на живом контроллере и индикаторе. Для этого я взял ту же макетницу и собрал всё на ней, соединив с отладочной платой. У каждого отдельно-взятого индикатора схема распиновки своя. У моего она вот такая:
Прошьём контроллер и увидим, что всё у нас нормально работает (нагляднее конечно на видео, которое приложено внизу)
Программатор и индикаторы можно приобрести здесь: