| Ваш IP: 44.192.70.216 | Online(42) - гости: 14, боты: 28 | Загрузка сервера: 1.04 ::::::::::::

ATtiny2313 + MAX7219 матрица 8×8

Ранее в https://rcl-radio.ru/?p=98749 был описан пример использования восьми разрядного семисегментного индикатора с последовательным интерфейсом на базе драйвера MAX7219. В этой статье будет аналогичный проект, но только с использованием светодиодной матрицы 8х8 на базе драйвера MAX7219. У меня в наличии имеется модуль который содержит сразу 4 ячейки матрицы 8х8, что позволяет его использовать например для создания простых часов. К качестве управления матрицей будет использован микроконтроллер ATtiny2313.

ATtiny2313 достаточно простой и бюджетный микроконтроллер, имеет всего 2048 байт внутрисистемной энергонезависимой ФЛЭШ-памяти и 128 байт внутренней SRAM памяти. Небольшой объем памяти накладывает определенные ограничения в использовании микроконтроллера, но его достаточно для выполнения простых операций. Для программирования ATtiny2313 можно использовать среду программирования Arduino IDE.

Поддержка Arduino IDE — https://rcl-radio.ru/?p=94074

MAX7219 — драйвер восьми разрядного цифрового LED индикатора с последовательным интерфейсом. Драйвер может управлять восемью семисегментными индикаторами с точкой, либо отдельно 64 светодиодами в LED панелях с общим катодом.

Драйвер MAX7219 управляется по трехпроводной последовательной шине Microwire (3-Wire).  Драйвер допускают каскадирование для управления большим числом индикаторов. Каждый из разрядов индикатора имеет независимую адресацию и его содержимое может быть обновлено без необходимости перезаписи всего индикатора. ИС MAX7219 также позволяют пользователю определять режим декодирования каждого разряда.

Для начала необходимо собрать схему показанную на рисунке:

Так же если у Вас нет в наличии ATtiny2313, то можно использовать плату Arduino Nano или UNO, при этом подключение MAX7219 будет иметь следующую распиновку:

PD2 D2 (ARDUINO)
PD3 D3 (ARDUINO)
PD4 D4 (ARDUINO)

Управляется MAX7219 через 16 битные регистры, старшим битом вперёд. В регистре первые 8 бит отводится под адрес регистра (фактически используются только 4-е младшие бита), остальные под 8 бит под данные.

Регистры управления драйвером MAX7219

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

  • 0х00 — не используется
  • 0х01 … 0х08 — регистры знакомест (вывод данных на индикаторы, в таблице слева указаны биты в режиме декодирования, справа показаны биты при отключенном режиме декодирования)

  • 0х09 — режим декодирования (0х00 — отключен режим декодирования, 0xFF — режим декодирования активен)

  • 0х0А — интенсивность свечения (яркость 16 значений)

  • 0х0B — выбор кол-ва отображаемых знакомест

  • 0x0C — спящий режим (0 — OFF, 1 — ON)

  • 0x0F — тест

Для активации работы драйвера MAX7219 необходимо в регистрах указать следующие данные:

  • адрес 0x0F, данные 0x00 – тест выключен
  • адрес 0x0С, данные 0x01 – выйти из сна
  • адрес 0x0B, данные 0x07 – кол-во знакомест 8
  • адрес 0x09, данные 0x00 – дешифратор отключен
  • адрес 0x0A, данные 0x04 – яркость уровень 4 из 16

Плата MAX7219 с индикаторами помимо питания имеет три контакта: DIN, CS, CLK

При логической единице на входе CS драйвер MAX7219 начинает воспринимать команды, на вход CLK подаются синхроимпульсы, а на вход DIN биты данных, которые считываются при нарастающем фронте синхроимпульса.

При использовании матрицы режим декодирования должен быть отключен, в регистре 0x09 должен быть 0. Так же при использовании несколько драйверов MAX7219, отправлять пакеты данных нужно столько раз сколько у Вас драйверов. Сам пакет состоит из одной строки в которой содержится по 2 байта на один драйвер. Например если матрица имеет 4 драйвера, то необходимо 4 раза отправить данные для регистра 0х01 для верхней строки, потом для так же для всех оставшихся 7 строк. Так же следует учитывать, что перед отправкой пакета данных нужно отпустить линию CS только один раз, а при окончании отправки данных поднять линию CS. Линии CS и CLK всех драйверов в матрице соединены вместе, а выход DOUT соединен со входом DIN в каждом следующем драйвере.

Далее подробно рассмотрим пример тестового запуска матрицы. Для примера выведем на матрицу следующую картинку:

#define DIN PD2
#define CS  PD3
#define CLK PD4
 
 
void setup() {
  delay(2);
  DDRD |= (1 << DIN) | (1 << CS) | (1 << CLK);
  max7219(0x0F, 0, 0, 0, 0);// тест выкл.
  max7219(0x0C, 1, 1, 1, 1);// вкл. индик.
  max7219(0x0A, 1, 1, 1, 1);// яркость
  max7219(0x09, 0, 0, 0, 0);// дешифраторы выкл.
  max7219(0x0B, 7, 7, 7, 7);// кол-во разрядов
  cl();
  delay(1000); 
}
 
void loop() {
  max7219(1, 0xFF, 0xFF, 0xFF, 0xFF);
  max7219(2, 0x80, 0x00, 0x00, 0x01);
  max7219(3, 0x80, 0x00, 0x00, 0x01);
  max7219(4, 0x80, 0xFF, 0xFF, 0x01);
  max7219(5, 0x80, 0xFF, 0xFF, 0x01);
  max7219(6, 0x80, 0x00, 0x00, 0x01);
  max7219(7, 0x80, 0x00, 0x00, 0x01);  
  max7219(8, 0xFF, 0xFF, 0xFF, 0xFF);
  delay(1000);
  }
 
void max7219(byte reg_n, byte h1, byte h2, byte h3, byte h4){
  PORTD &=~(1 << CS);WriteBit16(reg_n,h1);WriteBit16(reg_n,h2);WriteBit16(reg_n,h3);WriteBit16(reg_n,h4);PORTD |=(1 << CS);
  }  
