Работа с ЖКИ на контроллере HD44780 и его аналогах
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Здравствуйте, akl.
На самом же деле не надо ничего выдерживать.
ведь я проверяю флаг занятости BF.
а это означает - что не надо вводить никаких задержек.
На самом же деле не надо ничего выдерживать.
ведь я проверяю флаг занятости BF.
а это означает - что не надо вводить никаких задержек.
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Не надо ничего выдерживать - значит не надо.
С Новым годом!
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Вас тоже с наступающим!
Насчет lcd. В описании же ведь написано, что при условии чтения флага занятости hd44780 задержки вводить не надо.
Насчет lcd. В описании же ведь написано, что при условии чтения флага занятости hd44780 задержки вводить не надо.
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Код: Выделить всё
read_BF:
sbi portd, 2 ; E=1
in r18, pinc ; Считывание данных в r18
cbi portd, 2 ; E=0
retВот фрагмент Вашего чтения BF. Предварительно линии шины контроллера переведены на ввод.
Что делает контроллер
- принимает и следующим тактом, т.е. уже при выборке команды IN R18,PINC выставляет E=1
- через 1 мкс (при тактовой 1МГц) записывает состояние шины в регистр
- снимает сигнал E=0
Вроде, все правильно, но... Вы уверены, что линия управления E успеет передать изменение логических уровней 0->1->0 и за это время выходной драйвер HD44780 успеет выставить состояние регистра состояния с учетом параметров шины ( паразитных емкостей печати, шлейфа; плохом, в лучшем случае, согласовании импедансов линии - тут будет и "звон" и "отражение"). Я не уверен. Поэтому и ставлю задержки типа
Код: Выделить всё
write_lcd:
out portc, r16 ; Запись в lcd
;здесь нужна задержка
RCALL W
sbi portd, 2 ; E=1
RCALL W
cbi portd, 2 ; E=0
RCALL W
out portd, r17 ; Data????????????????? line Hi-Z
W:
ret
Намеренно не везде их проставил, чтобы Вы осознанно подошли к этому и далее проставили их самостоятельно. Я правильно сделал?
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Вроди бы правильно...
Только чтение флага занятости занимает 0мкс для hd44780
Только чтение флага занятости занимает 0мкс для hd44780
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Между командами надо выдерживать паузы.
А между командами записи данных в DDRAM???? и сколько?
А между командами записи данных в DDRAM???? и сколько?
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Уважаемые коты и кошки помогите разобраться с LM016 в протэусе. Имеется вот такая схема "Матричная клавиатура 4х4 динамическое считывание данных с портов"
. К схеме имеется готовая прошивка, но с индикатором WH1602. Собрал схему в протэусе, но вместо WH1602 я присоединил LM016. Вставил прошивку в МК. Запустил, ноги индикатора пинингуются, он загорается но при нажатии любой клавиши, на индикаторе ничего не появляется. Создавал еще несколько проектов в протеусе с заменой ЖКИ, тоже самое. Подсказали что, время задерки кажется не совподает. Я новичек, так что прошу сильно не бить. А вот и прошивка.
#include <avr/io.h>
#include <avr/interrupt.h>
#define NUMBER_SIZE 6 //Максимальная разрядность числа
#define RS 2 //RS=PD2
#define E 3 //E=PD3
#define TIME 10 //временная константа для ЖКИ
//Тактовая частота 4Mhz
unsigned char key_code[4][4]={{'C','D','E','F'},
{'B','3','6','9'},
{'A','2','5','8'},
{'0','1','4','7'}}; //Коды клавиш
unsigned char row[NUMBER_SIZE]={}; //массив, который содержит нажатые клавиши
unsigned char row_counter=0; //количество нажатых клавиш
unsigned long int number=0; //Число морганий курсора
void pause (unsigned 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, Е
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);
}
void init_timer (void)
{
TIMSK=(1<<TOIE0); //Разрешить прерывания по переполнению таймера0
TCCR0=(1<<CS00)|(1<<CS01)|(0<<CS02); //Делитель =/64
}
//Проверка, является ли х цифрой, если да результат =1, иначе результат =0
unsigned char is_digit (unsigned char x)
{
if ((x>='0')&&(x<='9')) return 1;
else return 0;
}
//Конвертирует "row" в int значение number
void get_number(void)
{ unsigned char i;
number=0;
for (i=0;i<row_counter;i++)
{
number=number*10;
number=number+row[i]-0x30;
}
}
//Пишем row на ЖКИ
void write_row (void)
{ unsigned char i;
lcd_com(0x86); //Перейдем в начало
for (i=0;i<row_counter;i++) //Пишем row
lcd_dat(row[i]);
for(i=row_counter;i<NUMBER_SIZE;i++) //Очистим незаполненные ячейки
lcd_dat(' ');
}
ISR (TIMER0_OVF_vect)
{ unsigned char i,j;
DDRC=0x00; //PortC как вход
PORTC=0x0f;
DDRB=0x0f; //PortB как выход
PORTB=0x00;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
i=4;
if ((PINC&0x01)==0x00) i=0; //Если нажата клавиша в 0й колонке, i=0
if ((PINC&0x02)==0x00) i=1; //...
if ((PINC&0x04)==0x00) i=2;
if ((PINC&0x08)==0x00) i=3;
DDRC=0x0f; //PortC как выход
PORTC=0x00;
DDRB=0x00; //PortB как вход
PORTB=0x0f;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
j=4;
if ((PINB&0x01)==0x00) j=0; //Если нажата клавиша в 0й строке, j=0
if ((PINB&0x02)==0x00) j=1; //...
if ((PINB&0x04)==0x00) j=2;
if ((PINB&0x08)==0x00) j=3;
if ((i!=4)&&(j!=4))
{ //Если была нажата клавиша
while ((PINB&_BV(j))==0x00) //Ждем отжатия
;
if ((is_digit(key_code[i][j])==1)&& //Нажата цифра и не достигнут лимит в NUMBER_SIZE
(row_counter<NUMBER_SIZE)) { //Добавить в row и увеличить row_counter
row[row_counter]=key_code[i][j];
row_counter++;
}
if (key_code[i][j]=='F') row_counter=0x00; //Если нажата 'F' очищаем row
if ((key_code[i][j]=='E')&&
(row_counter>0x00)) row_counter--; //Если нажата 'E'
//и есть введенные цифры – удалить последнюю
if (key_code[i][j]=='C') { //Если нажата 'C' тогда мигаем number раз
get_number();
while (number>0) //Мигаем number раз
{
lcd_com(0xc0);
lcd_dat(0xff);
pause(32000);
pause(32000);
pause(32000);
pause(32000);
lcd_com(0xc0);
lcd_dat(' ');
pause(32000);
pause(32000);
pause(32000);
pause(32000);
number=number-1;
}
}
write_row(); //Пишем row на ЖКИ
}
TCNT0=0x00; //Очищаем таймер и флаг переполнения
TIFR=0x00;
return;
}
int main(void)
{
DDRD=0xfc; //Инициализация PortD
PORTD=0x00;
pause(1000); //Задержка для включения ЖКИ
lcd_init(); //Инициализация ЖКИ
init_timer(); //Инициализация нулевого таймера
lcd_dat('D'); //Напишем на ЖКИ "Data= "
lcd_dat('a');
lcd_dat('t');
lcd_dat('a');
lcd_dat('=');
lcd_dat(' ');
sei(); //Разрешения прерываний
while(1) //Вечный цикл
;
return 1;
}
. К схеме имеется готовая прошивка, но с индикатором WH1602. Собрал схему в протэусе, но вместо WH1602 я присоединил LM016. Вставил прошивку в МК. Запустил, ноги индикатора пинингуются, он загорается но при нажатии любой клавиши, на индикаторе ничего не появляется. Создавал еще несколько проектов в протеусе с заменой ЖКИ, тоже самое. Подсказали что, время задерки кажется не совподает. Я новичек, так что прошу сильно не бить. А вот и прошивка.#include <avr/io.h>
#include <avr/interrupt.h>
#define NUMBER_SIZE 6 //Максимальная разрядность числа
#define RS 2 //RS=PD2
#define E 3 //E=PD3
#define TIME 10 //временная константа для ЖКИ
//Тактовая частота 4Mhz
unsigned char key_code[4][4]={{'C','D','E','F'},
{'B','3','6','9'},
{'A','2','5','8'},
{'0','1','4','7'}}; //Коды клавиш
unsigned char row[NUMBER_SIZE]={}; //массив, который содержит нажатые клавиши
unsigned char row_counter=0; //количество нажатых клавиш
unsigned long int number=0; //Число морганий курсора
void pause (unsigned 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, Е
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);
}
void init_timer (void)
{
TIMSK=(1<<TOIE0); //Разрешить прерывания по переполнению таймера0
TCCR0=(1<<CS00)|(1<<CS01)|(0<<CS02); //Делитель =/64
}
//Проверка, является ли х цифрой, если да результат =1, иначе результат =0
unsigned char is_digit (unsigned char x)
{
if ((x>='0')&&(x<='9')) return 1;
else return 0;
}
//Конвертирует "row" в int значение number
void get_number(void)
{ unsigned char i;
number=0;
for (i=0;i<row_counter;i++)
{
number=number*10;
number=number+row[i]-0x30;
}
}
//Пишем row на ЖКИ
void write_row (void)
{ unsigned char i;
lcd_com(0x86); //Перейдем в начало
for (i=0;i<row_counter;i++) //Пишем row
lcd_dat(row[i]);
for(i=row_counter;i<NUMBER_SIZE;i++) //Очистим незаполненные ячейки
lcd_dat(' ');
}
ISR (TIMER0_OVF_vect)
{ unsigned char i,j;
DDRC=0x00; //PortC как вход
PORTC=0x0f;
DDRB=0x0f; //PortB как выход
PORTB=0x00;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
i=4;
if ((PINC&0x01)==0x00) i=0; //Если нажата клавиша в 0й колонке, i=0
if ((PINC&0x02)==0x00) i=1; //...
if ((PINC&0x04)==0x00) i=2;
if ((PINC&0x08)==0x00) i=3;
DDRC=0x0f; //PortC как выход
PORTC=0x00;
DDRB=0x00; //PortB как вход
PORTB=0x0f;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
j=4;
if ((PINB&0x01)==0x00) j=0; //Если нажата клавиша в 0й строке, j=0
if ((PINB&0x02)==0x00) j=1; //...
if ((PINB&0x04)==0x00) j=2;
if ((PINB&0x08)==0x00) j=3;
if ((i!=4)&&(j!=4))
{ //Если была нажата клавиша
while ((PINB&_BV(j))==0x00) //Ждем отжатия
;
if ((is_digit(key_code[i][j])==1)&& //Нажата цифра и не достигнут лимит в NUMBER_SIZE
(row_counter<NUMBER_SIZE)) { //Добавить в row и увеличить row_counter
row[row_counter]=key_code[i][j];
row_counter++;
}
if (key_code[i][j]=='F') row_counter=0x00; //Если нажата 'F' очищаем row
if ((key_code[i][j]=='E')&&
(row_counter>0x00)) row_counter--; //Если нажата 'E'
//и есть введенные цифры – удалить последнюю
if (key_code[i][j]=='C') { //Если нажата 'C' тогда мигаем number раз
get_number();
while (number>0) //Мигаем number раз
{
lcd_com(0xc0);
lcd_dat(0xff);
pause(32000);
pause(32000);
pause(32000);
pause(32000);
lcd_com(0xc0);
lcd_dat(' ');
pause(32000);
pause(32000);
pause(32000);
pause(32000);
number=number-1;
}
}
write_row(); //Пишем row на ЖКИ
}
TCNT0=0x00; //Очищаем таймер и флаг переполнения
TIFR=0x00;
return;
}
int main(void)
{
DDRD=0xfc; //Инициализация PortD
PORTD=0x00;
pause(1000); //Задержка для включения ЖКИ
lcd_init(); //Инициализация ЖКИ
init_timer(); //Инициализация нулевого таймера
lcd_dat('D'); //Напишем на ЖКИ "Data= "
lcd_dat('a');
lcd_dat('t');
lcd_dat('a');
lcd_dat('=');
lcd_dat(' ');
sei(); //Разрешения прерываний
while(1) //Вечный цикл
;
return 1;
}
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Уважаемые коты и кошки помогите разобраться с LM016 в протэусе. Имеется вот такая схема "Матричная клавиатура 4х4 динамическое считывание данных с портов"
. К схеме имеется готовая прошивка, но с индикатором WH1602. Собрал схему в протэусе, но вместо WH1602 я присоединил LM016. Вставил прошивку в МК. Запустил, ноги индикатора пинингуются, он загорается но при нажатии любой клавиши, на индикаторе ничего не появляется. Создавал еще несколько проектов в протеусе с заменой ЖКИ, тоже самое. Подсказали что, время задерки кажется не совподает. Я новичек, так что прошу сильно не бить. А вот и прошивка.
#include <avr/io.h>
#include <avr/interrupt.h>
#define NUMBER_SIZE 6 //Максимальная разрядность числа
#define RS 2 //RS=PD2
#define E 3 //E=PD3
#define TIME 10 //временная константа для ЖКИ
//Тактовая частота 4Mhz
unsigned char key_code[4][4]={{'C','D','E','F'},
{'B','3','6','9'},
{'A','2','5','8'},
{'0','1','4','7'}}; //Коды клавиш
unsigned char row[NUMBER_SIZE]={}; //массив, который содержит нажатые клавиши
unsigned char row_counter=0; //количество нажатых клавиш
unsigned long int number=0; //Число морганий курсора
void pause (unsigned 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, Е
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);
}
void init_timer (void)
{
TIMSK=(1<<TOIE0); //Разрешить прерывания по переполнению таймера0
TCCR0=(1<<CS00)|(1<<CS01)|(0<<CS02); //Делитель =/64
}
//Проверка, является ли х цифрой, если да результат =1, иначе результат =0
unsigned char is_digit (unsigned char x)
{
if ((x>='0')&&(x<='9')) return 1;
else return 0;
}
//Конвертирует "row" в int значение number
void get_number(void)
{ unsigned char i;
number=0;
for (i=0;i<row_counter;i++)
{
number=number*10;
number=number+row[i]-0x30;
}
}
//Пишем row на ЖКИ
void write_row (void)
{ unsigned char i;
lcd_com(0x86); //Перейдем в начало
for (i=0;i<row_counter;i++) //Пишем row
lcd_dat(row[i]);
for(i=row_counter;i<NUMBER_SIZE;i++) //Очистим незаполненные ячейки
lcd_dat(' ');
}
ISR (TIMER0_OVF_vect)
{ unsigned char i,j;
DDRC=0x00; //PortC как вход
PORTC=0x0f;
DDRB=0x0f; //PortB как выход
PORTB=0x00;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
i=4;
if ((PINC&0x01)==0x00) i=0; //Если нажата клавиша в 0й колонке, i=0
if ((PINC&0x02)==0x00) i=1; //...
if ((PINC&0x04)==0x00) i=2;
if ((PINC&0x08)==0x00) i=3;
DDRC=0x0f; //PortC как выход
PORTC=0x00;
DDRB=0x00; //PortB как вход
PORTB=0x0f;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
j=4;
if ((PINB&0x01)==0x00) j=0; //Если нажата клавиша в 0й строке, j=0
if ((PINB&0x02)==0x00) j=1; //...
if ((PINB&0x04)==0x00) j=2;
if ((PINB&0x08)==0x00) j=3;
if ((i!=4)&&(j!=4))
{ //Если была нажата клавиша
while ((PINB&_BV(j))==0x00) //Ждем отжатия
;
if ((is_digit(key_code[i][j])==1)&& //Нажата цифра и не достигнут лимит в NUMBER_SIZE
(row_counter<NUMBER_SIZE)) { //Добавить в row и увеличить row_counter
row[row_counter]=key_code[i][j];
row_counter++;
}
if (key_code[i][j]=='F') row_counter=0x00; //Если нажата 'F' очищаем row
if ((key_code[i][j]=='E')&&
(row_counter>0x00)) row_counter--; //Если нажата 'E'
//и есть введенные цифры – удалить последнюю
if (key_code[i][j]=='C') { //Если нажата 'C' тогда мигаем number раз
get_number();
while (number>0) //Мигаем number раз
{
lcd_com(0xc0);
lcd_dat(0xff);
pause(32000);
pause(32000);
pause(32000);
pause(32000);
lcd_com(0xc0);
lcd_dat(' ');
pause(32000);
pause(32000);
pause(32000);
pause(32000);
number=number-1;
}
}
write_row(); //Пишем row на ЖКИ
}
TCNT0=0x00; //Очищаем таймер и флаг переполнения
TIFR=0x00;
return;
}
int main(void)
{
DDRD=0xfc; //Инициализация PortD
PORTD=0x00;
pause(1000); //Задержка для включения ЖКИ
lcd_init(); //Инициализация ЖКИ
init_timer(); //Инициализация нулевого таймера
lcd_dat('D'); //Напишем на ЖКИ "Data= "
lcd_dat('a');
lcd_dat('t');
lcd_dat('a');
lcd_dat('=');
lcd_dat(' ');
sei(); //Разрешения прерываний
while(1) //Вечный цикл
;
return 1;
}
. К схеме имеется готовая прошивка, но с индикатором WH1602. Собрал схему в протэусе, но вместо WH1602 я присоединил LM016. Вставил прошивку в МК. Запустил, ноги индикатора пинингуются, он загорается но при нажатии любой клавиши, на индикаторе ничего не появляется. Создавал еще несколько проектов в протеусе с заменой ЖКИ, тоже самое. Подсказали что, время задерки кажется не совподает. Я новичек, так что прошу сильно не бить. А вот и прошивка.#include <avr/io.h>
#include <avr/interrupt.h>
#define NUMBER_SIZE 6 //Максимальная разрядность числа
#define RS 2 //RS=PD2
#define E 3 //E=PD3
#define TIME 10 //временная константа для ЖКИ
//Тактовая частота 4Mhz
unsigned char key_code[4][4]={{'C','D','E','F'},
{'B','3','6','9'},
{'A','2','5','8'},
{'0','1','4','7'}}; //Коды клавиш
unsigned char row[NUMBER_SIZE]={}; //массив, который содержит нажатые клавиши
unsigned char row_counter=0; //количество нажатых клавиш
unsigned long int number=0; //Число морганий курсора
void pause (unsigned 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, Е
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);
}
void init_timer (void)
{
TIMSK=(1<<TOIE0); //Разрешить прерывания по переполнению таймера0
TCCR0=(1<<CS00)|(1<<CS01)|(0<<CS02); //Делитель =/64
}
//Проверка, является ли х цифрой, если да результат =1, иначе результат =0
unsigned char is_digit (unsigned char x)
{
if ((x>='0')&&(x<='9')) return 1;
else return 0;
}
//Конвертирует "row" в int значение number
void get_number(void)
{ unsigned char i;
number=0;
for (i=0;i<row_counter;i++)
{
number=number*10;
number=number+row[i]-0x30;
}
}
//Пишем row на ЖКИ
void write_row (void)
{ unsigned char i;
lcd_com(0x86); //Перейдем в начало
for (i=0;i<row_counter;i++) //Пишем row
lcd_dat(row[i]);
for(i=row_counter;i<NUMBER_SIZE;i++) //Очистим незаполненные ячейки
lcd_dat(' ');
}
ISR (TIMER0_OVF_vect)
{ unsigned char i,j;
DDRC=0x00; //PortC как вход
PORTC=0x0f;
DDRB=0x0f; //PortB как выход
PORTB=0x00;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
i=4;
if ((PINC&0x01)==0x00) i=0; //Если нажата клавиша в 0й колонке, i=0
if ((PINC&0x02)==0x00) i=1; //...
if ((PINC&0x04)==0x00) i=2;
if ((PINC&0x08)==0x00) i=3;
DDRC=0x0f; //PortC как выход
PORTC=0x00;
DDRB=0x00; //PortB как вход
PORTB=0x0f;
pause(10); //Задержка для устренения всяких переходных процессов, важно ее не забыть!
j=4;
if ((PINB&0x01)==0x00) j=0; //Если нажата клавиша в 0й строке, j=0
if ((PINB&0x02)==0x00) j=1; //...
if ((PINB&0x04)==0x00) j=2;
if ((PINB&0x08)==0x00) j=3;
if ((i!=4)&&(j!=4))
{ //Если была нажата клавиша
while ((PINB&_BV(j))==0x00) //Ждем отжатия
;
if ((is_digit(key_code[i][j])==1)&& //Нажата цифра и не достигнут лимит в NUMBER_SIZE
(row_counter<NUMBER_SIZE)) { //Добавить в row и увеличить row_counter
row[row_counter]=key_code[i][j];
row_counter++;
}
if (key_code[i][j]=='F') row_counter=0x00; //Если нажата 'F' очищаем row
if ((key_code[i][j]=='E')&&
(row_counter>0x00)) row_counter--; //Если нажата 'E'
//и есть введенные цифры – удалить последнюю
if (key_code[i][j]=='C') { //Если нажата 'C' тогда мигаем number раз
get_number();
while (number>0) //Мигаем number раз
{
lcd_com(0xc0);
lcd_dat(0xff);
pause(32000);
pause(32000);
pause(32000);
pause(32000);
lcd_com(0xc0);
lcd_dat(' ');
pause(32000);
pause(32000);
pause(32000);
pause(32000);
number=number-1;
}
}
write_row(); //Пишем row на ЖКИ
}
TCNT0=0x00; //Очищаем таймер и флаг переполнения
TIFR=0x00;
return;
}
int main(void)
{
DDRD=0xfc; //Инициализация PortD
PORTD=0x00;
pause(1000); //Задержка для включения ЖКИ
lcd_init(); //Инициализация ЖКИ
init_timer(); //Инициализация нулевого таймера
lcd_dat('D'); //Напишем на ЖКИ "Data= "
lcd_dat('a');
lcd_dat('t');
lcd_dat('a');
lcd_dat('=');
lcd_dat(' ');
sei(); //Разрешения прерываний
while(1) //Вечный цикл
;
return 1;
}
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
измени
//Иниализация ЖКИ
void lcd_init (void)
{
lcd_com(0x02);
pause(100*TIME);
lcd_com(0x2c); //4-проводный интерфейс, 5x8 размер символа
pause(100*TIME);
lcd_com(0x0c); //Показать изображение, курсор не показывать
pause(100*TIME);
lcd_com(0x01); //Очистить DDRAM и установить курсор на 0x00
pause (100*TIME);
}
//Иниализация ЖКИ
void lcd_init (void)
{
lcd_com(0x02);
pause(100*TIME);
lcd_com(0x2c); //4-проводный интерфейс, 5x8 размер символа
pause(100*TIME);
lcd_com(0x0c); //Показать изображение, курсор не показывать
pause(100*TIME);
lcd_com(0x01); //Очистить DDRAM и установить курсор на 0x00
pause (100*TIME);
}
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Stalker46 писал(а):Между командами надо выдерживать паузы.
А между командами записи данных в DDRAM???? и сколько?
Для того, чтобы не гадать "сколько?" и служит флаг занятости BF. Если временная диаграмма обмена с HD44780 (установка адреса, RS, RW, E) выдержана, остается только анализ BF. В итоге это значительно ускоряет правильную выдачу на индикацию.
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
да не, я сделал программную задержку в 1,5мс, 40мкс.
Но это для записи команд в IR.
А для записи данных в DR нужно всего лишь выдержать вот такие временные параметры:

и не выдерживать никаких 40мкс или 1,5мс после записи.
Ведь так?
Ведь эти 1,5мс или 40мкс - это всего лишь задержки внутренней инициализации LCD (например, установка курсора или адреса, там...)
Но это для записи команд в IR.
А для записи данных в DR нужно всего лишь выдержать вот такие временные параметры:
и не выдерживать никаких 40мкс или 1,5мс после записи.
Ведь так?
Ведь эти 1,5мс или 40мкс - это всего лишь задержки внутренней инициализации LCD (например, установка курсора или адреса, там...)
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Не совсем так. Например:
-адресный вывод на экран, т.е. в формате адрес-данные
-генерирование и вывод собственных символов из CGRAM
-использование DDRAM в качестве внешней памяти
Даже при монотонном выводе на индикацию двух строк нужно хотя бы раз скомандовать IR переход AC на вторую строку, т.е затратить 40мкс.
Можно ввести простую задержку, остановив практически контроллер, а можно, с помощью BF, выполнить какие-то другие полезные действия.
-адресный вывод на экран, т.е. в формате адрес-данные
-генерирование и вывод собственных символов из CGRAM
-использование DDRAM в качестве внешней памяти
Даже при монотонном выводе на индикацию двух строк нужно хотя бы раз скомандовать IR переход AC на вторую строку, т.е затратить 40мкс.
Можно ввести простую задержку, остановив практически контроллер, а можно, с помощью BF, выполнить какие-то другие полезные действия.
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Все, понял, спасибо:) но все равно лишний раз заходите в эту тему:) я не раз еще буду спрашивать)))
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
.include "tn2313def.inc" ; Используем микроконтроллер Attiny2313
.cseg
.org 0
rjmp reset
;********************************************************************
reset:
ldi r16, low (RAMEND) ; Инициализация стека
out SPL, r16
rcall lcd_init
;********************************************************************
lcd_init:
ldi r16, 0b10000000 ; PUD>>1
out MCUCR, r16
ldi r16, 0b11111111 ; Настройка порта B
out ddrb, r16
ldi r16, 0b00000111 ; Настройка порта D
out ddrd, r16
;********************************************************************
ldi r16, 0b00000001 ; Сброс предделителя T0
out GTCCR, r16
;********************************************************************
ldi r16, 0b00000000 ; RS>>0
ldi r17, 0b00110000 ; Установка парамеров (Lcd Data 8 bit)
rcall delay_20000mks ; Пауза 20000мкс
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
ldi r17, 0b00111000 ; Установка параметров
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
ldi r17, 0b00001000 ; Выключение дисплея
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
ldi r17, 0b00000001 ; Очистка дисплея
rcall write_lcd ; Запись в lcd
rcall delay_1500mks ; Пауза 1500мкс
ldi r17, 0b00000110 ; Установка режима ввода данных
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
ret
;********************************************************************
delay_20000mks:
ldi r18, 0b
ldi r19, 0b
rjmp init_delay
delay_1500mks:
ldi r18, 0b
ldi r19, 0b
rjmp init_delay
delay_40mks:
ldi r18, 0b
ldi r19, 0b
init_delay:
out TCNT0, r18 ; Ввод переменной задержки
out TCCR0B, r19 ; Настройка предделителя
test:
in r20, TIFR ; Чтение TIFR
sbrs r20, 1 ; Пропустить, если TOV0>>1
rjmp test
out TCCR0B, r16 ; Остановка T0
ret
;********************************************************************
write_lcd:
out portd, r16 ; Установить значение линии RS
out portb, r17 ; Вывести байт данных DB0-DB7
sbi portd, 2 ; E>>1
cbi portd, 2 ; E>>0
out portd, r16 ; DB0-DB7 Hi-Z
ret
;********************************************************************
user_write_IR:
ldi r16, 0b00000000 ; Адресация IR
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
ret
;********************************************************************
user_write_DR:
ldi r16, 0b00000001 ; Адресация DR
rcall write_lcd ; Запись в lcd
rcall delay_40mks ; Пауза 40мкс
ret
Пока что вот так))))
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
yaotzin спасибо. Всё заработало. Урааааа
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
Babayjon писал(а):yaotzin спасибо. Всё заработало. Урааааа
это методом тыка lcd_com(0x02); а почему оно так хз =))) сам мучался, наверное надо прочитать инструкцию к LM016L - хотя нафига=) если это только для протеуса.
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
и все же странные странности происходят с моим LCD...
сделал все с задержками, даже увеличил их раз в 5, на дисплей выводятся глюки.
т.е. включил питание - дисплей инициализировался, но не вывел символы, или проинициализировался и вывел все что надо (это хорошо, не глюк), или вообще не проинициализировался.... вообщем глючит по-страшному.
Ну что еще не так?:)
сделал все с задержками, даже увеличил их раз в 5, на дисплей выводятся глюки.
т.е. включил питание - дисплей инициализировался, но не вывел символы, или проинициализировался и вывел все что надо (это хорошо, не глюк), или вообще не проинициализировался.... вообщем глючит по-страшному.
Ну что еще не так?:)
Не умеешь - не берись, но не взявшись не научишься...
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
процесс инициализации (блок схема) правильной инициализации показана в спецификации контроллера LCD, начни с этого, и сделай так как там написано.
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
У кого какой максимальной длины был шлейф до работающего дисплея с данным контроллером?
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
от скорости зависит.
У меня на частоте 1 МГц с минимально-допустимыми задержками на 30см работает хорошо
У меня на частоте 1 МГц с минимально-допустимыми задержками на 30см работает хорошо
Не умеешь - не берись, но не взявшись не научишься...