Печать

Подключение семисегментных индикаторов с помощью сдвигового регистра 74HC164. Делаем простой вольтметр на Attiny13.

Автор: AntonChip Опубликовано . Опубликовано в Программирование на Си

Рейтинг:   / 12
ПлохоОтлично 

Применение сдвиговых регистров таких как 74HC164 обусловлено возможностью управления большим количеством выходных линий с помощью 3-х линий управления, например эти регистры можно использовать для подключения гирлянд или матриц из светодиодов. Они широко используются в бытовой и промышленной аппаратуре для вывода данных на индикаторы или опросе матричной клавиатуры. Из управляющих входов в этой микросхеме есть: DATA, RESET, CLK и есть 8-выходов, получается эта микросхема преобразует последовательный код в параллельный. Вход RESET который сбрасывает установленные значения на выходе обычно не используется, так как занимает лишний вывод у микроконтроллера, он должен всегда быть поднятым к Vcc. Обнулять значения можно посылкой из 8бит логических единиц. Вход CLK продвигает значение по регистру. На вход DATA поступают данные в последовательном режиме.

Для заполнения регистра нужно выполнить такую последовательность:

1. Сравниваем старший бит передаваемого байта с нулем, если он равен нулю передаем в DATA ноль, если не равен передаем единицу;
2. На тактовый вход CLK подаем ноль;
3. На тактовый вход CLK подаем единицу;
4. Сдвигаем передаваемое значение на 1 разряд;
5. Проделываем эти операции пока не передадим весь байт нашего значения.

Подробнее со сдвиговым регистром разберемся на примере вольтметра постоянного напряжения до 50 Вольт. Микроконтроллер на этот раз будет Attiny13, так как у него всего 5 рабочих линий порта PB он как раз нам подходит. Работает он от внутреннего генератора частотой 4,8 MHz. АЦП настроен стандартно, вход ADC1. Каждый сегмент индикаторов подключается через резистор 220 Ом, индикаторы используются с общим катодом.  Для предотвращения мерцания сегментов индикаторов их общие катоды подключаются через транзистор, который включается только тогда, когда все значение будет передано в регистр. Схема вольтметра показана ниже:

Подключение семисегментных индикаторов с помощью сдвигового регистра 74HC164

Исходный код примера с подробными комментариями:

// Управление семисегментными индикаторами через регистр сдвига 74HC164
#include <avr/io.h>
#include <util/delay.h> 

// Массив значений для индикатора
//------------------0-----1-----2-----3-----4-----5                      
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D,
//------------------6-----7-----8------9
                   0x7D, 0x07, 0x7F, 0x6F};

// Функция вывода 1 разряда
void write_byte_1(char data) 
{ 
for(char i = 0; i < 8 ; i++) 
{ 
if((data & 0x80)!= 0) // Сравниваем 8-й бит с нулем 
PORTB |= (1 << PB0); // DATA 1
else 
PORTB &= ~(1 << PB0); // DATA 0
PORTB &= ~(1 << PB1); // CLK 0
PORTB |= (1 << PB1); // CLK 1
data = data << 1; // Сдвигаем биты 
} 
} 

// Функция вывода 2 разряда
void write_byte_2(char data) 
{ 
for(char i = 8; i < 16 ; i++) 
{ 
if((data & 0x80)!= 0) // Сравниваем 8-й бит с нулем 
PORTB |= (1 << PB0); // DATA 1
else 
PORTB &= ~(1 << PB0); // DATA 0
PORTB &= ~(1 << PB1); // CLK 0
PORTB |= (1 << PB1); // CLK 1
data = data << 1; // Сдвигаем биты
}
} 

// Функция вывода 3 разряда
void write_byte_3(char data) 
{ 
for(char i = 16; i < 24 ; i++) 
{ 
if((data & 0x80)!= 0) // Сравниваем 8-й бит с нулем 
PORTB |= (1 << PB0); // DATA 1
else 
PORTB &= ~(1 << PB0); // DATA 0
PORTB &= ~(1 << PB1); // CLK 0
PORTB |= (1 << PB1); // CLK 1
data = data << 1; // Сдвигаем биты
}
}