void WriteBit16(byte reg, byte data){  
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((reg >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((data >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
        PORTD &= ~(1 << CLK);PORTD |= (1 << DIN);
  }
 
void cl(){for(char i=1;i<=8;i++){max7219(i, 0, 0, 0, 0);}}

Скетч использует 824 байт (40%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 9 байт (7%) динамической памяти, оставляя 119 байт для локальных переменных. Максимум: 128 байт.

Отправка данных:

void WriteBit16(byte reg, byte data){  
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((reg >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((data >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
        PORTD &= ~(1 << CLK);PORTD |= (1 << DIN);
  }

Показанный выше код реализует работу шины SPI, как видно сначала идет запись адреса регистра, а после запись данных в драйвер MAX7219. При этом линия CS в этом коде не задействована.

Для 4-х драйверов необходимо отправить сразу четыре пакета для одной строки, следующий код реализует эту возможность:

void max7219(byte reg_n, byte h1, byte h2, byte h3, byte h4){
  PORTD &=~(1 << CS);WriteBit16(reg_n,h1);WriteBit16(reg_n,h2);WriteBit16(reg_n,h3);WriteBit16(reg_n,h4);PORTD |=(1 << CS);}  

Как видно, в этом коде уже используется линия CS, один раз в начале отправки пакетов данных и один раз после завершения отправки пакетов.

Функция max7219 реализуем управление светодиодами одной строки состоящей их 32 светодиодов, для управления всеми светодиодами матрицы, эту функцию необходимо использовать 8 раз указывая свой номер строки.

Инициация матрицы:

  max7219(0x0F, 0, 0, 0, 0);// тест выкл.
  max7219(0x0C, 1, 1, 1, 1);// вкл. индик.
  max7219(0x0A, 1, 1, 1, 1);// яркость
  max7219(0x09, 0, 0, 0, 0);// дешифраторы выкл.
  max7219(0x0B, 7, 7, 7, 7);// кол-во разрядов

Так же как при управлениями строками матрицы, все настройки драйвера необходимо отправлять столько раз, сколько у Вас используется драйверов. Перед инициацией матрицы рекомендуется делать задержку в 2 мкс.

Сам рисунок показанный на картинке выводит следующий код:

  max7219(1, 0xFF, 0xFF, 0xFF, 0xFF);
  max7219(2, 0x80, 0x00, 0x00, 0x01);
  max7219(3, 0x80, 0x00, 0x00, 0x01);
  max7219(4, 0x80, 0xFF, 0xFF, 0x01);
  max7219(5, 0x80, 0xFF, 0xFF, 0x01);
  max7219(6, 0x80, 0x00, 0x00, 0x01);
  max7219(7, 0x80, 0x00, 0x00, 0x01);  
  max7219(8, 0xFF, 0xFF, 0xFF, 0xFF);

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

#define DIN PD2
#define CS  PD3
#define CLK PD4
 
void setup() {
  delay(2);
  DDRD |= (1 << DIN) | (1 << CS) | (1 << CLK);
  max7219_L(0x0F, 0);// тест выкл.
  max7219_L(0x0C, 0x01010101);// вкл. индик.
  max7219_L(0x0A, 0x01010101);// яркость
  max7219_L(0x09, 0);// дешифраторы выкл.
  max7219_L(0x0B, 0x07070707);// кол-во разрядов
  cl();
  delay(1000); 
}
 
void loop() {
  max7219_L(1, 0xFFFFFFFF);
  max7219_L(2, 0x80000001);
  max7219_L(3, 0x80000001);
  max7219_L(4, 0x80FFFF01);
  max7219_L(5, 0x80FFFF01);
  max7219_L(6, 0x80000001);
  max7219_L(7, 0x80000001);  
  max7219_L(8, 0xFFFFFFFF); 
  delay(100);
  }
 
void max7219_L(byte reg_n, long h){
  byte h1 = ((h & 0xFF000000) >> 24);
  byte h2 = ((h & 0x00FF0000) >> 16);
  byte h3 = ((h & 0x0000FF00) >> 8);
  byte h4 = (h & 0x000000FF);
  PORTD &=~(1 << CS);WriteBit16(reg_n,h1);WriteBit16(reg_n,h2);WriteBit16(reg_n,h3);WriteBit16(reg_n,h4);PORTD |=(1 << CS);
  }  
 
void WriteBit16(byte reg, byte data){  
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((reg >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((data >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
        PORTD &= ~(1 << CLK);PORTD |= (1 << DIN);
  }
 
void cl(){for(char i=1;i<=8;i++){max7219_L(i, 0);}}

Используя для управления строкой один байт, проще выводить цифры и символы, делать бегущую строку.

  max7219_L(1, 0xFFFFFFFF);
  max7219_L(2, 0x80000001);
  max7219_L(3, 0x80000001);
  max7219_L(4, 0x80FFFF01);
  max7219_L(5, 0x80FFFF01);
  max7219_L(6, 0x80000001);
  max7219_L(7, 0x80000001);  
  max7219_L(8, 0xFFFFFFFF); 

Работает функция max7219_L аналогично функции max7219 из первого примера кода, но в функции max7219_L  число LONG перед оправкой в драйвер разбирается на четыре 8-битных байта:

void max7219_L(byte reg_n, long h){
  byte h1 = ((h & 0xFF000000) >> 24);
  byte h2 = ((h & 0x00FF0000) >> 16);
  byte h3 = ((h & 0x0000FF00) >> 8);
  byte h4 = (h & 0x000000FF);
  PORTD &=~(1 << CS);WriteBit16(reg_n,h1);WriteBit16(reg_n,h2);WriteBit16(reg_n,h3);WriteBit16(reg_n,h4);PORTD |=(1 << CS);}  

Для примера использования матрицы основанной на 4-х драйверах MAX7219, соберем простые часы:

// ATtiny2313 20 MHz
 
#define DIN PD2
#define CS  PD3
#define CLK PD4
 
byte d0,d1,d2,d3,i1,bb,i3;
unsigned int i2;
byte hh,mm;
byte dat[10][8] = {{B00111100,B01100110,B01101110,B01111110,B01110110,B01100110,B00111100,B00000000},
                   {B00011000,B00111000,B00011000,B00011000,B00011000,B00011000,B00011000,B00000000},
                   {B00111100,B01100110,B00000110,B00011100,B00110000,B01100000,B01111110,B00000000},
                   {B00111100,B01100110,B00000110,B00011100,B00000110,B01100110,B00111100,B00000000},
                   {B00001110,B00011110,B00110110,B01100110,B01111110,B00000110,B00000110,B00000000},
                   {B01111110,B01100000,B01111100,B00000110,B00000110,B01100110,B00111100,B00000000},
                   {B00011100,B00110000,B01100000,B01111100,B01100110,B01100110,B00111100,B00000000},
                   {B01111110,B00000110,B00000110,B00001100,B00011000,B00011000,B00011000,B00000000},
                   {B00111100,B01100110,B01100110,B00111100,B01100110,B01100110,B00111100,B00000000},
                   {B00111100,B01100110,B01100110,B00111110,B00000110,B00001100,B00111000,B00000000}};        
 
void setup() {
  TCCR1A = 0;   
  TCCR1B = 0;   
  OCR1A = 31250; // 0.1 s
  TCCR1B |= (1 << WGM12); 
  TCCR1B |= (1 << CS11) | (1 << CS10);  // 64  
  TIMSK |= (1 << OCIE1A);  
  delayMicroseconds(2000);
  DDRD |= (1 << DIN) | (1 << CS) | (1 << CLK);
  PORTB |= (1 << 2) | (1 << 3);
  max7219_L(0x0F, 0);// тест выкл.
  max7219_L(0x0C, 0x01010101);// вкл. индик.
  max7219_L(0x0A, 0x01010101);// яркость
  max7219_L(0x09, 0);// дешифраторы выкл.
  max7219_L(0x0B, 0x06060606);// кол-во разрядов
}
 
void loop() {
  d0=hh/10;
  d1=hh%10;
  d2=mm/10;
  d3=mm%10;
 
  if(((PINB >> 2) & 1) == 0){mm++; if(mm>59){mm = 0;}del();}
  if(((PINB >> 3) & 1) == 0){hh++; if(hh>23){hh = 0;}del();}
  if(i1 <= 5)bb = 3; else bb = 0;
 
  max7219_L(1, (unsigned long)dat[d0][0]<<24 | (unsigned long)dat[d1][0]<<17 | (unsigned int)dat[d2][0]<<7 | dat[d3][0]);
  max7219_L(2, (unsigned long)dat[d0][1]<<24 | (unsigned long)dat[d1][1]<<17 | (unsigned int)dat[d2][1]<<7 | dat[d3][1] | (int long)bb << 15);
  max7219_L(3, (unsigned long)dat[d0][2]<<24 | (unsigned long)dat[d1][2]<<17 | (unsigned int)dat[d2][2]<<7 | dat[d3][2] | (int long)bb << 15);
  max7219_L(4, (unsigned long)dat[d0][3]<<24 | (unsigned long)dat[d1][3]<<17 | (unsigned int)dat[d2][3]<<7 | dat[d3][3]);
  max7219_L(5, (unsigned long)dat[d0][4]<<24 | (unsigned long)dat[d1][4]<<17 | (unsigned int)dat[d2][4]<<7 | dat[d3][4] | (int long)bb << 15);
  max7219_L(6, (unsigned long)dat[d0][5]<<24 | (unsigned long)dat[d1][5]<<17 | (unsigned int)dat[d2][5]<<7 | dat[d3][5] | (int long)bb << 15);
  max7219_L(7, (unsigned long)dat[d0][6]<<24 | (unsigned long)dat[d1][6]<<17 | (unsigned int)dat[d2][6]<<7 | dat[d3][6]);
 
  i3=0;
  }//loop
 
 
void max7219_L(byte reg_n, unsigned long h){
  byte h1 = h >> 24;
  byte h2 = h >> 16;
  byte h3 = h >> 8;
  byte h4 = h;
  PORTD &=~(1 << CS);WriteBit16(reg_n,h1);WriteBit16(reg_n,h2);WriteBit16(reg_n,h3);WriteBit16(reg_n,h4);PORTD |=(1 << CS);
  }  
 
void WriteBit16(byte reg, byte data){  
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((reg >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
     for(char i = 7; i >= 0; i--){
        PORTD &= ~(1 << CLK);
        if(((data >> i) & 1) == 1){PORTD |= (1 << DIN);}else{PORTD &= ~(1 << DIN);}
        PORTD |=(1 << CLK);}
        PORTD &= ~(1 << CLK);PORTD |= (1 << DIN);
  }
 
ISR(TIMER1_COMPA_vect){
     i2++;i1++;
     if(i1 > 9){i1 = 0;}
     if(i2 > 599){mm++;i2 = 0;}
     if(mm > 59){hh++;mm = 0;}
     if(hh > 23){hh = 0;}
     } 
 
void del(){while(i3<199){i3++;delayMicroseconds(2000);}}

Скетч использует 2044 байт (99%) памяти устройства. Всего доступно 2048 байт.
Глобальные переменные используют 100 байт (78%) динамической памяти, оставляя 28 байт для локальных переменных. Максимум: 128 байт.

Скетч часов содержит массив цифр от 0 до 9:

byte dat[10][8] = {{B00111100,B01100110,B01101110,B01111110,B01110110,B01100110,B00111100,B00000000},
                   {B00011000,B00111000,B00011000,B00011000,B00011000,B00011000,B00011000,B00000000},
                   {B00111100,B01100110,B00000110,B00011100,B00110000,B01100000,B01111110,B00000000},
                   {B00111100,B01100110,B00000110,B00011100,B00000110,B01100110,B00111100,B00000000},
                   {B00001110,B00011110,B00110110,B01100110,B01111110,B00000110,B00000110,B00000000},
                   {B01111110,B01100000,B01111100,B00000110,B00000110,B01100110,B00111100,B00000000},
                   {B00011100,B00110000,B01100000,B01111100,B01100110,B01100110,B00111100,B00000000},
                   {B01111110,B00000110,B00000110,B00001100,B00011000,B00011000,B00011000,B00000000},
                   {B00111100,B01100110,B01100110,B00111100,B01100110,B01100110,B00111100,B00000000},
                   {B00111100,B01100110,B01100110,B00111110,B00000110,B00001100,B00111000,B00000000}};        

Каждая строка массива описывает одну цифру. Создавать свои различные символы очень просто, достаточно байты массива расположить не в строку, а в столбик, после чего все станет понятно. Например цифра 5:

B01111110 -******-
B01100000 -**-----
B01111100 -*****--
B00000110 -----**-
B00000110 -----**-
B01100110 -**--**-
B00111100 --****--
B00000000 --------

В часах для отсчета времени используется таймер_1, переполнение которого происходит с интервалом 0,1 сек. Настройки таймера рассчитаны на работу с тактовой частотой в 20 МГц. Если у Вас другая тактовая частота, то необходимо подобрать параметр регистра сравнения OCR1A.

Делитель таймера установлен на 64, для определения параметра регистра сравнения воспользуйтесь следующим примером:

F = 20 000 000 / 64 / 31250 = 10 Гц (Т = 0,1 сек)

Установка времени часов осуществляется двумя кнопками (HH:MM)

Комментарии

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

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

Случайные статьи

  • УМЗЧ класса D на TPA3122D2

    УМЗЧ класса D на TPA3122D2

    На ИМС TPA3122D2 можно собрать усилитель звуковой частоты класса D. Выходная мощность усилителя 15В (при напряжении питания 28В и сопротивлении нагрузки 8 Ом) на канал. Из-за высокого КПД микросхеме TPA3122D2 не нужен радиатор охлаждения. Так же микросхему TPA3122D2 можно использовать в мостовом соединении каналов. МикросхемаTPA3122D2 работает в диапазоне напряжений от 10 …Подробнее...
  • LED светильник с регулируемой яркостью (18 светодиодов)

    LED светильник с регулируемой яркостью (18 светодиодов)

    На регуляторе напряжения LM2941C можно сделать простой светодиодный светильник рассчитанный на 18 светодиодов. Яркость свечения светодиодов можно регулировать пока входное напряжение будет выше 10,5В. Источник: http://www.solorb.com/elect/solarcirc/18ledlit/index.html lm2941.pdfПодробнее...
  • Микросхемы-регуляторы громкости

    LA1362 — одно канальный регулятор громкости Ток потребления 40мА Коэффициент регулировки -70…+22дБ Частотный диапазон от 20 до 20000Гц К гармоник не более 0,5% Входное/выходное сопротивление 75/10кОм Напряжение питания 9…18В Uвх/Uвых 1/1,5В Корпус типа SIL9 LA2600 — двух канальный регулятор громкости Ток потребления 40мА Коэффициент регулировки -70…+22дБ Частотный диапазон от 20 …Подробнее...
  • Акустический выключатель для люстры

    Данная схема управляется хлопками в ладоши. Это переключатель для 2-х групп ламп с суммарной мощностью 300Вт. Акустические импульсы воспринимаются электретным микрофоном М1. Питание на него подается через R1, который одновременно служит его нагрузкой. Далее следует усилитель на VT1. Усиленные импульсы поступают на формирователь лог. импульсов, выполненный на интегральном таймере D1. …Подробнее...
  • К1460УД2х — СДВОЕННЫЙ МОЩНЫЙ ОПЕРАЦИОННЫЙ УСИЛИТЕЛЬ

    К1460УД2х — СДВОЕННЫЙ МОЩНЫЙ ОПЕРАЦИОННЫЙ УСИЛИТЕЛЬ

    К1460УД2х – интегральная микросхема представляет собой сдвоенный мощный операционный усилитель, пригодная для использования в качестве мощного ОУ в широком диапазоне областей применения, хорошо подходит для управления индуктивными нагрузками, в частности, для управления электродвигателями постоянного тока. Микросхема К1460УД2Рх является прямым аналогом микросхемы TCA0372 фирмы «MOTOROLA». ОСОБЕННОСТИ • Выходной ток до 1.0 А • Скорость нарастания …Подробнее...