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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> LCD + ATmega8, Нет изображения на ЖКИ
roman_golovenkov
сообщение May 2 2011, 13:51
Сообщение #16


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

Группа: Участник
Сообщений: 80
Регистрация: 10-02-09
Пользователь №: 44 637



Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе.
CODE
#include <mega16.h>
#include <delay.h>

// Задание выводимой строки текста.
char flash *static_text = "Hello, world!";

// Задание регистров порта подключения ЖКИ-модуля.
#define LCD_PORT PORTD
#define LCD_DDR DDRD
// Задание номера бита порта для вывода сигнала Е.
#define LCD_E PORTD3
// Задание номера бита порта для вывода сигнала RS.
#define LCD_RS PORTD2

// Команда очистки экрана.
#define CLEAR_COMMAND 0b00000001

// Команда возврата курсора на начальную позицию.
#define HOME_COMMAND 0b00000010

// Команда выбора направления сдвига курсора и экрана:
// инкремент счетчика адреса,
// без сдвига изображения.
#define EMS_COMMAND 0b00000110

// Команда выбора отображения:
// изображение включено,
// курсор в виде подчерка выключен,
// курсор в виде мерцающего знакоместа выключен.
#define DISPLAY_COMMAND 0b00001100

// Команда задания сдвига курсора или экрана.
//#define SHIFT_COMMAND 0b0001xx--

// Команда инициализации и задания режима работы индикатора
// для 8-разрядного режима работы шины данных:
// 4-хразрядная шина данных.
// Здесь тетрады переставлены местами для корректной работы
// подпрограммы записи команды в ЖКИ-модуль.
#define INIT_8_COMMAND 0b00000010

// Команда инициализации и задания режима работы индикатора:
// использование двухстрочного режима отображения информации,
// матрица 5х8 точек,
// 4-хразрядная шина данных.
#define INIT_COMMAND 0b00101000

// Команда задания адреса в CGRAM.
#define CGRAM_COMMAND 0b01000000

// Команда задания адреса в DDRAM.
#define DDRAM_COMMAND 0b10000000

// Смещение первого знакоместа второй строки.
#define SECOND_ROW 0x40

// Количество одновременно отображаемых символов на ЖКИ.
#define TOTAL_CHARS 16

// Длительность программных задержек.
#define INIT_DELAY 50
#define INIT_CONTROL_DELAY 50
#define WAIT_LINE_DELAY 1
#define WRITE_DATA_DELAY 50
#define WRITE_DATA_LONG_DELAY 2000

// Переставляет тетрады в байте.
#pragma warn-
unsigned char swap(unsigned char data)
{
#asm
ld r30, Y
swap r30
#endasm
}
#pragma warn+

// Определение задержки для формирования сигналов на линиях.
#define lcd_wait_line() delay_us(WAIT_LINE_DELAY)

// Записывает данные в ЖКИ-модуль.
void _lcd_write_data(unsigned char data)
{
unsigned char lsn;

// Вывод данных на 4-хразрядную шину.

// Получение и вывод старшей тетрады.
lsn = LCD_PORT & 0x0F;
LCD_PORT = data & 0xF0 | lsn;

// Установка стробирующего сигнала Е.
LCD_PORT.LCD_E = 1;
// Задержка сигнала на линии.
lcd_wait_line();
// Снятие стробирующего сигнала Е.
LCD_PORT.LCD_E = 0;
// Задержка сигнала на линии.
lcd_wait_line();

// Получение и вывод младшей тетрады.
LCD_PORT = swap(data) & 0xF0 | lsn;

// Установка стробирующего сигнала Е.
LCD_PORT.LCD_E = 1;
// Задержка сигнала на линии.
lcd_wait_line();
// Снятие стробирующего сигнала Е.
LCD_PORT.LCD_E = 0;
// Задержка сигнала на линии.
lcd_wait_line();

// Формирование задержки для ожидания выполнения команды ЖКИ-модулем.
if (!LCD_PORT.LCD_RS && (CLEAR_COMMAND == data || HOME_COMMAND == data))
{
delay_us(WRITE_DATA_LONG_DELAY);
}
else
{
delay_us(WRITE_DATA_DELAY);
}
}

// Записывает команду в регистр IR ЖКИ-модуля.
void lcd_control(unsigned char control)
{
// Установка линии RS в низкое состояние - сигнал записи команды.
LCD_PORT.LCD_RS = 0;
// Задержка сигнала на линии.
lcd_wait_line();
_lcd_write_data(control);
}

