Реклама ⓘ
Главная » Микроконтроллеры
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Реклама ⓘ

Библиотека для символьного дисплея на базе 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 собственных символов, которые Вы сами и придумаете. Для большей ясности, дабы мне не повторять автора, можете почитать интересную статью: //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 Иллюстрация работы

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

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

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

Теги:

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

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

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

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

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

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

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

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

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

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

[Автор]
#
Извините, не могу. Я не использую 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

[Автор]
#
Судя по вставке Вашего кода, вы используете не мою библиотеку. Моя, вероятнее всего, с ПИК-контроллером работать не будет. У русских символов другие адреса в памяти знакогенератора дисплея, см. тут 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

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

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

[Автор]
#
Для начала Вам нужно перевести эти данные из переменной "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-микроконтроллеров
Регулятор мощности 2 кВт Бокс для хранения компонентов
вверх