реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Сорри но опять инициализация LCD, Не получается запустить LCD основаный на HD44780
John23
сообщение Jan 23 2008, 13:43
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 15
Регистрация: 17-01-08
Пользователь №: 34 156



Здравствуйте!
Понимаю что до дыр затёртая тема, но всё же прочитав подобные темы не смог применить к своей инициализации. У меня 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. Подскажите что у меня не так.
Заранее спасибо.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 23 2008, 14:19
Сообщение #2


Гуру
******

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



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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Freeze Anti
сообщение Jan 23 2008, 17:36
Сообщение #3


Частый гость
**

Группа: Новичок
Сообщений: 153
Регистрация: 29-03-07
Из: Саратов
Пользователь №: 26 613



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


--------------------
!!! All you need is LOVE !!!
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Jan 23 2008, 17:56
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



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

Не нужно, это рекомендуемые МИНИМАЛЬНЫЕ задержки, если времени лишнего много, то и так нормально.
Кстати - какая тактовая частота процессора? Если выше 10Мгц, то между
Код
sbi(PORTC,3);
  cbi(PORTC,3);

неплохо было бы добавить задержку, на пару тактов процессора.
Интересное решение - передавать нибблы отдельно. Не подскажете, чем оно вызвано?
Go to the top of the page
 
+Quote Post
Freeze Anti
сообщение Jan 23 2008, 18:12
Сообщение #5


Частый гость
**

Группа: Новичок
Сообщений: 153
Регистрация: 29-03-07
Из: Саратов
Пользователь №: 26 613



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

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


--------------------
!!! All you need is LOVE !!!
Go to the top of the page
 
+Quote Post
Kirill Frolov
сообщение Jan 23 2008, 20:05
Сообщение #6


Частый гость
**

Группа: Новичок
Сообщений: 111
Регистрация: 10-02-07
Из: St.Petersburg, Russia
Пользователь №: 25 241



Цитата(John23 @ Jan 23 2008, 16:43) *
применить к своей инициализации. У меня 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=" записью в файл выводимых битиков с отметкой времени (виртуального, понятно, или реализуйте честные задержки с помощью средств ОС) -- и смотрите в чём не сходится с даташитом.


--------------------
[ZX]
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Jan 23 2008, 21:33
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



И еще что заметил - первый переход в 4 битный режим выполняется тогда, когда дисплей еще в 8 битном. Так что первый раз должно быть примерно так:
Код
Write_8Bit(0x21, 40); // первый перевод в 4-х битный режим

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

Сообщение отредактировал Qwertty - Jan 23 2008, 21:34
Go to the top of the page
 
+Quote Post
John23
сообщение Jan 24 2008, 08:07
Сообщение #8


Участник
*

Группа: Новичок
Сообщений: 15
Регистрация: 17-01-08
Пользователь №: 34 156



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

Цитата(Сергей Борщ @ Jan 23 2008, 18:19) *
Во-первых посмотрите листинг. 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 их нет.
Go to the top of the page
 
+Quote Post
aesok
сообщение Jan 24 2008, 08:16
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



Цитата(John23 @ Jan 24 2008, 11:07) *
Я так понимаю нужно для начала найти цивилизованную delay_ms и delay_us(), которыми все успешно пользуются, подскажите где можно взять, а то почему то в моём WinAvr их нет.


Скачайте отсюда последнию версию:
http://sourceforge.net/projects/winavr/

Анатолий.
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 24 2008, 08:25
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



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


Подключите файл:
#include <util/delay.h>

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


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
John23
сообщение Jan 24 2008, 09:14
Сообщение #11


Участник
*

Группа: Новичок
Сообщений: 15
Регистрация: 17-01-08
Пользователь №: 34 156



Цитата(aesok @ Jan 24 2008, 12:16) *
Скачайте отсюда последнию версию:
http://sourceforge.net/projects/winavr/

Скачал новый WinAvr20071221 и опять проблемы начались:
- он не запускается почему то
- раньше я bat файл запускал который компилил проэкт, а затем переоткрывал его в AvrStudio, там видимо с makefile несоответствие
Я видел что люди WinAvr плагином к AvrStudio прикручивают, как мне сделать так же и как переправить makefile. wassat.gif
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Jan 24 2008, 10:59
Сообщение #12


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(John23 @ Jan 24 2008, 12:14) *
Я видел что люди WinAvr плагином к AvrStudio прикручивают, как мне сделать так же и как переправить makefile. wassat.gif

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

Сообщение отредактировал Qwertty - Jan 24 2008, 11:00
Go to the top of the page
 
+Quote Post
John23
сообщение Jan 24 2008, 14:02
Сообщение #13


Участник
*

Группа: Новичок
Сообщений: 15
Регистрация: 17-01-08
Пользователь №: 34 156



Не стал заморачиваться с неработающим у меня WinAvr 20071221. Поставил назад старый. Перебрал варианты, содрал _delay_ms() из библиотеки - задержка то вроде работает, но всё равно единственное что делает экранчик - так это горит при подаче питания.
Может переписать как то заново?
Надоел уже мне этот экранчик порядком, обидно тратить столько времини для того чтобы привести к жизни этот противный кусочек железа, выполняющий не такую уж важную роль.
Спасибо за участие.
Go to the top of the page
 
+Quote Post
Kirill Frolov
сообщение Jan 24 2008, 18:20
Сообщение #14


Частый гость
**

Группа: Новичок
Сообщений: 111
Регистрация: 10-02-07
Из: St.Petersburg, Russia
Пользователь №: 25 241



Цитата(John23 @ Jan 24 2008, 11:07) *
Здравствуйте попытаюсь оправдаться. Пользовался рекомендациями отсюда, потому именно такой порядок инициализации а не другой, вот только задержки не в микро- а в миллиекундах.


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

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


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

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


Я тоже...

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


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

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


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


--------------------
[ZX]
Go to the top of the page
 
+Quote Post
Freeze Anti
сообщение Jan 24 2008, 19:11
Сообщение #15


Частый гость
**

Группа: Новичок
Сообщений: 153
Регистрация: 29-03-07
Из: Саратов
Пользователь №: 26 613



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

еще... советую использовать в пересылке
верхнего полубайта

PORTC = (value >> 4);

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

PORTC = (value & 0x0F);

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

| (PORTC & 0xF0);

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

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


--------------------
!!! All you need is LOVE !!!
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 08:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.01487 секунд с 7
ELECTRONIX ©2004-2016