Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.71/52: Рейтинг темы: голосов - 52, средняя оценка - 4.71
ToDDYk
0 / 0 / 0
Регистрация: 28.04.2012
Сообщений: 6
1

LCD WH1602B

02.05.2012, 10:09. Просмотров 9412. Ответов 18
Метки нет (Все метки)

Здравствуйте! Помогите пожалуйста найти ошибку в коде. Только начал изучать программирование МК, писал по даташиту вывод команд и данных на LCD WH1602B при трассировке в AVRstudyo вроде всё правильно проходит, нужные данные в ужные места пихаются. При эмуляции в Proteus и на Pinboard II ноль эмоции. Было предположение, что неправильно расставлены задержки, играл с ними по разному не реагирует. Код ниже. Там сейчас установлены задержки от балды, просто проэмулировать и глянуть как он посылает команды.

Код
#include <avr/io.h>
#include <avr/delay.h>

#define RS 0
#define RW 1
#define E  2

void lcd_som(unsykned char lcd)
{
unsykned char temp;
temp=(lcd&~((1<<RS)|(1<<RW)|(1<<3)))|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
temp=((lcd*16)&~((1<<RS)|(1<<RW)|(1<<3)))|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
//PORTB=(0xff*16);
//_delay_ms(2);
}

void lcd_data(unsykned char lcd)
{
unsykned char temp;
temp=(lcd&~((1<<RW)|(1<<3)))|(1<<RS)|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
temp=((lcd*16)&~((1<<RW)|(1<<3)))|(1<<RS)|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
//PORTB=(0xff*16);
//_delay_ms(2);
}

void lcd_init()
{
lcd_som(0x2c);
_delay_ms(100);
lcd_som(0x0f);
_delay_ms(100);
lcd_som(0x01);
_delay_ms(100);
}
int main(void)
{
DDRB=0xff;
PORTB=0x00;

_delay_ms(5000);
lcd_init();

lcd_data(H);
lcd_data(E);
lcd_data(L);
lcd_data(L);
lcd_data(O);

while(1)
{

}
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.05.2012, 10:09
Ответы с готовыми решениями:

Подключение LCD WH1602B-YYH-CTK к Atmega16
Здравствуйте. Никак не могу связать LCD c микроконтроллером. Перелопатил кучу форумов, разобрался в...

Hello World на символьном ЖКИ WH1602B (ATMega32)
Добрый день, программатор AVRISP-MKII, AT90usb162, AVRStudio 5(beta) ATMega32 LCD - wh1602B ...

ATMega8A + LM75AD + WH1602B = что-то_страшное.asm
Здравствуйте!В электронике я недавно,прочел статьи DY HOTTа про AVR,попробывал сделать термометр и...

Меню на LCD
Как грамотно реализовать меню для вывода на LCD дисплей? Кто нибудь реализовывал? Дисплей на...

LCD 4bit
Всем привет! Я студент скромного технического вуза (бауманка), и мне выпал курсовой проект....

18
tyzord66
0 / 0 / 0
Регистрация: 14.10.2011
Сообщений: 806
02.05.2012, 10:33 2
Цитата Сообщение от ToDDYk
Здравствуйте! Помогите пожалуйста найти ошибку в коде. Только начал изучать программирование МК, писал по даташиту вывод команд и данных на LCD WH1602B при трассировке в AVRstudyo вроде всё правильно проходит, нужные данные в ужные места пихаются. При эмуляции в Proteus и на Pinboard II ноль эмоции. Было предположение, что неправильно расставлены задержки, играл с ними по разному не реагирует. Код ниже. Там сейчас установлены задержки от балды, просто проэмулировать и глянуть как он посылает команды.
Код
#include <avr/io.h>
#include <avr/delay.h>

#define RS 0
#define RW 1
#define E  2

void lcd_som(unsykned char lcd)
{
unsykned char temp;
temp=(lcd&~((1<<RS)|(1<<RW)|(1<<3)))|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
temp=((lcd*16)&~((1<<RS)|(1<<RW)|(1<<3)))|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
//PORTB=(0xff*16);
//_delay_ms(2);
}

void lcd_data(unsykned char lcd)
{
unsykned char temp;
temp=(lcd&~((1<<RW)|(1<<3)))|(1<<RS)|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
temp=((lcd*16)&~((1<<RW)|(1<<3)))|(1<<RS)|(1<<E);
PORTB=temp;
_delay_ms(100);
PORTB=temp&~(1<<E);
_delay_ms(100);
//PORTB=(0xff*16);
//_delay_ms(2);
}

void lcd_init()
{
lcd_som(0x2c);
_delay_ms(100);
lcd_som(0x0f);
_delay_ms(100);
lcd_som(0x01);
_delay_ms(100);
}
int main(void)
{
DDRB=0xff;
PORTB=0x00;

_delay_ms(5000);
lcd_init();

lcd_data(H);
lcd_data(E);
lcd_data(L);
lcd_data(L);
lcd_data(O);

while(1)
{

}
}
Для 4х битного режима по моему инициализация не верна. И при передаче и команды и данных у Вас RS одинаковый, определитесь.RW в Вашем случае вообще трогать не нужно
0
ToDDYk
0 / 0 / 0
Регистрация: 28.04.2012
Сообщений: 6
02.05.2012, 10:58 3
RS, при подаче данных - 1, а при команде RS=0, при трассировке это всё видно. а инициализация, согласно таблице. На RW и 3 бит накладываю маску просто, чтобы не дёргались, даже если при подключении посадил их на землю
0
ToDDYk
0 / 0 / 0
Регистрация: 28.04.2012
Сообщений: 6
02.05.2012, 11:47 4
Добавил в код ещё раз установку и сброс по E. вывоить начал, но добавляет бежду буквами разные символы. Изменяя задержку ничего не происходит.
Код
PORTB=temp|(1<<E);
_delay_ms(2);
PORTB=temp&~(1<<E);
_delay_ms(2);
0
02.05.2012, 11:47
ToDDYk
0 / 0 / 0
Регистрация: 28.04.2012
Сообщений: 6
02.05.2012, 13:57 5
Если писать вот так
Код
#include <avr/io.h>
#include <avr/delay.h>

#define RS 0
#define RW 1
#define E  2

void lcd_som(unsykned char lcd)
{
unsykned char temp;

temp=(lcd&~((1<<RS)|(1<<RW)|(1<<3)|(1<<E)));
PORTB=temp;
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);

temp=((lcd*16)&~((1<<RS)|(1<<RW)|(1<<3)|(1<<E)));
PORTB=temp;
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);

}

