субота, 29 жовтня 2016 р.

STM32: Бібліотека для роботи з LCD WH1602(4) або іншим сумісним дисплеєм з контролером HD44780


Передмова

Ця бібліотека є вільним програмним забезпеченням і може вільно розповсюджується та змінюватись. Я не автор бібліотеки, а вніс зміни щодо автоматизації налаштувань, вніс зміни щодо більшої абстракції, а також усунув недолік, який псував все задоволення від роботи з цією бібліотекою, це випадкове "сміття" на екрані при увімкненні живлення. Щоб прибрати "сміття" потрібно було перезавантажувати пристрій кнопкою "reset". Бібліотека доволі вдала, як на мене, і має великий спектр функцій, щоб задовольнити будь які потреби, у відтворені інформації на дисплей типу WH1602 (WH1604) з контролером HD44780. Ця бібліотека створювалась початково, як кросплатформена для AVR, PIC, ARM. Чи збереглась кросплатформеність перевірити не маю змоги. Але на мікроконтролерах STM32F1xx і STM32F4xx перевірено - працює. В мережі можна зустріти різні варіації цієї бібліотеки, але набір функцій один і той самий. Зроблені мною зміни спрощують налаштування бібліотеки. В принципі налаштовувати взагалі нічого не потрібно. Ну може зовсім трішечки :-)

Схема підключення

Схема підключення
Схема підключення на малюнку. Підключати будемо по 4-х провідниковій схемі з заземленим сигналом W/R. Це означає що нам потрібно під'єднати до мікроконтролера шість дротів від дисплея. Такі як D4, D5, D6, D7, E, RS. До яких саме виводів мікроконтролеру під'єднувати дисплей, це вже вирішувати вам самим. Бібліотека допускає підключення кожного виводу дисплея на різні порти і будь які піни обраного/обраних порту/портів. Під'єднайте до дисплею живлення, це ніжка 2 - "+5 Вольт". Загальний мінус на ніжки дисплею 1 та 5. Та до ніжки дисплею під номером 3 резистивний дільник з підстроєчним резистором 10к для регулювання контрасту інформації, яка висвічується на екрані. Якщо ваш дисплей має підсвічування екрану, то можна ще подати живлення на підсвічування, це 15 і 16 ніжки дисплею. Живлення подати напряму, або через транзисторний ключ, який керується з ніжки мікроконтролеру. Тоді підсвічування можна вмикати та вимикати програмно, або навіть регулювати яскравість підсвічування налаштувавши ніжку, яка керує ключем підсвічування, як PWM (ШИМ).

CubeMX

Щоб бібліотека працювала правильно потрібно всі виводи, якими буде з'єднано мікроконтролер з екраном WH1602, обізвати в програмі CubeMX за принципом:
  • Enable (E) - LCD_E
  • RS - LCD_RS
  • D4 - LCD_D4
  • D5 - LCD_D5
  • D6 - LCD_D6
  • D7 - LCD_D7
Обираєте зручні для вас, або вільні виводи мікроконтролеру. Виставляєте їх в режим "GPIO_Output" та називаєте за принципом, як я зазначив вище. Приклад на малюнку. Червоними зонами позначив потрібне для підключення LCD:
Оголошення назв і режиму виводів для підключення LCD в CubeMX
Щодо підключення LCD в CubeMX то це все. Генеруєте код для свого мікроконтролеру та засобу (середовища)  розробки:
Генеруємо код
Якщо користуєтесь засобом розробки CooCox CoIDE, то як імпортувати проект створений CubeMX до CooCox'у в цій статті Імпорт проекту в CooCoxIDE з CubeMX. Якщо середовищем розробки зі списку, що пропонує CubeMX, то ви маєте вже готовий проект на виході. Тепер я переходжу до CooCox CoIDE, а ви до свого середовища розробки. Постараюсь показати сам принцип без прив'язки до конкретного засобу розробки.

Підключаємо бібліотеку до проекту

  1. Завантажте архів бібліотеки "hd44780.zip" собі на диск. В архіві знаходиться тека "hd44780" з підтеками "inc" та "src". В теці "inc" файли "lcd_cfg.h" - всілякі налаштування та попередні установки, "hd44780.h" - макроси, дефайни, прототипи функцій. В теці "src" файл "hd44780.c" - з функціями бібліотеки. 
  2. Копіюємо файли бібліотеки до проекту. Можна скопіювати самі файли бібліотеки до проекту. Заголовні файли "h" у теку "inc" проекту, а сирцеві файли "c" до теки "src" проекту. Або скопіювати в корінь проекту всю теку бібліотеки "hd44780".
  3. Додати бібліотеку до проекту. Ці файли треба додати до проекту вже в самому засобі розробки яким ви користуєтесь. Як це зробити залежить від вашого засобу розробки. Наприклад, в CooCox CoIDE, я просто перетягую теку бібліотеки "hd44780" до теки проекту і тисну "Оk" в діалоговому вікні, що з'являється. Після цих маніпуляцій бібліотеку під'єднано до проекту.
Додавання бібліотеки до проекту
Як у вас інший засіб розробки, наприклад "Atolic True Studio" чи "System Workbench for STM32" то просто додайте (скопіюйте) файли бібліотеки, заголовні "h" до теки проекту "inc", а сирцеві "c" до теки "src" проекту. В засобі розробки оновіть проект через контекстне меню "refresh", або кнопкою "F5". Додані файли з'являться в дереві проекту.
Оновлення проекту

Передпроцесорні директиви #include 

Тепер, коли на рівні файлів все під'єднано як слід, треба в коді додати лиш один рядок в головний файл "main.c":
1
#include "hd44780.h"
Наш проект згенеровано CubeMX то цей рядок потрібно вставити в місце між рядками:
1
2
3
/* USER CODE BEGIN Includes */
#include "hd44780.h"
/* USER CODE END Includes */
А також потрібно до файлу бібліотеки "lcd_cfg.h" додати рядок з заголовним файлом драйверу "HAL" чи "SPL", який ви використовуєте. А непотрібні рядки з "include" закоментувати чи видалити. Я працюю з мікроконтролерами сотої серії "stm32f1xx" і використовую драйвер "HAL", то в мене буде рядок в файлі "lcd_cfg.h":
1
#include "stm32f1xx.h"
Наприклад, як би я використовував SPL бібліотеки, то в файлі "lcd_cfg.h" знадобився б такий рядок:
1
#include "stm32f10x.h"
Оце і все. Можна компілювати проект для перевірки. Як зроблено все правильно то компілятор скомпілює проект без помилок.

Список функцій бібліотеки

Бібліотека для своєї роботи і зручності користувача - має ряд функцій. Внутрішні функції розглядати не будемо, а розглянемо ті функції, що потрібні нам для виводу на дисплеї різноманітної інформації.
  • lcdInit - функція початкової ініціалізації дисплею;
  • lcdClrScr - функція очищення дисплею, курсор в початкове положення;
  • lcdReturn - функція повернення курсору в початкове положення;
  • lcdSetMode - функція встановлення режимів: дисплей увімк/вимк, курсор блимає увімк/вимк, курсор увімк/вимк;
  • lcdGoto - функція встановлює курсор в певне місце: рядок, стовпець;
  • lcdPuts - функція виводу текстового рядка;
  • lcdPutc - функція виводу окремого символу типу char;
  • lcdLoadChar - функція завантаження до пам'яті дисплею користувацького символу;
  • lcdDrawChar - функція малювання на дисплеї користувацького символу;
  • lcdBackSpace - функція зміщення курсору на один символ ліворуч і його знищення;
  • lcdScroll - функція зміщення всього тексту на один стовпець в потрібному напрямку (ліворуч або праворуч);
  • cursorShift - функція зміщення курсору на позицію праворуч чи ліворуч без знищення символу, що вже зображений. Призначена для редагування/виправлення тексту;
  • lcdItos - функція виводу на екран числа типу integer;
  • lcdFtos - функція виводу на екран числа типу float;
  • lcdNtos - функція виводу на екран числа типу integer з певним числом розрядів. Зайві розряди відсікаються. Розряди, яких не вистачає заповнюються нулями. Для фіксованого розташування на екрані;
  • lcdDrawBar - функція малювання індикатору виконання;
  • lcdClrBar - функція очищення індикатору виконання.

Список деяких параметрів бібліотеки

В файлі "lcd_cfg.h"
//-------------------------------
// DEFAULT CONFIGURATIONS
//-------------------------------
#define DEFAULT_DISPLAY_CONFIG  DISPLAY_CONFIG_4bit_2L_5x8
#define DEFAULT_ENTRY_MODE   ENTRY_MODE_INC_NO_SHIFT
#define DEFAULT_VIEW_MODE   VIEW_MODE_DispOn_BlkOff_CrsOff
#define USE_BUSY_FLAG    0u /* 1 (true) or 0 (false) */
  • дисплей під'єднано по 4-х бітному режиму, на 2 або 4 рядки, з шрифтом 5х8 пікселів;
  • зліва направо, без зсуву видимої частини DDR RAM пам'яті;
  • дисплей увімкнено, блимання вимкнуто, курсор вимкнуто;
  • чи використовується сигнал дисплею R/W, в нашому випадку - ні, тому 0.
#define MCU_FREQ_VALUE    SystemCoreClock/1000000 /* MHz. Minimal value = 1 MHz */
В змінній SystemCoreClock зберігається частота MCU в Герцах, ділимо на мільйон, отримуємо в мегаГерцах. Для правильних таймінгів дисплею.
//-------------------------------
// SET FORMATTED OUTPUT OPTIONS
//-------------------------------
#define USE_FORMATTED_OUTPUT   1u /* 1 (true) or 0 (false) */
#define TAB_SPACE     4u /* 1 .. 255 */
  • використовувати символи форматування /t, /n, /r в рядках з текстом - 1, не використовувати - 0;
  • довжина табуляції - 4.
//-------------------------------
// PROGRESS BAR OPTIONS
//-------------------------------
#define USE_PROGRESS_BAR   0u    /* 1 (true) or 0 (false) */
#define USE_REGRESS_BAR    1u    /* 1 (true) or 0 (false) */
#define PROGRESS_BAR_LINE   LCD_2nd_LINE /* Select lcd line: 1, 2, 3, 4, ... */
#define PROGRESS_BAR_HEIGHT   5u     /* in pixel: 1(min), 2, 3, 4, 5, 6, 7, 8(max) */
#define PROGRESS_BAR_WIDTH   10u    /* Number of chars in lcd line:  1, 2, .. , 8, 16, 20 */
  • використовувати індикатор виконання, що прогресує - 1, ні - 0;
  • використовувати індикатор виконання, що регресує - 1, ні -0;
  • індикатор виконання буде в другому рядку індикатора;
  • висота індикатора виконання в пікселях;
  • ширина індикатора в знакомісцях.

Демонстраційна програма

Замість того, щоб пояснювати в подробицях кожну функцію бібліотеки, це ви можете і самі знайти в коментарях самої бібліотеки, або в просторах інтернету. Наприклад тут. Краще приведу програму, яка наочно демонструє можливості бібліотеки.

З CubeMX

Як вже з самого початку ми генерували проект за допомоги генератору коду ініціалізації CubeMX, то і приклад пишемо у визначених CubeMX ділянках коду.
На початку програми в файлі "main.c", до функції "main" оголошуємо прототип функції для імітації друкування тексту з клавіатури. Сама функцію розташуємо вже після головної функції "main":
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
void imitationPrinting(char *ptr);
/* USER CODE END PFP */
Далі в тілі функції "main" до початку безкінечного циклу в блоці 1 - оголошуємо всі змінні які знадобляться для демонстрації:
/* USER CODE BEGIN 1 */
 uint32_t SystemFreq = HAL_RCC_GetHCLKFreq();
 char str[17] = {};
 float pi = 3.14;
 int t = 123;
 unsigned char men1[FONT_HEIGHT] = {0x0e,0x0e,0x04,0x1f,0x04,0x1a,0x01,0x00};
 unsigned char men2[FONT_HEIGHT] = {0x07,0x07,0x0a,0x07,0x02,0x05,0x09,0x00};
  /* USER CODE END 1 */
