Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Добавлено: Пт фев 13, 2015 09:58:21
Друг Кота
Карма: 67
Рейтинг сообщений: 1060
Зарегистрирован: Чт сен 18, 2008 12:27:21 Сообщений: 19693 Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения:0 Медали: 1
Эээ... как вы себе это представляете?
_________________ [ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ] Измерить нннада?
Есть сделанная плата с этим индикатором. Сделана так, что колодка выводов снизу, жестко впаяна в плату. Соответственно, при запуске индикатора оказалось что все символы вверх ногами Теперь сижу курю даташит. Если не получится решить программно, то предется крутить индикатор, чего бы не хотелось делать.
Использование модульных источников питания открытого типа широко распространено в современных устройствах. Присущие им компактность, гибкость в интеграции и высокая эффективность делают их отличным решением для систем промышленной автоматизации, телекоммуникационного оборудования, медицинской техники, устройств «умного дома» и прочих приложений. Рассмотрим подробнее характеристики и особенности трех самых популярных вариантов AC/DC-преобразователей MW открытого типа, подходящих для применения в промышленных устройствах - серий EPS, EPP и RPS представленных на Meanwell.market.
Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Добавлено: Пт фев 13, 2015 10:31:04
Друг Кота
Карма: 67
Рейтинг сообщений: 1060
Зарегистрирован: Чт сен 18, 2008 12:27:21 Сообщений: 19693 Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения:0 Медали: 1
eess9 писал(а):
Теперь сижу курю даташит.
Вот я про это и спрашивал, что вы хотите там найти? Если только рисовать свои "перевёрнутые" символы.
_________________ [ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ] Измерить нннада?
Друзья, прошу помощи с запуском дисплея! Модель: МТ-16S2H-2YLG. (Даташит http://lib.chipdip.ru/243/DOC000243344.pdf) МК: C8051F320, язык C. В общем никак не могу завести сие чудо. Код для дисплея взял из интернета, но переделал (видимо, криво) и исправил кое-что под 4-битный режим. Некоторых вещей в изначальном коде до сих пор не понял, в выводе строк тоже пока не до конца разобрался, но мне хотя бы 1 символ вывести P1.4-P1.7 = DB4-DB7 P1.1=EN; P1.2 = RW; P1.3=DC; Код: Спойлер
sbit EN = P1^1; sbit RW = P1^2; sbit DC = P1^3; /* * ВСЕ МЕТОДЫ ДОЛЖНЫ БЫТЬ УВЕРЕНЫ, ЧТО РАБОТАЮТ В 8-БИТ РЕЖИМЕ * ДРОБЕНИЕ НА ПОЛУБАЙТЫ ПРОИЗВОДИТЬ НЕПОСРЕДСТВЕННО В * МЕТОДАХ GET DATA И SET DATA!!! */ //************************************************************* void LCD_delay (void)//Маленькая задержка { TH1 = 0xFF;//Задержка ~60мкс TL1 = 0xC0;// TCON_TR1=1;//Запуск таймер 1 while(TCON_TF1==0);//Ожидание поднятия флага переполнения таймера 1 TCON_TR1=0;//Стоп таймер 1 TCON_TF1=0;//Сбросить флаг переполнения } unsigned char Get_Data (void)//Берем данные с дисплея. { unsigned char CH=0; DATABUS_CF &= 0x0F; // Режим с открытым истоком регистр обнулить (кроме P1^0-P1^3, они не наши) 0000 1111 DATABUS |= 0xF0; // Данные на ввод, DB4-7 должны быть "1" CH=DATABUS; EN=1; LCD_delay();//По идее задержка не нужна EN=0; return CH; // Взять данные } //************************************************************* void Set_Data (unsigned char CH)//Отрпавить биты в порт { unsigned char temp=0x00; temp = CH; DATABUS_CF |= 0xF0;//Режим push pull Для левой части, то есть работаем на ВЫВОД CH = CH | 0x0F;//Левая часть - первый полубайт. Правую ставим в "1", что бы не сбить EW, RW и DC DATABUS &= CH; //Сперва отправим левую часть CH, так как она старше в DB7:DB4 EN=0;// LCD_delay();//По идее задержка тут не нужна EN=1;//Отправили первый полуйбайт temp=temp<<4;//Сдвинем на 4 бита влево temp = temp | 0x0F;//Левая часть - второй полубайт. Правую ставим в "1", что бы не сбить EW, RW и DC DATABUS &= temp; } //************************************************************* /////////////////////// xdata unsigned char IF_LCD; //********************************************************************** code const unsigned char LCDCODE[132] = {0xdb,0xd1,0xdc,0xd9,0x41,0xA0,0x42,0xa1, 0xe0,0x45,0xA3,0xA4,0xa5,0xa6,0x4b,0xa7, 0x4d,0x48,0x4f,0xa8,0x50,0x43,0x54,0xa9, 0xaa,0x58,0xe1,0xab,0xac,0xe2,0xad,0xae, 0x62,0xaf,0xb0,0xb1,0x61,0xb2,0xb3,0xb4, 0xe3,0x65,0xb6,0xb7,0xb8,0xb9,0xba,0xbb, 0xbc,0xbd,0x6f,0xbe,0x70,0x63,0xbf,0x79, 0xe4,0x78,0xe5,0xc0,0xc1,0xe6,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7}; //********************************************************************** void LCD_Init (void) { unsigned char i=0; EN=0; DC=0;//Работаем с командой RW=0; delay(1);//Стартовое ожидание не менее 20 мс, используем внешний делей на 100мс //Тут мы еще в 8 бит режиме, передавать надо все сразу!!! for (i=0;i<3;i++) { EN=1; //DATABUS_CF &= 0x0F; // Режим с открытым истоком почему так? вроде же push pull надо? DATABUS_CF |= 0xF0;//Режим push pull Для левой части DATABUS |= 0x30;//0011 смотри даташит EN=0; LCD_delay(); } EN=1; //DATABUS_CF &= 0x0F; // Режим с открытым истоком почему так? вроде же push pull надо? DATABUS_CF |= 0xF0;//Режим push pull Для левой части DATABUS |= 0x20;//0010 смотри даташит, ставим разрядность EN=0; LCD_delay(); //Далее - уже 4 битный режим, можно проверять флаг занятости (см. даташит) LCD_SetCom(0x28);//0010 100(P)0 Разрядность 4-бит, страница знакогенератора "0"(P) LCD_SetCom(0x08);//0000 1000 Включение модуля, курсора нет, ничего не мигает LCD_SetCom(0x01);//0000 0001 Очищает модуль и помещает курсор в самую левую позицию. Ждать не мене 1,5 мс LCD_SetCom(0x06);//0000 0110 Курсор сдвигаеться вправо, сдвиг дисплея запрещен //????? //PROFIT! }
//********************************************************************** void LCD_Put (unsigned char DB)//Подготовить дисплей к приему команды. Без опроса BUSY но с задержкой, удобно для инициализации { DC=0;//Работаем с командой RW=0; EN=1; Set_Data(DB);//Помещаем даныые в порт LCD_delay();//Зачем ты тут? EN=0; }
//********************************************************************** /*пример из lcd.h * #define LCD_Reset() LCD_SetCom (0x38);LCD_SetCom (0x0E);LCD_SetCom (0x06); * */ void LCD_SetCom (unsigned char DB)//Отправить команду на дисплей и убедиться в выполнении { EN=1; DC=0;//Работаем с командой RW=0;//Пишем внутрь LCD_Put(DB); LCD_Wait(); }
//********************************************************************** void LCD_Wait (void)//Задержка и проверка BUSY { unsigned char CH; volatile unsigned int TIMEOUT=15000;
DC=0;//Работаем с командой EN=1; RW=1;//Берем ИЗ дисплея while (TIMEOUT--) { CH=Get_Data(); CH&=0x80; if(CH==0) break; } EN=0;//Почему это тут?????? LCD_delay();//Зачем? RW=0;//Хватит брать из дисплея }
LCD_SetCom (0x80|Offset[Y]|(X & 0x3F)); } //********************************************************************** unsigned char LCD_ReCode (unsigned char CH)//ПОлучает код символа из массива { if ((CH<0x20)&(CH!=0x0d)) return 0x20; else if (CH==0x0d) return 0x7e; else if ((CH<0xA7)&(CH< 0x7b)) return CH; else if (CH>=0xc0) return LCDCODE[CH-0xc0+4]; }
//********************************************************************** void LCD_WriteData (unsigned char DAT)//Записывает 1 символ { EN=1; RW=0;//Отправляем в дисплей DC=1;//Работаем с данными Set_Data(LCD_ReCode(DAT));//Помещаем даные в порт EN=0; LCD_Wait(); DC=0; }
//********************************************************************** void LCD_String (char *s)//Записывает строку { register int i;
Вызываем из главного *c файла: LCD_Init(); LCD_Put(0xBB); И...получаем ничего. Хотя иногда индикатор выдает это: Спойлер При этом, если отключить индикатор от питания, а затем через какое то время включить, изображение останется (а контроллер то по идее давно крутится во while(1);)! Пробовал увеличить зарежки, а так же разнообразные танцы с бубном - один раз даже чуть не сломал дисплей (подсветка ВНЕЗАПНО выключась, а сзади диплея серьезно поднагрелось). В общем решительно ничего не понимаю и надеюсь лишь на ваш совет!
А контраст вы как регулируете? Проверьте изначально по контрасту часть вашей схемы, потом добейтесь минимального засвечивания знакомест первой строки при включении. В си не помогу сильно, т.к. больше на ассемблере концентрируюсь принципиально. Однако, все беды у людей в 98 % случаев именно с инициализацией дисплеев. Копайте оттуда. Правильно инициализированный покажет вам две строки, т.е. при регулировании контраста, можно будет добавить яркости и второй строки тоже. Если это вышло, тогда можете пробовать выводить символы. Задержки можно делать больше, но не меньше, чем указано в даташитах на них. И по инициализации, посмотрите, чтобы три раза подавалась одна и таже команда, атолько потом переход в режим 4х линий... Я выше (несколько страниц назад) описывал оптимальную инициализацию для них, которую и использовал (и до меня она прекрасно работала). У меня завелся, причем очень даже стабильно.
Если вы в коде написали комментарии с вопросами "Почему и зачем это тут?", то: ЕN - это строб импульс (посмотрите временные диаграммы в даташите, там все очень доходчиво нарисовано), После строба следует задержка, дисплей тормозной агрегат, его ответов или проглатывание команд приходится ждать.
А никак - заземлил Uо и все. В ДШ проде бы написано, что это даст заводские настройки контрастности. У меня и резисторов то под рукой нет
Цитата:
Правильно инициализированный покажет вам две строки
Не очень понял эту часть. Вроде же бы он один из этапов инициализации - полная очистка дисплея? То есть то, что у меня одна из строк полностью загорается - хороший знак?
Цитата:
ЕN - это строб импульс
В целом алгоритм работы устройства я изучил. Все более-менее понятно (за исключением, нужно ли делать задержку между пересылкой двух полубайт в 4-бит режиме.) Проблемы как раз в моей СИшной реализации, инетовский пример не до конца понятен, а мои передлки кода делают ситуацию еще более туманной. Кто бы глянул мой код, буду очень благодарен!
Если покрутить контрастность на просто подключенном дисплее, то он покажет только верхнюю строку от "совсем прозрачной" до "совсем закрашенной". Нужно поймать момент, когда будут чуток видны знакоместа. А если правильно дисплей инициализировали и включили его в режим отображения двух строк, то можно будет контрастностью уже регулировать две строки сразу. Т.е. он покажет и вторую строку. Поставьте резистор переменный в районе 10-20 кОм и покрутите. Может у вас и пишутся символы, но вы их не видите из-за неправильной регулировки контраста. Это первое. Полная очистка не запрещает регулировать контраст. )))) При инициализации надо все управляющие линии держать в нуле изначально. Т.е. сделать их выходами и прижать к земле. Потом задержка на время включения дисплея, что-то в районе 20 мс. Самая долгая. Потом выдаете команду 0b00110000 После нее строб импульс (подняли строб, подожданил 500 нс, опустили строб, подождали 500 нс.) Потом задержка, можно такую же, как в начале. ))) Потом опять строб, т.к. команду на линиях ДБ7-ДБ4 никто не менял, она отправляется снова. Опять задержка как в начале. Опять строб с той же командой. Опять задержка. Теперь выставляем команду 0b00100000 опять строб опять задержка (можно ту же самую, как в начале)
И уходим на чтение флага занятости, и если свободен, то выводим команду 0b00101000 (и дергаем строб), сдвигаем (переворачиваем тетрады) и опять строб. и т.д. очистили дисплей - готовы выводить свои символы. ))))
З.Ы. да. про задержку после полубайта, я не делал, т.к. строб сам с задержкой должен быть в районе 500 нс. И когда строб подняли, значит полубайт проглотился (точнее сказать, что полубайт проглотился тогда, когда строб уронили), можно сдвигать (или переворачивать тетрады местами) и отправлять вторую половину.
2 4elovek37: Можете глянуть на мою библиотеку - там инициализация понятна.
Эту 4-битную часть я для упрощения понимания вырезал из своей более универсальной библиотеки, поддерживающей и 4-bit, и 8-bit и I²C (через PCF8574, у китайцев на алиэкспрессе полпулярна связка такой платы + дисплея) режимы.
Линия RW дисплея предполагается замкнутой на землю, вместо чтения флага занятости просто 100мкс задержка - её хватает.
Здоровья всем! После бесплодных попыток подружить дисплей QAPASS(1602) и тиньку 2313, по 4-х битной шине, спрошу: может ли этот режим быть просто как либо отключен в контроллере дисплея? Попадались кому нибудь подобные экземпляры? По 8 битной шине работает нормально.
СКАЗОЧНИК, только сегодня добрался до радиомагазина - приобрел подстроечный резистор "alpha 2L2 B25K" на 25кОм Вот он: Спойлер В ДШ контроллера почему то нарисованы схемы с 2 резисторами, чего я не очень понимаю. Да и у этого еще и 3 ноги Как мне правильно его подключить, так: или так: P.S. Да, я фотошоп мастер
СКАЗОЧНИК, спаял, теперь действительно могу регулировать яркость, от совсем невидимого, до максимально видимого: Окончательно убедился, что с нынешней версией кода дисплей неуправляется, результат выполнения команды
Код:
LCD_Init();
виден выше (при чем строка появляется только после 2 включения микроконтроллера) - как это трактовать я пока не знаю... Соответственно, команда типа
У вас еще микроконтроллер, который я не знаю. ))) Поэтому придется вам разбираться с даташитом на этот дисплей. Благо, все на русском есть и довольно понятно написано. Напишите инициализацию дисплея самостоятельно, там все просто.
СКАЗОЧНИК, начал писать собственный код с нуля. При просмотре Вашей инструкции заметил одно принципиальное отличие в наших подходах. У меня: 1)Поднять EN в "1" 2)Подготовить и загрузить данные в порт 3)Опустить EN в "0" 4)Задержка У Вас: 1)Подготовить и загрузить данные в порт 2)Поднять EN в "1" 3)Задержка 500 наносекунд 4)Опустить EN в "0" 5)Задержка Порядок настолько важен? Новый код написал согласно Вашему плану. В общем, мой свеженаписанный код пока победного результата не дал, зато я избавился от черной полосы (кстати, код такого символа - 0xFF, что наводит на определенные мысли). Собственно, код (максимально закоментированный, что бы можно было понять логику действий): Спойлер
Код:
/* * newLCD.c * * Created on: 21.02.2015 * Author: Богдан */
void NLCD_delay (void) { TH1 = 0xFF;//Задержка ~60мкс TL1 = 0xC0;// TCON_TR1=1;//Запуск таймер 1 while(TCON_TF1==0);//Ожидание поднятия флага переполнения таймера 1 TCON_TR1=0;//Стоп таймер 1 TCON_TF1=0;//Сбросить флаг переполнения } void NLCD_SetPort (unsigned char dat) { volatile int i=0;//Не оптимизируется компилятором unsigned char temp=0x00;//Для манипуляций с данными temp = dat; dat = dat & 0xF0;//dat=XXXX0000 (где x - отправляемый полубайт) DATABUS = DATABUS & 0x0F;//P1= 0000XXXX(где х - значения DC, RW, EN и P0.0) DATABUS = DATABUS | dat; //Отправлена старшая часть байта EN=1;//Строб вверх! for (i=0;i<4;i++);//Маленькая задержка для 100% отправки данных EN=0;//Строб опущен, дисплей принимает данные temp=temp<<4;//Сдвинем на 4 бита влево проверь это temp = temp & 0xF0;//dat=XXXX0000 (где x - отправляемый полубайт) DATABUS = DATABUS & 0x0F;//P1= 0000XXXX(где х - значения DC, RW, EN и P0.0) DATABUS = DATABUS | temp;//Отправлена младшая часть байта EN=1;//Строб вверх! for (i=0;i<4;i++);//Маленькая задержка для 100% отправки данных EN=0;//Строб опущен, дисплей принимает данные } void NLCD_init() { //RW всегда держать 0;//Пока что мы будем писать только ВНУТРЬ volatile int i=0,k=0;//Не оптимизируются компилятором DATABUS=0x00; delay(1);//Задержка 100 мс //Далее - 8 бит режим DATABUS = DATABUS | 0x30;//0011 смотри даташит for (k=0;k<3;k++) { EN=1;//Строб вверх for (i=0;i<4;i++);//Маленькая задержка для 100% отправки данных EN=0;//Строб опущенн, дисплей принимает данные NLCD_delay(); } DATABUS = DATABUS & 0x0F;//P1= 0000XXXX(где х - значения DC, RW, EN и P0.0) DATABUS = DATABUS | 0x20;//0010 смотри даташит, ставим разрядность EN=1;//Строб вверх for (i=0;i<4;i++);//Маленькая задержка для 100% отправки данных EN=0;//Строб опущенн, дисплей принимает данные NLCD_delay(); //Далее - уже 4 битный режим, можно проверять флаг занятости (см. даташит) NLCD_SetCommand(0x28);//0010 100(P)0 Разрядность 4-бит, страница знакогенератора "0"(P) NLCD_SetCommand(0x08);//0000 1000 Включение модуля, курсора нет, ничего не мигает NLCD_SetCommand(0x01);//0000 0001 Очищает модуль и помещает курсор в самую левую позицию. Ждать не мене 1,5 мс delay(1); NLCD_SetCommand(0x06);//0000 0110 Курсор сдвигаеться вправо, сдвиг дисплея запрещен } void NLCD_SetData (unsigned char dat) {
DC=1;//Работаем с данными NLCD_SetPort (dat); NLCD_delay(); } void NLCD_SetCommand (unsigned char command) { DC=0;//Работаем с командой NLCD_SetPort (command); NLCD_delay(); }
В самом начале инициализации пропишите DC=0, я вроде не увидел у вас, что эта линия прижата к земле. И строб тоже к земле и RW тоже. Еще.. я не разобрался, как у вас организовано чтение флага занятости...
И еще, по идее если написать цикл с условием не с инкрементом, а декрементом, то компилятор должен более плотный код сгенерировать. Т.к. у ассемблера есть команда проверки на ноль, а проверки равенства какому-либо числу - уже больше команд.
И еще. Можно для пущей уверенности, что никакие наводки не парят мозг, оставшиеся линии ДБ0-ДБ3 повесить на землю. Факт не доказанный, однако так спокойнее.
ЗАРАБОТАЛО Все это время я пытался выводить инфу на выключенном дисплее Из сообщения, указанного Albert_V:
Цитата:
единственное, у них не написано про то, что после INIT-а надо дать команду "включить индикатор"
А ведь действительно, ни в родном ДШ на мой индикатор, ни в ДШ по ссылке из сообщения такой инфы нет! Огромное спасибо товарищам СКАЗОЧНИК, Albert_V и WiseLord
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения