Работа с ЖК индикатором на отладочной плате STM32L-Discovery. Работа с символьными жк дисплеями Библиотека для работы с жки

Для работы с символьными графическими дисплеями предлагаем воспользоваться библиотекой LiquidCrystal которая входит в стандартный набор Arduino IDE и предназначена для работы по 8-битному (4-битному) параллельному интерфейсу. Если Ваш дисплей подключается к Arduino по шине I2, то Вам нужно установить библиотеку LiquidCrystal_I2C (большинство функций которой повторяют функции первой библиотеки).

Поддерживаемые дисплеи:

Дисплей Подключение и инициализация
LCD1602 - символьный дисплей (16x02 символов),


#include
[ , 8 , 9 , 10 , 11 ]);
void setup(){ lcd.begin(16 , 2); }

// Пояснение:

void setup(){ ОБЪЕКТ.begin(КОЛ_СТОЛБЦОВ, КОЛ_СТРОК); }


LiquidCrystal ОБЪЕКТ (RS , E , D0 , D1 , D2 , D3 , D4 , D5 , D6 , D7);


с интерфейсом I2C (синий)

#include
#include
LiquidCrystal_I2C lcd(0x27 или 0x3F , 16 , 2);
void setup(){ lcd.init(); }

// Пояснение:



LCD1602 I2C - символьный дисплей (16x02 символов),
с интерфейсом I2C (зелёный)

#include
#include
LiquidCrystal_I2C lcd(0x27 или 0x3F , 16 , 2);
void setup(){ lcd.init(); }

// Пояснение:
LiquidCrystal_I2C ОБЪЕКТ (АДРЕС_I2C , КОЛ_СТОЛБЦОВ, КОЛ_СТРОК);
// АДРЕС_I2C может быть либо 0x27, либо 0x3F

LCD2004 - символьный дисплей (20x04 символов),
с параллельным интерфейсом (синий)

#include
LiquidCrystal lcd(2 , 3 , 4 , 5 , 6 , 7 [ , 8 , 9 , 10 , 11 ]);
void setup(){ lcd.begin(20 , 4); }

// Пояснение:
LiquidCrystal ОБЪЕКТ (RS , E , D4 , D5 , D6 , D7);
void setup(){ ОБЪЕКТ.begin(КОЛ_СТОЛБЦОВ, КОЛ_СТРОК); }

// Если используется 8 проводов шины данных, то указываем их все
LiquidCrystal ОБЪЕКТ (RS , E , D0 , D1 , D2 , D3 , D4 , D5 , D6 , D7);

LCD2004 I2C - символьный дисплей (20x04 символов),
с интерфейсом I2C (синий)
#include
#include
LiquidCrystal_I2C lcd(0x27 или 0x3F , 20 , 4);
void setup(){ lcd.init(); }

// Пояснение:
LiquidCrystal_I2C ОБЪЕКТ (АДРЕС_I2C , КОЛ_СТОЛБЦОВ, КОЛ_СТРОК);
// АДРЕС_I2C может быть либо 0x27, либо 0x3F

#1 Пример

Выводим надпись на дисплей LCD1602 подключённый по шине I2C. Для работы с дисплеем LCD2004 нужно изменить 3 строку на LiquidCrystal_I2C lcd(0x27,20,4);

#include // Подключаем библиотеку для работы с LCD дисплеем по шине I2C LiquidCrystal_I2C lcd(0x27,16,2); // Объявляем объект библиотеки, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2) // Если надпись не появилась, замените адрес 0x27 на 0x3F void setup(){ // lcd.init(); // Инициируем работу с LCD дисплеем lcd.backlight(); // Включаем подсветку LCD дисплея lcd.setCursor(0, 0); // Устанавливаем курсор в позицию (0 столбец, 0 строка) lcd.print("LCD"); // Выводим текст "LCD", начиная с установленной позиции курсора lcd.setCursor(0, 1); // Устанавливаем курсор в позицию (0 столбец, 1 строка) lcd.print("www.iarduino.ru"); // Выводим текст "www.iarduino.ru", начиная с установленной позиции курсора } // // void loop(){} // Код внутри функции loop выполняется постоянно. Но так как мы выводим статичный текст, нам достаточно его вывести 1 раз при старте, без использования кода loop

#2 Пример

Выводим надпись на дисплей LCD1602 подключённый по 4-битной параллельной шине. Для работы с дисплеем LCD2004 нужно изменить 5 строку на lcd.begin(20, 4);

#include // Подключаем библиотеку LiquidCrystal для работы с LCD дисплеем LiquidCrystal lcd(2,3,4,5,6,7); // Объявляем объект библиотеки, указывая выводы дисплея (RS,E,D4,D5,D6,D7) // Если используется 8 проводов шины данных, то указываем (RS,E,D0,D1,D2,D3,D4,D5,D6,D7) void setup(){ // lcd.begin(16, 2); // Инициируем работу с LCD дисплеем, указывая количество (столбцов, строк) lcd.setCursor(0, 0); // Устанавливаем курсор в позицию (0 столбец, 0 строка) lcd.print("LCD2004"); // Выводим текст "LDC1602", начиная с установленной позиции курсора lcd.setCursor(0, 1); // Устанавливаем курсор в позицию (0 столбец, 1 строка) lcd.print("www.iarduino.ru"); // Выводим текст "www.iarduino.ru", начиная с установленной позиции курсора } // // void loop(){} // Код внутри функции loop выполняется постоянно. Но так как мы выводим статичный текст, нам достаточно его вывести 1 раз при старте, без использования кода loop

#3 Пример

Выводим надпись «Русский язык» на дисплей LCD1602 подключённый по шине I2C:

#include // Подключаем библиотеку для работы с шиной I2C #include // Подключаем библиотеку для работы с LCD дисплеем по шине I2C LiquidCrystal_I2C lcd(0x27,16,2); // Объявляем объект библиотеки, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2) // uint8_t symbol = { // Объявляем массив из 6 собственных символов (к и й я з ы), каждый символ состоит из 8 байт { 0, 0,18,20,24,20,18, 0 }, // к { 0, 0,17,19,21,25,17, 0 }, // и {10, 4,17,19,21,25,17, 0 }, // й { 0, 0,15,17,15, 5, 9, 0 }, // я { 0, 0,14,17, 6,17,14, 0 }, // з { 0, 0,17,17,29,19,29, 0 }}; // ы // void setup(){ // lcd.init(); // Инициируем работу с LCD дисплеем lcd.backlight(); // Включаем подсветку LCD дисплея lcd.createChar(1, symbol); // Загружаем 1 символ "к" в ОЗУ дисплея lcd.createChar(2, symbol); // Загружаем 2 символ "и" в ОЗУ дисплея lcd.createChar(3, symbol); // Загружаем 3 символ "й" в ОЗУ дисплея lcd.createChar(4, symbol); // Загружаем 4 символ "я" в ОЗУ дисплея lcd.createChar(5, symbol); // Загружаем 5 символ "з" в ОЗУ дисплея lcd.createChar(6, symbol); // Загружаем 6 символ "ы" в ОЗУ дисплея lcd.setCursor(0, 0); // Устанавливаем курсор в позицию (0 столбец, 0 строка) lcd.print("Pycc\1\2\3 \4\5\6\1"); // Выводим текст "Pycckий языk", где "Pycc" написано латиницей, а "kий языk" - символами из ОЗУ дисплея } // Если нужно вывести символ из ОЗУ дисплея, то пишем \ и номер символа // void loop(){} // Код внутри функции loop выполняется постоянно. Но так как мы выводим статичный текст, нам достаточно его вывести 1 раз при старте, без использования кода loop

Функции, общие для библиотек LiquidCrystal и LiquidCrystal_I2C:

  • begin(cols,rows,); – Инициализация дисплея с указанием количества столбцов, строк и размера символа.
  • clear(); – Очистка дисплея с установкой курсора в положение 0,0 (Занимает много времени!).
  • home(); – Установка курсора в положение 0,0 (Занимает много времени!).
  • display(); – Быстрое включение дисплея (без изменения данных в ОЗУ).
  • noDisplay(); – Быстрое выключение дисплея (без изменения данных в ОЗУ).
  • blink(); – Включение мигающего курсора (с частотой около 1 Гц).
  • noBlink(); – Выключение мигающего курсора.
  • cursor(); – Включение подчеркивания курсора.
  • noCursor(); – Выключение подчеркивания курсора.
  • scrollDisplayLeft(); – Прокрутка дисплея влево. Сдвиг координат дисплея на один столбец влево (без изменения ОЗУ).
  • scrollDisplayRight(); – Прокрутка дисплея вправо. Сдвиг координат дисплея на один столбец вправо (без изменения ОЗУ).
  • leftToRight(); – Указывает в дальнейшем сдвигать положение курсора, после вывода очередного символа, на один столбец вправо.
  • rightToLeft(); – Указывает в дальнейшем сдвигать положение курсора, после вывода очередного символа, на один столбец влево.
  • noAutoscroll(); – Указывает в дальнейшем выравнивать текст по левому краю от позиции курсора (как обычно).
  • autoscroll(); – Указывает в дальнейшем выравнивать текст по правому краю от позиции курсора.
  • createChar(num,array); – Запись пользовательского символа в CGRAM дисплея под указанным номером.
  • setCursor(col,row); – Установка курсора в позицию указанную номером колонки и строки.
  • print(text); – Вывод текста, символов или цифр на экран дисплея. Синтаксис схож с одноимённой функцией класса Serial.

Функции, реализованные только в библиотеке LiquidCrystal_I2C:

  • init(); – Инициализация дисплея. Должна быть первой командой библиотеки LiquidCrystal_I2C после создания объекта. На самом деле данная функция есть и в библиотеке LiquidCrystal, но в той библиотеке она вызывается автоматически (по умолчанию) при создании объекта.
  • backlight(); – Включение подсветки дисплея.
  • noBacklight(); – Выключение подсветки дисплея.
  • setBacklight(flag); – Управление подсветкой (true - включить / false - выключить), используется вместо функций noBacklight и backlight.

Подключение:

// Для шины I2C:
#include
#include
LiquidCrystal_I2C lcd(address , col , row );
void setup(){
lcd.init();
}

Параметр:
  • address: Адрес дисплея на шине I2C - 0x27 или 0x3F
  • col:
  • row:
// Для параллельной шины из 4 проводов:
#include
LiquidCrystal lcd( RS , E , D4 , D5 , D6 , D7 );
void setup(){
lcd.begin( col , row );
}
Параметр:
  • RS: № вывода Arduino к которому подключён вывод RS
  • E: № вывода Arduino к которому подключён вывод E
  • D0...D3: № выводов Arduino к которым подключены выводы D0-D3
  • D4...D7: № выводов Arduino к которым подключены выводы D4-D7
  • col: количество столбцов реализованное у дисплея
  • row: количество строк реализованное у дисплея
// Для параллельной шины из 8 проводов:
#include
LiquidCrystal lcd( RS , E , D0 , D1 , D2 , D3 , D4 , D5 , D6 , D7 );
void setup(){
lcd.begin( col , row );
}
begin(col , row , );
Инициализация дисплея с указанием размеров экрана и символов.
Параметр:
  • col: количество столбцов реализованное у дисплея
  • row: количество строк реализованное у дисплея
  • size: размер символов, указывается константой:
    LCD_5x8DOTS (по умолчанию), или LCD_5x10DOTS
/* Для шины I2C: */ #include // Подключаем библиотеку для работы с шиной I2C #include // Подключаем библиотеку для работы с LCD дисплеем по шине I2C LiquidCrystal_I2C lcd(0x3F,20,4); // Объявляем объект библиотеки, указывая параметры дисплея (адрес I2C = 0x3F, количество столбцов = 20, количество строк = 4) // void setup(){ // lcd.init(); // Инициируем работу с LCD дисплеем lcd.backlight(); // Включаем подсветку LCD дисплея... // Выводим информацию, которая должна отображаться при старте } // // void loop(){} // ... // Выводим информацию которая должна меняться по алгоритму Вашего кода } // /* Для 4 проводной параллельной шины: */ #include // Подключаем библиотеку LiquidCrystal для работы с LCD дисплеем LiquidCrystal lcd(2,3,4,5,6,7); // Объявляем объект библиотеки, указывая выводы дисплея (RS,E,D4,D5,D6,D7) // Если используется 8 проводов шины данных, то указываем (RS,E,D0,D1,D2,D3,D4,D5,D6,D7) void setup(){ // lcd.begin(16, 2); // Инициируем работу с LCD дисплеем, указывая количество (столбцов, строк) ... // Выводим информацию, которая должна отображаться при старте } // // void loop(){} // ... // Выводим информацию которая должна меняться по алгоритму Вашего кода } //

Функции управления дисплеем:

display();
Включает дисплей после того как он был выключен функцией noDisplay.
Примечание: Функция выполняется быстро и без изменений в ОЗУ дисплея.
noDisplay();
Выключает дисплей.
Данные на дисплее не будут отображаться до вызова функции display, но и не сотрутся из памяти ОЗУ, а после вызова функции display, опять будут отображаться.
Примечание: Функция выполняется быстро и без изменений в ОЗУ дисплея.
scrollDisplayLeft();
Сдвигает координаты дисплея на один столбец влево.



scrollDisplayRight();
Сдвигает координаты дисплея на один столбец вправо.
Постоянный вызов данной функции создаст эффект бегущей строки.
Координаты сдвигаются как для имеющейся на дисплее информации, так и для той, которая будет выведена после.
Примечание: Функция выполняется без изменений ОЗУ дисплея.
Если вызвать функцию 40 раз подряд, то координата вернётся в изначальную точку
clear();
Очистка дисплея с установкой курсора в положение 0,0.
Информация имеющаяся на дисплее безвозвратно сотрётся.
Примечание: Занимает много времени.
backlight();
Включение подсветки дисплея.
noBacklight();
Выключение подсветки дисплея.
Примечание: Функция реализована только в библиотеке LiquidCrystal_I2C.
setBacklight(flag );
Управление подсветкой (вместо функций noBacklight и backlight).
Параметр:
  • flag: значение true - включает, а false - выключает подсветку.
