Главная » Микроконтроллеры
Призовой фонд
на июль 2017 г.
1. Осциллограф DSO138
Паяльник
2. Регулируемый паяльник 60 Вт
Паяльник
3. 200 руб.
От пользователей

Библиотека для символьного дисплея на базе HD44780

Хотел бы представить Вашему вниманию свою собственную библиотеку для работы с широко распространёнными символьными дисплеями на базе контроллера HD44780.


Рис.1 Внешний вид дисплея на базе контроллера HD44780 ( 2 строки Х 16 символов).

Библиотека написана на С#, в Atmel Studio 6.2. Библиотека состоит из двух файлов: HD44780_Config.h и HD44780.c. Первый файл является заголовочным, он, собственно, и подключается в Ваш разрабатываемый проект директивой #include "HD44780_Config.h". Также, в этом файле мы прописываем все необходимые нам начальные настройки. Вот, собственно, исходный код этого заголовочно - настроечного файла:

#ifndef HD44780_Config
#define HD44780_Config

#define uchar unsigned char
#define Sbit(reg,bit) (reg|=(1< #define Cbit(reg,bit) (reg&=~(1< #define CheckBit(reg,bit) (reg&(1< #define FirstStr_StartPosition_DDRAM_Addr 0x80
#define SecondStr_StartPosition_DDRAM_Addr 0xC0

/*
 *указываем разрядность шины данных дисплея (1-8 бит, 0-4 бита)
 */
#define Data_Length 0

/*
 *указываем количество строк дисплея (1-2 строки, 0-1 строка)
 */
#define NumberOfLines 1

/*
 *указываем размер шрифта дисплея (1–шрифт 5x10 точек, 0–шрифт 5x7 точек)
 */
#define Font 1

/*
 *указываем порт МК, к которому подключена линия E
 *указываем номер бита порта МК, к которому подключена линия E
 */
#define PORT_Strob_Signal_E PORTC
#define PIN_Strob_Signal_E 1

/*
 *указываем порт МК, к которому подключена линия RS
 *указываем номер бита порта МК, к которому подключена линия RS
 */
#define PORT_Strob_Signal_RS PORTC
#define PIN_Strob_Signal_RS 0

/*
 *порты ввода-вывода шины данных дисплея D4-D7
 *номер бита порта ввода-вывода шины данных дисплея D4-D7
 */
#if Data_Length==0   //4-х проводная шина данных
  #define PORT_bus_4 PORTD
  #define PIN_bus_4 4
  #define PORT_bus_5 PORTD
  #define PIN_bus_5 5
  #define PORT_bus_6 PORTD
  #define PIN_bus_6 6
  #define PORT_bus_7 PORTD
  #define PIN_bus_7 7
/*
 *указываем порты ввода-вывода шины данных дисплея D0-D7
 *указываем номер бита порта ввода-вывода шины данных дисплея D0-D7
 */
#elif Data_Length==1   //8-ми проводная шина данных
  #define PORT_bus_0 PORTD
  #define PIN_bus_0 0
  #define PORT_bus_1 PORTD
  #define PIN_bus_1 1
  #define PORT_bus_2 PORTD
  #define PIN_bus_2 2
  #define PORT_bus_3 PORTD
  #define PIN_bus_3 3
  #define PORT_bus_4 PORTD
  #define PIN_bus_4 4
  #define PORT_bus_5 PORTD
  #define PIN_bus_5 5
  #define PORT_bus_6 PORTD
  #define PIN_bus_6 6
  #define PORT_bus_7 PORTD
  #define PIN_bus_7 7
#endif

/*
 *функция инициализации дисплея. Должна вызываться первой.
 */
void LCD_Init(void);

/*
 *функция команды полной очистки DDRAM-памяти дисплея и установка курсора в
 *нулевую позицию
 */
void LCD_Full_Clean(void);

/*
 *функция команды установки курсора и положения дисплея в нулевую позицию
 */
void LCD_CursorPosition_ToStart(void);

