Дисплей 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 пин это подсветка - подключил отдельно к источнику питания.