roman_golovenkov 0 2 мая, 2011 Опубликовано 2 мая, 2011 (изменено) · Жалоба Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе. #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 (;;) { } Изменено 2 мая, 2011 пользователем roman_golovenkov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 2 мая, 2011 Опубликовано 2 мая, 2011 (изменено) · Жалоба Почитал http://electronix.ru/forum/index.php?s=&am...st&p=143374, и решил линию управления RW переключить с GND на линию PD1. Поэтому если будут исходники с чтением состояния ЖКИ, очень хотелось бы ознакомиться. Вот работающий проект - разберётесь. WinAWR или атмеловский тулчейн. Интересующая Вас часть (работа с проверкой готовности) находится в файле hd44780.c Изменено 2 мая, 2011 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
melandr 0 2 мая, 2011 Опубликовано 2 мая, 2011 · Жалоба Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе. У Вас компилятор IAR, а то я пытаюсь скомпилить в AVRStudio, а он ругается? Вот работающий проект - разберётесь. WinAWR или атмеловский тулчейн. Интересующая Вас часть (работа с проверкой готовности) находится в файле hd44780.c Спасибо буду разбираться с Вашим исходником. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
roman_golovenkov 0 3 мая, 2011 Опубликовано 3 мая, 2011 (изменено) · Жалоба У Вас компилятор IAR, а то я пытаюсь скомпилить в AVRStudio, а он ругается? Компилировал в CoDeVision Изменено 3 мая, 2011 пользователем roman_golovenkov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 3 мая, 2011 Опубликовано 3 мая, 2011 · Жалоба Вот это - temp=(lcd|(1<<RS))|(1<<E); и все остальные манипуляции с lcd - неправильные Нужно маскировать старшую часть lcd, иначе она у вас накладывается на управляющие сигналы: temp=((lcd&0x0F)|(1<<RS))|(1<<E); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 3 мая, 2011 Опубликовано 3 мая, 2011 · Жалоба иначе она у вас накладывается на управляющие сигналы:Там маскируются те биты, для которых управляющие сигналы сброшены. А для тех, которые надо выставлять - совершенно неважно, была там единица или нет. Да, некрасиво, но работать должно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 3 мая, 2011 Опубликовано 3 мая, 2011 · Жалоба Там маскируются те биты, для которых управляющие сигналы сброшены. А для тех, которые надо выставлять - совершенно неважно, была там единица или нет.Не маскируются вообще никакие биты. В частности бит E (там, где он стоять не должен) Да, некрасиво, но работать должно.Неа, точнее не везде :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 3 мая, 2011 Опубликовано 3 мая, 2011 · Жалоба Не маскируются вообще никакие биты. В частности бит E (там, где он стоять не должен) Читаем по губам: 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 temp=((lcd*16)&~(1<<RS))|(1<<E); //RS=0 – это команда PORTD=temp; //Выводим на portD младшую тетраду команды, сигналы RS, E В первой строке ((lcd*16)&~(1<<RS)) также сбрасывается RS, хотя он и так сброшен в процессе lcd*16, а E безусловно взводится. Неа, точнее не везде :rolleyes:Ну да, там где нужны остальные биты порта такая конструкция принесет приятные :smile3046: сюрпризы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 3 мая, 2011 Опубликовано 3 мая, 2011 · Жалоба Да, действительно. Не заметил :( Все равно это не комильфо :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
melandr 0 3 мая, 2011 Опубликовано 3 мая, 2011 · Жалоба Я так понимаю, что хоть программа написана не сильно красиво, но должна работать? Я сам заметил, что немного неудобно манипулировать управляющими линиями ЖКИ, и одновременно передавать данные, но у меня сейчас стоит задача запустить ЖКИ, а дальше оптимизировать и улучшать код. Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе. Так скомпилил в CodeVision, немного изменил, для мигания светодиодом. В протеусе запустил все норм, на экране в протеусе появилась надпись. В железе светодиод мигает, а изображения нет. Есть подозрение, что шлейф соединяющий отладочную плату с ЖКИ, не передает все сигналы. Так как изображения нет, но контрастность регулируется в верхней строке. Завтра прикуплю разьемы на шлейф, и переделаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
melandr 0 4 мая, 2011 Опубликовано 4 мая, 2011 · Жалоба Попробуйте этот код, ток у меня на 16 меге. Все работает: ив Протеусе, и в железе. Все норм, спасибо. Заработало в железе, после того как шлейф переделал. Мой код правда не работает буду разбираться со своим кодом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
melandr 0 7 мая, 2011 Опубликовано 7 мая, 2011 · Жалоба Переделал код CodeVision под WinAVR. Вот код: #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 Также непонятно как использовать флеш память в функции // Записывает строку для отображения из памяти программ в ЖКИ-модуль. void lcd_putsf(char *str) { char c; while (c = *str++) { lcd_putchar©; } } Кто может подскажите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 7 мая, 2011 Опубликовано 7 мая, 2011 · Жалоба Компилятор ожидает логическое выражение в операторе while (c = *str++). Не знаю логики программы, возможно, должно быть while (c == *str++) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
melandr 0 7 мая, 2011 Опубликовано 7 мая, 2011 (изменено) · Жалоба Не знаю логики программы, возможно, должно быть while (c == *str++) Код для CodeVision записан выше на странице, он нормально работает. Я просто переделываю код под WinAVR. Дело в том, что в коде для CodeVision для этого выражения отключены предупреждения компилятора. Я так понимаю это выражение служит для обработки строки символов в цикле. А выходом из цикла является символ конца строки "\0". Но WinAVR дает предупреждение, а не ошибку. А код не работает. Изменено 7 мая, 2011 пользователем Melandr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 7 мая, 2011 Опубликовано 7 мая, 2011 (изменено) · Жалоба Из памяти программ читать удобно чем-либо из WinAVR\avr\include\avr\pgmspace.h. -- Насчёт предупреждения, - поставьте ещё скобки, вот так вот: while(( )). Явно показываем компилятору что мы не ошиблись, и на ноль\не ноль проверяем действительно результат операции присваивания. Изменено 7 мая, 2011 пользователем SysRq Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться