Уважаемые коты и кошки помогите разобраться с 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
-0x30;
}
}
//Пишем row на ЖКИ
void write_row (void)
{ unsigned char i;
lcd_com(0x86); //Перейдем в начало
for (i=0;i<row_counter;i++) //Пишем row
lcd_dat(row);
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[j])==1)&& //Нажата цифра и не достигнут лимит в NUMBER_SIZE
(row_counter<NUMBER_SIZE)) { //Добавить в row и увеличить row_counter
row[row_counter]=key_code[j];
row_counter++;
}
if (key_code[j]=='F') row_counter=0x00; //Если нажата 'F' очищаем row
if ((key_code[j]=='E')&&
(row_counter>0x00)) row_counter--; //Если нажата 'E'
//и есть введенные цифры – удалить последнюю
if (key_code[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;
}