Перейти к содержанию
    

В общем ситуация такая, всю жизнь сидел на 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);
}

Изменено пользователем Dars

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может это поможет?

http://www.gaw.ru/html.cgi/txt/lcd/chips/hd44780/start.htm

Мне лично в свое время помогло.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У кого есть библиотечка выложите пожалуйста :)

Попробуй моё, писал под IAR

Ну или ткините кто нибудь в ошибку (если вся программа не есть ошибка).

Это лучьше самому, уж очень много у LCD зависит от таймов и начальной инициализации ...

IARLCD4bit.RAR

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2haker_fox

 

Да я как раз по той статье и даташиту Hitachi и делаю, задолбали эти задержки, только процессорное время жрут!

 

2&-rey

 

Спасибо. Ща сяду буду разбираться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Ща сяду буду разбираться.

там у меня обшибка вкралась :(

функцию Init_instruction()

нужно записать так:

void Init_instruction(unsigned char DataLCD)
{
  Do_Write(__swap_nibbles(DataLCD) & LCD_MASK);
}

хотя код проверялся на ЖКД и работал, все таки так будет проавильнее, чтоб не нарушать отчетности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то все равно он не работает.... :(

Может все таки кто ткнет на ошибку, экран вроде включается, но на команды не реагирует. Я указал режим с курсором а курсора тоже нет :(

 

Вот функция инициализации:

 

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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот 100% рабочий исходник. Правда для IBM PC, среда Borland C++ 3.1, но сути дела это не меняет. Попробуйте приминить инициализацию дисплея из прикрепленного файла.

HD44780.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот 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);, но это неправильно... :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ура!!! Замигал курсор, haker_fox & &-rey :a14: за помощь! Всего надо было строчку

 

LCD_PORT |= (LCD_DATA & 0xF0);

 

заменить на

 

char temp;
temp=PORTC;
temp |= (LCD_DATA & 0xF0);
temp &= (LCD_DATA | 0x0F);
LCD_PORT = temp;

Изменено пользователем Dars

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Dars, смахивает на шаманство. А физический смысл каков?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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 производится запись всего числа.

Объяснил как смог.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если кому-то интересно, вот модули, которые я написал для работы с LCD и использую в своих проектах.

 

Если не пользоваться ОС, то модуль мало чем интересен. Просто библиотека низкоуровневых функций для работы с контроллером LCD и все.

 

Однако, если пользоваться операционкой (я пока остановил свой выбор на scmRTOS Гарри Журова), то все становится интересней. Для вывода на экран используется промежуточный "видео-буфер". При вызове какой-либо функции вывода на экран производится запись в буфер и сразу же продолжается выполнение текущего процесса. Затем, когда все высокоприоритетные процессы выполнят свою работу и отдадут управление, принимается за работу низкоприоритетный процесс TxtDrvProc, который в цикле выталкивает видео-буфер в hd44780. В программе не требуется вызывать функцию инициализации LCD вручную. Достаточно, чтобы процесс TxtDrvProc просто периодически получал управление и он все сделает сам. Весь вывод на экран осуществляется посредством вызова функций библиотеки "txtlib.h". Есть функции для вывода целых, дрбн. с фиксированной точкой, строк, двоичных, шестнадцатеричных, прогресс-бара, и даты/времени.

 

Кроме того, в архиве есть удобный класс для работы с датой/временем. Для хранения используется один unsigned long, в котором хранится кол-во секунд, прошедших с 1-го января 2001-го года. Доступ к значению года, месяца, числа, часов, минут и секунд осуществляется путем вычислений. Таким образом экземпляр класса занимает всего 4 байта в ОЗУ. Высокосные годы также обрабатываются.

 

Вся настройка осуществляется в файлах *_config.h

hd44780.rar

Изменено пользователем ArtemK

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...