/*
 *функция команды направления сдвига курсора после записи и разрешения сдви-
 *га дисплея вместе с курсором:
 *I_D(Increment/Decrement)-направление сдвига курсора после записи (I_D=1-сдвиг вправо, I_D=0–сдвиг влево);
 *S(Shift)–разрешение сдвига дисплея вместе с курсором (S=1-сдвиг разрешен, S=0-сдвиг запрещен);
 */
void LCD_AutoMovCurDispDirect(uchar I_D, uchar S);

/*
 *функция команды включения-выключения дисплея, включение-выключение курсора
 *и его мигания:
 *D(Display)–включение дисплея (D=1-дисплей включен, D=0-дисплей отключен)
 *C(Cursor)-видимость курсора (C=1–видимый курсор, C=0–погашенный курсор);
 *B(Blink)-мигание курсора (B=1–курсор мигает, B=0–курсор не мигает);
 */
void LCD_DisplEnable_CursOnOffBlink(uchar D, uchar C, uchar B);

/*
 *функция команды перемешения дисплея/курсора, направления перемешения:
 *S_C(Screen/Cursor)–перемещение дисплея/курсора (S_C=1–перемещается дисплей, S_C=0–перемещается курсор)
 *R_L(Right/Left)-направление перемещения дисплея/курсора (R_L=1–перемещение вправо, R_L=0–перемещение влево).
 */
void LCD_MovingCurDispDirection(uchar S_C, uchar R_L);

/*
 *функция вывода символов на дисплей. Параметры:
 *Addr-код символа (адрес в памяти знакогенератора)
 *Str-номер строки, в которой нужно вывести символ
 *Cursor-позиция символа в строке
 */
void LCD_Show(uchar Addr, uchar Str, uchar Cursor);

/*
 *функция записи пользовательских символов в память знакогенератора CGRAM
 *дисплея. Диапазон адресов параметра Addr: 0х00-0x07 (8 пользовательских симво-
 *лов). 1 символ занимает 8 байт данных
 */
void LCD_UserSymbolsWrite(uchar Addr, uchar *data);

/*
 *функция управляющих сигналов RS, E и шины данных. Вызывается для передачи дан-
 *ных дисплею. В качестве параметра RS передаётся 0 или 1. Если 0-команда, 1-данные.
 */
void BusLinesState(uchar *data, uchar RS);

#endif

Здесь, в общем и целом, каждая функция и каждый заданный макрос описаны между знаками комментария /* */. Большее внимание хотелось бы уделить макросам, определяющим инициализационные настройки:

#define Data_Length 0

Данный макрос определяет, по какой схеме Вы хотите подключить свой дисплей к микроконтроллеру - 4-х проводная (Data_Length 0) или 8-ми проводная (Data_Length 1).


Рис.2 Схемы подключения дисплея к МК

а) 8-ми проводная б) 4-х проводная

Если вы выбираете 4-х проводную схему, то побитно записываете порты МК, к которым подключены линии дисплея, в этот макрос:

#if Data_Length==0   //4-х проводная шина данных
  #define PORT_bus_4 PORTD
  #define PIN_bus_4 4
  #define PORT_bus_5 PORTD
  #define PIN_bus_5 5
  #define PORT_bus_6 PORTD
  #define PIN_bus_6 6
  #define PORT_bus_7 PORTD
  #define PIN_bus_7 7

Например, где PORT_bus_4 - это имя порта МК, к которому подключена линия дисплея DB4. Аналогично и с записью бита порта: PIN_bus - номер бита порта, к которому подключена линия дисплея DB4.

Если вы выбираете 8-ми проводную схему, то побитно записываете порты МК, к которым подключены линии дисплея, в этот макрос:

#elif Data_Length==1   //8-ми проводная шина данных
  #define PORT_bus_0 PORTD
  #define PIN_bus_0 0
  #define PORT_bus_1 PORTD
  #define PIN_bus_1 1
  #define PORT_bus_2 PORTD
  #define PIN_bus_2 2
  #define PORT_bus_3 PORTD
  #define PIN_bus_3 3
  #define PORT_bus_4 PORTD
  #define PIN_bus_4 4
  #define PORT_bus_5 PORTD
  #define PIN_bus_5 5
  #define PORT_bus_6 PORTD
  #define PIN_bus_6 6
  #define PORT_bus_7 PORTD
  #define PIN_bus_7 7
#endif

Здесь все так же, только проводов больше. Зачем же такие сложности, спросите вы? Ответ прост-благодаря этому, Вы можете подключать линии дисплея абсолютно в разброс по всем портам МК, к которым захотите и ножки которых будут свободны. Просто зачастую получается так, что при проектировании какого-либо устройства не удаётся сохранить абсолютно свободным целый порт. Я часто сталкивался с этой проблемой, и решил её таким вот образом. Здесь Вы не привязаны к конкретным ножкам МК, какие цифры напишете и названия портов в вышеприведённых макросах настройки, по таким линиям микроконтроллера и будет работать ваш дисплей.

Остальные макросы и функции, я думаю, не вызовут затруднений в использовании, поскольку их описание приводится непосредственно в исходном коде заголовочного файла. Единственная функция, которой я хотел бы уделить дополнительное внимание-функция записи в память CGRAM пользовательских символов, которых нет в таблице ASCI:

LCD_UserSymbolsWrite(uchar Addr, uchar *data);

Данная функция позволяет нам записать в энергозависимую память знакогенератора 8 собственных символов, которые Вы сами и придумаете. Для большей ясности, дабы мне не повторять автора, можете почитать интересную статью: http://cxem.net/mc/book52.php. Там расписана вся работа дисплея на аппаратном уровне. Моя статья и библиотека призваны упростить применение дисплея=)

Так, я немножко отвлёкся от темы..... Запись в дисплей пользовательских символов!!! - Для упрощения этой задачи, в дополнение к библиотеке, я написал простую программу:


Рис.3 Внешний вид программы для рисования пользовательских символов

Синие квадратики соответствуют не активированным пикселям сегмента дисплея. Кликом мыши можно переключать эти пиксели между видимым состоянием и не видимым. Программа рассчитывает значения байтов данных и автоматически создаёт готовый массив одного символа Symbol[8], состоящего из восьми байт. После того, как вы закончили рисование своего символа, копируете весь массив в Ваш проект и запихиваете его в память дисплея функцией LCD_UserSymbolsWrite вот так:

LCD_UserSymbolsWrite(i,&Symbol[0]);

где i - адрес памяти CGRAM, предназначенный для пользовательских символов. Диапазон адресов: 0х00-0х07;

&Symbol[0] - указатель на нулевой (начало) элемент массива с данными для сегмента.

К статье приложен пример использования, там можно будет конкретно посмотреть тело программы + имеется проект в Протеусе.


Рис.4 Внешний вид программы для рисования пользовательских символов с готовым результатом


Рис.5 и 6 Иллюстрация работы

В общем и целом, вроде бы всё. Если что-то будет непонятно, почитать можно тут: http://cxem.net/mc/book52.php.

Если даже после этого останутся вопросы - задавайте в комментариях. Спасибо за внимание!

Прикрепленные файлы:

Теги:

Опубликована: 0 1
Я собрал 0 1
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 3.5 Проголосовало: 1 чел.

Комментарии (19) | Я собрал (0) | Подписаться

0
viktor26 #
Весь Гугл перелопатил в поисках этой библиотеки, даже нашел ее, а тут ваша появилась, теперь у меня их две. Надо теперь сравнить с какой легче работать
Ответить
0

[Автор]
stalker1424 #
Оценивайте на здоровье. Потом отпишитесь о впечатлениях, если не трудно
Ответить
0
Ура собрал, работает. Большое спасибо за статью все понятно, заработало без лишних заморочек (это первая моя конструкция на микроконтроллере)
Ответить
0

[Автор]
stalker1424 #
Очень рад. Как раз та самая реакция, которую я ждал. Не зря старался, значит
Ответить
0
Николай #
А русские символы выводятся при 4-х проводной схеме подключения?
Ответить
+1

[Автор]
stalker1424 #
Русские символы можно вывести, если на заводе в дисплей они были прошиты. Если нет-то увы... Разве что вы сами их нарисуете, но тут тоже проблема-в памяти дисплея доступно лишь 8 свободных адресов под пользовательские символы. Схема подключения на это не влияет, она влияет лишь на скорость передачи данных дисплею (по 4-х проводной данные передаются в 2 раза дольше) и на экономию ножем МК.
Ответить
0
Павел #
У меня есть дисплей WH1602, но он не поддерживает русские буквы, а в схему нужен с русскими, возможно его как то подключить чтобы он начал показывать русские буквы?
Ответить
0

[Автор]
stalker1424 #
См. комментарий выше Николаю
Ответить
0
P32L #
Дайте пожалуйста пример кода на СИ как вывести русские символы на дисплей для PIC.
Ответить
0

[Автор]
stalker1424 #
Извините, не могу. Я не использую PIC - контроллеры в своём творчестве, к сожалению. Никогда с ними не имел дело
Ответить
0
P32L #
Просто я начинающий и не могу понять каким образом вывести русские символы на LCD.С английскими все понятно.
char txt4[] = "example";
void main(){
Lcd_Init();
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Out(1,1,txt4);
}
Куда вставить Symbol[8]={0x0, 0x0, 0xA, 0x0, 0x11, 0xE, 0x0, 0x0}?
Ответить
0

[Автор]
stalker1424 #
Судя по вставке Вашего кода, вы используете не мою библиотеку. Моя, вероятнее всего, с ПИК-контроллером работать не будет. У русских символов другие адреса в памяти знакогенератора дисплея, см. тут http://cxem.net/mc/book52.php. Если же завод-изготовитель дисплея прошили китайские иероглифы вместо кириллицы, то тут уже ничего не поделаете, кроме как самому их нарисовать и записать в энергозависимую память CGRAM дисплея по предназначенным для пользовательских символов адресам (0х00-0х07). Symbol[8] нужно вставить в функцию записи пользовательских символов LCD_UserSymbolsWrite, а потом из этих адресов (0х00-0х07) выводить на дисплей. Но, это применимо к моей библиотеке. А что делать там, что вы используете, я понятия не имею. А вы не пробовали в массив txt4[] записать русские буквы? что при этом у Вас выводится на дисплей? Иероглифы?
Отредактирован 16.11.2014 15:55
Ответить
0
Zlodey #
Вот это:
*указываем разрядность шины данных дисплея (1-8 бит, 0-4 бита)
#define Data_Length 0
*указываем количество строк дисплея (1-2 строки, 0-1 строка)
#define NumberOfLines 1
Я бы написал по красивее
*указываем разрядность шины данных дисплея (8 бит или 4 бита)
#define Data_Length 8
*указываем количество строк дисплея (1 или 2 строки)
#define NumberOfLines 1
А то у вас какая то головоломка получилась
Ответить
0

[Автор]
stalker1424 #
Где же тут головоломка? в комментариях всё пояснено. Ну уж если Вам так нравится, исправьте по Вашему усмотрению
Ответить
0
Игорь #
Извините я не понял, а как выводить на дисплей после sprintf(); и других.
Ответить
0
Дмитрий #
А как вывести на LCD численную переменную?
Ответить
0

[Автор]
stalker1424 #
По таблице, которую можно найти тут
Ответить
0
Александр #
А как с помощью данной библиотеки вывести переменную с неизвестным количеством знаков, например с датчика я получаю влажность:
int8_t humidity = 0;
humidity = dht11_gethumidity();
Как теперь мне вывести переменную humidity на экран?
Ответить
0

[Автор]
stalker1424 #
Для начала Вам нужно перевести эти данные из переменной "humidity" в показание влажности. Например, если там лежит 0xAF (ну, допустим что максимальное показание 0xFF соответствует 100% влажности), то производим вычисление процента простой пропорцией: (0xAF(175) * 100)\0xFF(255) = 68%. Теперь цифру 68 надо вывести раздельно, делаем это так: цифра 6 в памяти дисплея находится по адресу 0x36, а цифра 8 по адресу 0x38, отсюда видно, что к каждой цифре нужно прибавить 0x30 и отправить командой LCD_Show в дисплей.
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Pickit 2 - USB-программатор PIC-микроконтроллеров
Pickit 2 - USB-программатор PIC-микроконтроллеров
Модуль радиореле на 4 канала Конструктор регулируемого преобразователя напряжения LM317
вверх