// Записывает команду в регистр IR ЖКИ-модуля при инициализации.
void lcd_init_control(unsigned char control)
{
lcd_control(control);
// Задержка при инициализации должна быть больше.
delay_ms(INIT_CONTROL_DELAY);
}

// Записывает символ в регистр DR ЖКИ-модуля.
void lcd_putchar(unsigned char c)
{
// Установка линии RS в высокое состояние - сигнал записи данных.
LCD_PORT.LCD_RS = 1;
// Задержка сигнала на линии.
lcd_wait_line();
_lcd_write_data©;
}

// Инициализирует ЖКИ-модуль.
void lcd_init(void)
{
// Порт подключения ЖКИ-модуля работает на вывод.
LCD_DDR |= 0b11111100;

// Предварительная задержка.
delay_ms(INIT_DELAY);
// Отправка команды инициализации для 8-разрядного режима работы шины
// данных, переключение на 4-хразрядную шину.
lcd_init_control(INIT_8_COMMAND);
// Отправка команды инициализации уже для 4-хразрядного режима.
lcd_init_control(INIT_COMMAND);
// Повторная отправка команды инициализации.
lcd_init_control(INIT_COMMAND);
// Задание режима отображения.
lcd_init_control(DISPLAY_COMMAND);
// Очистка экрана.
lcd_init_control(CLEAR_COMMAND);
// Выбор направления сдвига курсора и экрана.
lcd_init_control(EMS_COMMAND);
}

// Записывает строку для отображения из памяти даных в ЖКИ-модуль.
#pragma used+
void lcd_puts(char *str)
{
char c;
#pragma warn-
while (c = *str++)
{
#pragma warn+
lcd_putchar©;
}
}
#pragma used-

// Записывает строку для отображения из памяти программ в ЖКИ-модуль.
#pragma used+
void lcd_putsf(char flash *str)
{
char c;
#pragma warn-
while (c = *str++)
{
#pragma warn+
lcd_putchar©;
}
}
#pragma used-

void main(void)
{
// Инициализация ЖКИ-модуля.
lcd_init();

// Вывод заданного текста в первой строке с первого знакоместа.
lcd_putsf(static_text);

// Переключение на четвёртое знакоместо второй строки.
lcd_control(DDRAM_COMMAND + SECOND_ROW + 3);

// Вывод заданного текста во второй строке с четвёртого знакоместа.
lcd_putsf(static_text);

for (;;)
{
}


Сообщение отредактировал roman_golovenkov - May 2 2011, 13:56
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение May 2 2011, 21:41
Сообщение #17


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Цитата(Melandr @ Apr 29 2011, 21:12) *
Почитал http://electronix.ru/forum/index.php?s=&am...st&p=143374, и решил линию управления RW переключить с GND на линию PD1. Поэтому если будут исходники с чтением состояния ЖКИ, очень хотелось бы ознакомиться.


Вот работающий проект - разберётесь. WinAWR или атмеловский тулчейн. Интересующая Вас часть (работа с проверкой готовности) находится в файле hd44780.c

Сообщение отредактировал Genadi Zawidowski - May 2 2011, 21:44
Go to the top of the page
 
+Quote Post
Melandr
сообщение May 2 2011, 22:53
Сообщение #18


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435



Цитата(roman_golovenkov @ May 2 2011, 16:51) *
Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе.

У Вас компилятор IAR, а то я пытаюсь скомпилить в AVRStudio, а он ругается?

Цитата(Genadi Zawidowski @ May 3 2011, 00:41) *
Вот работающий проект - разберётесь. WinAWR или атмеловский тулчейн. Интересующая Вас часть (работа с проверкой готовности) находится в файле hd44780.c

Спасибо буду разбираться с Вашим исходником.
Go to the top of the page
 
+Quote Post
roman_golovenkov
сообщение May 3 2011, 00:26
Сообщение #19


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

Группа: Участник
Сообщений: 80
Регистрация: 10-02-09
Пользователь №: 44 637



Цитата
У Вас компилятор IAR, а то я пытаюсь скомпилить в AVRStudio, а он ругается?


Компилировал в CoDeVision

Сообщение отредактировал roman_golovenkov - May 3 2011, 00:27
Go to the top of the page
 
+Quote Post
XVR
сообщение May 3 2011, 10:18
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Вот это -
Код
temp=(lcd|(1<<RS))|(1<<E);
и все остальные манипуляции с lcd - неправильные
Нужно маскировать старшую часть lcd, иначе она у вас накладывается на управляющие сигналы:
Код
temp=((lcd&0x0F)|(1<<RS))|(1<<E);

Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 3 2011, 10:50
Сообщение #21


Гуру
******

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



QUOTE (XVR @ May 3 2011, 13:18) *
иначе она у вас накладывается на управляющие сигналы:
Там маскируются те биты, для которых управляющие сигналы сброшены. А для тех, которые надо выставлять - совершенно неважно, была там единица или нет. Да, некрасиво, но работать должно.


--------------------
На любой вопрос даю любой ответ
"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
XVR
сообщение May 3 2011, 13:41
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(Сергей Борщ @ May 3 2011, 14:50) *
Там маскируются те биты, для которых управляющие сигналы сброшены. А для тех, которые надо выставлять - совершенно неважно, была там единица или нет.
Не маскируются вообще никакие биты. В частности бит E (там, где он стоять не должен)
Цитата
Да, некрасиво, но работать должно.
Неа, точнее не везде rolleyes.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 3 2011, 15:18
Сообщение #23


Гуру
******

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



QUOTE (XVR @ May 3 2011, 16:41) *
Не маскируются вообще никакие биты. В частности бит E (там, где он стоять не должен)

Читаем по губам:
QUOTE (Melandr @ Apr 29 2011, 15:48) *
CODE
  temp=(lcd&~(1<<RS))|(1<<E);        //RS=0 – это команда
  PORTD=temp;                            //Выводим на portD старшую тетраду данных, сигналы RS, E  
   asm("nop");                        //Небольшая задержка в 1 такт МК, для стабилизации
  PORTD=temp&~(1<<E);                    //Сигнал записи данных
В первой строке (lcd&~(1<<RS)) маскируется RS, а E стоять должен и он стоять будет: |(1<<E). В последней E маскируется и в порт записывается число со сброшенным битом E

QUOTE (Melandr @ Apr 29 2011, 15:48) *
CODE
  temp=((lcd*16)&~(1<<RS))|(1<<E);    //RS=0 – это команда
  PORTD=temp;                            //Выводим на portD младшую тетраду команды, сигналы RS, E
В первой строке ((lcd*16)&~(1<<RS)) также сбрасывается RS, хотя он и так сброшен в процессе lcd*16, а E безусловно взводится.

QUOTE (XVR @ May 3 2011, 16:41) *
Неа, точнее не везде rolleyes.gif
Ну да, там где нужны остальные биты порта такая конструкция принесет приятные smile3046.gif сюрпризы.


--------------------
На любой вопрос даю любой ответ
"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
XVR
сообщение May 3 2011, 17:08
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Да, действительно. Не заметил sad.gif
Все равно это не комильфо sm.gif
Go to the top of the page
 
+Quote Post
Melandr
сообщение May 3 2011, 21:22
Сообщение #25


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435



Я так понимаю, что хоть программа написана не сильно красиво, но должна работать? Я сам заметил, что немного неудобно манипулировать управляющими линиями ЖКИ, и одновременно передавать данные, но у меня сейчас стоит задача запустить ЖКИ, а дальше оптимизировать и улучшать код.

Цитата(roman_golovenkov @ May 2 2011, 16:51) *
Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе.


Так скомпилил в CodeVision, немного изменил, для мигания светодиодом. В протеусе запустил все норм, на экране в протеусе появилась надпись. В железе светодиод мигает, а изображения нет. Есть подозрение, что шлейф соединяющий отладочную плату с ЖКИ, не передает все сигналы. Так как изображения нет, но контрастность регулируется в верхней строке. Завтра прикуплю разьемы на шлейф, и переделаю.
Go to the top of the page
 
+Quote Post
Melandr
сообщение May 4 2011, 21:02
Сообщение #26


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435



Цитата(roman_golovenkov @ May 2 2011, 16:51) *
Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе.

Все норм, спасибо. Заработало в железе, после того как шлейф переделал. Мой код правда не работает буду разбираться со своим кодом.
Go to the top of the page
 
+Quote Post
Melandr
сообщение May 7 2011, 11:21
Сообщение #27


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435



Переделал код CodeVision под WinAVR. Вот код:
CODE

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

// Задание выводимой строки текста.
char *static_text PROGMEM = "Hello, world!";

// Задание регистров порта подключения ЖКИ-модуля.
#define LCD_PORT PORTD
#define LCD_DDR DDRD
// Задание номера бита порта для вывода сигнала Е.
#define LCD_E PD3
// Задание номера бита порта для вывода сигнала RS.
#define LCD_RS PD2
// Задание номера бита порта для вывода сигнала RW
#define LCD_RW PD1
//Задание регистров порта для светодиода
#define LED_PORT PORTC
#define LED_DDR DDRC
//Задание номера бита порта для светодиода
#define LED PC0

// Команда очистки экрана.
#define CLEAR_COMMAND 0b00000001

// Команда возврата курсора на начальную позицию.
#define HOME_COMMAND 0b00000010

// Команда выбора направления сдвига курсора и экрана:
// инкремент счетчика адреса,
// без сдвига изображения.
#define EMS_COMMAND 0b00000110

// Команда выбора отображения:
// изображение включено,
// курсор в виде подчерка выключен,
// курсор в виде мерцающего знакоместа выключен.
#define DISPLAY_COMMAND 0b00001100

// Команда задания сдвига курсора или экрана.
//#define SHIFT_COMMAND 0b0001xx--

// Команда инициализации и задания режима работы индикатора
// для 8-разрядного режима работы шины данных:
// 4-хразрядная шина данных.
// Здесь тетрады переставлены местами для корректной работы
// подпрограммы записи команды в ЖКИ-модуль.
#define INIT_8_COMMAND 0b00000010

// Команда инициализации и задания режима работы индикатора:
// использование двухстрочного режима отображения информации,
// матрица 5х8 точек,
// 4-хразрядная шина данных.
#define INIT_COMMAND 0b00101000

// Команда задания адреса в CGRAM.
#define CGRAM_COMMAND 0b01000000

// Команда задания адреса в DDRAM.
#define DDRAM_COMMAND 0b10000000

// Смещение первого знакоместа второй строки.
#define SECOND_ROW 0x40

// Количество одновременно отображаемых символов на ЖКИ.
#define TOTAL_CHARS 16

// Длительность программных задержек.
#define INIT_DELAY 50
#define INIT_CONTROL_DELAY 50
#define WAIT_LINE_DELAY 1
#define WRITE_DATA_DELAY 50
#define WRITE_DATA_LONG_DELAY 2000

// Переставляет тетрады в байте.
unsigned char swap(unsigned char data)
{
asm(
"swap %0":
"=r" (data):
"0" (data)
);
return data;
}

// Определение задержки для формирования сигналов на линиях.
#define lcd_wait_line() _delay_us(WAIT_LINE_DELAY)

// Записывает данные в ЖКИ-модуль.
void _lcd_write_data(unsigned char data)
{
unsigned char lsn;

// Вывод данных на 4-хразрядную шину.

// Получение и вывод старшей тетрады.
lsn = LCD_PORT & 0x0F;
LCD_PORT = (data & 0xF0) | lsn;

// Установка стробирующего сигнала Е.
LCD_PORT |=(1<<LCD_E);
// Задержка сигнала на линии.
lcd_wait_line();
// Снятие стробирующего сигнала Е.
LCD_PORT &= ~(1<<LCD_E);
// Задержка сигнала на линии.
lcd_wait_line();

// Получение и вывод младшей тетрады.
LCD_PORT = (swap(data) & 0xF0) | lsn;

// Установка стробирующего сигнала Е.
LCD_PORT |= (1<<LCD_E);
// Задержка сигнала на линии.
lcd_wait_line();
// Снятие стробирующего сигнала Е.
LCD_PORT &= ~(1<<LCD_E);
// Задержка сигнала на линии.
lcd_wait_line();

// Формирование задержки для ожидания выполнения команды ЖКИ-модулем.
if (!LCD_RS && (CLEAR_COMMAND == data || HOME_COMMAND == data))
{
_delay_us(WRITE_DATA_LONG_DELAY);
}
else
{
_delay_us(WRITE_DATA_DELAY);
}
}

// Записывает команду в регистр IR ЖКИ-модуля.
void lcd_control(unsigned char control)
{
// Установка линии RS в низкое состояние - сигнал записи команды.
LCD_PORT &= ~(1<<LCD_RS);
// Задержка сигнала на линии.
lcd_wait_line();
_lcd_write_data(control);
}

// Записывает команду в регистр IR ЖКИ-модуля при инициализации.
void lcd_init_control(unsigned char control)
{
lcd_control(control);
// Задержка при инициализации должна быть больше.
_delay_ms(INIT_CONTROL_DELAY);
}

// Записывает символ в регистр DR ЖКИ-модуля.
void lcd_putchar(unsigned char c)
{
// Установка линии RS в высокое состояние - сигнал записи данных.
LCD_PORT |= (1<<LCD_RS);
// Задержка сигнала на линии.
lcd_wait_line();
_lcd_write_data©;
}

// Инициализирует ЖКИ-модуль.
void lcd_init(void)
{
// Порт подключения ЖКИ-модуля работает на вывод.
LCD_DDR |= 0b11111100;

// Предварительная задержка.
_delay_ms(INIT_DELAY);
// Отправка команды инициализации для 8-разрядного режима работы шины
// данных, переключение на 4-хразрядную шину.
lcd_init_control(INIT_8_COMMAND);
// Отправка команды инициализации уже для 4-хразрядного режима.
lcd_init_control(INIT_COMMAND);
// Повторная отправка команды инициализации.
lcd_init_control(INIT_COMMAND);
// Задание режима отображения.
lcd_init_control(DISPLAY_COMMAND);
// Очистка экрана.
lcd_init_control(CLEAR_COMMAND);
// Выбор направления сдвига курсора и экрана.
lcd_init_control(EMS_COMMAND);
}

// Записывает строку для отображения из памяти даных в ЖКИ-модуль.
void lcd_puts(char *str)
{
char c;
while (c = *str++)
{
lcd_putchar©;
}
}

// Записывает строку для отображения из памяти программ в ЖКИ-модуль.
void lcd_putsf(char *str)
{
char c;
while (c = *str++)
{
lcd_putchar©;
}
}

int main(void)
{
// Инициализация ЖКИ-модуля.
lcd_init();

// Вывод заданного текста в первой строке с первого знакоместа.
lcd_putsf(static_text);

// Переключение на четвёртое знакоместо второй строки.
lcd_control(DDRAM_COMMAND + SECOND_ROW + 3);

// Вывод заданного текста во второй строке с четвёртого знакоместа.
lcd_putsf(static_text);

//Конфигурираем порт для мигания светодиодом
LED_DDR |= 0b11111111;

for (;;)
{
//Мигаем светодиодом для проверки работоспособности программы
LED_PORT |= (1<<LED);
_delay_ms(1000); //задержка 1 секунда
LED_PORT &= ~(1<<LED);
_delay_ms(1000); //задержка 1 секунда
}
return 0;
}


Выдает в строке
while (c = *str++)
такое предупреждение warning: suggest parentheses around assignment used as truth value
Также непонятно как использовать флеш память в функции

CODE

// Записывает строку для отображения из памяти программ в ЖКИ-модуль.
void lcd_putsf(char *str)
{
char c;
while (c = *str++)
{
lcd_putchar©;
}
}

Кто может подскажите.
Go to the top of the page
 
+Quote Post
=GM=
сообщение May 7 2011, 11:44
Сообщение #28


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Компилятор ожидает логическое выражение в операторе while (c = *str++).

Не знаю логики программы, возможно, должно быть while (c == *str++)


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Melandr
сообщение May 7 2011, 13:46
Сообщение #29


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 5-04-10
Пользователь №: 56 435



Цитата(=GM= @ May 7 2011, 14:44) *
Не знаю логики программы, возможно, должно быть while (c == *str++)


Код для CodeVision записан выше на странице, он нормально работает. Я просто переделываю код под WinAVR. Дело в том, что в коде для CodeVision для этого выражения отключены предупреждения компилятора. Я так понимаю это выражение служит для обработки строки символов в цикле. А выходом из цикла является символ конца строки "\0". Но WinAVR дает предупреждение, а не ошибку. А код не работает.

Сообщение отредактировал Melandr - May 7 2011, 13:54
Go to the top of the page
 
+Quote Post
SysRq
сообщение May 7 2011, 14:08
Сообщение #30


Чайник, 1 литр
****

Группа: Свой
Сообщений: 655
Регистрация: 17-05-06
Из: Moscow
Пользователь №: 17 168



Из памяти программ читать удобно чем-либо из WinAVR\avr\include\avr\pgmspace.h.

--

Насчёт предупреждения, - поставьте ещё скобки, вот так вот: while(( )). Явно показываем компилятору что мы не ошиблись, и на ноль\не ноль проверяем действительно результат операции присваивания.

Сообщение отредактировал SysRq - May 7 2011, 14:31
Go to the top of the page
 
+Quote Post

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

 


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


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