Примечание: Функция реализована только в библиотеке LiquidCrystal_I2C.
/* Выводим надпись для наблюдения за функциями управления дисплеем: */ lcd.cursor(0,0); // Устанавливаем курсор в крайний верхний угол дисплея (0 столбец, 0 строка) lcd.print("iarduino.ru"); // Выводим текст "iarduino.ru" (первая буква "i" будет находиться в позиции "0,0", а последняя "u" в позиции "10,0", невидимый курсор в позиции "11,0") // lcd.noDisplay(); // Выключаем дисплей (надпись исчезнет с дисплея) lcd.display(); // Включаем дисплей (надпись появится на дисплее в том же месте) lcd.scrollDisplayLeft(); // Сдвигаем координаты столбцов влево (на дисплее будет отображаться "arduino.ru" без первой буквы "i", которая выйдет за пределы дисплея, но останется в его ОЗУ) lcd.scrollDisplayRight(); // Сдвигаем координаты столбцов вправо (на дисплее будет отображаться "iarduino.ru" на том же месте, где и была выведена изначально) lcd.clear(); // Чистим дисплей (надпись безвозвратно исчезнет с дисплея) lcd.noBacklight(); // Отключаем подсветку дисплея lcd.backlight(); // Включаем подсветку дисплея lcd.setBacklight(0); // Отключаем подсветку дисплея lcd.setBacklight(1); // Включаем подсветку дисплея

Функции управления курсором:

setCursor(col , row );
Установка курсора в указанную позицию.
Параметр:
  • col: номер столбца (начиная с 0).
  • row: номер строки (начиная с 0)
home();
Установка курсора в позицию 0,0. Работает как функция setCursor(0,0);
Примечание: Занимает много времени.
blink();
Включение мигающего курсора.
Примечание: Курсор занимает всё поле символа и мигает с частотой около 1 Гц, в той позиции где он был установлен ранее.
noBlink();
Выключение мигающего курсора.
Примечание: Курсор становится невидим, но его позиция сохраняется.
cursor();
Включение подчеркивания курсора.
Примечание: Курсор принимает вид символа подчёркивания и находится в той позиции, где он был установлен ранее.
noCursor();
Выключение подчеркивания курсора.
Примечание: Курсор становится невидим, но его позиция сохраняется.
lcd.setCursor(0, 1); // Устанавливаем курсор на первый символ второй строки (нумерация строк и столбцов начинается с 0) lcd.home(); // Устанавливаем курсор на первый символ первой строки (как при вызове lcd.setCursor(0,0);) lcd.blink(); // Делаем курсор видимым (на месте курсора будет мигать прямоугольник) lcd.noBlink(); // Делаем курсор невидимым (убираем мигающий прямоугольник) lcd.cursor(); // Делаем курсор видимым (на месте курсора появится знак подчёркивания) lcd.noCursor(); // Делаем курсор невидимым (убираем знак подчёркивания) // Если курсор попадает на место где есть символ, то этот символ не исчезает

Функции указывающие направление и выравнивание:

leftToRight();
Указывает, что после каждого нового символа, положение курсора должно сдвигаться на один столбец вправо.
Примечание: Если вывести текст "abc" на дисплее отобразится "abc" и текст будет находиться правее от изначального положения курсора.
(Как обычно)
rightToLeft();
Указывает, что после каждого нового символа, положение курсора должно сдвигаться на один столбец влево.
Примечание: Если вывести текст "abc" на дисплее отобразится "cba" и текст будет находиться левее от изначального положения курсора.
(Письменность справа налево)
noAutoscroll();
Указывает, что в дальнейшем, текст нужно выравнивать по левому краю от изначальной позиции курсора.
Примечание: если установить курсор в позицию 10,0 и вывести текст, то в данной позиции будет находиться первый символ выведенного текста.
(Как обычно)
autoscroll();
Указывает, что в дальнейшем, текст нужно выравнивать по правому краю от изначальной позиции курсора.
Примечание: если установить курсор в позицию 10,0 и вывести текст, то в данной позиции будет находиться курсор.
(Координаты дисплея будут сдвинуты влево, как будто Вы вызвали функцию scrollDisplayLeft столько раз, сколько букв в выведенном тексте)
lcd.leftToRight(); // Указываем курсору сдвигаться вправо (Как обычно в европейской письменности) lcd.clear(); lcd.setCursor(5,0); lcd.print("ABC"); // На дисплее увидим: " ABC " (После "A" курсор сдвинулся вправо и вывелась "B", далее курсор сдвинулся вправо и вывелась "C") lcd.rightToLeft(); // Указываем курсору сдвигаться влево (Как в письменности справа налево) lcd.clear(); lcd.setCursor(5,0); lcd.print("ABC"); // На дисплее увидим: " CBA " (После "A" курсор сдвинулся влево и вывелась "B", далее курсор сдвинулся влево и вывелась "C") lcd.noAutoscroll(); // Устанавливаем выравнивание по левому краю (Как обычно) lcd.clear(); lcd.setCursor(5,0); lcd.print("ABC"); // На дисплее увидим: " ABC " (Как обычно) lcd.autoscroll(); // Устанавливаем выравнивание по правому краю (Координаты дисплея будут сдвинуты влево на количество выведенных символов) lcd.clear(); lcd.setCursor(5,0); lcd.print("ABC"); // На дисплее увидим: " ABC " (Координаты дисплея будут сдвинуты на 3 символа влево, так как после каждого символа совершается вызов функции scrollDisplayLeft)

Функции ввода текста и символов:

createChar(num,array);
Запись пользовательского символа в CGRAM дисплея под указанным номером.
Если Вы хотите вывести текст (функцией print) в котором должен находиться установленный Вами символ, укажите слэш и номер под которым был записан этот символ: print("C\1MBO\2").
Параметр:
  • num: номер под которым будет записан символ.
  • array: массив представляющий записываемый символ.
Примечание: Массив состоит из нескольких байт, количество которых равно количеству строк в символе. Каждый установленный бит байта соответствует установленному (отображаемому) пикселю символа.
print(text);
Вывод текста, символов или цифр на экран дисплея.
Параметр:
  • text: символ, число или строка для вывода на дисплей.
Примечание: Синтаксис схож с одноимённой функцией класса Serial.
#include // Подключаем библиотеку для работы с шиной I2C #include // Подключаем библиотеку для работы с LCD дисплеем по шине I2C LiquidCrystal_I2C lcd(0x27,16,2); // Объявляем объект библиотеки, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2) // uint8_t symbol_d = {0b00000, // 1 строка символа "д" 0b00000, // 2 строка символа "д" 0b00110, // 3 строка символа "д" 0b01010, // 4 строка символа "д" 0b01010, // 5 строка символа "д" 0b01010, // 6 строка символа "д" 0b11111, // 7 строка символа "д" 0b10001}; // 8 строка символа "д" Весь массив можно записать одной строкой: uint8_t symbol_d={0,0,6,10,10,10,31,17}; // uint8_t symbol_i = {0b00000, // 1 строка символа "и" 0b00000, // 2 строка символа "и" 0b10001, // 3 строка символа "и" 0b10011, // 4 строка символа "и" 0b10101, // 5 строка символа "и" 0b11001, // 6 строка символа "и" 0b10001, // 7 строка символа "и" 0b00000}; // 8 строка символа "и" Весь массив можно записать одной строкой: uint8_t symbol_i={0,0,17,19,21,25,17,0}; void setup(){ // lcd.init(); // Инициируем работу с LCD дисплеем lcd.backlight(); // Включаем подсветку LCD дисплея lcd.createChar(1,symbol_d); // Загружаем в память дисплея первый символ lcd.createChar(2,symbol_i); // Загружаем в память дисплея второй символ lcd.clear(); // Чистим экран lcd.setCursor(0,0); // Устанавливаем курсор в крайний верхний угол lcd.print("Pa\1\2o"); // Выводим текст "Paдиo" при этом символы "P", "a" , "o" пишем латиницей, } // а символы "д", "и" выводим из памяти дисплея, указывая их номера // void loop(){ // lcd.setCursor(0,1); lcd.print(" "); // стираем всю нижнюю строку lcd.setCursor(0,1); lcd.print("i"); lcd.print("arduino"); lcd.print(".ru"); // выводим текст "i" "arduino" ".ru" в нижней строке delay(2000); // ждём 2 секунды lcd.setCursor(0,1); lcd.print(" "); // стираем всю нижнюю строку lcd.setCursor(0,1); lcd.print(12.345); // выводим число 12.34 (выводится 2 знака после запятой) delay(2000); // ждём 2 секунды lcd.setCursor(0,1); lcd.print(" "); // стираем всю нижнюю строку lcd.setCursor(0,1); lcd.print(12, HEX); // выводим число 12 в виде шестнадцатиричного числа delay(2000); // ждём 2 секунды lcd.setCursor(0,1); lcd.print(" "); // стираем всю нижнюю строку lcd.setCursor(0,1); lcd.print(1); // выводим число 1 delay(2000); // ждём 2 секунды }
  • Модуль FC-113 сделан на базе микросхемы PCF8574T, которая представляет собой 8-битный сдвиговый регистр - «расширитель» входов-выходов для последовательной шины I2C. На рисунке микросхема обозначена DD1.
  • R1 - подстроечный резистор для регулировки контрастности ЖК дисплея.
  • Джампер J1 используется для включения подсветки дисплея.
  • Выводы 1…16 служат для подключения модуля к выводам LCD дисплея.
  • Контактные площадки А1…А3 нужны для изменения адреса I2C устройства. Запаивая соответствующие перемычки, можно менять адрес устройства. В таблице приведено соответствие адресов и перемычек: "0" соответствует разрыву цепи, "1" - установленной перемычке. По умолчанию все 3 перемычки разомкнуты и адрес устройства 0x27 .

2 Схема подключения ЖК дисплея к Arduino по протоколу I2C

Подключение модуля к Arduino осуществляется стандартно для шины I2C: вывод SDA модуля подключается к аналоговому порту A4, вывод SCL - к аналоговому порту A5 Ардуино. Питание модуля осуществляется напряжением +5 В от Arduino. Сам модуль соединяется выводами 1…16 с соответствующими выводами 1…16 на ЖК дисплее.


3 Библиотека для работы по протоколу I2C

Теперь нужна библиотека для работы с LCD по интерфейсу I2C. Можно воспользоваться, например, вот этой (ссылка в строке "Download Sample code and library").

Скачанный архив LiquidCrystal_I2Cv1-1.rar разархивируем в папку \libraries\ , которая находится в директории Arduino IDE.

Библиотека поддерживает набор стандартных функций для LCD экранов:

Функция Назначение
LiquidCrystal() создаёт переменную типа LiquidCrystal и принимает параметры подключения дисплея (номера выводов);
begin() инициализация LCD дисплея, задание параметров (кол-во строк и символов);
clear() очистка экрана и возврат курсора в начальную позицию;
home() возврат курсора в начальную позицию;
setCursor() установка курсора на заданную позицию;
write() выводит символ на ЖК экран;
print() выводит текст на ЖК экран;
cursor() показывает курсор, т.е. подчёркивание под местом следующего символа;
noCursor() прячет курсор;
blink() мигание курсора;
noBlink() отмена мигания;
noDisplay() выключение дисплея с сохранением всей отображаемой информации;
display() включение дисплея с сохранением всей отображаемой информации;
scrollDisplayLeft() прокрутка содержимого дисплея на 1 позицию влево;
scrollDisplayRight() прокрутка содержимого дисплея на 1 позицию вправо;
autoscroll() включение автопрокрутки;
noAutoscroll() выключение автопрокрутки;
leftToRight() задаёт направление текста слева направо;
rightToLeft() направление текста справа налево;
createChar() создаёт пользовательский символ для LCD-экрана.

4 Скетч для вывода текста на LCD экран по шине I2C

Откроем образец: Файл Образцы LiquidCrystal_I2C CustomChars и немного его переделаем. Выведем сообщение, в конце которого будет находиться мигающий символ. В комментариях к коду прокомментированы все нюансы скетча.

#include // подключаем библиотеку Wire #include // подключаем библиотеку ЖКИ #define printByte(args) write(args); // uint8_t heart = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0}; // битовая маска символа «сердце» LiquidCrystal_I2C lcd(0x27, 16, 2); // Задаём адрес 0x27 для LCD дисплея 16x2 void setup() { lcd.init(); // инициализация ЖК дисплея lcd.backlight(); // включение подсветки дисплея lcd.createChar(3, heart); // создаём символ «сердце» в 3 ячейке памяти lcd.home(); // ставим курсор в левый верхний угол, в позицию (0,0) lcd.!"); // печатаем строку текста lcd.setCursor(0, 1); // перевод курсора на строку 2, символ 1 lcd.print(" i "); // печатаем сообщение на строке 2 lcd.printByte(3); // печатаем символ «сердце», находящийся в 3-ей ячейке lcd.print(" Arduino "); } void loop() { // мигание последнего символа lcd.setCursor(13, 1); // перевод курсора на строку 2, символ 1 lcd.print("\t"); delay(500); lcd.setCursor(13, 1); // перевод курсора на строку 2, символ 1 lcd.print(" "); delay(500); }

Кстати, символы, записанные командой lcd.createChar(); , остаются в памяти дисплея даже после выключения питания, т.к. записываются в ПЗУ дисплея 1602.

5 Создание собственных символов для ЖК дисплея

Немного подробнее рассмотрим вопрос создания собственных символов для ЖК экранов. Каждый символ на экране состоит из 35-ти точек: 5 в ширину и 7 в высоту (+1 резервная строка для подчёркивания). В строке 6 приведённого скетча мы задаём массив из 7-ми чисел: {0x0, 0xa, 0x1f, 0x1f, 0xe, 0x4, 0x0} . Преобразуем 16-ричные числа в бинарные: {00000, 01010, 11111, 11111, 01110, 00100, 00000} . Эти числа - не что иное, как битовые маски для каждой из 7-ми строк символа, где "0" обозначают светлую точку, а "1" - тёмную. Например, символ сердца, заданный в виде битовой маски, будет выглядеть на экране так, как показано на рисунке.

6 Управление ЖК экраном по шине I2C

Загрузим скетч в Arduino. На экране появится заданная нами надпись с мигающим курсором в конце.


7 Что находится «за» шиной I2C

В качестве бонуса рассмотрим временную диаграмму вывода латинских символов "A", "B" и "С" на ЖК дисплей. Эти символы имеются в ПЗУ дисплея и выводятся на экран просто передачей дисплею их адреса. Диаграмма снята с выводов RS, RW, E, D4, D5, D6 и D7 дисплея, т.е. уже после преобразователя FC-113 «I2C параллельная шина». Можно сказать, что мы погружаемся немного «глубже» в «железо».


Временная диаграмма вывода латинских символов "A", "B" и "С" на LCD дисплей 1602

На диаграмме видно, что символы, которые имеются в ПЗУ дисплея (см. стр.11 даташита, ссылка ниже), передаются двумя полубайтами, первый из которых определяет номер столбца таблицы, а второй - номер строки. При этом данные «защёлкиваются» по фронту сигнала на линии E (Enable), а линия RS (Register select, выбор регистра) находится в состоянии логической единицы, что означает передачу данных. Низкое состояние линии RS означает передачу инструкций, что мы и видим перед передачей каждого символа. В данном случае передаётся код инструкции возврата каретки на позицию (0, 0) ЖК дисплея, о чём также можно узнать, изучив техническое описание дисплея.

И ещё один пример. На этой временной диаграмме показан вывод символа «Сердце» на ЖК дисплей.


Опять, первые два импульса Enable соответствуют инструкции Home() (0000 0010 2) - возврат каретки на позицию (0; 0), а вторые два - вывод на ЖК дисплей хранящийся в ячейке памяти 3 10 (0000 0011 2) символ «Сердце» (инструкция lcd.createChar(3, heart); скетча).

Читатель нашего блога Михаил (mishadesh ) создал отличную библиотеку для работы с LCD и предложил написать статью для демонстрации ее возможностей. Собственно, сегодня именно об этом и пойдет речь 😉 Разберем, какие реализованы функции, а также в конце статьи будет выложен пример для работы с дисплеем.

Как обычно начнем с обсуждения железа… А тут на самом деле и не о чем говорить. Как и в первой статье, посвященной работе с дисплеями (), мы будем использовать отладочную плату Mini STM32 . Собственно, подключение дисплея, основные команды для записи данных, последовательность инструкций для инициализации – все это там есть =) Поэтому сейчас переходим сразу к обсуждению библиотеки для работы с графическими дисплеями.

Вот полный список функций с пояснениями:

Следующая функция, как видно из ее названия, меняет ориентацию экрана. Возможно два положения экрана, соответственно два возможных значения параметра orientation :

  • Orientation_Portrait
  • Orientation_Album

Функция отрисовывает на графическом дисплее символ, располагая его по переданным в функцию координатам, а также задавая его цвет. Начертание символа соответствует шрифту, определенному в файле font.c (файл идет в составе библиотеки).

Из функции LCD_DrawChar() плавно вытекает следующая функция:

void LCD_DrawString(char * s, uint16_t x, uint16_t y, uint16_t color, uint16_t backColor, uint8_t isTransparent) ;

Тут понятно и без лишних слов 😉 Функция печатает на LCD строку текста. Базой для этой функции является предыдущая – LCD_DrawChar() .

Помимо символов и текста, конечно же, необходимо иметь возможность нарисовать основные графические примитивы, например линию или круг. Для этого реализовано следующее:

void LCD_drawLine ( int x1, int y1, int x2, int y2, uint16_t color) ; void LCD_DrawRect ( int x1, int y1, int x2, int y2, uint16_t color, uint8_t filled ) ; void LCD_DrawEllipse(uint16_t X1, uint16_t Y1, uint16_t R, uint16_t color) ;

Для рисования линии нужно передать в функцию координаты начальной точки, координаты конечной точки, а также нужный цвет. Для прямоугольника – координаты верхнего левого угла и координаты правого нижнего угла (!). Последний параметр filled – определяет, необходимо ли выполнять заливку фигуры. Единица – значит да, фигура будет закрашена выбранным цветом, ноль – будет нарисован только контур фигуры. С этим понятно) Осталась только окружность – функция DrawEllipse() . Здесь вместо координат начала и конца (верхнего/нижнего углов) передаем в качестве аргументов центр окружности и радиус.

Ну и напоследок еще одна функция:

void LCD_FillScr(uint16_t color) ;

Функция позволяет залить экран сплошным цветом.

Все перечисленные функции реализованы в файле GUI_DRV.c .

Помимо них библиотека включает в себя функции для записи данных в дисплей (LCD_DRIVER.c ) а также уже упомянутые шрифты (font.c ). Как видите, все четко отсортировано по разным файлам, так что в принципе все очень понятно, поэтому давайте перейдем к практическому примеру!

Давайте разбираться! Идем в файл main.c … Не буду приводить полный код функций инициализации периферии и дисплея, все это можно посмотреть непосредственно в файле, либо в предыдущей статье, ссылка на которую была в начале этой статьи 😉 Функция main() :

int main(void ) { initPeriph() ; initFSMC() ; initLCD() ; delay(10000 ) ; LCD_FillScr(0xFFFF ) ; delay(100 ) ; LCD_SetOrient(Orientation_Album) ; delay(100 ) ; LCD_DrawString("Библиотека для LGDP4532" , 30 , 30 , 0x888F , 0x0000 , 0 ) ; LCD_DrawRect(100 , 100 , 200 , 200 , 0x0000 , 0 ) ; LCD_DrawRect(120 , 120 , 180 , 180 , 0xFF00 , 1 ) ; LCD_DrawEllipse(150 , 150 , 50 , 0xF000 ) ; while (1 ) { } }

Начинаем с инициализации, закрашиваем экран белым цветом и устанавливаем альбомную ориентацию экрана. И теперь переходим к отрисовке графики)

Выводим на экран строку, а также два прямоугольника и круг. Результат налицо:

Очевидно, что все работает отлично 😉

Итак, на этом на сегодня заканчиваем, огромное спасибо Михаилу за проделанную работу и приведенные материалы. Вот контакты автора библиотеки:

Skype – mishadesh

Mail – [email protected]

На этом все, спасибо за внимание, до скорых встреч!

Общие сведения

На отладочной плате STM32L-Discovery установлен жидкокристаллический индикатор (ЖКИ, англ. LCD. Liquid crystal display), имеющий шесть 14 сегментных знаков, 4 знака двоеточия (Colon), 4 точки (DP), 4 полоски (Bar). Все сегменты объединены в группы СOM0, COM1, COM2, COM3 по 24 сегмента. Каждая группа имеет свой отдельный «общий провод».


На отладочной плате установлен микроконтроллер STM32L152RBT6. В микроконтроллере есть встроенный контроллер ЖКИ, который управляет монохромными жидкокристаллическими индикаторами.
Контроллер ЖКИ:

  1. Позволяет настраивать частоту обновлений (частоту кадров - частота, с которой обновляется информация на ЖКИ)
  2. Поддерживает статический и мультиплексный режим управления
  3. Поддерживает программную установку контраста
  4. Позволяет использовать несколько уровней управляющего напряжения (до четырех)
  5. Использует двойную буферизацию, позволяющую обновлять данные в регистрах LCD_RAM в любое время выполнения программы, не нарушая целостность отображаемой информации

Регистры памяти контроллера ЖКИ

В микроконтроллере STM32L152RB выделены специальные регистры LCD_RAM, информация, хранимая в которых, соответствует группе сегментов COM0 - COM3. Каждой группе соответствует два 32 разрядных регистра. Такое количество регистров позволяет микроконтроллеру управлять ЖКИ c большим количеством сегментов, чем установленным на отладочной плате.

Для управления ЖКИ со 176 сегментами используются 4 группы COM0 - COM3 по 44 сегмента каждая, для управления ЖКИ с 320 сегментами используются 8 групп COM0 - COM7 по 40 сегментов каждая.



На отладочной плате STM32L-Discovery используется ЖКИ с 96 сегментами, разделенными на 4 группы COM0 - COM3 по 24 сегмента каждая.


ЖКИ на отладочной плате STM32L-Discovery подключен таким образом, что используются биты S40, S41 вторых регистров LCD_RAM в каждой группе и биты S0-S27 первых регистров LCD_RAM. Для уменьшения количества используемых регистров, информация из битов S40-S43 будет записываться в свободные биты S28-S31, используя функцию переназначения (remapping).

Блок делителей частоты

Блок делителей частоты (Frequency generator) позволяет добиться различной частоты кадров (frame rates) на ЖКИ в диапазоне от 32 кГц до 1 МГц. В качестве источника тактирующего сигнала могут использоваться:
  1. Внешний НЧ генератор с частотой 32 кГц (LSE. Low speed external)
  2. Внутренний НЧ генератор с частотой 37 кГц (LSI. Low speed internal)
  3. Внешний ВЧ генератор с делителями частоты на 2,4,8 и 16 и максимальной частотой 1 МГц. (HSE. High speed external)
Для достижения точной синхронизации и снижения смещения напряжения постоянного тока через сегменты ЖКИ источник тактирующего сигнала должен обладать стабильностью. Тактирующий сигнал LCDCLK поступает в контроллер ЖКИ. Частота тактового сигнала делится, в соответствии с коэффициентами деления, которые устанавливаются битами PS, DIV регистра LCD_FCR (Frame Control Register). Результирующая частота на выходе блока делителей частоты рассчитывается по формуле:

F ck_div =F LCDCLK / (2 PS *(16+DIV))

Частота кадров рассчитывается по формуле:

F Frame =f ck_div *duty

Где duty – коэффициент заполнения – отношение длительность импульса к его периоду. За время одного кадра на ЖКИ последовательно выводится информация из регистров LCD_RAM[x], LCD_RAM и тд. Для ЖКИ установленного на отладочной плате, за один кадр контроллер ЖКИ должен вывести информацию из 4 групп сегментов COM0 - COM3, следовательно, длительность управляющего импульса для одной группы будет 1/4 длительности кадра, т.е. duty=1/4.

Управление ЖКИ

Существует два способа управления ЖКИ – статический режим управления и мультиплексный режим управления. При статической индикации каждый сегмент разряда индикатора подключен к выходу микроконтроллера. Применительно к ЖКИ, на отладочной плате STM32LDiscovery, потребуется 6*14=84 выводов микроконтроллера (без учета двоеточий, точек и полосок). Из-за использования такого количества выводов, подключение другой периферии станет невозможным. Микроконтроллер STM32L152RB имеет 64 вывода. При мультиплексном режиме управлении (динамический режим управления) одинаковые сегменты разрядов индикатора объединены в группы. Отображение информации происходит за счет поочередного зажигания сегментов разрядов индикатора, с частотой, не воспринимаемой человеческим глазом.

Мультиплексное управление позволяет управлять большим количеством сегментов. Вместо раздельного управления каждым элементом, они могу адресоваться по строкам и столбцам (COM и SEG), таким образом, упрощается управляющая схема, т.к. каждому сегменту не требуется собственная управляющая линия. Для включения выбранного сегмента, на него надо подать разность потенциалов COM и SEG. Пример работы первого разряда индикатора (на индикатор выводится «1:»):


Первый разряд индикатора в момент времени t 0


Первый разряд индикатора в момент времени t 1


Первый разряд индикатора в момент времени t 2


Общая схема подключения сегментов к выводам ЖКИ


Схема подключения выводов ЖКИ к портам микроконтроллера

Для линий SEG используется управляющее напряжение, количество уровней которого определяется коэффициентом bias. ЖКИ на отладочной плате использует мультиплексный режим управления с duty=1/4 и bias=1/3. Значение duty и bias устанавливаются через регистр LCD_CR (Control Register) в битах DUTY и BIAS.

Практика

Конфигурирование портов микроконтроллера

Для управления ЖКИ порты микроконтроллера должны быть настроены соответствующим образом:
  1. На выход
  2. Использование альтернативной функции AF 11 (Alternate function)
  3. Иметь частоты вывода в порт 400 кГц
  4. Использовать режим работы push-pull
  5. Без подтягивающих резисторов
При работе порта в режиме альтернативной функции, выходной буфер данных порта управляется сигналами, поступающими с периферии. Заголовочный файл stm32lxx.h библиотеки CMSIS содержит описание всех регистров периферии, а также структуры доступа к ним.

Выводы ЖКИ подключены к портам GPIOA (PA1-PA3,PA8-PA10,PA15), GPIOB (PB3-PB5, PB8-PB15), GPIOC (PC0-PC3,PC6-PC11) микроконтроллера. Для работы ЖКИ, на выбранные порты необходимо подать тактовый сигнал. Тактирование портов GPIO микроконтроллера происходит от шины AHB системы RCC (Reset and Clock Control) – системы тактировании и сброса. Подача тактового сигнала осуществляется установкой соответствующих битов в регистре RCC_AHBENR (AHB peripheral clock enable register).

Регистр RCC_AHBENR (на рисунке приведены первые 15 разрядов)

