Dars 0 5 февраля, 2006 Опубликовано 5 февраля, 2006 (изменено) · Жалоба В общем ситуация такая, всю жизнь сидел на CodeVision, а тут решил перейти на IAR. А там как оказалось нет библиотеки для ЖК, ну я взял и попытался написать простенькую прогу которая выводит букву А на экран ( 20 * 4 ), ну и нифига у меня не работает :( У кого есть библиотечка выложите пожалуйста :) Ну или ткините кто нибудь в ошибку (если вся программа не есть ошибка). #include <delay.h> #include <iom128.h> #include <intrinsics.h> void DB_SET_RESET (int DB7, int DB6, int DB5, int DB4); void LCD_PORT_INIT (void); void LCD_INIT (void); void LCD_PRINT (void); void LCD_CLEAR (void); int main( void ) { delay_s(2); //Пауза DDRB |= (1<<4); PORTB |= (1<<4); // Зажгли светодиод LCD_PORT_INIT(); //Установили порт С на выход LCD_CLEAR(); //Очистка экрана LCD_PRINT(); //Выводим букву А for(;;); return 0; } void DB_SET_RESET (int DB7, int DB6, int DB5, int DB4) { if (DB7) PORTC |= (1<<7); // DB7 = 1 else PORTC &= 0x7F; // DB7 = 0 if (DB6) PORTC |= (1<<6); // DB6 = 1 else PORTC &= 0xBF; // DB6 = 0 if (DB5) PORTC |= (1<<5); // DB5 = 1 else PORTC &= 0xDF; // DB5 = 0 if (DB4) PORTC |= (1<<4); // DB4 = 1 else PORTC &= 0xEF; // DB4 = 0 } void LCD_PORT_INIT (void) { /* Инициализация портов для LCD */ DDRC |= (1<<0); // RS DDRC |= (1<<1); // RW DDRC |= (1<<2); // EN DDRC |= (1<<4); // DB4 DDRC |= (1<<5); // DB5 DDRC |= (1<<6); // DB6 DDRC |= (1<<7); // DB7 } void LCD_INIT (void) { PORTC = 0x30; // RS=0,R/W=0,E=0, DB7=0, DB6=0, DB5=1, DB4=1 delay_ms(5); PORTC = 0x30; // RS=0,R/W=0,E=0, DB7=0, DB6=0, DB5=1, DB4=1 delay_us(100); PORTC = 0x30; // RS=0,R/W=0,E=0, DB7=0, DB6=0, DB5=1, DB4=1 delay_us(100); DB_SET_RESET(0,0,1,0); // Установка 4 битного режима DB7=0, DB6=0, DB5=1, DB4=0 delay_ms(2); DB_SET_RESET(0,0,1,0); //Установка параметров DB7=0, DB6=0, DB5=1, DB4=0 delay_ms(2); DB_SET_RESET(1,0,0,0); //DB7=1, DB6=0, DB5=0, DB4=0 delay_ms(2); DB_SET_RESET(0,0,0,0); //Включение дисплея DB7=0, DB6=0, DB5=0, DB4=0 delay_ms(2); DB_SET_RESET(1,0,0,0); //DB7=1, DB6=0, DB5=0, DB4=0 delay_ms(2); DB_SET_RESET(0,0,0,0); //Очистка дисплея DB7=0, DB6=0, DB5=0, DB4=0 delay_ms(2); DB_SET_RESET(0,0,0,1); //DB7=0, DB6=0, DB5=, DB4=1 delay_ms(2); DB_SET_RESET(0,0,0,0); //Установка режима ввода данных DB7=0,DB6=0,DB5=1,DB4=0 delay_ms(2); DB_SET_RESET(0,1,1,0); //DB7=0, DB6=1, DB5=1, DB4=0 delay_ms(2); } void LCD_PRINT (void) { /* Установка адреса 0 */ PORTC &= 0xFE; // RS = 0 PORTC &= 0xFD; // R/W = 0 PORTC |= (1<<2); // E = 1 PORTC |= (1<<7); // DB7 = 1 DB_SET_RESET(1,0,0,0); PORTC &= 0xFB; // E = 0 delay_us(50); PORTC |= (1<<2); // E = 1 DB_SET_RESET(0,0,0,0); // DB7=0, DB6 = 0, DB5 = 0, DB4 = 0 PORTC &= 0xFB; // E = 0 delay_us(50); /* Вывод буквы A */ PORTC |= (1<<0); // RS = 1 PORTC |= (1<<2); // E = 1 DB_SET_RESET(0,1,0,0); PORTC &= 0xFB; // E = 0 delay_us(40); PORTC |= (1<<2); // E = 1 DB_SET_RESET(0,0,0,1); PORTC &= 0xFB; // E = 0 delay_us(50); } void LCD_CLEAR(void) { PORTC &= 0xFE; // RS = 0 PORTC &= 0xFD; // R/W = 0 PORTC |= (1<<2); // E = 1 DB_SET_RESET(0,0,0,0); PORTC &= 0xFB; // E = 0 delay_ms(2); PORTC |= (1<<2); // E = 1 DB_SET_RESET(0,0,0,1); PORTC &= 0xFB; // E = 0 delay_ms(2); } Изменено 5 февраля, 2006 пользователем Dars Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 6 февраля, 2006 Опубликовано 6 февраля, 2006 · Жалоба Может это поможет? http://www.gaw.ru/html.cgi/txt/lcd/chips/hd44780/start.htm Мне лично в свое время помогло. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
visht 0 6 февраля, 2006 Опубликовано 6 февраля, 2006 · Жалоба У кого есть библиотечка выложите пожалуйста :) Попробуй моё, писал под IAR Ну или ткините кто нибудь в ошибку (если вся программа не есть ошибка). Это лучьше самому, уж очень много у LCD зависит от таймов и начальной инициализации ... IARLCD4bit.RAR Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dars 0 6 февраля, 2006 Опубликовано 6 февраля, 2006 · Жалоба 2haker_fox Да я как раз по той статье и даташиту Hitachi и делаю, задолбали эти задержки, только процессорное время жрут! 2&-rey Спасибо. Ща сяду буду разбираться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
visht 0 7 февраля, 2006 Опубликовано 7 февраля, 2006 · Жалоба Спасибо. Ща сяду буду разбираться. там у меня обшибка вкралась :( функцию Init_instruction() нужно записать так: void Init_instruction(unsigned char DataLCD) { Do_Write(__swap_nibbles(DataLCD) & LCD_MASK); } хотя код проверялся на ЖКД и работал, все таки так будет проавильнее, чтоб не нарушать отчетности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dars 0 10 февраля, 2006 Опубликовано 10 февраля, 2006 · Жалоба Что-то все равно он не работает.... :( Может все таки кто ткнет на ошибку, экран вроде включается, но на команды не реагирует. Я указал режим с курсором а курсора тоже нет :( Вот функция инициализации: void LCD_INIT (void) { delay_ms(45); //Задержка после включения питания LCD_WRITE_NIBL(0x30); //Три раза пишем команду 0x30 delay_ms(4); delay_us(100); LCD_WRITE_NIBL(0x30); delay_us(100); LCD_WRITE_NIBL(0x30); delay_us(40); LCD_WRITE_NIBL(0x20); //Один раз 0x20 delay_us(40); LCD_WRITE_BYTE(0x28); //Function Set LCD_WRITE_BYTE(0x0F); //Включаем экран и курсор delay_us(40); LCD_WRITE_BYTE(0x01); //Очищаем экран delay_ms(1); delay_us(500); LCD_WRITE_BYTE(0x06); //ENTRY_MODE_SET delay_us(40); }; void LCD_WRITE_BYTE (unsigned char LCD_DATA) { LCD_RW=0; LCD_WRITE_NIBL (LCD_DATA); LCD_WRITE_NIBL (__swap_nibbles (LCD_DATA)); }; void LCD_WRITE_NIBL (unsigned char LCD_DATA) { __disable_interrupt(); LCD_E=1; delay_ns(20); LCD_PORT |= (LCD_DATA & 0xF0); delay_ns(230); LCD_E=0; delay_ns(250); __enable_interrupt(); }; DB7 повешен на PORTC7, DB6 на PORTC6, DB5 на PORTC5, DB4 на PORTC4. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 11 февраля, 2006 Опубликовано 11 февраля, 2006 · Жалоба Вот 100% рабочий исходник. Правда для IBM PC, среда Borland C++ 3.1, но сути дела это не меняет. Попробуйте приминить инициализацию дисплея из прикрепленного файла. HD44780.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dars 0 11 февраля, 2006 Опубликовано 11 февраля, 2006 · Жалоба Вот 100% рабочий исходник. Правда для IBM PC, среда Borland C++ 3.1, но сути дела это не меняет. Попробуйте приминить инициализацию дисплея из прикрепленного файла. Спасибо за исходник. Я понял в чем ошибка. У меня неправильная функция записи нибла в порт. Дело в том что у меня RS,RD,EN повешены на тот же прорт что и DB7,DB6,DB5,DB4. RS ------ bit 0 PORTC RD ------ bit 1 PORTC EN ------ bit 2 ... DB4 --- bit 4 ... DB5 --- bit 5 ... DB6 --- bit 6 ... DB7 --- bit 7 ... И я не понимаю как можно четырем старшим битам порта, присвоить значения четырех старших бит числа в виде 0xFF. Побитно тупо. Пока писал так LCD_PORT |= (LCD_DATA & 0xF0);, но это неправильно... :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dars 0 11 февраля, 2006 Опубликовано 11 февраля, 2006 (изменено) · Жалоба Ура!!! Замигал курсор, haker_fox & &-rey :a14: за помощь! Всего надо было строчку LCD_PORT |= (LCD_DATA & 0xF0); заменить на char temp; temp=PORTC; temp |= (LCD_DATA & 0xF0); temp &= (LCD_DATA | 0x0F); LCD_PORT = temp; Изменено 11 февраля, 2006 пользователем Dars Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
IgorKossak 0 11 февраля, 2006 Опубликовано 11 февраля, 2006 · Жалоба Dars, смахивает на шаманство. А физический смысл каков? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dars 0 11 февраля, 2006 Опубликовано 11 февраля, 2006 · Жалоба Dars, смахивает на шаманство. А физический смысл каков? Смысл чего? Кода? Если да, то смысл такой. Работая в четырехбитном режиме, чтобы записать 8 битную команду, надо сначала на (DB7...DB4), вывести старшие биты числа(Bit7...Bit4) а потом младшие(Bit3..0), короче по всем правилам два раза сделать запись. Для этого вызывается функция LCD_WRITE_BYTE . Первый раз она передает функции LCD_WRITE_NIBL принятое значение. LCD_WRITE_NIBL записывает старшие 4 бита числа, в старшие 4 бита порта(в общем DB7=Bit7 числа, DB6=Bit6 числа). char temp; temp=PORTC; temp |= (LCD_DATA & 0xF0); temp &= (LCD_DATA | 0x0F); LCD_PORT = temp; Вот это присваивает старшим 4 битам порта, значение старших 4 бит числа, не меняя младших.(если мы передали число 0101 1101 то значение DB7=0,DB6=1,DB5=0,DB4=1. Второй раз вызывая функцию мы передаем ей значение __swap_nibbles(data_lcd) и она записывает в DB7..4 уже младшие 4 бита. Таким образом в LCD производится запись всего числа. Объяснил как смог. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ArtemK 0 13 февраля, 2006 Опубликовано 13 февраля, 2006 (изменено) · Жалоба Если кому-то интересно, вот модули, которые я написал для работы с LCD и использую в своих проектах. Если не пользоваться ОС, то модуль мало чем интересен. Просто библиотека низкоуровневых функций для работы с контроллером LCD и все. Однако, если пользоваться операционкой (я пока остановил свой выбор на scmRTOS Гарри Журова), то все становится интересней. Для вывода на экран используется промежуточный "видео-буфер". При вызове какой-либо функции вывода на экран производится запись в буфер и сразу же продолжается выполнение текущего процесса. Затем, когда все высокоприоритетные процессы выполнят свою работу и отдадут управление, принимается за работу низкоприоритетный процесс TxtDrvProc, который в цикле выталкивает видео-буфер в hd44780. В программе не требуется вызывать функцию инициализации LCD вручную. Достаточно, чтобы процесс TxtDrvProc просто периодически получал управление и он все сделает сам. Весь вывод на экран осуществляется посредством вызова функций библиотеки "txtlib.h". Есть функции для вывода целых, дрбн. с фиксированной точкой, строк, двоичных, шестнадцатеричных, прогресс-бара, и даты/времени. Кроме того, в архиве есть удобный класс для работы с датой/временем. Для хранения используется один unsigned long, в котором хранится кол-во секунд, прошедших с 1-го января 2001-го года. Доступ к значению года, месяца, числа, часов, минут и секунд осуществляется путем вычислений. Таким образом экземпляр класса занимает всего 4 байта в ОЗУ. Высокосные годы также обрабатываются. Вся настройка осуществляется в файлах *_config.h hd44780.rar Изменено 13 февраля, 2006 пользователем ArtemK Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться