Сдвиговый регистр 74HC595 находит то же применение что и регистр 74HC164, но у первого больше функций и возможностей. У него есть так называемая "защелка", которая управляет выходами регистра, т.е. как только все биты поступят в регистр их надо "защелкнуть", зафиксировать, чтобы данные появились на его выходе, данные на выходах не изменятся пока мы вновь не "защёлкнем" их. Выходы регистра можно установить в высокоомное состояние(HI-Z), т. е. они будут висеть в воздухе, нагрузка полностью отключается. Также как и 74HC164, регистры 74HC595 можно соединять последовательно цепочками, это применяется например в матричных светодиодных индикаторах.

Описание выводов регистра:

- Q0…Q7 – выходы;
- GND – земля;
- 'Q7 – выход предназначенный для последовательного соединения регистров;
- MR – сброс регистра;
- SH_CP – вход для тактовых импульсов;
- ST_CP – вход «защёлкивающий» данные;
- OE – вход переводящий выходы из HI-Z в рабочее состояние;
- DS – вход данных;
- VCC – питание 5 вольт.

Для управления регистром в обычной ситуации достаточно всего лишь трёх  выводов : SH_CP, ST_CP, DS. Рассмотрим работу регистра на примере цифрового термометра с датчиком LM35. LM35 - прецизионный датчик температуры с аналоговым выходом. В нашем примере будет измеряет температуру от 0 до 150 градусов Цельсия. При подаче двухполярного питания может измерять отрицательную температуру.

Характеристики датчика LM35:

- отображение в градусах Цельсия;
- линейная зависимость 10 мВ/°С;
- точность измерения 0,5°С;
- предел измерения температуры от -55°С до +150°С;
- напряжение питания 4-30В;
- выпускаются в корпусах TO-46, SO-8, TO-92, TO-220.

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

Контроллер используем наиболее подходящий - Attiny13, который работает от внутреннего генератора частотой 4,8 MHz. Семисегментные индикаторы используются любые с общим катодом, они подключаются к регистрам через токоограничительные ризисторы сопротивлением 220 Ом.

Функция write_display отвечает за передачу данных в регистры, в переменную data заносятся передаваемые данные, переменная nbytes определяет количество регистров, в нашем примере их 3 штуки.

Измерение сигнала с датчика происходит по окончанию преобразования АЦП, затем это значение конвертируется, усредняется и передается в регистры, в общем ничего сложного. Ниже исходный текст программы c подробным описанием:

// Подключение семисегментных индикаторов с помощью сдвигового регистра 74HC595.
// Делаем простой термометр на Attiny13 и LM35.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
volatile unsigned char adc_counter;
volatile unsigned long adc_buffer;
unsigned int temperature;
unsigned char display[3];

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

// Прерывание по окончанию преобразования АЦП
ISR(ADC_vect)
{
adc_buffer += ADC; // Накапливаем в буфер значения АЦП
adc_counter++; // Увеличиваем счетчик измерений
}
 
// Функция вывода данных через регистр
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); // DATA 1
PORTB |= (1 << PB2); // CLK 1
PORTB &= ~(1 << PB2); // CLK 0
}
else
{
PORTB &= ~(1 << PB0); // DATA 0
PORTB |= (1 << PB2); // CLK 1
PORTB &= ~(1 << PB2); // CLK 0
}
mask = mask >> 1; // Сдвигаем биты
}
}
// Защелкиваем регистр
PORTB |= (1 << PB1);
PORTB &= ~(1 << PB1);
}
 
int main(void)
{
// Настройка портов ввода/вывода
DDRB = 0b00000111;
PORTB = 0b00000000;

// Настойка АЦП
ADMUX |= (1 << MUX1)|(1 << MUX0);  // Вход ADC3
ADCSRA |= (1 << ADEN) // Разрешение АЦП
       |(1 << ADSC)  // Начинаем преобразование
       |(1 << ADATE)   // Непрерывный режим работы АЦП
       |(1 << ADPS2)|(1 << ADPS1) // Предделитель на 64
       |(1 << ADIE); // разрешаем прерывание по окончанию преобразования
 
ACSR |= (1 << ACD); // Выключаем аналаговый компаратор
DIDR0 |= (1 << ADC3D); // Отключаем неиспользуемые цифровые входы
 
sei(); // Глобально разрешаем прерывания
 
while(1)
{

if(adc_counter > 250)
{
// Усредняем и преобразуем в мВ, U = ADC*Uref/1024
temperature = ((adc_buffer*5*100)/1024)/adc_counter;
adc_counter = 0;
adc_buffer = 0;
}
 
display[0] =  SEGMENTE[temperature%10];
display[1] =  SEGMENTE[temperature/10%10];
// Если температура меньше 100 гасим незначащий ноль
if(temperature < 100) display[2] =  SEGMENTE[10];
else display[2] =  SEGMENTE[temperature/100%10]; 

write_display(display,3); // Отправляем данные на индикатор

}
}


Файлы к статье "Подключение семисегментных индикаторов с помощью сдвигового регистра 74HC595. Делаем простой термометр на Attiny13 и LM35"
Описание:

Проект AVRStudio4

Размер файла: 35.33 KB Количество загрузок: 519 Скачать

Комментарии  

0 #1 Alex1708 11.05.2015 08:44
можно ли расширить функционал ?
добавить к этому термометру функцию термостата , 2 кнопки (+) и (-) для установки температуры и выход исполнительного устройства?
в итоге получилось бы очень дешевое термореле
Сообщить модератору
0 #2 si4karuk 27.03.2017 19:40
Привет. Хотел с помощью данного урока, научиться управлять отдельными светодиодами. Использую все те же три регистра 595, но никак не получается засветить отдельный из 24х светодиодов не потушив уже зажженный.
Я понимаю что нужна еще одна функция в которую надо отправить, к примеру
Код:func(24, 1)
где 24 номер светодиода, а 1 или 0 - вкл или выкл светодиода, но сам не могу это написать.... Помогите чем смогите
Сообщить модератору
+1 #3 Фдуч 30.03.2017 14:14
si4karuk, Никаких дополнительных функций не нужно.
Просто отсылай на индикатор только те биты, которые должны засвечивать светодиоды. В примере используются 7-сегментные индикаторы, которые из черточек должны отображать конкретные цифры - образы этих цифр собрвны в массив SEGMENTE[]. Сделай массив SEGMENTE[] = {0х01, 0х02, 0х04, 0х08, 0х10, 0х20, 0х40, 0х80}; В нем каждый элемент зажигает один светодиод. Массив создан для одного регистра.
Перебирая в цикле - можно создать бегущую точку на каждом регистре.
Если нужна одна точка (а не 3), то выхода два: или в массиве прописать все возможные варианты для 26 светодиодов или условиями выделять с какой момент в какой регистр что писать.
А какие-то другие варианты можно получить объединяя элементы массива операцией ИЛИ (например так display[0] = SEGMENTE[0] | SEGMENTE[2])
Сообщить модератору
+1 #4 Андрей_нт 16.05.2017 17:32
Здраствуйте! Подскажите,что добавить в код,чтобы данный термометр показывал и отрицательную температуру?в даташите указано что датчик выдаёт -550мВ при -55 градусах,и 1500 мВ при +150. Или АЦП не "понимает" отрицательные значения,и переделать код невозможно?А то хочется сделать уличный термометр,и данная схема(из-за 595 регистров)очень подходит. Заранее спасибо всем кто откликнется.
Сообщить модератору
+1 #5 AntonChip 17.05.2017 12:57
Цитирую Андрей_нт:
Здраствуйте! Подскажите,что добавить в код,чтобы данный термометр показывал и отрицательную температуру?
Необходимо организовать схему смещения уровня вывода GND датчика температуры, например на транзисторе. Тогда например 0 градусов будет напряжение 500мВ, а -10 градусов 400мВ, в архив добавил пример
Сообщить модератору
0 #6 Андрей_нт 17.05.2017 15:55
AntonChip,Больш ое спасибо! вы просто волшебник! Да как оперативно ответили!!!
Сообщить модератору
0 #7 AntonChip 17.05.2017 17:37
Цитирую Андрей_нт:
AntonChip,Большое спасибо! вы просто волшебник! Да как оперативно ответили!!!

пожалуйста, попрошу проверить программу в железе, если все нормально выложу код в статье
Сообщить модератору
+1 #8 Евгений2018 19.06.2017 10:01
Здравствуйте! Как с помощью данного урока превратить его в светодиодную шкалу. Интересует момент - задаю код АЦП - зажигается светодиод, по аналогии описанному в уроке шкала на ATmege 8?
Сообщить модератору
+1 #9 AntonChip 19.06.2017 20:54
Цитирую Евгений2018:
Здравствуйте! Как с помощью данного урока превратить его в светодиодную шкалу. Интересует момент - задаю код АЦП - зажигается светодиод, по аналогии описанному в уроке шкала на ATmege 8?

Добавил в архив примерчик
Сообщить модератору
+2 #10 Евгений2018 20.06.2017 06:25
AntonChip! Большое спасибо за оперативный ответ!! Воевал с кодом 2 недели, а требовалась организация переменной "temp_1" с массивом!. В железе проверил вольтметр - шкала - вольтметр действует. Есть еще пожелание рассмотреть на примере данного урока вариант динамической индикации на 595 регистрах.
Сообщить модератору
0 #11 Ньютон 23.10.2022 16:04
Здравствуйте , хочу выразить свою благодарность автору благодаря вам я научился программировать и освоил мк . У меня у вам большая просьба . Не могли бы вы написать , поменять кусок кода для индикаторов с динамической индикацией .Индикаторы (с общими сегментами ). Спасибо .
Сообщить модератору
0 #12 AntonChip 23.10.2022 22:54
Цитирую Ньютон:
Не могли бы вы написать , поменять кусок кода для индикаторов с динамической индикацией .Индикаторы (с общими сегментами ). Спасибо .
Здравствуйте, вопрос не совсем понятен
Сообщить модератору