Управление жк дисплеем на микроконтроллере AVR

В этой статье вы познакомитесь с управления ЖК дисплеем с помощью команд в CodeVisionAVR, на примере типовой схемы включения микроконтроллера ATmega8 и алфавитно-цифровым ЖК экраном со встроенным чипом HD44780 компании Hitachi. Данный дисплей способен выводить символы в одну, две и четыре сроки по 8, 16, 20 и 40 символов.

Очень подробно и со схемами о подключении ЖК дисплея WH1602A на контроллере HD44780

Микросборка HD44780 это контроллер жидкокристаллического экрана со знакогенератором. Используется в символьном ЖКИ типа WH1602A, производится фирмой hitachi. Контроллер получил огромное распространение, благодаря своей функциональности и низкой цене.

символьный ЖК экран WH1602A

WH1602A может быть выпущен в двух вариантах на напряжение питания 5 вольт, или 3,3. При этом в цепи питания не всегда имеется токоограничительный резистор. Смотрите внимательно, может быть только перемычка. Ниже привожу схему включения сопротивления для настройки контрастности.

Схема управления контрастностью WH1602A

Теперь индикатор можно подключить к микроконтроллеру ATmega8 и кварцу на 4 МГц. Схема упрощенная, типовой обвес МК ATmega8 можно посмотреть тут.

Схема управления жк дисплеем на микроконтроллере

Первые три разряда порта D используются для управления, а оставшиеся четыре для данных. В случае необходимости можно работать с этими ЖК по 8 битной шине. Со схемой думаю все понятно, поэтому перейдем к программной части.

Создаем новый проект в CodeVisionAVR заходим в код-генератор на вкладку LCD и выбирают PORTD

CodeVisionAVR код-генератор вкладку LCD

Тем самым мы разрешили программе работать с ЖК дисплеем подключив его к порту D. Ниже можно выбрать количество символов в строке. Далее сохраняем проект и смотрим на получившийся код.

Рекомендую посмотреть вот на этот фрагмент кода после директивы препроцессора #include <mega8.h>

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h>>

Первая строка это комментарий, во второй мы открываем блок для возможности ввода ассемблерных команд. Третья строка присваивает порт к которому подсоединен ЖК. Если вы по ошибке в генераторе кода выбрали не тот порт, то его можно поменять на правильный в этой строке. Номер порта легко можно узнать в файле инициализации микроконтроллера. Четвертая строка закрывает блок ассемблерного кода, а в последней мы подключаем все нужное для работы с ЖК.

Теперь о функциях.

Первая из них это инициализации дисплея. Выглядит в коде она так:

void lcd_init(unsigned char lcd_columns)

она инициализирует экран, а передаваемым параметром является количества символов в строке:

// LCD module initialization
lcd_init(16);
void lcd_gotoxy(unsigned char x, unsigned char y)

Эта функция переводит курсор в позицию x, y. где x - это буква. Слева направо от 0 до 15/19/39 (зависит от количества букв в строке) . А y - это строка. Сверху вниз от 0 до 0/1/3.

void lcd_putchar(char c)

Выводит один символ в текущую позицию. Например:

lcd_putchar('A')
или
lcd_putchar(0x41)

В любом случае на выходе будем иметь один и тот же результат. То есть параметр может быть как символом, так и его кодом.

lcd_gotoxy(0,0); lcd_putchar('A'); lcd_gotoxy(0,1); lcd_putchar(0x41);

Давайте взглянем на результат.

Вывод буквы на дисплей WH1602A

Следующая функция вывод строки на ЖК.

void lcd_puts(char *str)

Она выводит строку находящуюся в SRAM начиная с текущей позиции.

lcd_gotoxy(0,0);
lcd_puts("СТРОКА");

Результат:

вывод строки на ЖК экран
void lcd_putsf(char *str)

Выводит строку находящуюся во FLASH начиная с текущей позиции.

lcd_gotoxy(0,0);
lcd_putsf("СТРОКА");

На экране видим то-же, что и в предыдущем случае

void lcd_clesr(void)

Эта команда стирает все что есть на экране, а курсор устанавливает в крайнее левое положение верхней строки.

Теперь о том как выводить значение переменных. Для этого мы будем использовать библиотеку stdio.h. Возвращаемся на самый верх программного кода и после директивы препроцессора #include <lcd.h> добавляем #include <stdio.h>, т.е:

// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x12 ;PORTD
#endasm
#include <lcd.h >
#include <stdio.h >

Новая команда, которую мы будем осваивать занимается форматированием текста.

void printf(char flash *fmtstr [,arg1, arg2, ...])

В параметре char flash *fmtstr указываем формат выводимого значения, а в аргументы arg1, arg2, ... прописываем имя переменной. Допустим:

unsigned char temp = 123;
printf("temp = %05d\n", temp);

Т.о 1-я строка создает переменную и присваивает ей определенное значение, а вторая сначала выводит запись temp =, затем 00123. Почему выводится именно 00123. А потому что у нас есть одно условие %05d\n которое говорит:

1) % - форматируем значения 1-го аргумента
2) 0 - выводим n знаков, пустые забиваются нулями
3) 5 - выводим 5 знаков, если число меньше 5 знаков, то заполняем нулями. Об этом говорит пункт 2. Числовое значение будет выровнено по правому краю.
4) d - выводим число в десятичной системе счисления.
5) \n - После вывода символа осуществляем переход на следующую строку.
void sprintf(char flash, char flash *fmtstr [,arg1, arg2, ...])

Эта команда форматирует строку и записывает ее в массив. После мы можем вывести его на дисплей

unsigned char temp = 123;
unsigned char string[20];
sprintf(string, "temp = %05d\n", temp);
lcd_puts(string);
Вывод строки на ЖК экран

Кратко по типам преобразования.

i - Для вывода десятичной целой со знаком
d - тоже
u - Для вывода десятичной целой без знака
e - Для вывода вещественного с плавающей точкой вида -d.d e-d
E - тоже вида -d.d E-d
f - Для вывода вещественного с плавающей точкой вида -d.d
x - Для вывода в шестнадцатеричном виде маленькими буквами
X - тоже большими буквами
c - Для вывода в символа

Допустим если мы теперь введем %-05d то знак "-" осуществим выравнивание по левому краю, а пустышки нулями забиваться не будут. Если мы попытаемся ввести число с плавающей точкой, то оно вводится не будет. Для того чтобы компилятор начал понимать float придется его немного настроить. Для этого в меню Project->Configure и выбираем вкладку C Compiler. В свойстве (s)printf Features: выбираем float, width, precision.