Для портов GPIOA, GPIOB, GPIOC необходимо установить 1 в 0, 1, 2 разряды регистра.

Далее я буду приводить код записи информации в регистр с использованием битмаски и с использованием шестнадцатеричных кодов. Использование битмасок удобнее, но работа с шестнадцатеричными кодами позволяет понять суть работы с регистрами.

RCC->AHBENR |=(RCC_AHBENR_GPIOAEN|RCC_AHBENR_GPIOBEN|RCC_AHBENR_GPIOCEN); или RCC->AHBENR = 0x7; /* 0x7=111 */

Для указания режимов работы порта используется регистр GPIOx_MODER (GPIO port mode register) (x = A..H). Все разряды регистра сгруппированы в группы MODERy, где y номер пина соответствующего порта. Порты необходимо настроить на режим альтернативной функции, т.е. в группе, отвечающей за пин, установить значение 10. Для порта GPIOA нужно настроить пины 1-3,8-10,15, т.е установить 1 в 3,5,7,17,19,21,31 разряды.


Регистр GPIOx_MODER (GPIO port mode register)

GPIOA->MODER |= (GPIO_MODER_MODER1_1 | GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1 | GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1 | GPIO_MODER_MODER15_1); или GPIOA->MODER = 0x802A00A8; /* 0x802A00A8=1000 0000 0010 1010 0000 0000 1010 1000 */
Порты микроконтроллера необходимо перевести в режим push-pull. Для этого необходимо в регистре GPIOx_OTYPER (GPIO port output type register) установить 1 в разряды, отвечающие за пины.


Регистр GPIOx_OTYPER (GPIO port output type register)

GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_1 | GPIO_OTYPER_OT_2 | GPIO_OTYPER_OT_3 | GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10 | GPIO_OTYPER_OT_15); или GPIOA->OTYPER &= ~0x0000870E; /* 0x870E=1000 0111 0000 1110 */
Оба варианта воздействуют на выбранные пины. (Для порта GPIOA настраиваются пины 1-3,8-10,15). Если необходимо перевести все пины порта в режим push-pull, можно записать в регистр значение:
GPIOA->OTYPER = 0x0;
Для указания частоты вывода информации в порт используется регистр GPIOx_OSPEEDR (GPIO port output speed register). Все разряды регистра сгруппированы в группы OSPEEDRy, где y номер пина соответствующего порта. В данной работе должна быть установлена частота 400 кГц т.е. в группе, отвечающей за пин, установить значение 00.


Регистр GPIOx_OSPEEDR (GPIO port output speed register)

GPIOA->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR1 | GPIO_OSPEEDER_OSPEEDR2 | GPIO_OSPEEDER_OSPEEDR3 | GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR10 | GPIO_OSPEEDER_OSPEEDR15); или GPIOA->OSPEEDR &= ~0xC03F00FC; /*0xC03F00FC=1100 0000 0011 1111 0000 0000 1111 1100 */
Если необходимо установить частоту вывода в порт 400 кГц для всех пинов, можно записать в регистр значение:
GPIOA->OSPEEDR = 0x0;
Для отключения подтягивающих резисторов pull-up, pull-down для выбранных пинов используется регистр GPIOx_PUPDR (GPIO port pullup/ pull-down register). Все разряды регистра сгруппированы в группы PUPDRy, где y – номер пина соответствующего порта. Для отключение подтягивающих резисторов в группе, отвечающей за пин, устанавливается значение 00.


Регистр GPIOx_PUPDR (GPIO port pull-up/pull-down register)

GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR1 | GPIO_PUPDR_PUPDR2 | GPIO_PUPDR_PUPDR3 | GPIO_PUPDR_PUPDR8 | GPIO_PUPDR_PUPDR9 | GPIO_PUPDR_PUPDR10 | GPIO_PUPDR_PUPDR15); или GPIOA->PUPDR &= ~0xC03F00FC; /*0xC03F00FC=1100 0000 0011 1111 0000 0000 1111 1100 */
Если необходимо отключить подтягивающие резисторы для всех пинов, можно записать в регистр значение:
GPIOA->PUPDR = 0x0;
Для использования альтернативной функции для портов микроконтроллера используются два регистра GPIOx_AFRL (GPIO alternate function low register), отвечающий за младшие пины (с 0 по 7) и GPIOx_AFRH (GPIO alternate function high register), отвечающий за старшие пины (с 8 по 15). Все разряды регистров сгруппированы в группы AFRLy и AFRHy, где y – номер пина соответствующего порта. Порты должны быть настроены на использование альтернативной функции AF11, для этого в группе, отвечающей за пин, должно быть установлено значение 1011.


Регистр GPIOx_AFRL (GPIO alternate function low register)


Регистр GPIOx_AFRH (GPIO alternate function high register)

Для этого необходимо записать в регистры значения:
GPIOA->AFR = 0xBBB0; /* 0xBBB0 = 1011 1011 1011 0000*/ GPIOA->AFR = 0xB0000BBB; /* 0xB0000BBB=1011 0000 0000 0000 0000 1011 1011 1011*/

AFR = 0xBBB0 – записывает значение в регистр GPIOx_AFRL.
AFR = 0xB0000BBB – записывает значение в регистр GPIOx_AFRH.

Настройки соответствующих пинов портов GPIOB, GPIOC производятся аналогично.

Настройка контроллера ЖКИ

При работе с контроллером ЖКИ, как и с другой периферией, на него необходимо подать тактовый сигнал. Тактовый сигнал также подается на систему управления питанием. Контроллер и система управления питанием для тактирования используют шину APB1. Для разрешения тактирования в регистре RCC_APB1ENR (APB1 peripheral clock enable register) необходимо установить 1 в 9 и 28 разрядах.


Регистр RCC_APB1ENR (APB1 peripheral clock enable register)

RCC->APB1ENR |= RCC_APB1ENR_PWREN|RCC_APB1ENR_LCDEN; или RCC->APB1ENR |= 0x10000200; /* 0x10000200=1 0000 0000 0000 0000 0010 0000 0000 */
Для работы контроллера ЖКИ необходимо указать источник тактовых сигналов. Источник указывается в регистре RCC_CSR. По умолчанию запись в этот регистр запрещена. В регистре управления питанием PWR_CR (PWR power control register) снимается защита от записи в регистр RCC_CSR. Регистр RCC_CSR управляет источниками тактирования часов RTC и контроллера ЖКИ
Запись в регистр RCC_CSR разрешается установкой 1 в 8 разряд регистра PWR_CR.


Регистр PWR_CR (PWR power control register)

PWR->CR |= PWR_CR_DBP; или PWR->CR |= 0x100; /* 0x100 =1 0000 0000 */
Для смены источника тактирования контроллера ЖКИ (и часов RTC тоже) необходимо сначала выполнить сброс источника тактирования установкой бита RTCRST (установкой 1 в 23 разряд) в регистре RCC_CSR (Control/status register).


Регистр RCC_CSR (Control/status register)

RCC->CSR |= RCC_CSR_RTCRST;
Или записав в регистр значение, используя оператор «|=», т.к. значение по
умолчанию регистра отлично от 0x0:
RCC->CSR |= 0x800000; /* 0x800000 = 1000 0000 0000 0000 0000 0000 */
Для выбора нового источника тактирования необходимо убрать бит RTCRST:
RCC->CSR &= ~RCC_CSR_RTCRST; или RCC->CSR &= ~0x800000;
В качестве источника тактового сигнала выбирается внешний НЧ генератор. Для включения генератора в регистре RCC_CSR необходимо установить бит LSEON (установить 1 в 8 разряд):
RCC->CSR |= RCC_CSR_LSEON; или RCC->CSR |= 0x100; /* 0x100 = 1 0000 0000 */
После включения генератора необходимо некоторое время на его стабилизацию. Готовность генератора проверяется аппаратной установкой бита LSERDY в регистре RCC_CSR:
while(!(RCC->CSR&RCC_CSR_LSERDY));
Выбор внешнего НЧ генератора в качестве источника тактового сигнала осуществляется установкой в группе RTCSEL регистра RCC_CSR значения 01:
RCC->CSR |= RCC_CSR_RTCSEL_LSE; или RCC->CSR |= 0x10000; /* 0x10000 = 01 0000 0000 0000 0000 */
В контроллере ЖКИ необходимо установить нужный режим bias. Для этого в регистре LCD_CR (LCD control register) необходимо установить значение 10 в группу BIAS. Перед установкой бит необходимо очистить биты от «мусора».


Регистр LCD_CR (LCD control register)

Сброс битов:
LCD->CR &= ~LCD_CR_BIAS; или LCD->CR &= ~0x60;
Выбор режима bias=1/3 с использованием битмаски:
LCD->CR |= LCD_CR_BIAS_1; или LCD->CR |= 0x40;
Устанавливаем режим duty=1/4. Для этого также вначале сбрасываем все биты:
LCD->CR &=~LCD_CR_DUTY; или LCD->CR &= ~0x1C;
Устанавливаем значение 011 в группу DUTY регистра LCD_CR для
режима duty=1/4:
LCD->CR |= LCD_CR_DUTY_0|LCD_CR_DUTY_1; или LCD->CR |= 0xС;
Активируем функцию переназначения выводов. Для этого устанавливаем 1 в 7 разряд регистра LCD_CR:
LCD->CR |= LCD_CR_MUX_SEG; или LCD->CR |= 0x80;
Устанавливаем значения коэффициентов деления частоты тактового сигнала LCDCLK. Значения коэффициентов выставляются в регистре LCD_FCR (LCD frame control register). Вначале также очищаем все биты, затем устанавливаем нужные.


Регистр LCD_FCR (LCD frame control register)

LCD->FCR &= ~LCD_FCR_PS; LCD->FCR &= ~LCD_FCR_DIV; или LCD->FCR &= ~0x3C00000; LCD->FCR &= ~0x3C0000;
Значения коэффициентов деления частоты тактового сигнала устанавливаем равными ck_ps = LCDCLK/16, ck_div = ck_ps/17. Для этого устанавливаем 1 в 24 и в 18 разряды:
LCD->FCR |= 0x1040000; /*0x1040000 = 1 0000 0100 0000 0000 0000 0000*/
Для установки нужного уровня контраста необходимо установить значение 010 в группу СС, так же предварительно очистив биты от старых значений:
LCD->FCR &= ~LCD_FCR_CC; LCD->FCR |= LCD_FCR_CC_1; или LCD->FCR &= ~0x1C00; LCD->FCR |= 0x800; /*0x800 = 1000 0000 0000*/
После установки всех значений необходимо некоторое время на синхронизацию регистра LCD_FCR. Синхронизация регистра проверяется аппаратной установкой бита FCRSF в регистре LCD_SR (LCD status register).

Регистр LCD_SR (LCD status register)

While(!(LCD->SR&LCD_SR_FCRSR));
В качестве источника напряжения для ЖКИ выбираем внутренний step-up converter для формирования V lcd . Для этого в первый разряд регистра LCD_CR (LCD control register) устанавливается значение 0:
LCD->CR &= ~LCD_CR_VSEL; или LCD->CR &= ~0x2;
Разрешение работы ЖКИ контроллера происходит установкой 1 в 0 разряд регистра LCD_CR (LCD control register):
LCD->CR |= LCD_CR_LCDEN; или LCD->CR |= 0x1;
После установки в качестве источника напряжения внутреннего step-up converter, необходимо дождаться его готовности. Готовность проверяется аппаратной установкой бита RDY в регистре LCD_SR (LCD status register):
while(!(LCD->SR&LCD_SR_RDY));
После разрешения работы контроллера ЖКИ, необходимо дождаться его готовности. Готовность проверяется аппаратной установкой бита ENS в регистре LCD_SR (LCD status register):
while(!(LCD->SR&LCD_SR_ENS));

Формирование изображения на ЖКИ

Все сегменты индикатора объединены в группы COM0 - COM3 по 24 сегмента в каждой (SEG0-SEG23). Информация о сегментах хранится в регистрах LCD_RAM памяти контроллера ЖКИ. Разводка печатной платы такова, что номера сегментов не соответствуют номерам разрядов регистров LCD_RAM.

Что бы отобразить 1 в первом разряде ЖКИ, необходимо зажечь сегменты 1B,1C. Сегмент 1B принадлежит группе COM0, сегмент 1C принадлежит группе COM1. Следовательно информация о них должна быть записана в регистры RAM (LCD_RAM0), RAM (LCD_RAM2) соответственно. За сегмент 1B отвечает вывод ЖКИ LCDSEG22, информация о котором храниться в разряде SEG40 регистра RAM (LCD_RAM1). С использованием функции переназначения за сегмент LCDSEG22 будет отвечать разряд SEG28 регистра RAM (LCD_RAM0). За сегмент 1С отвечает вывод ЖКИ LCDSEG1, информация о котором храниться в разряде SEG1 регистра RAM (LCD_RAM2).

LCD->RAM= 0x10000000; /*0x10000000 = 1 0000 0000 0000 0000 0000 0000 0000 */ LCD->RAM = 0x2; /*0x2= 10 */
До записи значений в регистры памяти необходимо проверить завершена ли предыдущая передача данных на ЖКИ. Для этого проверяется бит UDR (Update display request) регистра LCD_SR (LCD status register). Контроллер ЖКИ имеет два выходных буфера, информация заносится в первый буфер, а выводится на ЖКИ из второго буфера. Бит UDR устанавливается во время передачи из первого буфера во второй, защищая от записи регистры LCD_RAM:
while(LCD->SR & LCD_SR_UDR);
После записи информации в регистры LCD_RAM необходимо установить бит UDR в регистре LCD_SR (LCD status register)(установить 1 во 2 разряд):
LCD->SR |= LCD_SR_UDR; или LCD->SR |= 0x4; /*0x4 = 100 */