Как стать автором
Обновить

Подключение жидкокристаллического дисплея LCD1602 (HD44780) к микроконтроллеру ATmega8 в 8-битном режиме

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров9.9K
Автор оригинала: lokeshc

Примечание:

Статья не является оригинальным переводом. Статья созданы на базе статьи (см. источник информации указанный ниже) путем его перевода, использования основного текста оригинала и дополнена автором; данный код протестирован на реальном устройстве ф. Winstar.

LCD-дисплеи (Liquid Crystal Displays) используют для отображения состояния или параметров в различных приборах.

Жидкокристаллический дисплей LCD1602 представляет собой 16-выводное устройство, имеющее 8 выводов для передачи данных (D0-D7) и 3 вывода управления (RS, RW, EN). Остальные 5 выводов предназначены для питания и подсветки ЖК-дисплея. Цифры «1602» указывают на формат выводимой (отображаемой) информации: 16x02 символов (рисунок 1).

Выводы управления помогают нам настроить LCD-дисплей в командном режиме или режиме передачи данных. Они также помогают настроить режим чтения или записи, а также время чтения или записи.

LCD-дисплей 16x2 можно использовать в 4-битном или 8-битном режиме в зависимости от технических требований. Чтобы использовать его, нам необходимо отправить определенные команды на LCD-дисплей в командном режиме, и как только ЖК-дисплей будет настроен в соответствии с нашими требованиями, мы сможем отправить необходимые данные в режиме передачи данных.

Для получения дополнительной информации о LCD-дисплее 16x02 и о том, как его использовать, необходимо обратиться к datasheet.

Рисунок 1 – Распиновка жидкокристаллического дисплея LCD1602 (HD44780)
Рисунок 1 – Распиновка жидкокристаллического дисплея LCD1602 (HD44780)

Схема подключения жидкокристаллического дисплея LCD1602 (HD44780) к микроконтроллеру ATmega8 в 8-битном режиме показана на рисунке 2.

Рисунок 2 – Подключение жидкокристаллического дисплея LCD1602 к микроконтроллеру ATmega8 в 8-битном режиме
Рисунок 2 – Подключение жидкокристаллического дисплея LCD1602 к микроконтроллеру ATmega8 в 8-битном режиме

Подстрочный резистор R1 предназначен для точной подстройки контрастности дисплея. Резистор R2 предназначен для ограничения тока на аноде подсветки дисплея.

Таблица 1 – Аппаратные соединения

Выводы LCD-дисплея

Выводы ATmega8

Выводы для передачи данных D0-D7

PORTB

RS

PORTC0

RW

PORTC1

E

PORTC2

Функция инициализации дисплея:

1. Включить питание на LCD-дисплее

2. Необходимо подождать не менее 15 мс, время инициализации включения питания для LCD1602.

3. Отправить команду 0x38 которая переводит LCD-дисплей в 2-строчный, 8-битный режим и 5x8 точек.

4. Отправить одну из команд включения курсора дисплея (0x0E, 0x0C).

5. Отправить команду 0x06 (сдвиг курсора вправо).

Листинг кода:

void LCD_Init (void)	/* LCD Initialize function */
{
	LCD_Command_Dir = 0xFF;	/* Make LCD command port direction as o/p */
	LCD_Data_Dir = 0xFF;	/* Make LCD data port direction as o/p */

	_delay_ms(20);		/* LCD Power ON delay always >15ms */
	LCD_Command (0x38);	/* Initialization of 16X2 LCD in 8bit mode */
	LCD_Command (0x0C);	/* Display ON Cursor OFF */
	LCD_Command (0x06);	/* Auto Increment cursor */
	LCD_Command (0x01);	/* clear display */
	LCD_Command (0x80);	/* cursor at home position */
}

Теперь, когда LCD–дисплей инициализирован, он готов принимать данные для отображения.

 Функция записи команд (инструкций):

1. Отправим значение команды на порт передачи данных LCD1602.

2. Установим вывод RS на «низкий» уровень, RS = 0 (регистр команд).

3. Установим вывод RW на «низкий» уровень, RW = 0 (операция записи)

4. Подадим импульс от «высокого» до «низкого» на выводе Enable (E) с минимальной задержкой 450 нс.

Когда мы подаем разрешающий импульс, LCD-дисплей фиксирует данные, имеющиеся на выводах D0 – D7, и выполняет их как команду, поскольку RS - это регистр команд.

 Листинг кода:

void LCD_Command(unsigned char cmnd)
{
	LCD_Data_Port= cmnd;
	LCD_Command_Port &= ~(1<<RS);	/* RS=0 command reg. */
	LCD_Command_Port &= ~(1<<RW);	/* RW=0 Write operation */
	LCD_Command_Port |= (1<<EN);	/* Enable pulse */
	_delay_us(1);
	LCD_Command_Port &= ~(1<<EN);
	_delay_ms(3);
}

Функция записи данных:

1. Отправим команду на порт передачи данных.

2. Установим вывод RS на «высокий» уровень, RS = 1 (регистр данных)

3. Установим вывод RW на «низкий» уровень, RW = 0 (операция записи)

4. Подадим импульс от «высокого» до «низкого» на выводе Enable (E).

Когда мы подаем разрешающий импульс, LCD-дисплей фиксирует имеющиеся данные (на выводах D0-D7) и отображает их на матрице 5x8, поскольку RS - это регистр данных.

Листинг кода:

void LCD_Char (unsigned char char_data)	/* LCD data write function */
{
	LCD_Data_Port = char_data;
	LCD_Command_Port |= (1<<RS);	/* RS=1 Data reg. */
	LCD_Command_Port &= ~(1<<RW);	/* RW=0 write operation */
	LCD_Command_Port |= (1<<EN);	/* Enable Pulse */
	_delay_us(1);
	LCD_Command_Port &= ~(1<<EN);
	_delay_ms(1);
}

Функция отображения строки:

Эта функция принимает строку (массив символов) и отправляет по одному символу в функцию данных LCD-дисплея до конца строки. Цикл for используется для отправки символа на каждой итерации. Символ NULL указывает на конец строки.

Листинг кода:

void LCD_String (char *str)		
{
	int i;
	for(i=0;str[i]!=0;i++)  /* send each char of string till the NULL */
	{
		LCD_Char (str[i]);  /* call LCD data write */
	}
}

Примечания:

1. Задержка включения LCD-дисплея. После включения LCD1602 мы не можем немедленно отправлять на него команды, поскольку ему требуется время на инициализацию 15 мс. Поэтому при программировании нам нужно позаботиться о том, чтобы обеспечить достаточную задержку включения питания (> 15 мс), а затем отправлять команды на LCD-дисплей.

2. После проверки команд LCD1602 требуется время (в микросекундах) для их выполнения. Но для команды 0x01 (т.е. очистить отображение) выполнение занимает 1,64 мс. Следовательно, после отправки команды 0x01 необходимо обеспечить достаточную задержку (> 1,63 миллисекунды).

Листинг программы:

#define F_CPU 8000000UL			/* Define CPU Frequency e.g. here 8MHz */
#include <avr/io.h>			/* Include AVR std. library file */
#include <util/delay.h>			/* Include inbuilt defined Delay header file */

#define LCD_Data_Dir DDRB		/* Define LCD data port direction */
#define LCD_Command_Dir DDRC		/* Define LCD command port direction register */
#define LCD_Data_Port PORTB		/* Define LCD data port */
#define LCD_Command_Port PORTC		/* Define LCD data port */
#define RS PC0				/* Define Register Select (data/command reg.)pin */
#define RW PC1				/* Define Read/Write signal pin */
#define EN PC2				/* Define Enable signal pin */
 

void LCD_Command(unsigned char cmnd)
{
	LCD_Data_Port= cmnd;
	LCD_Command_Port &= ~(1<<RS);	/* RS=0 command reg. */
	LCD_Command_Port &= ~(1<<RW);	/* RW=0 Write operation */
	LCD_Command_Port |= (1<<EN);	/* Enable pulse */
	_delay_us(1);
	LCD_Command_Port &= ~(1<<EN);
	_delay_ms(3);
}

void LCD_Char (unsigned char char_data)	/* LCD data write function */
{
	LCD_Data_Port= char_data;
	LCD_Command_Port |= (1<<RS);	/* RS=1 Data reg. */
	LCD_Command_Port &= ~(1<<RW);	/* RW=0 write operation */
	LCD_Command_Port |= (1<<EN);	/* Enable Pulse */
	_delay_us(1);
	LCD_Command_Port &= ~(1<<EN);
	_delay_ms(1);
}

void LCD_Init (void)			/* LCD Initialize function */
{
	LCD_Command_Dir = 0xFF;		/* Make LCD command port direction as o/p */
	LCD_Data_Dir = 0xFF;		/* Make LCD data port direction as o/p */
	_delay_ms(20);			/* LCD Power ON delay always >15ms */
	
	LCD_Command (0x38);		/* Initialization of 16X2 LCD in 8bit mode */
	LCD_Command (0x0C);		/* Display ON Cursor OFF */
	LCD_Command (0x06);		/* Auto Increment cursor */
	LCD_Command (0x01);		/* Clear display */
	LCD_Command (0x80);		/* Cursor at home position */
}

