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

Сорри но опять инициализация LCD

Здравствуйте!

Понимаю что до дыр затёртая тема, но всё же прочитав подобные темы не смог применить к своей инициализации. У меня Atmega 128, с ней портом С подсоединён двустрочный LCD основаный на HD44780. Провожу всеми описываемую инициализацию, но результата нет.

Если не сильно надоело отвечать на подобные вопросы подскажите пожалуйста как быть.

Имеется вот такой вот примитивчик инициализации...

 

void delay_ms(unsigned short ms) 
   {
        unsigned short outer1, outer2;
        outer1 = 200;
        while (outer1) {
                outer2 = 1000;
                while (outer2) {
                        while ( ms ) ms--;
                        outer2--;
                }
                outer1--;
        }
   }
//-------------------------------------------------------------------------------------
//инициализация дисплея
//-------------------------------------------------------------------------------------
//VLED - PC0
//RS   - PC1 
//R/W  - PC2
//E    - PC3
//DB4..DB7 - PC4..PC7
//N  - line number (2)
//F  - font type (5x8)
//DL - data length (4 bit)
//D  - display
//C  - cursor
//B  - blink

void Write_8Bit(int value, int pause)
{
  PORTC=value;
  sbi(PORTC,3);
  cbi(PORTC,3);
  PORTC=0xF1;/установить DB4-DB7 в HI
  delay_ms(pause);  
}

void Write_4Bit(int hi, int low, int pause)
{
  PORTC=hi;//старший полубайт
  sbi(PORTC,3);
  cbi(PORTC,3);
  PORTC=low;//младший полубайт
  sbi(PORTC,3);
  cbi(PORTC,3);   
  PORTC=0xF1;//установить DB4-DB7 в HI
  delay_ms(pause);  
  }

void disp_init(void)
{
   DDRC=0xFF;// порт С на выход
  PORTC=0x01;// включить питание
  delay_ms(40);  //пауза после включения питания

for(int c=0; c<3; c++) //3 раза устанавливается 8 битный режим
{
  Write_8Bit(0x31, 40); 
} 

  Write_4Bit(0x21,0x01,40); // переход в 4 битный режим
  Write_4Bit(0x21,0x81,40); //переход в 4 битный режим, повтор
  Write_4Bit(0x01,0x81,40); //выключить дисплей
  Write_4Bit(0x01,0x61,40); //установить направление сдвига курсора
  Write_4Bit(0x01,0xF1,40); //включить индикатор и разрешить курсор, установить его тип
  Write_4Bit(0x01,0x11,40); //очистить индикатор и курсор домой
}

На дисплее ничего не происходит , кроме того что он светится при подаче на него питания. При посылке битов всегда добавляю 1 для того чтобы питание не пропало, потому как оно физически подсоеденено к PC0. Подскажите что у меня не так.

Заранее спасибо.

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


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