int main(void) 
{ 
DDRB = 0b00001011; 
PORTB = 0x00;

ADCSRA |= (1 << ADEN) // Разрешение АЦП
       |(1 << ADPS2)|(1 << ADPS1); // Предделитель на 64
ADMUX |= (1 << MUX0); // Вход ADC1

ACSR |= (1 << ACD); // Выключаем аналаговый компаратор
DIDR0 |= (1 << ADC1D); // Отключаем неиспользуемые цифровые входы

unsigned int value;

while(1)
{ 
ADCSRA |= (1 << ADSC); // Начинаем преобразование
while (ADCSRA & (1 << ADSC)){}; // Ждем завершения преобразования

value = (ADC*27)/50; // Uin = 4,99*110k/10k = 54,89V
                     // k = 548/1023 = 0,54
					 // 0,54 = 27/50
PORTB &= ~(1 << PB3); // Выключаем индикатор
write_byte_1(SEGMENTE[value%10]); // Выводим 1 разряд
write_byte_2((SEGMENTE[value%100/10])|0x80); // Выводим 2 разряд
write_byte_3(SEGMENTE[value%1000/100]); // Выводим 3 разряд
PORTB |= (1 << PB3); // Включаем индикатор
_delay_ms(250);
}
}

Файлы:
Проект AVRStudio 4
Дата 19.06.2016 Размер файла 45.98 KB Закачек 108

Комментарии  

+2 #1 skullhead 23.10.2013 14:25
спасибо за статью!очень наглядно и доступно.
Сообщить модератору
0 #2 Alyes 22.10.2014 12:43
Спасибо! хорошая статья! attiny13 с ее АЦП и + работа с сдвиговым регистром.
Сообщить модератору
0 #3 thespawn007 14.02.2015 02:19
И сколько их можно подключить на одну пару ног контроллера? 8?
Сообщить модератору
+1 #4 AntonChip 14.02.2015 11:25
Цитирую thespawn007:
И сколько их можно подключить на одну пару ног контроллера? 8?

Для данного примера можно 32
Сообщить модератору
0 #5 aiw 07.03.2016 12:53
а возможно ли использовать вместо трех одноразрядных индикаторов один триразрядный? Понадобится один регистр и изменение программы?
Сообщить модератору
0 #6 AntonChip 11.03.2016 22:58
1 регистр, изменение программы, но у attiny13 не хватит ножек
Сообщить модератору
0 #7 Eugene 15.06.2016 15:01
Уважаемый автор вы бы не могли скинуть хекс файл проэкта. А то я уже и забыл какой программой его создать с данного кода. Заранее спасибо.
Сообщить модератору
+1 #8 AntonChip 19.06.2016 11:48
Цитирую Eugene:
Уважаемый автор вы бы не могли скинуть хекс файл проэкта. А то я уже и забыл какой программой его создать с данного кода. Заранее спасибо.

Добавил в архив
Сообщить модератору
0 #9 Eugene 23.06.2016 13:02
Спасибо вам!!! Все заработало с первого раза. Но меня смущает мигание индикатора. Вы не подскажите как решить этот вопрос??? Заранее спасибо.
Сообщить модератору
0 #10 ArthurMelkumov 08.08.2016 19:51
Здравствуйте. Подскажите, что выполняется в строках кода №79-81? А именно интересуют действия в скобках с процентом.
Сообщить модератору
+1 #11 AntonChip 11.08.2016 22:24
Цитирую ArthurMelkumov:
Здравствуйте. Подскажите, что выполняется в строках кода №79-81? А именно интересуют действия в скобках с процентом.

% - это операция деления с остатком, таким способом переменную value "разделяем" на отдельные разряды
Сообщить модератору

Рекомендуем посмотреть