RadioRadar - Радиоэлектроника, даташиты, схемы

https://www.radioradar.net/radiofan/measuring_technics/register_74hc595_seven_segment_indicator.html

Сдвиговый регистр 74HC595 и семисегментный индикатор

Регистр сдвига – это набор триггеров, которые записывают и хранят биты информации последовательно при каждом тактовом импульсе. Таким образом, чтобы записать в сдвиговый регистр восемь бит информации, необходимо подавать бит (логический ноль или единицу) одновременно с тактовым импульсом восемь раз один за другим.

 

Микросхема 74HC595

Представляет собой восьмибитный регистр сдвига с возможностью "защелкивания" (фиксирования) данных по отдельному управляющему сигналу. Работает микросхема с последовательным интерфейсом SPI (Serial Peripheral Interface, обязательно требуется синхронизация данных с тактовым сигналом).

Корпус микросхемы может быть планарным (кодировка 74HC595D) или стандарта DIP16 (в этом случае кодировка 74HC595N).

Принципиальная схема регистра выглядит следующим образом.

Принципиальная схема регистра

Рис. 1. Принципиальная схема регистра

 

(сверху 8-битный регистр сдвига, в середине регистр хранения, ниже – выходной регистр)

Микросхема 74HC595

Рис. 2. Микросхема 74HC595

 

Данные подаются на вход DS. Снимаются с выводов Q0-Q7.

GRD – "земля", VCC – питание +5 В (не более 6 В).

SH_CP – контакт для подачи тактовых сигналов (должны быть синхронизированы с битами данных).

MR – позволяет сбросить (обнулить) регистр.

ST_CP – "защелка" введенных данных.

OE – отвечает за переключение между Z-состоянием и рабочим режимом.

Через контакт Q7’ можно соединять последовательно между собой несколько микросхем 74HC595.

Семисегментный индикатор

Это наиболее распространенный элемент, позволяющий наглядно отобразить цифровую информацию (а иногда и буквенную). Типовой светодиодный или жидкокристаллический элемент выглядит следующим образом.

Светодиодный или жидкокристаллический элемент

Рис. 3. Светодиодный или жидкокристаллический элемент

 

С помощью семи сегментов можно показать пользователю 128 (27) различных комбинаций свечения.

Комбинации свечения

Рис. 4. Комбинации свечения

 

Использование регистра и индикатора вместе

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

Используя 74HC595 можно включить в схему не один индикатор, а несколько (в зависимости от того, сколько разрядов индикации требуется).

Самый простой пример (можно даже собрать в программе Proteus) соединения 74HC595 с индикатором ниже.

Схема соединения 74HC595 с индикатором

Рис. 5. Схема соединения 74HC595 с индикатором

 

Управлять логикой работы индикатора будет следующий листинг:

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#define CLK PB5 // часы
#define DS PB3 // данные
#define E PB2 // ввод
#define PORT PORTB
#define DDR DDRB
void SPI_MasterTransmit(uint8_t Data);
int main()
{
//установка формата SPI
DDR|=(1<<CLK)|(1<<DS)|(1<<E); // вывод
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0); // включение SPI, режим MASTER, делитель частоты 1/16
while (1)
{
char i;
for(i=0;i<10;i++)
{
PORT &= ~(1<<E);
SPI_MasterTransmit(i);
PORT|=(1<<E);
_delay_ms(1000);
}
};
return 0;
}
void SPI_MasterTransmit(uint8_t Data) {
static const uint8_t seg[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
SPDR=(Data < 10)? seg[Data] : Data;
while(!(SPSR & (1<<SPIF)));
};

На выходе вы получите циклично изменяющиеся цифры от нуля до девяти через определенный интервал времени.

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

Чтобы было понятнее, приведем кодировку команд сопоставленную с десятичными цифрами.

Цифра

HEX

0

0x3F

1

0x06

2

0x5B

3

0x4F

4

0x66

5

0x6D

6

0x7D

7

0x07

8

0x7F

9

0x6F

h

0x80

Возможно так будет нагляднее (в двоичном коде на контактах светодиодного индикатора).

Обозначения А-H – это светодиоды на панели (смотри обозначения ниже).

 

Светодиоды на панели

Рис. 6. Светодиоды на панели

 

То есть, чтобы индикатор показал нам цифру 1, нужно отправить код (00000110 или в шестнадцатеричном формате 0x06), тогда загорятся светодиоды c и b. Обратите внимание, здесь массив данных для отображения никак не соотносится с реальными числами, то есть 0x06 – это 6 в десятеричной системе счисления, а светодиоды отобразят 1.

Перейдем к более практическим задачам.

В качестве наглядного примера с использованием последовательного подключения нескольких регистров сдвига 74HC595, управляющих каждый своим разрядом дисплея, может подойти схема термометра на программируемой микросхеме Attiny13.

Сама схема.

Схема устройства

Рис. 7. Схема устройства

 

Генератор тактовой частоты в Attiny13 встроенный. Данные температуры в контроллер передаются с датчика LM35. И после реализации логики в программируемой микросхеме данные для отображения последовательно передаются в 74HC595, которые в свою очередь накопленные 8 бит информации передают на семисегментные светодиоды.

Листинг программы будет выглядеть так:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned int adc_counter, temperature, value;
ISR(SIG_ADC)
{
value = value + ((ADC*26)/53);
adc_counter++;
}
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D,
void write_display(unsigned char *data, unsigned char nbytes)
{
unsigned char mask,i;
for(i = 0; i < nbytes; i++)
{
mask = 0x80;
for(char k = 0; k < 8; k++)
{
if(data[i] & mask)
{
PORTB |= (1 << PB0);
PORTB |= (1 << PB2);
PORTB &= ~(1 << PB2);
}
else
{
PORTB &= ~(1 << PB0);
PORTB |= (1 << PB2);
PORTB &= ~(1 << PB2);
}
mask = mask >> 1;
}
}
PORTB |= (1 << PB1);
PORTB &= ~(1 << PB1);
}
int main(void)
{
DDRB = 0b00000111;
PORTB = 0b00000000;
ADMUX |= (1 << MUX1)|(1 << MUX0);
ADCSRA |= (1 << ADEN)
|(1 << ADPS2)|(1 << ADPS1)
|(1 << ADIE);
ACSR |= (1 << ACD);
DIDR0 |= (1 << ADC3D);
sei();
unsigned char display[3];
while(1)
{
ADCSRA |= (1 << ADSC);
if(adc_counter > 300)
{
temperature = value/adc_counter;
adc_counter = 0;
value = 0;
_delay_ms(50);
}
if(temperature < 100)
{
display[0] = SEGMENTE[temperature % 10];
display[1] = SEGMENTE[(temperature / 10) % 10];
display[2] = SEGMENTE[10];
}
else
{
display[0] = SEGMENTE[temperature % 10];
display[1] = SEGMENTE[(temperature / 10) % 10];
display[2] = SEGMENTE[(temperature / 100) % 10];
}
write_display(display,3);
}
}

Автор: RadioRadar