Ініціалізуємо наш дисплей в ділянці позначену як "USER CODE BEGIN 2":
/* USER CODE BEGIN 2 */
lcdInit(); // ініціалізація дисплею
/* USER CODE END 2 */
В безкінечному циклі пишемо нашу демонстраційну програму де я постарався використати всі функції бібліотеки, та написав коментар до кожного рядка:
  /* USER CODE BEGIN WHILE */
  while (1)
  {
   // очищення дисплею
   lcdClrScr();
   // встановлення позиції курсору
   lcdGoto(LCD_1st_LINE,1);
   //друкуємо текстовий рядок з переносом на інший рядок
   lcdPuts("CooCox CoIDE\nFreq MCU ");
   // друкуємо частоту мікроконтролеру в Mhz
   lcdItos(SystemFreq/1000000);
   lcdPuts(" Mhz");
   // чекаємо 3 секунди
   HAL_Delay(3000);
   /*
    * В циклі зміщуємо все що на екрані на 16 позицій праворуч
    */
   for (int i = 0; i < 16; ++i)
   {
    lcdScroll(RIGHT);
    HAL_Delay(250);
   }
   // очищаємо дисплей
   lcdClrScr();
   // до буферу str відправляємо текст
   sprintf(str,"STM32F103RB and");
   // функція імітації друкування тексту
   imitationPrinting(str);
   // до буферу str відправляємо текст
   sprintf(str,"LCD WH1602A Demo");
   // встановлення позиції курсору
   lcdGoto(LCD_2nd_LINE,0);
   // функція імітації друкування тексту
   imitationPrinting(str);
   // чекаємо 3 секунди
   HAL_Delay(3000);
   /*
    * В циклі зміщуємо все що на екрані на 16 позицій ліворуч
    */
   for (int i = 0; i < 16; ++i)
   {
    lcdScroll(LEFT);
    HAL_Delay(250);
   }
   // чекаємо секунду
   HAL_Delay(1000);
   /*
    * В циклі зміщуємо все що на екрані на 16 позицій праворуч
    */
   for (int i = 0; i < 16; ++i)
   {
    lcdScroll(RIGHT);
    HAL_Delay(250);
   }
   // чекаємо 2 секунди
   HAL_Delay(2000);
   // очищаємо дисплей
   lcdClrScr();
   // виводимо на екран текст
   lcdPuts("Float = ");
   // виводимо на екран число типу float з двома знаками після коми
   lcdFtos(pi,2);
   // встановлення позиції курсору
   lcdGoto(LCD_2nd_LINE,0);
   // виводимо на екран текст
   lcdPuts("Integer = ");
   // виводимо на екран число типу integer
   lcdItos(t);
   // чекаємо 3 секунди
   HAL_Delay(3000);
   // вмикаємо режим: дисплей увімкнутий, миготіння курсору вимкнуте, курсор увімкнутий
   lcdSetMode(VIEW_MODE_DispOn_BlkOff_CrsOn);
   // встановлення позиції курсору
   lcdGoto(LCD_2nd_LINE,16);
   // в циклі видаляємо весь рядок backspace'ом
   for (int i = 0; i < 16; ++i)
   {
    lcdBackSpace();
    HAL_Delay(100);
   }
   // встановлюємо позицію курсору
   lcdGoto(LCD_1st_LINE,16);
   // в циклі видаляємо весь рядок backspace'ом
   for (int i = 0; i < 16; ++i)
   {
    lcdBackSpace();
    HAL_Delay(100);
   }
   // встановлюємо режим: дисплей увімкнутий, миготіння вимкнуте, курсор вимкнутий
   lcdSetMode(VIEW_MODE_DispOn_BlkOff_CrsOff);
   // повертаємо курсор до дому
   lcdReturn();
   // друкуємо текст з табуляцією
   lcdPuts("\tLoading...");
   // встановлюємо позицію курсору
   lcdGoto(PROGRESS_BAR_LINE, PROGRESS_BAR_WIDTH);
   // друкуємо текст
   lcdPuts("[   %]");
   // в циклі показуємо індикатор виконання
   for(uint8_t i = 0; i <= PROGRESS_BAR_MAX_LOAD; ++i)
   {
    // встановлення позиції курсора
    lcdGoto(PROGRESS_BAR_LINE, PROGRESS_BAR_WIDTH + 1);
    // друкування відсотків виконання в чітко заданій позиції на три розряди
    lcdNtos((i*100)/PROGRESS_BAR_MAX_LOAD, 3 );
    // показуємо поточний стан індикатора виконання
    lcdDrawBar(i);
    // чекаємо 1/10 секунди
    HAL_Delay(100);
   }
   // чекаємо 3 секунди
   HAL_Delay(3000);
   // очищаємо дисплей
   lcdClrScr();
   /*
    * завантажуємо символ користувача до комірки пам'яті 6 і 7 в дисплей
    * комірки пам'яті від 0 по 5 зайняті індикатором виконання
    * якщо ви не використовуєте індикатор виконання, то можна завантажувати
    * з 0 комірки пам'яті дисплею
    */
   lcdLoadChar(men1,6);
   lcdLoadChar(men2,7);
   // друкуємо текст з табуляцією і переходом на новий рядок
   lcdPuts("\tRunning men\n");
   // в циклі показуємо людину що біжить :)))
   for(uint8_t i = 0; i < 8; i++)
   {
    lcdPutc(6);
    HAL_Delay(250);
    cursorShift(LEFT);
    lcdPutc(' ');
    lcdPutc(7);
    HAL_Delay(250);
    cursorShift(LEFT);
    lcdPutc(' ');
   }
   /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */
Та не забуваємо про функцію, яку написали для демонстраційної програми і оголосили її прототип на початку програми. Функцію пишемо після головної функції "main" в головному файлі "main.c" в користувацькому блоці 4, який визначив CubeMX:
/* USER CODE BEGIN 4 */
// функція імітації друкування тексту з клавіатури
void imitationPrinting(char *ptr)
{
 // встановлюємо режим з увімкнутим курсором
 lcdSetMode(VIEW_MODE_DispOn_BlkOff_CrsOn);
 // поки не кінець рядку
 while(*ptr != 0)
 {
  // друкуємо поточний символ
  lcdPutc(*ptr++);
  // чекаємо 1/10 секунди
  HAL_Delay(100);
 }
 // встановлюємо режим з вимкнутим курсором
 lcdSetMode(VIEW_MODE_DispOn_BlkOff_CrsOff);
}
/* USER CODE END 4 */
Та не забуваємо що в демонстраційній програмі використовуємо індикатор виконання "progress bar", а для цього  в файлі lcd_cfg.h константу USE_PROGRESS_BAR встановлюємо в 1u. "#define USE_PROGRESS_BAR    1u".

Без CubeMX

Підключення бібліотеки до проекту абсолютно таке саме як я описав вище. Створюєте проект для свого мікроконтролера в своєму засобі розробки. До файлу main.c додаєте рядок - #include "hd44780.h" в файлі бібліотеки lcd_cfg.h перевірте чи файл драйверу SPL чи HAL вказано правильно для вашого контролеру MCU, наприклад - #include "stm32f1xx.h".
А також потрібно потурбуватись самим про ініціалізацію виводів мікроконтролеру підключених до LCD. В кінці файлу "hd44780.c" є функція  "lcdGpioInit" в середині якої треба написати ініціалізацію виводів і портів, які під'єднано до дисплею.
Ось приклад, як це може виглядати, якщо виводи дисплею під'єднано до виводів мікроконтролеру PIN_0 - RS, PIN_1 - E, PIN_4...PIN_7 - D4...D7 порту "C":
void lcdGpioInit(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  __HAL_RCC_GPIOC_CLK_ENABLE();

  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
}
А на початку файлу "main.c" треба додати декілька #define, щоб бібліотека працювала правильно. Зверніть увагу! Програма CubeMX додає до назви виводів, які ми називаємо для підключення LCD, ще PIN і GPIO_Port. Наприклад, сигнал RS під'єднано до виводу мікроконтролера PC0, тоді потрібно директивами #define позначити pin - LCD_RS_Pin як GPIO_PIN_0, та port - LCD_RS_GPIO_Port як GPIOC. І так для всіх виводів до яких під'єднано LCD:
#define LCD_RS_Pin GPIO_PIN_0
#define LCD_RS_GPIO_Port GPIOC
#define LCD_E_Pin GPIO_PIN_1
#define LCD_E_GPIO_Port GPIOC
#define LCD_D4_Pin GPIO_PIN_4
#define LCD_D4_GPIO_Port GPIOC
#define LCD_D5_Pin GPIO_PIN_5
#define LCD_D5_GPIO_Port GPIOC
#define LCD_D6_Pin GPIO_PIN_6
#define LCD_D6_GPIO_Port GPIOC
#define LCD_D7_Pin GPIO_PIN_7
#define LCD_D7_GPIO_Port GPIOC
Ну а все інше так само як і з CubeMX. Додайте до головного файлу "main.c" демонстраційну програму яка вже наведена вище. Компілюєте, прошиваєте, спостерігаєте.

Що саме додав до бібліотеки

До файлу "lcd_cfg.h" додав макроси щоб автоматично налаштовувалась бібліотека під визначені користувачем порти і виводи мікроконтролеру, що під'єднані до дисплею. Дяка за ідею користувачу "voland" з українського форуму програмістів.
#define MASK2PIN(mask) ((mask&GPIO_PIN_0)?0:(mask&GPIO_PIN_1)?1:(mask&GPIO_PIN_2)?2:(mask&GPIO_PIN_3)?3: \
   (mask&GPIO_PIN_4)?4:(mask&GPIO_PIN_5)?5:(mask&GPIO_PIN_6)?6:(mask&GPIO_PIN_7)?7: \
   (mask&GPIO_PIN_8)?8:(mask&GPIO_PIN_9)?9:(mask&GPIO_PIN_10)?10:(mask&GPIO_PIN_11)?11: \
   (mask&GPIO_PIN_12)?12:(mask&GPIO_PIN_13)?13:(mask&GPIO_PIN_14)?14:(mask&GPIO_PIN_15)?15:0)

#define RS_PIN_NUMBER (MASK2PIN(LCD_RS_Pin))
#define E_PIN_NUMBER (MASK2PIN(LCD_E_Pin))
#define RW_PIN_NUMBER (MASK2PIN(LCD_RW_Pin))
#define D7_PIN_NUMBER (MASK2PIN(LCD_D7_Pin))
#define D6_PIN_NUMBER (MASK2PIN(LCD_D6_Pin))
#define D5_PIN_NUMBER (MASK2PIN(LCD_D5_Pin))
#define D4_PIN_NUMBER (MASK2PIN(LCD_D4_Pin))
Можливо якийсь компілятор неадекватно сприйме таку конструкцію з опціями оптимізації, але в мене з трьома різними компіляторами оброблялось все коректно. Майте на увазі.

Автоматично визначається робоча частота MCU:
#define MCU_FREQ_VALUE    SystemCoreClock/1000000 /* MHz. Minimal value = 1 MHz */

Змінив функцію початкової ініціалізації дисплею, додаванням послідовності команд 0x30, 0x30, 0x28, щоб перемикання в 4-х бітний режим було надійним. Початково, послідовності 0x30, 0x30 не було. З-за цього на екрані після подачі живлення з'являлось випадкове "сміття". Лікувалось перезавантаженням пристрою кнопкою "ресет". А це дещо не зручно.
/*! \brief Initialize the LCD.
 *  \note This library use the 4-bit interface. */
void lcdInit(void)
{
 /* GPIO initialization. */
 setAllPinsAsOutputs();
 /* LCD initialization. */
 lcdWrite(0x30);
 lcd10usDelay(BUSY_CYCLE_TIME);
 lcdWrite(0x30);
 lcd10usDelay(BUSY_CYCLE_TIME);
 lcdConfig(DEFAULT_DISPLAY_CONFIG);
 lcdSetMode(DEFAULT_VIEW_MODE);
 lcdSetMode(DEFAULT_ENTRY_MODE);
 lcdClrScr();
 lcdReturn();
 #if (USE_PROGRESS_BAR)
  lcdInitBar();
 #endif
}

Невеличкі поради

Як не будете в своєму проекті використовувати "progress bar", то в файлі "lcd_cfg.h" назначте константі USE_PROGRESS_BAR значення 0. Це зекономить вам чимало байтів пам'яті мікроконтролеру. Та вивільнить аж 6 комірок пам'яті під користувацькі символи в дисплеї. 

Відео приклад підключення і використання бібліотеки HD44780

Плата розробника STM32F103RB Nucleo. Засіб розробки True Studio.


Плата розробника STM32F407VG Discovery. Засіб розробки System Workbench for STM32.


Файли з бібліотекою і проектами