Управление драйвером семисегментных индикаторов MAX7219
В этой статье хочу показать как программно управлять модулем с драйвером MAX7219 и восемью семисегментными индикаторами. Довелось пообщаться с этим модулем и надо сказать, мне он очень понравился. Понравилось и то, как легко им управлять и то, что он освобождает микроконтроллер от обслуживания динамической индикации. С ним можно вообще данные переписывать только при их изменении, как с LCD дисплеем. Привожу здесь код программы (демо) для микроконтроллера на языке Си.
В общем то управление драйвером простое, как сдвиговым регистром по трехпроводной схеме (3-Wire). Вернее он и имеет как раз в своем составе сдвиговый регистр. Алгоритм управления такой. Низким уровнем на входе CS разрешаем принимать данные. Данные отсылаются по 16 бит, старшим битом вперед. Биты с 15 по 8 это или адрес знакоместа (значения от 1 до 8), или служебная команда (значения от 9 до 15). Биты с 7 по 0 это данные, либо для инструкции, либо образ (маска) символа. Каждый выставленный бит на входе DIN записывается в регистр по фронту тактового импульса на входе CLK. После того как все биты переданы, "защелкиваем" их, выставив единичку на входе CS.
Управляет драйвер восемью светодиодными семисегментными индикаторами с общим катодом. Это означает, что чтобы погасить все сегменты индикатора, надо прописать в него 0, а что бы зажечь, нужно прописать 255. Каждый из разрядов индикатора имеет независимую адресацию и его содержимое может быть обновлено без необходимости перезаписи всего индикатора.
Внешний вид модуля MAX7219.
Сама плата выполнена качественно, а вот индикаторы на ней припаяны кривовато. Подключение индикаторов странное. Ожидалось, что под номером 1 будет индикатор расположенный слева, но как видим слева идут 8, 7, 6 и т. д.. Почему-то распаяны они именно так, хоть это и не критично, и легко корректируется в коде программы.
Даже на минимальной яркости индикаторы светят очень ярко для фотоаппарата. А вообще нормальная яркость свечения на середине регулировки, значения от шести до восьми.
А так индикаторы смотрятся через светофильтр. Яркость свечения не уменьшилась, а вот незасвеченные сегменты уже не видно.
Код "демки" на языке Си.
/**************************************************************/ /*** Управление драйвером семисегментных индикаторов MAX7219 **/ /************** нагруженным на восемь индикаторов. ************/ /************ Микроконтроллер: PIC16F628A *********************/ /************ Среда разработки MPLAB IDE v8.89 - язык C *******/ #include pic.h // нужен для HI-TECH C компилятора #include htc.h // для работы с функцией задержки #define _XTAL_FREQ 4000000 // прописываем частоту генератора /************* прописали выводы микроконтроллера **************/ #define knopkaup RA0 // кнопка больше #define knopkadown RA1 // кнопка меньше #define DIN RB0 // определение ввод данных #define CLK RB1 // определение тактирующего сигнала #define CS RB2 // определение выбор устройства #define DIN_OFF() DIN = 0; // данные в ноль #define DIN_ON() DIN = 1; // данные в еденичку #define STR_OFF() CLK = 0; // Строб в ноль #define STR_ON() CLK = 1; // Строб в еденичку #define WR_OFF() CS = 0; // начало передачи #define WR_ON() CS = 1; // завершение передачи /******************* логические операции **********************/ #define TestBit(x,y) (x & (1 << y)) // проверка бита /********************** конфигурация **************************/ __CONFIG // Биты конфигурации (INTIO // Внутренний генератор 4 мГц & UNPROTECT // off защиту памяти & BOREN // on контроль питания & MCLRDIS // off вывод начальной установки & PWRTEN // on таймер задержки запуска & WDTDIS // off сторожевой таймер & LVPDIS ); // off низковольтное программирование /************************ переменные **************************/ unsigned char const cifra[11] = {0b01111110, 0b00110000, 0b01101101, 0b01111001, 0b00110011, 0b01011011, 0b01011111, 0b01110000, 0b01111111, 0b01111011, 0b00000000}; unsigned char const segment[6] = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100, 0b00000010}; unsigned char i, c, bright_indik, hg1, hg2, hhg1, hhg2; /************************* функции ****************************/ void podgot(void) { TRISA = 0b00000011; // направление работы ножек порта А TRISB = 0b00000000; // направление работы ножек порта В CMCON = 0x07; // отключение компараторов PORTB = 0xff; // очищаем порт B RBPU = 0x01; // подтягивающие R (0-вкл, 1-выкл) } void w3_write(unsigned char adres, unsigned char data) { char i; WR_OFF(); // начало передачи for(i = 8; i > 0;i --) { if(TestBit(adres, i - 1)) { DIN_ON(); // выставили единичку } else { DIN_OFF(); // выставили нолик } STR_ON(); // такт в единичку __delay_us(5); // длительность строба STR_OFF(); // такт в ноль } for(i = 8; i > 0; i --) { if(TestBit(data, i - 1)) { DIN_ON(); // выставили единичку } else { DIN_OFF(); // выставили нолик } STR_ON(); // такт в единичку __delay_us(5); STR_OFF(); // такт в ноль } WR_ON(); // завершение передачи } void clear(void) { char i; for(i = 8; i > 0; i --) { w3_write(i, cifra[10]); // гасим все индикаторы } } void inic7219(void) { w3_write(0x0F, 0x00); // тест выключен w3_write(0x0C, 0x01); // нормальный режим w3_write(0x0B, 0x07); // кол-во знаков 8 w3_write(0x09, 0x00); // дешифраторы отключены w3_write(0x0A, bright_indik); // яркость свечения clear(); } void klava(void) { if(knopkaup == 0 && bright_indik != 15) { bright_indik ++; clear(); w3_write(0x0A, bright_indik); // яркость свечения hg1 = bright_indik / 10; // значение первой цифры hg2 = bright_indik % 10; // значение второй цифры hhg1 = cifra[hg1]; // маска первой цифры hhg2 = cifra[hg2]; // маска второй цифры w3_write(5, hhg1); // прописали первую цифру w3_write(4, hhg2); // прописали вторую цифру __delay_ms(1500); clear(); return; } if(knopkadown == 0 && bright_indik != 0) { bright_indik --; clear(); w3_write(0x0A, bright_indik); hg1 = bright_indik / 10; hg2 = bright_indik % 10; hhg1 = cifra[hg1]; hhg2 = cifra[hg2]; w3_write(5, hhg1); w3_write(4, hhg2); __delay_ms(1500); clear(); } } /******************* основная программа ***********************/ void main(void) { podgot(); bright_indik = 8; // яркость по умолчанию inic7219(); __delay_ms(500); while(1) { for(c = 0; c < 3; c ++) { for(i = 0; i < 6; i ++) { w3_write(8, segment[i]); w3_write(7, segment[i]); w3_write(6, segment[i]); w3_write(5, segment[i]); w3_write(4, segment[i]); w3_write(3, segment[i]); w3_write(2, segment[i]); w3_write(1, segment[i]); __delay_ms(80); } } __delay_ms(500); clear(); klava(); for(i = 8; i > 0; i --) { w3_write(i, cifra[i]); __delay_ms(500); } __delay_ms(500); clear(); klava(); } }
Теперь о коде. Главная здесь функция w3_write(), на ней все построено. При вызове функция получает два аргумента, adres и data и засылает их в регистр. Сначала восемь бит адреса или инструкции, затем восемь бит данных. Как уже было сказано, старшим битом вперед. После подачи питания и конфигурирования микроконтроллера вызывается подпрограмма inic7219(), которая прописывает в микросхему некоторую последовательность команд, после которой микросхема начинает нормально работать. Без инициализации микросхема ничего высвечивать не будет.
KRAB4.CC также читайте. KRAB5.CC подробнее. KRAB8.CC здесь еще больше. KRAB9.CC по материалам сайта. свадьба в шатре
Еще в коде программы производится опрос двух кнопок. Это регулировка яркости свечения индикаторов. Если подключить модуль к отладочной плате, то можно увидеть, как действует регулировка. В Протеусе к сожалению этого не видно. Значения яркости от трех до пятнадцати яркость одинаковая. От ноля до двух индикаторы вообще не светятся.
О соответствии битов data и сегментов индикаторов. Старший, седьмой бит управляет точкой (DP), биты с шестого по нулевой сегменты A,B,C,D,E,F и G соответственно. В принципе образы всех цифр уже прописаны в массиве cifra[]. Но если возникнет надобность закодировать какой-то иной символ, то можно воспользоваться онлайн-генератором здесь на сайте. В нем можно задать любую последовательность сегментов.