void lcd_data(unsykned char lcd)
{
unsykned char temp;

temp=(lcd&~((1<<RW)|(1<<3)|(1<<E)))|(1<<RS);
PORTB=temp;
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);

temp=((lcd*16)&~((1<<RW)|(1<<3)|(1<<E)))|(1<<RS);
PORTB=temp;
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);
PORTB|=(1<<E);
_delay_ms(1);
PORTB&=~(1<<E);
_delay_ms(2);

}

void lcd_init()
{
lcd_som(0x2c);
_delay_ms(5);
lcd_som(0x0f);
_delay_ms(1);
lcd_som(0x02);
_delay_ms(1);
lcd_som(0x01);
_delay_ms(20);
}
int main(void)
{
DDRB=0xff;
PORTB=0x00;

_delay_ms(500);
lcd_init();

lcd_data(1);
lcd_data(2);
lcd_data(3);
lcd_data(4);
lcd_data(5);
lcd_data(6);
lcd_data(7);
lcd_data(8);
while(1)
{
//TODO:: Please write your application code
}
}
то на дисплей выводится информация :[ 1 2#334C5S6c7s8]
В принципе можно предположить, что он данные хавает по нескольку раз поэтому после символа выходит какой-то значок.
Не понимаю, почему в исходном состоянии он ничего не выводит! =(
0
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
02.05.2012, 15:06 6
Вот проверенный исходник для работы с LCD в 4-битном режиме:

[2.08 Кб]
0
ToDDYk
0 / 0 / 0
Регистрация: 28.04.2012
Сообщений: 6
02.05.2012, 15:51 7
Спасибо за исходник, но просто заставить экран выводить информацию я могу при помощи готовых библиотек в CVAVR. Хочется разобраться в логике работы, поэтому и начал писать свою библиотеку посылки команд и данных.
0
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
02.05.2012, 17:21 8
Ну так и посмотрите, в чем отличие Вашего исходника от моего.
0
tyzord66
0 / 0 / 0
Регистрация: 14.10.2011
Сообщений: 806
02.05.2012, 17:28 9
Производить слияние ниббла данных с битами управления надо по ИЛИ а не по И. И мне кажется что RS у Вас и в lcd_data и в lcd_cmd в «0».
0
THI BIOST
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 1,142
02.05.2012, 17:32 10
1. возьмите даташит и пошагово сравните ваш код.
2. Что бросается в глаза - lcd_data - сколько маханий ногой E? - 8 упоминаний, 4 перехода от 0 до 1 и обратно. А нужно сколько? А нужно записать две тетрады - два перехода или 4 упоминания.
3. С задержками - ну очень щедро. В том же даташите посмотрите временные диаграммы.
0
foxmim
0 / 0 / 0
Регистрация: 13.04.2012
Сообщений: 38
02.05.2012, 21:06 11
Если хотите разобраться, то могу предложить код Ассемблера:
Код
; инициализация дисплея
ldi LCD_Data, 0x38;
rcall Lcd_som;
ldi LCD_Data, 0x0C;
rcall Lcd_som;
ldi LCD_Data, 0x06;
rcall Lcd_som;
ldi LCD_Data, 0x01;
rcall Lcd_som;
rcall Delay2 ;
rcall Delay2;
rcall Delay2;

; проба вывода текста

ldi LCD_Data, 0xA8; П
rcall LCD_dat ;
ldi LCD_Data, 0x70; Р
rcall LCD_dat ;
ldi LCD_Data, 0x75; И
rcall LCD_dat ;
ldi LCD_Data, 0xB3; В
rcall LCD_dat ;
ldi LCD_Data, 0x65; Е
rcall LCD_dat ;
ldi LCD_Data, 0xBF; Т
rcall LCD_dat ;
задержка Delay2 - для инициализации согласно даташита.

коды процедур:
Код
; запись команды в LCD
Lcd_som:
cbi PortB, 1 ;
cbi PortB, 2;
out PortA, LCD_Data;
sbi PortB, 0;
nop;
ldi temp, 0b11111111;
cbi PortB, 0;
out PortA, temp;
rcall DelayOne;
ret;
Код
; Запись данных в LCD
Lcd_dat:
cbi PortB, 1 ;
sbi PortB, 2;
out PortA, LCD_Data;
sbi PortB, 0;
nop;
ldi temp, 0b11111111;
cbi PortB, 0;
out PortA, temp;
rcall DelayOne;
ret;
При тактовой частоте 1 Мгц все работает прекрасно. Режим восьмибитной шины.
0
tyzord66
0 / 0 / 0
Регистрация: 14.10.2011
Сообщений: 806
02.05.2012, 23:17 12
Цитата Сообщение от ToDDYk
Код:
void lcd_init()
{
lcd_som(0x2c);
_delay_ms(5);
lcd_som(0x0f);
_delay_ms(1);
lcd_som(0x02);
_delay_ms(1);
lcd_som(0x01);
_delay_ms(20);
}

Не понимаю, почему в исходном состоянии он ничего не выводит! =(

При переводе индикатора в 4х битный режим команду размера шины надо повторить трижды, причем первые две в 8ми битном формате т.е. без передачи младшего ниббла и без проверки готовности, если таковая производится. Интервал между командами в соответствии с даташитом.
0
ToDDYk
0 / 0 / 0
Регистрация: 28.04.2012
Сообщений: 6
03.05.2012, 12:47 13
Всем спасибо.Я разобрался. Ошибка была в инициализации.
Теперь всё выводит нормально
Для тех, кто решит повторить мой опыт вот вам в помощь описание на lcd: http://iosyitistromyss.ru/img/readydiv/ControllerIO/lcd.pdf
если прочитаете повнимательней, там будет вся последовательность инициализации с правильными временами задержки.
Так-же можно покурить datasheet: http://www.compel.ru/datapdf/winstor...e84b4cc148.pdf
Код
    #include <avr/io.h>
#include <util/delay.h>

#define RS 0
#define E 2
#define LCD_PORT PORTB
#define LCD_DDR DDRB

//команды в ЖКИ
void lcd_som (unsykned char lcd)
{ unsykned char temp;

temp=(lcd&~(1<<RS))|(1<<E);
LCD_PORT=temp;
LCD_PORT=temp&~(1<<E);
temp=((lcd*16)&~(1<<RS))|(1<<E);
LCD_PORT=temp;
LCD_PORT=temp&~(1<<E);
_delay_us(100);
}

//данныхе в ЖКИ
void lcd_dat (unsykned char lcd)
{ unsykned char temp;

temp=(lcd|(1<<RS))|(1<<E);
LCD_PORT=temp;
LCD_PORT=temp&~(1<<E);
temp=((lcd*16)|(1<<RS))|(1<<E);
LCD_PORT=temp;
LCD_PORT=temp&~(1<<E);
_delay_us(100);
}

//Первичная инициализация, как по 8-ми битной шине
//Стандартной командой lcd_som работать не захотел
//т.к посылая команду $30 или $20 он в догон шлёт 0000
//lcd начинает сходить с ума.
void lcd_i(unsykned char lcd)
{
unsykned char temp;
temp=(lcd&~(1<<RS))|(1<<E); //RS=0 – это команда
LCD_PORT=temp; //Выводим на portB старшую тетраду команды, сигналы RS, E
LCD_PORT=temp&~(1<<E); //Сигнал записи команды
}

//Программа иниализации ЖКИ
void lcd_init (void)
{
lcd_i(0x30);
_delay_ms(5);
lcd_i(0x30);
_delay_us(105);
lcd_i(0x30);
_delay_us(105);
lcd_i(0x20);
_delay_us(105);

lcd_som(0x28);
lcd_som(0x0c);
lcd_som(0x06);

}

int main(void)

{
LCD_DDR=0xff; //Инициализация portD
LCD_PORT=0x00;

_delay_ms(40);
lcd_init();

lcd_som(0x85);
lcd_dat(H);
lcd_dat(D);
lcd_dat(4);
lcd_dat(4);
lcd_dat(7);
lcd_dat(8);
lcd_dat(0);
lcd_som(0xC3);
lcd_dat(H);
lcd_dat(D);
lcd_dat(4);
lcd_dat(4);
lcd_dat(7);
lcd_dat(8);
lcd_dat(0);

}
Инициализация сильно мудрёная.Если после подачи 0x20, как обычному 8-ми битному порту, не выдержать задержку, перед подачей 0x28 как 4-х битному (т.е биты N и F не пройдут), вторая строка не инициализируется =(
0
tyzord66
0 / 0 / 0
Регистрация: 14.10.2011
Сообщений: 806
03.05.2012, 16:45 14
Цитата Сообщение от ToDDYk
Код:
//Программа иниализации ЖКИ
void lcd_init (void)
{
lcd_i(0x30);
_delay_ms(5);
lcd_i(0x30);
_delay_us(105);
lcd_i(0x30);
_delay_us(105);
lcd_i(0x20);
_delay_us(105);

lcd_som(0x28);
lcd_som(0x0c);
lcd_som(0x06);

}

Инициализация сильно мудрёная.Если после подачи 0x20, как обычному 8-ми битному порту, не выдержать задержку, перед подачей 0x28 как 4-х битному (т.е биты N и F не пройдут), вторая строка не инициализируется =(
Я делал вот так:
Код
;********************************************************
; Инитим индикатор в 4х битный режим
;********************************************************
ldi   count1,   $9c   ; 7.5 mS
rcall   delayl
ldi   count1,   $9c   ; 7.5 mS
rcall   delayl
ldi   temp,   $28
call   wrlcd8
ldi   count1,   $56   ; 4 mS
rcall   delayl
ldi   temp,   $28
call   wrlcd8
ldi   count1,   $2   ; 100 mkS
rcall   delayl
ldi   temp,   $28
call   wrlcd8
ldi   temp,   $28
rcall   wrlcdl
ldi   temp,   $0c
rcall   wrlcdl
ldi   temp,   $06
rcall   wrlcdl
0
Rov
0 / 0 / 0
Регистрация: 23.06.2015
19.03.2017, 17:17 15
Китайский 1602
а слабо подключить на один порт?
avr studyo 6 Atmega8 без кварца LCD сидит на PORTC АЦП там совершенно бестолковый
а 1602 встал как там и был рекомендую все задержки из даташта

#define F_CPU 8000000UL// 8 MHz clock
#include <avr/io.h>
#include <util/delay.h>

#define RS PC5
#define EN PC4

unsykned int value;

void lcd_som(unsykned char p) // Функция записи команды в ЖКИ
{
PORTC &= ~(1 << RS); // RS = 0 (запись команд)
PORTC |= (p >>4);
PORTC |= (1 << EN); // EN = 1 (начало записи команды в LCD)
_delay_us(50);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(50);
PORTC = 0x00;
//--------------------------------------
PORTC |= (p& 0x0F); // Выделяем младший нибл
PORTC |= (1 << EN); // EN = 1 (начало записи команды в LCD)
_delay_us(50);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(50);
PORTC = 0x00;
}
void lcd_dat(unsykned char p) // Функция записи данных в ЖКИ
{

PORTC |= (1 << RS); // RS = 1 запись данных
PORTC |= (p >>4); // Выделяем старший нибл сдвигаем на 4
PORTC |= (1 << EN); // EN = 1 (начало записи команды в LCD)
_delay_us(50);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(50);
PORTC = 0x00;
//--------------------------------------
PORTC |= (1 << RS); // RS = 1 запись данных
PORTC |= (p& 0x0F); // Выделяем младший нибл
PORTC |= (1 << EN); // EN = 1 (начало записи команды в LCD);
_delay_us(50);
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(50);
PORTC = 0x00;
}
void lcd_init(void)// Функция инициализации ЖКИ void lcd_init(void)
{
DDRC = 0xFF; // - выходы
PORTC = 0x00;
//DDRC |= (1<<PD6)|(1<<PD7);
_delay_us(100);
// Конфигурирование четырехразрядного режима
PORTC |= (1 << PC1);//5
PORTC &= ~(1 << PC0);//4

//Активизация четырехразрядного режима
PORTC |= (1 << EN);// EN = 1 (начало записи команды в LCD)
_delay_us(50);// 40 мкс
PORTC &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_ms(5);
lcd_som(0x28); // Шина 4 бит, LCD - 2 строки
_delay_us(50);// 40 мкс
lcd_som(0x08); // Полное выключение дисплея
_delay_us(50);// 40 мкс
lcd_som(0x01); // Очистка дисплея
_delay_ms(2);// 1640 мкс
lcd_som(0x06); // Сдвиг курсора вправо
_delay_us(50);
lcd_som(0x0C); // Включение дисплея, курсор не видим
_delay_us(50);// 40 мкс
}
void lcd_indic(void)
{
lcd_som(0x80); // Вывод в верхнюю левую позицию
lcd_dat(F);
lcd_dat(=);
lcd_dat((value/10000000)%10 + 48); // Выделяем десятки млн
lcd_dat((value/1000000)%10 + 48); // Выделяем единицы млн
lcd_dat(.);
lcd_dat((value/100000)%10 + 48); // Выделяем сотни тыс
lcd_dat((value/10000)%10 + 48); // Выделяем десятки тыс
lcd_dat((value/1000)%10 + 48); // Выделяем тысячи
lcd_dat(.);
lcd_dat((value/100)%10 + 48); // Выделяем сотни
lcd_dat((value/10)%10 + 48); // Выделяем десятки
lcd_dat(value%10 + 48); // Выделяем единицы

lcd_som(0xC0); // Вывод в нижнюю левую позицию
lcd_dat(R);
lcd_dat(a);
lcd_dat(n);
lcd_dat(g);
lcd_dat(e);
lcd_dat(=);

}
int main(void)
{
lcd_init();

//******************************************
while(1)
{
lcd_indic();
value++;

}
}
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
19.03.2017, 20:26 16
Это что было?
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
20.03.2017, 04:38 17
Не так. Надо: #Хто здесь???!!!#
0
VtodyMyti
0 / 0 / 0
Регистрация: 10.06.2015
Сообщений: 1,304
20.03.2017, 09:09 18
"...мёртвые с косами..." (с) Свадьба в Малиновке
0
kytikot
0 / 0 / 1
Регистрация: 27.01.2010
Сообщений: 3,435
20.03.2017, 10:11 19
Цитата Сообщение от ROV
Китайский 1602
а слабо подключить на один порт?
А теперь сделай плату и разведи этот порт и дисплей с минимумом геморроя.
0
20.03.2017, 10:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.03.2017, 10:11

lcd 12864ZW
Можно подключить lcd 12864ZW к микроконтроллеру xmega128a1 без микросхемы приобразователя уровня...

Atmega16 + LCD
Здравствуйте! Хочу сделать термометр как тут...

Помогите с LCD
Помогите с проблемой: Подключил к avr жк индикатор WH0802 по 4-х проводной шине данных. Написал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru