Дисплей MT–12232B-2YLG и Arduino Uno
- Войдите на сайт для отправки комментариев
Всем привет! )) Захотелось поделиться своим опытом с подключением дисплея MT–12232B-2YLG к Arduino Uno и написания кода.
Столкнулся с этим дисплеем совсем случайно. Делал небольшой заказ и купил дисплей, внешне ни чем не отличая его от предшественника МЭЛТ МТ-16S2H. Пришел домой, собрал проект, а смотрю - пинов на нем не 16, а 20. Ну думаю, какая-то расширенная версия наверное)) Стал изучать документацию и сравнивать эти два экрана. И до меня дошло, что это совсем разные вещи. Мой оказался аж с двумя кристаллами, каждый из которых отвечает за свою сторону вывода графики. Стало грустно... Но любопытство не отпускало меня! Погуглил все, что есть по этому дисплею и понял, что ничего особо, то и нет. Есть пример от производителя на С++. Тогда я сел за штудирование документации и разработкой своего кода. В целом все получилось удачно. Дисплей заработал, отобразил логотипчик и я успокоился ))
Вот скетч, который у меня получился. 500 байт он весит без данных о логотипе, только чисто код по работе с дисплеем. Но я приведу весь код в пример.
// Разработано Dr_Grizzly // Версия 1.0 13.04.2020 // Скетч под дисплей МЭЛТ 12232B-2YLG // Пример кода отображает логотип Мэлт на экране. // Использовал ArduinoUNO и задействовал порты А0-А3 // Данный скетч воплне можно преобразовать в библиотеку // Реализация чтения данных с дисплея в следующей версии #define LCD_DISPLAY_ON 0xAF //DisplayON/OFF #define LCD_DISPLAY_OFF 0xAE #define LCD_RESET 0xE2 //Стартовая строка ЖКИ (Display Start Line) сбрасываетсяв 0, адресс страницы устанавливается равным 0, содер-жимое ОЗУ не изменяется #define LCD_END 0xEE //Снятие флага RMW #define LCD_RMW 0xE0 //Read ModifyWrite #define LCD_ADC_FORW 0xA0 //DC Select = прямое соответствие #define LCD_START_LINE 0xC0 //DisplaySTART Line #define LCD_MULTIPLEX 0xA9 //Duty Select = 1 для МТ-12232В #define LCD_STATIC_DRV_OFF 0xA4 //Static DriveON/OFF = обычное управление //Данные изображения, побитые по строкам и байты будут на индикаторе вертикально. //Это просто последовательность байт для записи в индикатор начиная с верхней страницы. //Полностью соответствуют картинке распределения ОЗУ в документации на модуль. byte Logo122[4][122]= //122x32 pixel, каждые 8 вертикальных точек собраны в байт { { 0xFF,0x01,0x01,0x01,0x01,0xC1,0xE1,0xB1,0x11,0x1D,0x1D,0x7F,0x7F,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFD,0xF9,0xB1, 0xF1,0xE1,0x81,0x01,0x01,0x01,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1, 0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1, 0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1, 0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1, 0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1, 0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xC1,0xFF }, { 0xFF,0xE0,0x7C,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x6F,0x6F,0x07, 0x07,0x06,0x00,0x00,0x03,0x03,0x0F,0x3F,0x07,0x07,0x07,0x03,0x03,0x07,0x0F,0x3B, 0x13,0x80,0x80,0x23,0x9E,0xF8,0xF8,0xF8,0xFC,0xFE,0xFE,0xFE,0xFC,0x00,0x00,0x00, 0x80,0x80,0xE0,0xF8,0xFC,0xFE,0xFE,0xFE,0xFC,0x00,0x00,0x00,0x60,0xF0,0xF8,0xF8, 0x7C,0x3E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x3E,0x3E,0x7E,0xFC,0xF8,0xF0,0xE0, 0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFC,0xFE, 0xFE,0xFE,0xFE,0xFC,0x00,0x1C,0x3E,0x3E,0x3E,0x3E,0x3E,0x3E,0x3E,0xFE,0xFE,0xFE, 0xFE,0xFE,0x3E,0x3E,0x3E,0x3E,0x3E,0x3E,0x1C,0xFF }, { 0xFF,0x07,0x7C,0xE0,0x80,0x00,0x1F,0x3F,0xFF,0xFF,0xFF,0xFF,0x0F,0x30,0x38,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, 0xE0,0xF0,0xFC,0xFF,0xFF,0x3F,0x0F,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0xFE,0xFF, 0x7F,0x7F,0x1F,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x18,0x3C,0x7E,0x7E,0x7E,0x7E,0x7E,0x7E,0x3C,0x3C,0x18,0x00,0x00,0x01,0xFF, 0xFF,0xFF,0xFF,0x00,0x00,0x80,0xE0,0xF0,0xFC,0xFE,0xFF,0x7F,0x1F,0x07,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF, 0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF }, { 0xFF,0x80,0x80,0x80,0x80,0x83,0x86,0x8C,0x98,0xB0,0xB0,0xE0,0xC0,0xC0,0x80,0x80, 0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xF8,0xFC,0xFF,0xFF, 0xBF,0x8F,0x87,0x81,0x80,0x80,0x80,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0x83,0x80, 0x80,0x80,0x80,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x80,0x80,0x86,0x8F,0x9F,0xBF, 0xFE,0xFC,0xF8,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF8,0xF8,0xFC,0xFE,0xBF,0x9F,0x8F, 0x87,0xE3,0xF9,0xFC,0xFF,0xFF,0xBF,0x9F,0x87,0x81,0x80,0x80,0x80,0x80,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFF,0xFF,0xFF, 0xFF,0xFF,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFF } }; struct lcd_type { //Порты вывода для МЭЛТ-12232В byte RES = 11; //Сброс / Выбор типа интерфейса byte A0 = 14; //Адресный сигнал—выбор между передачей данных и команд управления(А0) byte E1 = 15; //Разрешение обращений к модулю (а также строб данных)(1 кристалл) (А1) byte E2 = 16; //Разрешение обращений к модулю (а также строб данных)(2 кристалл) (А2) byte RW = 17; //Выбор режима записи или чтения (А3) uint8_t data_pins[8]; //порты данных }; lcd_type LCD; void myDelayMicroseconds(uint32_t us) { uint32_t tmr = micros(); while (micros() - tmr < us); } void WriteCode(byte b) { WriteByte(b,0,1,1); }//Команды выдаются всегда в оба кристалла индикатора void WriteDataL(byte b) { WriteByte(b,1,1,0); }//Данные в левую половину индикатора void WriteDataR(byte b) { WriteByte(b,1,0,1); }//Данные в правую половину индикатора void SendData(byte val) { for (int i = 0; i < 8; i++) { digitalWrite(LCD.data_pins[i], (val >> i) & 0x01); } myDelayMicroseconds(1); } void WriteByte(byte b, byte cd, byte lf, byte rd) { //При необходимости настроить здесь шину данных на вывод digitalWrite(LCD.RW, LOW); //LCD.RW=0; digitalWrite(LCD.A0, cd); //LCD.A0=cd; //Выдача байта в индикатор как данных или команды SendData(b); //;LCD.D=b; //Выдать байт на шину данных индикатора //Delay(>40ns); //Это время предустановки адреса (tAW) реализовано в отправке digitalWrite(LCD.E1, lf); //LCD.E1=l; digitalWrite(LCD.E2, rd); //LCD.E2=r; //Выдать нужные стробы в индикатор myDelayMicroseconds(1); //Delay(>160ns); //Длительность сигналов E1,E2=1 (время предустановки данных попало сюда (tDS)) digitalWrite(LCD.E1, LOW); //LCD.E1 = LCD.E2 =0; //Сбросить сигналы E1 и E2 digitalWrite(LCD.E2, LOW); //LCD.E1 = LCD.E2 =0; //Сбросить сигналы E1 и E2 myDelayMicroseconds(2); //Delay(>(2000ns-40ns-160ns)); //Минимально допустимый интервал между сигналами E1,E2=1 } void LCD_Init(){ digitalWrite(LCD.E1, LOW); //LCD.E=0;//Начальное значение сигнала индикатору digitalWrite(LCD.E2, LOW); digitalWrite(LCD.RES,LOW); //LCD.RES=0;//Выдать сигнал RES=0 индикатору myDelayMicroseconds(15); // Delay(>10us);//Задержка на время больше 10 мкс digitalWrite(LCD.RES,HIGH); //LCD.RES=1;//Снять сигнал RES delay(2); //Delay(>1ms);//Задержка на время больше 1 мс WriteCode(LCD_RESET); //Reset //LCD_RESET WriteCode(LCD_END); //ReadModifyWrite off //LCD_END WriteCode(LCD_STATIC_DRV_OFF);//Включить обычный режим //LCD_STATIC_DRV_OFF WriteCode(LCD_MULTIPLEX); //Мультиплекс 1/32 //LCD_MULTIPLEX WriteCode(LCD_START_LINE); //Верхнюю строку на 0 //LCD_START_LINE WriteCode(LCD_ADC_FORW); //NonInvert scan RAM //LCD_ADC_FORW WriteCode(LCD_DISPLAY_ON); //Display on //LCD_DISPLAY_ON } void setPins(){ pinMode(LCD.RES, OUTPUT); // Сброс / Выбор типа интерфейса pinMode(LCD.A0, OUTPUT); // Адресный сигнал—выбор между передачей данных и команд управления pinMode(LCD.E1, OUTPUT); // Разрешение обращений к модулю (а также строб данных)(1 кристалл) pinMode(LCD.E2, OUTPUT); // Разрешение обращений к модулю (а также строб данных)(2 кристалл) pinMode(LCD.RW, OUTPUT); // Выбор режима записи или чтения //Порты вывода для данных D0-D7 LCD.data_pins[0] = 9; //d0; LCD.data_pins[1] = 8; //d1; LCD.data_pins[2] = 7; //d2; LCD.data_pins[3] = 6; //d3; LCD.data_pins[4] = 5; //d4; LCD.data_pins[5] = 4; //d5; LCD.data_pins[6] = 3; //d6; LCD.data_pins[7] = 2; //d7; for (int i=0; i< 8 ; ++i) { pinMode(LCD.data_pins[i], OUTPUT); } } void setup() { setPins(); LCD_Init(); } void loop() { // put your main code here, to run repeatedly: byte p; //Номер текущей страницы индикатора byte c; //Позиция по горизонтали выводимого байта for(p=0; p<4; p++) {//Цикл по всем 4-м страницам индикатора WriteCode(p|0xB8);//Установка текущей страницы для обоих кристаллов индикатора WriteCode(0x00);//Установка текущего адреса для записи данных в 0 for(c=0; c<61; c++) {//Цикл вывода данных в левую половину индикатора WriteDataL(Logo122[p][c]);//Вывод очередного байта в индикатор } for(c=61; c<122; c++) {//Цикл вывода данных в правую половину индикатора WriteDataR(Logo122[p][c]);//Вывод очередного байта в индикатор } } }
Для подключения данного дисплея пришлось задействовать аналоговые пины, т.к не хватало выводов для управления. Пини прописаны в коде в классе lcd_type и в процедуре setPins. По ним можно составить карту подключения. 19 и 20 пин это подсветка - подключил отдельно к источнику питания.