void LCD_String (char *str)		/* Send string to LCD function */
{
	int i;
	for(i=0;str[i]!=0;i++)		/* Send each char of string till the NULL */
	{
		LCD_Char (str[i]);
	}
}

void LCD_String_xy (char row, char pos, char *str)/* Send string to LCD with xy position */
{
	if (row == 0 && pos<16)
	LCD_Command((pos & 0x0F)|0x80);	/* Command of first row and required position<16 */
	else if (row == 1 && pos<16)
	LCD_Command((pos & 0x0F)|0xC0);	/* Command of first row and required position<16 */
	LCD_String(str);		/* Call LCD string function */
}

void LCD_Clear()
{
	LCD_Command (0x01);		/* clear display */
	LCD_Command (0x80);		/* cursor at home position */
}
 
int main()
{

	LCD_Init();			/* Initialize LCD */

	LCD_String("Hello World");	/* write string on 1st line of LCD*/
	LCD_Command(0xC0);		/* Go to 2nd line*/
	LCD_String("8 bit");	/* Write string on 2nd line*/

	return 0;

После загрузки прошивки на дисплее LCD1602 мы увидим следующий результат, показанный на рисунке 3.

Хорошим тоном программирования является создание отдельной библиотеки для нашего ЖК-дисплея.

Рисунок 3 – Результат работы прошивки
Рисунок 3 – Результат работы прошивки

Расшифровка наиболее употребляемых команд, посылаемых от микроконтроллера в дисплей LCD1602 (HD44780) приведена в таблицах 2,3.

Таблица 2 – Расшифровка наиболее употребляемых команд, посылаемых от микроконтроллера в дисплей LCD1602 (HD44780)

Команда ЖКИ

HEX-код

Выполняемые действия

Время вып., мкс

Очистка дисплея

0x01

Пустой экран, очистка памяти, курсор в левой верхней позиции

1640

Возвращает курсор в начало

0x02

Курсор в левой верхней позиции, память не очищается

1640

Сдвиг курсора влево

0x04

После вывода очередного символа курсор автоматически сдвигается на одно знакоместо влево

40

Сдвиг курсора вправо

0x06

После вывода очередного символа курсор автоматически сдвигается на одно знакоместо вправо

40

Выключение дисплея

0x08

Полное отсутствие изображения на экране ЖКИ

40

Выключение курсора

0x0C

Разрешается вывод изображения, но курсор не виден

40

Прямоугольная форма курсора

0x0D

Разрешается вывод изображения, курсор в виде темного мигающего прямоугольника

40

Линейная форма курсора

0x0E

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

40

Комплексная форма курсора

0x0F

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

40

Интерфейс 4 бита, 1 строка

0x20

Связь с однострочным ЖКИ через 4 линии шины данных

40

Интерфейс 4 бита, 2 строки

0x28

Связь с двухстрочным ЖКИ через 4 линии шины данных

40

Интерфейс 8 бит, 1 строка

0x30

Связь с однострочным ЖКИ через 8 линий шины данных

40

Интерфейс 8 бит, 2 строки

0x38

Связь с двухстрочным ЖКИ через 8 линий шины данных

40

Доступ к ОЗУ знакогенератора

0x40-0x7F

Запись данных по этим адресам позволяет создавать 16 своих символов

40

Установка позиции курсора

0x80-0xCF

Курсор устанавливается в позицию согласно табл. 3

40

Время выполнения команд указано приблизительно. Оно определяется частотой внутреннего RC-генератора LCD-дисплея, которая, в свою очередь, зависит от технологического разброса и температуры нагрева корпуса.

Таблица 3 – Команды для перехода на определенное знакоместо верхней или нижней строки экрана для дисплея LCD1602 (HD44780)

Верхняя строка ЖКИ

0x80

0x81

0x82

0x83

0x84

0x85

0x86

0x87

0x88

0x89

0x8A

0x8B

0x8C

0x8D

0x8E

0x8F

0xC0

0xC1

0xC2

0xC3

0xC4

0xC5

0xC6

0xC7

0xC8

0xC9

0xCA

0xCB

0xCC

0xCD

0xCE

0xCF

Нижняя строка ЖКИ

См. также: Подключение жидкокристаллического дисплея LCD1602 (HD44780) к микроконтроллеру ATmega8 в 4-битном режиме

Источник информации: https://www.electronicwings.com/avr-atmega/lcd16x2-interfacing-with-atmega16-32

Теги:
Хабы:
Всего голосов 10: ↑4 и ↓60
Комментарии21

Публикации

Истории

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн