|
LCD + ATmega8, Нет изображения на ЖКИ |
|
|
|
Apr 28 2011, 22:30
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Доброго дня Всем! Думаю эта тема уже конкретно проработана на форуме, но нужного мне ответа не нашел. Пытаюсь подключить ЖКИ к контроллеру. Сначала пробовал использовать готовые библиотеки. Но ничего не получилось. Везде используется другая частота тактирования процессора, и я подозреваю, что я не попадаю в нужные временные задержки дл работы с ЖКИ. Прогу писал в GCC. Также запускал в Протеусе для проверки. Прога не заводилсь. Потом нашел исходничек маленький в CodeVision. Вот он: CODE /***************************************************** This program was produced by the CodeWizardAVR V2.05.0 Professional Automatic Program Generator © Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.comProject : Version : Date : 28.04.2011 Author : NeVaDa Company : Comments: Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 14,745600 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/ #include <mega8.h> //Библиотека для расчета задержки по времени #include <delay.h> // Alphanumeric LCD Module functions #include <alcd.h> // Declare your global variables here void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTB=0x00; DDRB=0x00; // Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0xFF; DDRC=0xFF; // Port D initialization // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 PORTD=0x00; DDRD=0xFF; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer1 Stopped // Mode: Normal top=0xFFFF // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer2 Stopped // Mode: Normal top=0xFF // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off MCUCR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00; // USART initialization // USART disabled UCSRB=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; // ADC initialization // ADC disabled ADCSRA=0x00; // SPI initialization // SPI disabled SPCR=0x00; // TWI initialization // TWI disabled TWCR=0x00; // Alphanumeric LCD initialization // Connections specified in the // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu: // RS - PORTD Bit 2 // RD - PORTD Bit 1 // EN - PORTD Bit 3 // D4 - PORTD Bit 4 // D5 - PORTD Bit 5 // D6 - PORTD Bit 6 // D7 - PORTD Bit 7 // Characters/line: 16 delay_us(500); lcd_init(16); #asm("sei") lcd_gotoxy (2,0); lcd_putsf("HELLO,WORLD!"); while (1) { PORTC=0xFE; delay_ms(1000);//задержка 1 секунда PORTC=0xFF; delay_ms(1000);//задержка 1 секунда } } Светодиод поцепил, чтобы было видно что программа работает. В протеусе эта программа запустилась, но в железе изображения на ЖКИ нет. Регулирую контрастность на ЖКИ, все нормально, сначала темнее верхний ряд, потом нижний. Подскажите в чем может быть проблема? Заранее благодарен за ответ. ЗЫ:Вылаживаю архив с исходником и проектом Протеус
LCD.rar ( 23.62 килобайт )
Кол-во скачиваний: 112ЗЫ2:Хотелось бы написать программу в GCC, так в КодеВижене ничего не видно, что и как работает, а интересно разобраться в работе с ЖКИ. Если у кого то есть исходничек для работы с ЖКИ 44780 и ATmega8 с кварцем 14,745600 МГц, большая просьба выложить или дать нормальную ссылочку.
|
|
|
|
|
Apr 29 2011, 12:48
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Цитата(Сергей Борщ @ Apr 29 2011, 13:40)  Так давайте, пишите. Выкладывайте исходники, схему (только в читаемом виде - картинку, не у всех есть честно купленный протеус). Вместе посмотрим - что не получается и разберемся почему. Спасибо за отзывчивость, вылаживаю все исходные данные. Вот код: CODE #include <avr/io.h> //библиотека ввода/вывода #define RS 2 //RS=PD2 - сигнал управления ЖКИ #define E 3 //E=PD3 - сигнал управления ЖКИ #define TIME 10 //Константа временной задержки для ЖКИ //Частота тактирование МК - 4Мгц //Программа формирования задержки void pause (long int a) { unsigned int i; for (i=a;i>0;i--); } //Программа передачи команд в ЖКИ void lcd_com (unsigned char lcd) { unsigned char temp; temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи команды temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи команды pause (10*TIME); //Пауза для выполнения команды } //Программа записи данных в ЖКИ void lcd_dat (unsigned char lcd) { unsigned char temp; temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи данных temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E asm("nop"); //Небольшая задержка в 1 такт МК, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи данных pause(TIME); //Пауза для вывода данных } //Программа иниализации ЖКИ void lcd_init (void) { lcd_com(0x2c); //4-проводный интерфейс, 5x8 размер символа pause(100*TIME); lcd_com(0x0c); //Показать изображение, курсор не показывать pause(100*TIME); lcd_com(0x01); //Очистить DDRAM и установить курсор на 0x00 pause (100*TIME); } //Основная программа int main(void) { DDRD=0xfc; //Инициализация portD PORTD=0x00;
DDRC=0xFF; PORTC=0xFF; //Инициализация portС
pause(1000); //Задержка, чтобы ЖКИ успел включиться lcd_init(); //Инициализация ЖКИ lcd_dat('w'); //Вывод "www.avrlab.com" lcd_dat('w'); lcd_dat('w'); lcd_dat('.'); lcd_dat('a'); lcd_dat('v'); lcd_dat('r'); lcd_dat('l'); lcd_dat('a'); lcd_dat('b'); lcd_dat('.'); lcd_dat('c'); lcd_dat('o'); lcd_dat('m'); lcd_com(0xc0); //Ставим курсор на начало 2-й строки ЖКИ lcd_dat('I'); //Записываем "It's so easy" lcd_dat('t'); lcd_dat('"'); lcd_dat('s'); lcd_dat(' '); lcd_dat('s'); lcd_dat('o'); lcd_dat(' '); lcd_dat('e'); lcd_dat('a'); lcd_dat('s'); lcd_dat('y'); while (1) { PORTC=0xFE; //мигаем светодиодом для проверки работоспособности программы pause(15000000);//задержка 0,5 секунда PORTC=0xFF; pause(15000000);//задержка 0,5 секунда } return 1; }
Задержки конечно сделано уххх..  , но не хочется заморачиваться с таймером, главное запустить ЖКИ. Значит эта программа мигает светодиодом что в железе, что в Протеус. Есть подозрения, что из-за смены частоты тактирования процессора (в исходном примере кварц был на 4 МГц, а у меня 14,745600МГц), изменились временные интервалы при работе с ЖКИ. Необходимо изменить переменную TEMP, но только на сколько и в какую сторону непонятно. Выкладываю схему подключения
|
|
|
|
|
Apr 29 2011, 13:47
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Melandr @ Apr 29 2011, 15:48)  Задержки конечно сделано уххх..  При включении оптимизации от этой задержки останется пшик. Ибо она не делает ничего полезного с точки зрения компилятора - просто тупо делает хорошую быструю программу медленнее. используйте функции из <avr/delay.h>, для них можно указывать задержку в единицах времени и они не зависят от оптимизации (ну разве что совсем без оптимизации дают гораздо большую задержку). QUOTE (Melandr @ Apr 29 2011, 15:48)  Есть подозрения, что из-за смены частоты тактирования процессора (в исходном примере кварц был на 4 МГц, а у меня 14,745600МГц), изменились временные интервалы при работе с ЖКИ. Вот от таких трудностей и защищена <avr/delay.h>. Изменился кварц - меняете строку #define F_CPU 4000000UL на #define F_CPU 14745600UL (или соответствующий параметр в makefile) а все остальное посчитает компилятор. Чуть позже допишу по остальному коду, там есть мелкие недочеты и главное - неправильная последовательность инициализации. Гляньте вот эту ссылку пока: http://electronix.ru/forum/index.php?s=&am...st&p=143374
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 29 2011, 15:58
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Цитата(Сергей Борщ @ Apr 29 2011, 16:47)  При включении оптимизации от этой задержки останется пшик. Ибо она не делает ничего полезного с точки зрения компилятора - просто тупо делает хорошую быструю программу медленнее. используйте функции из <avr/delay.h>, для них можно указывать задержку в единицах времени и они не зависят от оптимизации (ну разве что совсем без оптимизации дают гораздо большую задержку). Оптимизацию я отключил, чтобы циклы компилятор не убрал. По поводу функции delay, функция хорошая, но там есть ограничение по задержке, вроде бы 768мкс/частоту кварца в МГц, соответственно задержка получается маленькой. Мне непонятно не слишком ли маленькие задержки в одну оперцию asm "nop"?
|
|
|
|
|
Apr 29 2011, 18:12
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Почитал http://electronix.ru/forum/index.php?s=&am...st&p=143374, и решил линию управления RW переключить с GND на линию PD1. Поэтому если будут исходники с чтением состояния ЖКИ, очень хотелось бы ознакомиться.
|
|
|
|
|
Apr 29 2011, 20:22
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Начальную установку дисплея вы делаете неправильно. Основная проблема здесь в том, что по умолчанию при подаче питания дисплей устанавливается в 8-битный интерфейс, а если питание нехорошее, то он может вообще встать в неопределенное состояние. Поэтому на дисплей прежде всего надо подать команду 0х30 установки в режим 8-битного интерфейса. Рекомендуется подавать команду 3 раза. Тут надо учесть, что команду вы подаёте тетрадами, т.е. подавая команду 0х30, вы на самом деле подаёте две команды 0х3х и 0х0х, так что лучше подавать команду 0х33 два-три раза, без разницы. Затем можете подавать команду 0х20 для перехода в 4-битный интерфейс. Состояние дисплея читать пмсм без надобности.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Apr 29 2011, 23:37
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Вопрос по поводу питания. Если у меня напряжение питания 4,6 В, запустится ли ЖКИ? Также по поводу задержек, попробовать просимулировать, определить какие задержки, и скорректировать согласно даташиту?, или можно использовать те, что уже прописаны в программе?
|
|
|
|
|
May 1 2011, 12:37
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Как проверить флаг занятости, какая должна быть последовательность кода? Какие задержки?
Сообщение отредактировал Melandr - May 1 2011, 13:49
|
|
|
|
|
May 1 2011, 20:38
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
переписал немного программу, изменил процедуру инициализации ЖКИ, согласно рекомендациям на форуме. Вот код: CODE #include <avr/io.h> //библиотека ввода/вывода #include <util/delay.h> //библиотека задержек #define RW 1 //RW=PD1 - сигнал управления ЖКИ #define RS 2 //RS=PD2 - сигнал управления ЖКИ #define E 3 //E=PD3 - сигнал управления ЖКИ
//Программа передачи команд в ЖКИ void lcd_com (unsigned char lcd) { unsigned char temp; temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи команды temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи команды _delay_us(100); //Пауза для выполнения команды } //Программа записи данных в ЖКИ void lcd_dat (unsigned char lcd) { unsigned char temp; temp=(lcd|(1<<RS))|(1<<E); //RS=1 – это данные PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи данных temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи данных _delay_us(100); //Пауза для вывода данных } //Программа иниализации ЖКИ void lcd_init (void) { _delay_ms(15); lcd_com(0x33); //8-проводный интерфейс, _delay_ms(4.1); lcd_com(0x33); //8-проводный интерфейс, _delay_us(100); lcd_com(0x33); //8-проводный интерфейс, _delay_us(100); lcd_com(0x20); //4-проводный интерфейс, lcd_com(0x08); // полное выключение дисплея lcd_com(0x01); // очистка дисплея _delay_us(100); lcd_com(0x06); // сдвиг курсора вправо lcd_com(0x0D); // включение дисплея дисплея, мигающий курсор } //Основная программа int main(void) { DDRD=0xFE; //Инициализация portD PORTD=0x00;
DDRC=0xFF; PORTC=0xFF; //Инициализация portС
lcd_init(); //Инициализация ЖКИ lcd_dat('w'); //Вывод "www.avrlab.com" lcd_dat('w'); lcd_dat('w'); lcd_dat('.'); lcd_dat('a'); lcd_dat('v'); lcd_dat('r'); lcd_dat('l'); lcd_dat('a'); lcd_dat('b'); lcd_dat('.'); lcd_dat('c'); lcd_dat('o'); lcd_dat('m'); lcd_com(0xc0); //Ставим курсор на начало 2-й строки ЖКИ lcd_dat('I'); //Записываем "It's so easy" lcd_dat('t'); lcd_dat('"'); lcd_dat('s'); lcd_dat(' '); lcd_dat('s'); lcd_dat('o'); lcd_dat(' '); lcd_dat('e'); lcd_dat('a'); lcd_dat('s'); lcd_dat('y'); while (1) { PORTC=0xFE; //мигаем светодиодом для проверки работоспособности программы _delay_ms(1000);//задержка 1 секунда PORTC=0xFF; _delay_ms(1000);//задержка 1 секунда } return 1; }
Попробовал запустить в железе, светодиод мигает, а на экран ЖКИ информация не выводится. В протеусе тоже самое, на экране ничего нет. Ваши Комментарии ожидаю, в чем может быть проблема? В протеусе выдало такие предупреждения
Подключил сигнал управления RW к порту PD1, но почему-то вместо того чтобы быть в "0", в симуляторе PD1 находится в высоком состоянии. Что неправильно?
Сообщение отредактировал Melandr - May 1 2011, 21:23
|
|
|
|
|
May 1 2011, 21:50
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Изменил код, получается линия RW при записи байта устанавливалась в "1", теперь код такой: CODE #include <avr/io.h> //библиотека ввода/вывода #include <util/delay.h> //библиотека задержек #define RW 1 //RW=PD1 - сигнал управления ЖКИ #define RS 2 //RS=PD2 - сигнал управления ЖКИ #define E 3 //E=PD3 - сигнал управления ЖКИ
//Программа передачи команд в ЖКИ void lcd_com (unsigned char lcd) { unsigned char temp; temp=((lcd&~(1<<RS))&~(1<<RW))|(1<<E); //RS=0 – это команда PORTD=temp; //Выводим на portD старшую тетраду команды, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи команды temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи команды _delay_us(100); //Пауза для выполнения команды } //Программа записи данных в ЖКИ void lcd_dat (unsigned char lcd) { unsigned char temp; temp=((lcd&~(1<<RW))|(1<<RS))|(1<<E); //RS=1 – это данные PORTD=temp; //Выводим на portD старшую тетраду данных, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи данных temp=((lcd*16)|(1<<RS))|(1<<E); //RS=1 – это данные PORTD=temp; //Выводим на portD младшую тетраду данных, сигналы RS, E _delay_us(2); //Небольшая задержка в 2 мкс, для стабилизации PORTD=temp&~(1<<E); //Сигнал записи данных _delay_us(100); //Пауза для вывода данных } //Программа иниализации ЖКИ void lcd_init (void) { _delay_ms(15); lcd_com(0x33); //8-проводный интерфейс, _delay_ms(4.1); lcd_com(0x33); //8-проводный интерфейс, _delay_us(100); lcd_com(0x33); //8-проводный интерфейс, _delay_us(100); lcd_com(0x20); //4-проводный интерфейс, lcd_com(0x08); // полное выключение дисплея lcd_com(0x01); // очистка дисплея _delay_us(100); lcd_com(0x06); // сдвиг курсора вправо lcd_com(0x0D); // включение дисплея дисплея, мигающий курсор } //Основная программа int main(void) { DDRD=0xFE; //Инициализация portD PORTD=0x00;
DDRC=0xFF; PORTC=0xFF; //Инициализация portС
lcd_init(); //Инициализация ЖКИ lcd_dat('w'); //Вывод "www.avrlab.com" lcd_dat('w'); lcd_dat('w'); lcd_dat('.'); lcd_dat('a'); lcd_dat('v'); lcd_dat('r'); lcd_dat('l'); lcd_dat('a'); lcd_dat('b'); lcd_dat('.'); lcd_dat('c'); lcd_dat('o'); lcd_dat('m'); lcd_com(0xc0); //Ставим курсор на начало 2-й строки ЖКИ lcd_dat('I'); //Записываем "It's so easy" lcd_dat('t'); lcd_dat('"'); lcd_dat('s'); lcd_dat(' '); lcd_dat('s'); lcd_dat('o'); lcd_dat(' '); lcd_dat('e'); lcd_dat('a'); lcd_dat('s'); lcd_dat('y'); while (1) { PORTC=0xFE; //мигаем светодиодом для проверки работоспособности программы _delay_ms(1000);//задержка 1 секунда PORTC=0xFF; _delay_ms(1000);//задержка 1 секунда } return 1; }
в Протеусе теперь лог такой, но все равно ни в железе ни в протеусе не работает:
|
|
|
|
|
May 2 2011, 07:55
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435

|
Частоту кварца указал правильно. Сейчас подкоректирую программу и проверю. По поводу подсветки в протеусе подключил без подстроечного резистора, попробую поставить резистор.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|