Max7219 и пара проводов. Бегущая строка
Все давно привыкли, что у каждого электронного устройства есть экран, с помощью которого оно дает человеку всякую полезную информацию. MP3-плеер показывает название играемого трека, пульт квадрокоптера отображает полетную телеметрию, даже стиральная машина выводит на дисплей время до конца стирки, а на смартфоне вообще размещается целый рабочий стол персонального компьютера! Скорее всего, вашему очередному устройству тоже не помешает какой-нибудь небольшой дисплейчик 🙂 Попробуем сделать простые электронные часы! А в качестве табло используем распространенный и дешевый символьный жидкокристаллический дисплей 1602. Вот прямо такой, как на картинке: Кроме 16х2, достаточно популярным считается символьный дисплей 20х4 (четыре строки по 20 символов), а также графический дисплей с разрешением 128х64 точек. Вот они на картинках:
1. Подключение символьного ЖК дисплея 1602
У дисплея 1602 есть 16 выводов. Обычно они нумеруются слева-направо, если смотреть на него так как на картинке. Иногда выводы подписываются, типа: DB0, DB1, EN и т.п. А иногда просто указывают номер вывода. В любом случае, список выводов всегда одинаковый: 1 — «GND», земля (минус питания); 2 — «Vcc», питание +5В; 3 — «VEE», контраст; 4 — «RS», выбор регистра; 5 — «R/W», направление передачи данных (запись/чтение); 6 — «EN», синхронизация; 7-14 — «DB0», «DB1», .., «DB7″- шина данных; 15 — анод подсветки (+5В); 16 — катод подсветки (земля). Линии VEE, RS и четыре линии данных DB4, DB5, DB6, DB7 подключаем к цифровым выводам контроллера. Линию «R/W» подключим к «земле» контроллера (так как нам потребуется только функция записи в память дисплея). Подсветку пока подключать не будем, с этим, я полагаю, вы сами легко разберетесь 🙂 Принципиальная схема подключения дисплея к Ардуино УноВнешний вид макета
На всякий случай еще и в виде таблички:
ЖК дисплей 1602 | 1 | 2 | 4 | 6 | 11 | 12 | 13 | 14 | 15 | 16 |
Ардуино Уно | GND | +5V | 4 | 5 | 6 | 7 | 8 | 9 | +5V | GND |
2. Программируем «Hello, world!»
Для работы с ЖК дисплеями различных размеров и типов, в редакторе Arduino IDE имеется специальная библиотека LiquidCrystal . Чтобы подключить библиотеку, запишем первой строчкой нашей программы следующее выражение: #include3. Программируем часы
Теперь когда дисплей точно работает, попробуем превратить наше нехитрое устройство в настоящие электронные часы. Внимание! Для вывода времени нам потребуется библиотека «Time». Если она еще не установлена, то можно скачать архив по ссылке . Подключим ее: #include- year() — вернет нам год;
- month() — месяц;
- day() - день;
- hour() - час;
- minute() — вернет минуту;
- second() - секунду.
Привет Ребятушки. Сегодня запилим бегущую строку на светодиодных модулях MAX7219 и Arduino. Задача очень простая и не потребует от нас больших знаний в области электроники и программирования. Для начала предлагаю изучить немного теории по устройству светодиодной матрицы, принципу ее подключения и посмотреть видео результата к которому мы будем стремиться на протяжении всей статьи.
Светодиодная матрица - это графический индикатор, который можно использовать для вывода простых изображений, букв и цифр. Я не ставлю задачу подробно разобраться с устройством матричных индикаторов, однако стоит заметить, что по сути матрица состоит и 8х8 светодиодов. По сути все сводиться к динамической индикации. Основываясь на этом, понятно, что группировать несколько матриц вместе задача не из простых. На каждый новый ряд или колонку матриц, нужно добавлять новый сдвиговый регистр вместе с проводами и резисторами, а по-хорошему еще и микросхему ULN2003.
К счастью, инженеры давно уже разработали специализированные микросхемы для управления разного рода индикаторами. В этой статье мы рассмотрим матричный модуль с микросхемой MAX7219. Как станет понятно позже, работать с таким модулем одно удовольствие.
Модуль светодиодной матрицы с микросхемой MAX7219
Модуль представляет из себя плату с микросхемой, необходимой для неё обвязкой и, собственно, матричным индикатором. Обычно индикатор не впаивают в плату, а вставляют в разъем. Это сделано для того, чтобы группу модулей можно было сначала закрепить на какой то поверхности винтами, а затем вставить в них матрицы.
У модуля есть пять выводов на каждой стороне. С одной стороны данные входят в модуль, с другой стороны данные выходят из модуля и передаются в следующий. Это позволяет соединять матрицы у цепочку.
Входной разъем / Выходной разъем:
- VCC, GND - питание;
- DIN - вход данных;
- CS - выбор модуля (chip select);
- CLK - синхроимпульс.
Работает модуль от напряжения 5 Вольт.
Вывод пикселей с помощью библиотеки Max72xxPanel
Для управления микросхемой MAX7219 воспользуемся библиотекой Max72xxPanel . Скачать её можно по ссылкам в конце статьи.
Установим библиотеку и напишем небольшой код, который будет выводить на дисплей всего одну точку с координатами x=3 и y=4. Точка будет мигать с периодом 600 миллисекунд.
#include
#include #include int pinCS = 10; int numberOfHorizontalDisplays = 1; // количество матриц по-горизонтали int numberOfVerticalDisplays = 1; // количество матриц по-вертикали Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); void setup() { matrix.setIntensity(4); // яркость от 0 до 15 } void loop() { matrix.drawPixel(3, 4, HIGH); // зажигаем пиксель с координатами {3,4} matrix.write(); // вывод всех пикселей на матрицу delay(300); matrix.drawPixel(3, 4, LOW); // гасим пиксель matrix.write(); delay(300); } Как уже говорилось ранее, матричные модули с микросхемой MAX7219 можно легко объединять. Именно для этой цели в начале программы мы задаем количество матриц по-горизонтали и по-вертикали. В данном случае используется одна матрица, так что оба этих параметра будут равны 1.
Важно отметить, что после включения и выключения пикселей с помощью функции drawPixel , необходимо вызвать функцию write . Без функции write, пиксели не высветятся на матрице!
Теперь напишем код, который отобразит на матрице смайл. Смайл зашифруем с помощью массива из восьми байт. Каждый байт массива будет отвечать за строку матрицы, а каждый бит в байте за точку в строке.
#include
#include #include int pinCS = 10; int numberOfHorizontalDisplays = 1; // количество матриц по-горизонтали int numberOfVerticalDisplays = 1; // количество матриц по-вертикали Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); const byte data = { 0b00111100, 0b01000010, 0b10100101, 0b10000001, 0b10100101, 0b10011001, 0b01000010, 0b00111100 }; void setup() { matrix.setIntensity(7); // яркость от 0 до 15 matrix.fillScreen(LOW); // очистка матрицы for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { // зажигаем x-й пиксель в y-й строке matrix.drawPixel(x, y, data[y] & (1< Примечание. В библиотеке Max72xxPanel есть функция setRotation , которая задает ориентацию изображения на матрице. Например, если мы захотим повернуть смайл на 90 градусов, нужно будет сразу после вызова функции setIntensity вызвать setRotation с соответствующими аргументами:
matrix.setRotation(0, 1);
первый параметр - это индекс матрицы, в нашем случае он равен нулю; второй параметр - количество поворотов на 90 градусов.
Вывод текста с помощью библиотеки Adafruit-GFX-Library
Подобным же образом можно выводить на матрицу и любой другой символ, например, букву. Но чтобы иметь возможность отображать любую букву английского алфавита, нам необходимо будет определить в программе целых 26 восьмибайтных массива! Это очень муторно, и разумеется кто-то это уже сделал до нас.
В популярной библиотеке Adafruit-GFX-Library помимо функций для работы с графикой и текстом, имеется и база латинских букв в верхнем и нижнем регистрах, а также все знаки препинания и прочие служебные символы. Ссылка на библиотеку есть в конце статьи.
Отобразить символ на матрице можно с помощью функции drawChar .
drawChar(x, y, символ, цвет, фон, размер);
Первые два параметра функции отвечают за координаты верхнего левого угла символа. Третий параметр - это сам символ. Цвет символа в нашем случае будет равен 1 или HIGH, так как матрица двухцветная. Фон равен 0 или LOW. Последний параметр «размер» сделаем равным 1.
Напишем программу, которая будет по-очереди выводить на матрицу все буквы фразы: «HELLO WORLD!».
#include
#include #include int pinCS = 10; int numberOfHorizontalDisplays = 1; int numberOfVerticalDisplays = 1; Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); String tape = «HELLO WORLD»; int wait = 800; void setup() { matrix.setIntensity(1); // яркость от 0 до 15 } void loop() { for (int i = 0 ; i < tape.length(); i++) { matrix.fillScreen(LOW); matrix.drawChar(0, 0, tape[i], HIGH, LOW, 1); matrix.write(); delay(wait); } } Примечание. В библиотеке Adafruit_GFX имеется множество функций для работы с графикой. Например, drawCircle(3, 3, 2, HIGH) начертит окружность с центром {3,3} и радиусом 2. Последний параметр - цвет, но в случае монохромной матрицы он равен 1 или HIGH. Функция drawLine(0, 0, 3, 6, HIGH) начертит отрезок между точками {0,0} и {3,6}.
Бегущая строка на max7219
И так надеюсь мы разобрались с устройством и принципом вывода на одиночную матрицу. Теперь перейдем непосредственно к бегущей строке.
Что потребуется?
Для реализации идеи потребуется совсем немного деталей:
- два светодиодных модуля, состоящих из четырёх матриц 8 на 8 пикселей;
- соединительные провода;
- плата Arduino Nano;
Схема
На печатной плате используемого светодиодного модуля расположено 4 матрицы размером 8 на 8 пикселей. Каждое светодиодное табло управляется микросхемой MAX7219.
MAX7219 представляет собой контроллер управления led-дисплеями, матрицами с общим катодом и дискретными светодиодами в количестве до 64 шт. Для более комфортного восприятия информации, выводимой на светодиодное табло, рекомендуется устанавливать несколько модулей. Для этого их объединяют в последовательно включенные группы, то есть выход первого модуля (out) подключают к входу второго модуля (in). Моя сборка состоит из двух модулей (16 матриц), длины которых вполне хватит для удобного прочтения целых предложений. При этом подключение сборки к Arduino производиться точно также как и к одиночному модулю.
Программирование бегущей строки.
Бегущая строка из Arduino и светодиодных модулей под управлением MAX7219 практически готова. Настало время перейти к заключающей, программной части.
#include
#include #include int pinCS = 10; // Подключаем CS к 10-му пину, DIN к MOSI и CLK к SCK int numberOfHorizontalDisplays = 1; // Количество модулей по горизонтали int numberOfVerticalDisplays = 8; // Количество модулей по вертикали Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); String tape = ""; int wait = 10; // Скорость прокрутки в миллисикундах int spacer = 1; // Промежуток между символами (кол-во точек) int width = 5 + spacer; // Ширина символа /* Перекодировка русского шрифта из UTF-8 в Windows-1251 */ String utf8rus(String source) { int i,k; String target; unsigned char n; char m = { "0", "\0" }; k = source.length(); i = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x2F; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB7; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x6F; break; } } } m = n; target = target + String(m); } return target; } /* Код для работы с com-портом */ String Serial_Read() { unsigned char c; // переменная для чтения сериал порта String Serial_string = ""; // Формируемая из символов строка while (Serial.available() > 0) { // Если в сериал порту есть символы c = Serial.read(); // Читаем символ //Serial.print(c,HEX); Serial.print(" "); Serial.print(c); if (c == "\n") { // Если это конец строки return Serial_string; // Возвращаем строку } if (c == 0xB8) c = c - 0x01; // Коррекция кодов символа под таблицу???? так как русские символы в таблице сдвинуты относительно стандартной кодировки utf на 1 символ if (c >= 0xBF && c <= 0xFF) c = c - 0x01; Serial_string = Serial_string + String(char(c)); //Добавить символ в строку } return Serial_string; } void setup() { Serial.begin(9600); tape = utf8rus("сайт Amateur Radio WorkShop"); // Этот текст выводиться при включении или если в com-порт не пришла информация matrix.setIntensity(3); // Яркость от 0 до 15 matrix.setRotation(matrix.getRotation()+3); //1 - 90 2 - 180 3 - 270 } void loop() { if (Serial.available()){ tape=Serial_Read(); } for (int i = 0 ; i < width * tape.length() + matrix.width() - 1 - spacer; i++) { matrix.fillScreen(LOW); int letter = i / width; // Номер символа выводимого на матрицу int x = (matrix.width() - 1) - i % width; int y = (matrix.height() - 8) / 2; // Центрируем текст по вертикали while (x + width - spacer >= 0 && letter >= 0) { if (letter < tape.length()) { matrix.drawChar(x, y, tape, HIGH, LOW,1); } letter--; x -= width; } matrix.write(); // Вывод сообщения на экран delay(wait); } } Расписывать код не вижу смысла. Он и так хорошо прокомментирован. Однако есть некоторые особенности, о которых стоит упомянуть.
Примечание. Важно. Стандартная библиотека Adafruit_GFX изначально поддерживает только английские шрифты, поэтому ребята из России постарались и переписали библиотеку добавив русские шрифты и всякие вкусняшки. Все библиотеки и скетч доступны у меня на странице в GitHUB .
Кусок кода для работы с com-портом, нужен для того чтобы оперативно менять текст сообщения выводимого на светодиодный модуль. Однако он нужен нам не только для этого. В дальнейшем посредством этой функции мы свяжем наш и бегущую строку на Arduino.
Для работы с символьными графическими дисплеями предлагаем воспользоваться библиотекой LiquidCrystal которая входит в стандартный набор Arduino IDE и предназначена для работы по 8-битному (4-битному) параллельному интерфейсу. Если Ваш дисплей подключается к Arduino по шине I2, то Вам нужно установить библиотеку LiquidCrystal_I2C (большинство функций которой повторяют функции первой библиотеки).
Поддерживаемые дисплеи:
Дисплей | Подключение и инициализация |
---|---|
LCD1602 - символьный дисплей (16x02 символов), |
#include [ , 8 , 9 , 10 , 11 ]); void setup(){ lcd.begin(16 , 2); } // Пояснение:
|
с интерфейсом 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(); } // Пояснение: |
LCD2004 - символьный дисплей (20x04 символов), с параллельным интерфейсом (синий) |
#include LiquidCrystal lcd(2 , 3 , 4 , 5 , 6 , 7 [ , 8 , 9 , 10 , 11 ]); void setup(){ lcd.begin(20 , 4); } // Пояснение: // Если используется 8 проводов шины данных, то указываем их все |
LCD2004 I2C - символьный дисплей (20x04 символов), с интерфейсом I2C (синий) |
#include #include LiquidCrystal_I2C lcd(0x27 или 0x3F , 20 , 4); void setup(){ lcd.init(); } // Пояснение: |
#1 Пример
Выводим надпись на дисплей LCD1602 подключённый по шине I2C. Для работы с дисплеем LCD2004 нужно изменить 3 строку на LiquidCrystal_I2C lcd(0x27,20,4);
#include
#2 Пример
Выводим надпись на дисплей LCD1602 подключённый по 4-битной параллельной шине. Для работы с дисплеем LCD2004 нужно изменить 5 строку на lcd.begin(20, 4);
#include
#3 Пример
Выводим надпись «Русский язык» на дисплей LCD1602 подключённый по шине I2C:
#include
#4 Пример
Выводим время прошедшее после старта на дисплей LCD1602 подключённый по шине I2C:
#include
Функции, общие для библиотек 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:
|
Параметр:
|
// Для параллельной шины из 4 проводов:
#include LiquidCrystal lcd( RS , E , D4 , D5 , D6 , D7 ); void setup(){ lcd.begin( 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 ,
);
Инициализация дисплея с указанием размеров экрана и символов. |
Параметр:
|
Функции управления дисплеем:
display();
Включает дисплей после того как он был выключен функцией noDisplay. |
Примечание: Функция выполняется быстро и без изменений в ОЗУ дисплея. |
noDisplay();
Выключает дисплей. Данные на дисплее не будут отображаться до вызова функции display, но и не сотрутся из памяти ОЗУ, а после вызова функции display, опять будут отображаться. |
Примечание: Функция выполняется быстро и без изменений в ОЗУ дисплея. |
scrollDisplayLeft();
Сдвигает координаты дисплея на один столбец влево. |
|
scrollDisplayRight();
Сдвигает координаты дисплея на один столбец вправо. Постоянный вызов данной функции создаст эффект бегущей строки. Координаты сдвигаются как для имеющейся на дисплее информации, так и для той, которая будет выведена после. |
Примечание: Функция выполняется без изменений ОЗУ дисплея. Если вызвать функцию 40 раз подряд, то координата вернётся в изначальную точку |
clear();
Очистка дисплея с установкой курсора в положение 0,0. Информация имеющаяся на дисплее безвозвратно сотрётся. |
Примечание: Занимает много времени. |
backlight();
Включение подсветки дисплея. |
|
noBacklight();
Выключение подсветки дисплея. |
Примечание: Функция реализована только в библиотеке LiquidCrystal_I2C. |
setBacklight(flag );
Управление подсветкой (вместо функций noBacklight и backlight). |
Параметр:
|
Функции управления курсором:
setCursor(col ,
row );
Установка курсора в указанную позицию. |
Параметр:
|
home();
Установка курсора в позицию 0,0. Работает как функция setCursor(0,0); |
Примечание: Занимает много времени. |
blink();
Включение мигающего курсора. |
Примечание: Курсор занимает всё поле символа и мигает с частотой около 1 Гц, в той позиции где он был установлен ранее. |
noBlink();
Выключение мигающего курсора. |
Примечание: Курсор становится невидим, но его позиция сохраняется. |
cursor();
Включение подчеркивания курсора. |
Примечание: Курсор принимает вид символа подчёркивания и находится в той позиции, где он был установлен ранее. |
noCursor();
Выключение подчеркивания курсора. |
Примечание: Курсор становится невидим, но его позиция сохраняется. |
Функции указывающие направление и выравнивание:
leftToRight();
Указывает, что после каждого нового символа, положение курсора должно сдвигаться на один столбец вправо. |
Примечание: Если вывести текст "abc" на дисплее отобразится "abc" и текст будет находиться правее от изначального положения курсора. (Как обычно) |
rightToLeft();
Указывает, что после каждого нового символа, положение курсора должно сдвигаться на один столбец влево. |
Примечание: Если вывести текст "abc" на дисплее отобразится "cba" и текст будет находиться левее от изначального положения курсора. (Письменность справа налево) |
noAutoscroll();
Указывает, что в дальнейшем, текст нужно выравнивать по левому краю от изначальной позиции курсора. |
Примечание: если установить курсор в позицию 10,0 и вывести текст, то в данной позиции будет находиться первый символ выведенного текста. (Как обычно) |
autoscroll();
Указывает, что в дальнейшем, текст нужно выравнивать по правому краю от изначальной позиции курсора. |
Примечание: если установить курсор в позицию 10,0 и вывести текст, то в данной позиции будет находиться курсор. (Координаты дисплея будут сдвинуты влево, как будто Вы вызвали функцию scrollDisplayLeft столько раз, сколько букв в выведенном тексте) |
Функции ввода текста и символов:
createChar(num,array);
Запись пользовательского символа в CGRAM дисплея под указанным номером. Если Вы хотите вывести текст (функцией print) в котором должен находиться установленный Вами символ, укажите слэш и номер под которым был записан этот символ: print("C\1MBO\2"). |
Параметр:
|
print(text);
Вывод текста, символов или цифр на экран дисплея. |
Параметр:
|
Бегущая строка в LCD на HD44780.
Поиск "готового решения" бегущей строки на Си результата не дал. Поэтому пришлось делать самому.
Этот "кусок" кода позволяет выводить бегущую строку (справа-налево), в любом месте и с использованием любого количества знакомест, в LCD индикаторах с контроллером HD44780 или аналогичном.
Первое, на чем нужно остановиться, это то, что язык Си не позволяет работать со строками "напрямую". То есть невозможно скопировать символ из одной строки в другую при помощи оператора присваивания (= )... для этого нужно использовать специальную функцию strncpy() . Вообще говоря, для работы со строками в Си используются несколько функций. В самоМучителях использованию этих функций посвящена отдельная глава. В Help"e на CV_AVR описание функций для работы со троками находится в разделе " String Functions" . Прототипы этих функций находятся в файле string.h .
"...исходная строка..." - строка символы из которой нужно выводить в "бегущей" строке;
"...отображаемые символы..." - собственно "бегущая строка".
Для организации бегущей строки выбран такой алгоритм:
1. Отображаемые символы сдвигаются справо налево. Крайний левый при этом "теряется".
2. После сдвига, в крайний правый символ копируется очередной символ из исходной строки.
3. При достижении конца исходной строки, очередным становится первый символ исходной строки.
Для сдвига символов - для сдвигаемой ячейки считывается код символа из экранного ОЗУ (DDRAM) HD44780 и записывается в левостоящую ячейку ОЗУ.
Согласно DataSheet на HD44780 левый символ верхней строки имеет адрес в DDRAM - 0x00, а левый символ нижней строки - 0x40. При этом нужно помнить, что для того чтобы обратиться именно к экранному ОЗУ (а не к ОЗУ знакогенератора) необходимо чтобы бит RS был равен 1 (RS является старшим битом в байте адреса см.DataSheet).
В итоге получаем, что для того чтобы "обратиться" ко второму слева символу верхней строки необходимо "работать" с адресом 0x01 | 0x80 = 0x81 .
Функции записи и чтения "внутреннего содержимого" HD44780 есть в библиотеке (прототипы в lcd.h ).... поэтому..собственно программа:
/* для CV_AVR В данном примере бегущая строка выводиться в разряды с 8 (0xC7) по 16 нижней строки 16-ти разрядного индикатора. . ...... #include unsigned char n_sim=1,m_end=43; //43 - дина строки в примере beg_stroka(){ // сдвиг бегущей строки if(beg_str){ // запись очередного символа в крайний правую позицию lcd_gotoxy(15,1); |
Глоссарий: n_sim - указатель положения текущего символа в исходной строке; m_end - общее количество символов в исходной строке; beg_str - бит "разрещающий" сдвиг. C его помощью можно регулировать скорость "бега"; ish_str - исходная строка. |
Скорее всего, в каждом из существующих компиляторов Си имеются библиотечные функции для работы с HD44780. Поэтому "переделать" программу под "свой" компилятор не составит труда.
Исходную строку я "готовлю" при помощи известной утилиты "HD44780.exe". При ее использовании, в коментариях, указывается длина строки: "/* Maximum length of a line: 43 byte */"