Подскажите что у меня не так.
Во-первых посмотрите листинг. 99%, что тело вашей задержки выкинуто оптимизатором. Объявите параметр ms как volatile или перепишите внутренний цикл так: while ( ms-- ) __no_operation(); (это если иар, если WinAVR - while ( ms-- ) __asm__ __volatile__ ("nop" : : );

во-вторых "переход в 4 битный режим, повтор" - лишнее.

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


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

Сейчас не помню уже, но функцию Write_8Bit(0x31, 40); придется, наверное, убрать из-под цикла... там после каждого раза - разные задержки... после первого - 4,1мс, после второго - 100мкс, я мог что-то напутать, поэтому вам необходимо свериться с даташитом... там все написано...

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


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

Сейчас не помню уже, но функцию Write_8Bit(0x31, 40); придется, наверное, убрать из-под цикла... там после каждого раза - разные задержки... после первого - 4,1мс, после второго - 100мкс, я мог что-то напутать, поэтому вам необходимо свериться с даташитом... там все написано...

Не нужно, это рекомендуемые МИНИМАЛЬНЫЕ задержки, если времени лишнего много, то и так нормально.

Кстати - какая тактовая частота процессора? Если выше 10Мгц, то между

 sbi(PORTC,3);
  cbi(PORTC,3);

неплохо было бы добавить задержку, на пару тактов процессора.

Интересное решение - передавать нибблы отдельно. Не подскажете, чем оно вызвано?

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


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

Что-то я тут не понял... функция void disp_init(void)... вы какие значения передаете?.. окуда вы их взяли?.. непожи они на те, которые в даташите написаны... и еще... "переход в 4 битный режим" и "переход в 4 битный режим повтор" у вас - разные команды... посмотрите повнимательнее, что они делают...

 

и еще... а зачем создавать функцию delay_ms, если подобная функция есть в библиотеке... в WinAVR, например, в библиотеке utils/delay.h есть функции _delay_ms и _delay_us...

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


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

применить к своей инициализации. У меня Atmega 128, с ней портом С подсоединён двустрочный LCD основаный на HD44780. Провожу всеми описываемую инициализацию, но результата нет.

 

Половина подобных проблем решается осциллографом.

 

Имеется вот такой вот примитивчик инициализации...

void delay_ms(unsigned short ms) 
   {
        unsigned short outer1, outer2;
        outer1 = 200;
        while (outer1) {
                outer2 = 1000;
                while (outer2) {
                        while ( ms ) ms--;
                        outer2--;
                }
                outer1--;
        }
   }

 

Такой код НЕ РАБОТАЕТ в реальной жизни. Советую использовать один аппаратный таймер для счёта времени. Тем более если речь про миллисекунды, а не микро или наносекунды. Попутно этот таймер может ШИМ выдавать или чего-нибудь в этом роде.

 

Но это ещё не всё. Код в котором нужен delay(), опять же, не на микросекунды или наносекунды, а миллисекунды -- В РЕАЛЬНОЙ ЖИЗНИ НЕ РАБОТАЕТ. Просто потому, что из-за вот этой delay() колом встают все другие процессы, которые у вас есть, вроде же очевидно. Нет, я конечно немного лукавлю, и в простых совсем случаях именно такой код и работает, когда у вас кроме дисплея ничего нет, например.

 

//VLED - PC0

//RS - PC1

//R/W - PC2

//E - PC3

//DB4..DB7 - PC4..PC7

 

Я обычно таким (см. выше) вещам даю символические имена. Иначе код неочевидный получается. Да хоть через #define.

 

void Write_8Bit(int value, int pause)
{
  PORTC=value;
  sbi(PORTC,3);
  cbi(PORTC,3);
  PORTC=0xF1;/установить DB4-DB7 в HI
  delay_ms(pause);  
}

 

Во-первых здесь не delay_ms() нужен, а delay(~15uS), насколько я помню, хотя могу и ошибаться. Во-вторых, к сожалению (опять же могу ошибаться), у вас только 4-битный интерфейс, а при использовании 8-битного имеется возможность читать бит готовности в 7-м бите и таким образом исключить задержки. Хотя, практически, с ними даже проще -- реализуется автомат который просыпается не чаще чем в 15мкс (или за сколько там команды выполняются, наизусть не помню) и посылает обновления по байтику.

 

Подскажите что у меня не так.

 

Нечёткий код, весьма вероятно содержащий ошибку. Промоделируйте ситуацию на компьютере -- замените все "PORTC=" записью в файл выводимых битиков с отметкой времени (виртуального, понятно, или реализуйте честные задержки с помощью средств ОС) -- и смотрите в чём не сходится с даташитом.

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


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

И еще что заметил - первый переход в 4 битный режим выполняется тогда, когда дисплей еще в 8 битном. Так что первый раз должно быть примерно так:

Write_8Bit(0x21, 40); // первый перевод в 4-х битный режим

А вот повтор уже должен быть в 4-х битном, как у Вас и сделано.

И еще вопрос - компилятор видимо ИАР?

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

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


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

Здравствуйте попытаюсь оправдаться. Пользовался рекомендациями отсюда, потому именно такой порядок инициализации а не другой, вот только задержки не в микро- а в миллиекундах.

Пользуюсь WinAvr, но к сожалению не обнаружил ни util/delay.h(у меня таких библиотек не оказалось) ни других полезных функций для задержки, кроме тех которые описаны в avr/delay.h, то есть я увидил там только _delay_loop2() и _delay_loop1(), мне они показались непонятными и я содрал свою функцию с какого то обсуждения(к стати у меня их уже 3 и у всех разная реализация, даже не знаю кому верить).Поэтому хотел бы узнать где можно взять эти и другие полезные библиотечки.

Частота кварца по идее должна стоять 4, точно не уверен, но по моему там по умолчанию так стоит.

Полубиты решил записать функциями исключительно ради того чтоб меньше текста вылаживать на форум, до этого всё было тупо по порядку написано и без циклов, мне так же показалось это неудобным- вот и переписал немного.

 

Во-первых посмотрите листинг. 99%, что тело вашей задержки выкинуто оптимизатором. Объявите параметр ms как volatile или перепишите внутренний цикл так: while ( ms-- ) __no_operation(); (это если иар, если WinAVR - while ( ms-- ) __asm__ __volatile__ ("nop" : : );

во-вторых "переход в 4 битный режим, повтор" - лишнее.

Попробовал поправить цикл:

1)обьявил ms как volatile цыкл работает вечено

2)__asm__ __volatile__ ("nop" : : ); - компилятор почему то не знает

3)поставил asm("nop"); - компилятр не ругался но цыкл опять же работает вечно

4)"переход в 4 битный режим, повтор" - убрал, но скорее всего из за задержек пока это результата не дало

Я так понимаю нужно для начала найти цивилизованную delay_ms и delay_us(), которыми все успешно пользуются, подскажите где можно взять, а то почему то в моём WinAvr их нет.

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


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

Я так понимаю нужно для начала найти цивилизованную delay_ms и delay_us(), которыми все успешно пользуются, подскажите где можно взять, а то почему то в моём WinAvr их нет.

 

Скачайте отсюда последнию версию:

http://sourceforge.net/projects/winavr/

 

Анатолий.

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


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

Я так понимаю нужно для начала найти цивилизованную delay_ms и delay_us(), которыми все успешно пользуются, подскажите где можно взять, а то почему то в моём WinAvr их нет.

 

Подключите файл:

#include <util/delay.h>

 

и пользуйтесь:

_delay_ms(1000);//задержка 1 с. Чтобы работало, используйте ключик оптимизации (например -О1). Ну и прерывания удлиняют задержку, рекомендуется для точного отсчета прерывания отключить на время задержки.

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


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

Скачайте отсюда последнию версию:

http://sourceforge.net/projects/winavr/

Скачал новый WinAvr20071221 и опять проблемы начались:

- он не запускается почему то

- раньше я bat файл запускал который компилил проэкт, а затем переоткрывал его в AvrStudio, там видимо с makefile несоответствие

Я видел что люди WinAvr плагином к AvrStudio прикручивают, как мне сделать так же и как переправить makefile. :wassat:

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


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

Я видел что люди WinAvr плагином к AvrStudio прикручивают, как мне сделать так же и как переправить makefile. :wassat:

Скачать свежую студию с сервиспаками, старую снести, новую поставить. Она сама, в процессе установки найдет WinAvr. Makefile в студии можно использовать внешний. Или она сама его сгенерит.

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

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


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

Не стал заморачиваться с неработающим у меня WinAvr 20071221. Поставил назад старый. Перебрал варианты, содрал _delay_ms() из библиотеки - задержка то вроде работает, но всё равно единственное что делает экранчик - так это горит при подаче питания.

Может переписать как то заново?

Надоел уже мне этот экранчик порядком, обидно тратить столько времини для того чтобы привести к жизни этот противный кусочек железа, выполняющий не такую уж важную роль.

Спасибо за участие.

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


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

Здравствуйте попытаюсь оправдаться. Пользовался рекомендациями отсюда, потому именно такой порядок инициализации а не другой, вот только задержки не в микро- а в миллиекундах.

 

Для этого существуют ДАТАШИТЫ. А не сайты с сомнительным и не всегда коррректным содержанием.

 

1)обьявил ms как volatile цыкл работает вечено

 

Не вечно, а достаточно долго.

 

2)__asm__ __volatile__ ("nop" : : ); - компилятор почему то не знает

 

Я тоже...

 

3)поставил asm("nop"); - компилятр не ругался но цыкл опять же работает вечно

 

Потому, что и как в случае с volatile цикл перестаёт выкидываться оптимизатором компилятора и начинает-таки исполняться. Просто у вас время задано неверно.

 

Я так понимаю нужно для начала найти цивилизованную delay_ms и delay_us(), которыми все успешно пользуются, подскажите где можно взять, а то почему то в моём WinAvr их нет.

 

Ещё раз -- в реальных программах delay() не бывает.

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


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

Да не... на инициализацию дисплея можно и delay поставить... все равно полностью устройство еще не работает и можно немного погонять процессор вхолостую...

 

еще... советую использовать в пересылке

верхнего полубайта

 

PORTC = (value >> 4);

 

нижнего полубайта

 

PORTC = (value & 0x0F);

 

если у вас на этом порту еще что-то висит (например, часто вешают на порт старшими регистрами биты состояния дисплея), то к каждой из строчек стоит добавить

 

| (PORTC & 0xF0);

 

ИМХО, так понятней, что вы хотите сделать...

 

а вообще посмотрите примеры к WinAVR... может найдете что-то интересное для себя... в частности, там есть примеры работы с дисплеем...

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


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

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

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

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

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

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

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

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

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

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