4-x разрядный семисегментный индикатор на двух 74HC595 (Arduino)

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

Управление ИМС 74HC595 осуществляется через 3 линии:

  • SH_CP (11) — линия синхроимпульса для передачи данных из DS во внутренние ячейки (вход для тактовых импульсов).
  • ST_CP  (12) — линия синхроимпульса для передачи данных из внутренних ячеек, во внешние (синхронизация выходов).
  • DS  (14) — линия последовательных данных (Data Serial)

Основные характеристики 74HC595

  • Разрядность параллельного входа (выхода) — 8 бит
  • Фактор и количество пинов — DIP-16 и SO-16
  • Количество сигнальных линий для передачи данных — 3
  • Время установки — 20 нс
  • Максимальная частота — 100 МГц
  • Напряжение питания — 5 В
  • Ток потребления — 40 мА

Сдвиговый регистр 74HC595  может применяться для управления 4-x разрядным семисегментным индикатором. Для осуществления динамической индикации необходимо 2-а сдвиговых регистра, один будет управлять сегментами индикатора, а другой разрядами индикатора.

Для примера был выбран индикатор DA56-11EWA (с общим анодом) который состоит из двух разрядов, поэтому было использовано два таких индикатора.

Все одноименные сегментные выводы обеих индикаторов замкнуты между собой. Управление разрядами индикатора осуществляется через транзисторные ключи.

В качестве контроллера для управления сдвиговыми регистрами выбрана плата разработчика на базе микроконтроллера LGT8F328.

Схема

Управление сдвиговыми регистрами осуществляется через 4-е линии:

  • RCLK (ST_CP) — защелка
  • SCLK (SH_CP) — синхроимпульсы
  • DIO1 (DS) — линия данных для первого регистра
  • DIO2 (DS) — линия данных для второго регистра

Линии RCLK и SCLK общие для обоих регистров, а линия данных у каждого регистра своя.

Управление динамической индикацией осуществляется через таймер микроконтроллера, поэтому код помещенный в основной цикл кода не может повлиять на стабильность работы динамической индикации.

Для примера в основной цикл (loop) поместим переменную которая будет увеличивать свое значение на 1 каждые 100 мс, дополнительно активируем запятую во втором разряде индикатора.

/*              
                 Общий анод
--------------------------------------------------|                
Цифра|dp | G | F | E | D | C | B | A | Десятичный |
-----|---|---|---|---|---|---|---|---|------------|
  0  | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |    192     |
  1  | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |    249     |
  2  | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |    164     |
  3  | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |    176     |
  4  | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |    153     |
  5  | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |    146     |
  6  | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |    130     |
  7  | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |    248     |
  8  | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |    128     |
  9  | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |    144     |
 dp  | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |    127     |
-----*---*---*---*---*---*---*---*---*------------*
*/

#define RCLK 3
#define SCLK 4
#define DIO1 2
#define DIO2 6
 
byte razr[4] = {0b1110,0b1101,0b1011,0b0111};// 0123         
byte digit[13] = {192,249,164,176,153,146,130,248,128,144,127,255,191}; // 0 1 2 3 4 5 6 7 8 9 dp пусто -
int k;
byte a[4];
int i0,dp;
 
void setup(){
  Serial.begin(9600);
  noInterrupts();
  TCCR2B = 1 << CS22 | 1 << CS21;
  TIMSK2 = 1 << OCIE2A;
  OCR2A = 150;
  interrupts();
  pinMode(RCLK, OUTPUT);  // RCLK
  pinMode(SCLK, OUTPUT);  // SCLK
  pinMode(DIO1, OUTPUT);  // DIO1
  pinMode(DIO2, OUTPUT);  // DIO2
}

 
void loop(){
  k++;
  delay(100);
}

ISR(TIMER2_COMPA_vect) {
  a[0]=k/1000%10;
  a[1]=k/100%10;
  a[2]=k/10%10;
  a[3]=k%10;
 if(i0>3){i0=0;}
 if(i0==1){dp=0x80;}else{dp=0;}// i0=1 - запятая в 1 индикаторе (0123 === 01.23)
  digitalWrite(RCLK, LOW);
    for(int i1 = 7; i1 >=0; i1--){
     digitalWrite(SCLK,LOW);
     digitalWrite(DIO2, (razr[i0] >> i1) & 1); 
     digitalWrite(DIO1, ((digit[a[i0]]-dp) >> i1) & 1); 
     digitalWrite(SCLK,HIGH);
     } 
  digitalWrite(RCLK, HIGH);
  i0++;
} 

Далее для примера соберем простой термометр на базе цифрового датчика температуры DS18B20.

#include <OneWire.h>            // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip

OneWire  ds(7); // Вход датчика 18b20

#define RCLK 3
#define SCLK 4
#define DIO1 2
#define DIO2 6
 
byte razr[4] = {0b1110,0b1101,0b1011,0b0111};// 0123         
byte digit[14] = {192,249,164,176,153,146,130,248,128,144,127,255,191,0b11000110}; // 0 1 2 3 4 5 6 7 8 9 dp пусто - C
int k;
byte a[4];
int i0,dp;
 
void setup(){
  Serial.begin(9600);
  noInterrupts();
  TCCR2B = 1 << CS22 | 1 << CS21;
  TIMSK2 = 1 << OCIE2A;
  OCR2A = 150;
  interrupts();
  pinMode(RCLK, OUTPUT);  // RCLK
  pinMode(SCLK, OUTPUT);  // SCLK
  pinMode(DIO1, OUTPUT);  // DIO1
  pinMode(DIO2, OUTPUT);  // DIO2
}

 
void loop(){
  k=dsRead(0);
  delay(5000);
}

ISR(TIMER2_COMPA_vect) {
  a[0]=k/1000%10;
  a[1]=k/100%10;
  a[2]=k/10%10;
  a[3]=13;
 if(i0>3){i0=0;}
 if(i0==1){dp=0x80;}else{dp=0;}// i0=1 - запятая в 1 индикаторе (0123 === 01.23)
  digitalWrite(RCLK, LOW);
    for(int i1 = 7; i1 >=0; i1--){
     digitalWrite(SCLK,LOW);
     digitalWrite(DIO2, (razr[i0] >> i1) & 1); 
     digitalWrite(DIO1, ((digit[a[i0]]-dp) >> i1) & 1); 
     digitalWrite(SCLK,HIGH);
     } 
  digitalWrite(RCLK, HIGH);
  i0++;
} 

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) * 6.25; return (float)value; // Расчет температуры и вывод
}

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

Войти с помощью: