Библиотека для работы с HD44780

В прошлой статье мы рассмотрели теоретические основы управления LCD дисплеем на базе контроллера HD44780. Но разумеется теория без практики ничего не значит, а поэтому я предлагаю побаловаться с этим дисплеем вживую. Дисплей стоит не дорого, что-то в районе 6$, лично я экспериментировал с дисплеем под названием ACM1602K-FL-YTH-02. Редкостный отстой скажу я вам, не покупайте такой. Некоторые символы в левой половине экрана плохо видны, хотя первое время дисплей работал без проблем. Кстати точно такой-же дисплей пришлось вернуть обратно в магазин, у него полностью не работала левая его часть. Лучше купить на бакс подороже и не иметь проблем в будующем, мне например понравились наши отечественные МЭЛТовские дисплеи они кстати лишены некоторых проблем с русскими символами (об этом подробнее позже). Для того чтоб использовать ваш дисплей совместно с моей программой не производя ни каких изменений в коде, вы должны подключить его к контроллеру STM32 следующим образом: 
 
hd44780 and stm32
 
Сразу хочу сказать, что код рассчитан на двухстрочный 16-ти символьный дисплей, хотя я почти уверен что он заработает и с дисплеем 8х2 без всяких изменений, да и с однострочными наверное тоже.

Как использовать библиотеку

Первым делом нужно скопировать папку hd44780_driver вместе со всем её содержимым в директорию с файлами своего проекта. Файлов там всего два: Один заголовочный, с кучей малопонятных дефайнов, а другой непосредственно с кодом который реализует функционал. Если вы подключили дисплей к тому же самому порту и к тем же самым его выводам, то ничего изменять в заголовочном файле (который с расширением .h) не надо. Если же вы ради удобства разводки платы или по каким либо другим причинам решили пересадить дисплей на другие выводы то нужно их указать в заголовочном файле. Первым делом указываем порт. У меня указан порт С. После порта идет описание того к каким ножкам порта С подключены определённые ноги дисплея. Напомню, что вывод дисплея R/W я всегда жестко сажаю на землю, так как ничего из дисплея я не читаю, а только пишу в него. 

#define LCD_PORT GPIOC
#define LCD_CD 0
#define LCD_EN 1
#define LCD_DB4 2
#define LCD_DB5 3
#define LCD_DB6 4
#define LCD_DB7 5

На этом настройка заканчивается и теперь можно использовать функции библиотеки предварительно конечно же добавив в файл main.c строчку 

#include "hd44780_driver\hd44780_driver.h"
Теперь посмотрим что за функции есть в этой библиотеке, и начнем с инициализации дисплея. Она происходит после вызова функции lcd_init(). Первым делом происходит настройка ног порта которые определены в заголовочном файле. Если этот порт уже был настроен каким либо образом, то настройки других ног не перетираются. Именно для этого служат все эти адские конструкции из директив препроцессора в заголовочном файле. После настройки ног выполняется непосредственно сама инициализация. По умолчанию дисплей настраивается следующим образом: 4-х битный режим, включен курсор, при поступлении данных счетчик адреса увеличивается на единицу, дисплей чист, курсор в позиции X0, Y0. Для очистки дисплея используется функция lcd_clear(), с ней я думаю всё понятно. После её вызова очищается DDRAM и курсор встаёт в позицию с координатами 0,0. Если же вам требуется просто переместить  курсор без очистки дисплея, то на этот случай в библиотеке имеется своя функция lcd_set_xy(x,y), где x и y координаты курсора на экране. Так же присутствует функция lcd_set_state для управления отображением курсора и состоянием самого дисплея. При помощи неё можно прятать и показывать курсор и заставлять его мигать. Так же существует возможность выключать/включать LCD дисплей. Возможен вызов данной функции со следующими параметрами: 
  • lcd_set_state(LCD_DISABLE, CURSOR_DISABLE, NO_BLINK); - дисплей ничего не показывает, даже если данные в DDRAM есть. Если в качестве первого параметра выступает LCD_DISABLE, то по идее вторые два вообще не важны, так как ни какого курсора при выключенном дисплее мы не увидим.
  • lcd_set_state(LCD_ENABLE, CURSOR_DISABLE, NO_BLINK); - дисплей включен, курсора нет, ничего не мигает
  • lcd_set_state(LCD_ENABLE, CURSOR_DISABLE, BLINK); - дисплей включен, курсора нет, но мигает все знакоместо (черным квадратом)
  • lcd_set_state(LCD_ENABLE, CURSOR_ENABLE, NO_BLINK); - дисплей включен, есть не мигающий курсор
  • lcd_set_state(LCD_ENABLE, CURSOR_ENABLE, BLINK); - дисплей включен, курсор есть, мигает всё знакоместо. 
При помощи функции lcd_out можно вывести строку текста в текущую позицию курсора, которая может быть установлена вызовом функции lcd_set_xy. В функцию lcd_out следует передавать указатель на строку (строка разумеется должна заканчиваться нульсимволом). Следующая функция lcd_send принимает два параметра: Первый - байт данных, второй - COMMAND или DATA.  Не трудно догадаться, что она служит для передачи в дисплей байта данных или команды. И наконец функция lcd_set_user_char предназначена для того чтоб записать пользовательский символ в CGRAM память дисплея. Подробнее о том как это сделать, будет написано в примере. 

Пример использования библиотеки

Для того чтоб показать как оно работает я написал простенький пример который использует функции из этой библиотеки. Собственно вот он: 

#include "stm32F10x.h"
#include "hd44780_driver\hd44780_driver.h"
#include "stm32f10x_rcc.h"
int main(void)
{
  uint8_t user_char[8]; //Сюда будем записывать пользовательский символ
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //Вкл порт С
  lcd_init(); //Инициализируем дисплей
  user_char[0]=0b01110; //А вот тут
  user_char[1]=0b10001; // рисуем
  user_char[2]=0b10001; // наш символ
  user_char[3]=0b10001; //
  user_char[4]=0b10001; // Это типа рыба :-)
  user_char[5]=0b01010;
  user_char[6]=0b10001;
  user_char[7]=0b10001;
  lcd_set_user_char(0, user_char); // Наша рыба это символ номер ноль
  lcd_out("This is fish"); //Выводим надпись в нулевую строку
  lcd_set_xy(0,1); //переводим курсор в первую строку
  lcd_send(0,DATA); //Выводим символ номер ноль
  lcd_set_state(LCD_ENABLE, CURSOR_ENABLE, BLINK); //Включаем курсор и мигалку
  while(1)
    {
    }
}

 
В результате выполнения этого кода на дисплее появится надпись и наша рыба которую мы изобразили. Если этот пример не запустился, пишете в комментариях и попробуем разобраться. 

Вместо заключения

Библиотека так себе, написал её буквально за полтора вечера, особо ничего не оптимизировал, поэтому прошу не пинать меня ногами если вы увидите в ней что-то вырвиглазное :-) Несмотря на это она таки работает! Хочу отметить два важных момента: Во-первых - чтоб работал русский язык нужно перекодировать русскую фразу. Т.е. написать lcd_out("Привет мир"); не получится, вместо русских букв там будут каракули,не не совпадает кодировка. Кстати МЭЛТовские дисплеи имеют команду для смены кодировки, и тогда можно отправлять в дисплей русские буквы так как они есть без перекодирования. В интернетах имеются спец программы позволяющее это сделать, просто надо немного погуглить. Кстати можно просто допилить функцию lcd_out чтоб она сама выполняла перекодировку русских символов. Возможно я улучшу её позже, сейчас в этом нет необходимости. Во-вторых в библиотеке есть функция предназначенная для создания небольшой задержки. Если ваш контроллер работате на каких-то запредельных частотах - просто увеличте значение tmpvar раза в полтора. Если у вас не работает конечно. Сделать это можно в файле hd44780_driver.c строка номер 5. Ну и собственно прикладываю архив со своим проектом в кокосе.