В процессе работы над новой версией библиотеки вдруг стало понятно, что библиотека LCD быть выполнена автономно отдельно от основной библиотеки - из нее перенесены нужные фрагменты кода. Некоторое дублирование кода, но не значительное.
Выкладываю библиотеку с тестовым примером - любители С++ могут почитать и использовать вне FLProg или создать свои блоки по собственному вкусу.
Библиотека поддерживает до 15-ти одновременно работающих дисплея (на четырех проверялось), оптимизированы посылки в результате чего существенно сокращена нагрузка на шину i2c.
Блок контроля имеет собственный тактовый генератор 100мс, который используется для периодической запуска блоков записи в дисплей.
Сильно оптимизирована работа с битовыми переменными, что позволило существенно ускорить работу.
Оптимизировано использование памяти - и той, и той требуется меньше.
Вывод цифровых переменных может сопровождаться заголовком, который также как и переменная имеет свой размер и параметр выравнивания в выводимом поле. И прочее, прочее...
Работает на AVR328,MEGA2560,ESP8266(совместно с Wi-Fi не тестировалось),ESP32,STM32 - на фото показано.
Тест выводит 2 моргающих символа, два меняющихся символа (в конце строк), четыре меняющихся переменных с заголовками.
Результаты в режиме работы - AVR328 -60 мкс, ESP8266-19 мкс, ESP32-4,5мкс, STM32F103C-14мкс.
Во время передачи в i2c посылка примерно 550мкс на полбайта - это определяется скоростью шины i2c и тем, что в Arduino библиотека Wire не использует возможности аппаратного прерывания, но зато там свои плюсы...
Скетч теста относительно небольшой.
//======================================================
// Тест вывода на дисплей в фоновом режиме
// Библиотека "RT_HW_LCD_HD44780.h"
// Адрес дисплея =63(можно поменять),
// Адрес контрольного пина->AVR328,MEGA2560,DUE=13; ESP8266,ESP32=2; STM103C=PC13
// Устойчиво поддерживает горячее переподключение.
//======================================================
#include "RT_HW_LCD_HD44780.h"
//++++++++Выбор параметров под тип контроллера
#if defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__SAM3X8E__)
#define pinControl 13
#elif defined(ESP8266) || defined(ESP32)
#define pinControl 2
#elif defined(_BOARD_GENERIC_STM32F103C_H_)
#define pinControl PC13
#else
#define pinControl 13
#endif
//==================================================================
RT_HW_LCD_HD44780_DEVICE z1;
RT_HW_LCD_HD44780_DATA_CHAR star1,star2, char1, char2;
RT_HW_LCD_HD44780_DATA_INT16 int1, int2, int3, int4, float1, float2;
byte eventBack;
//---------------------------
uint8_t addrLCD=63; //----Адрес дисплея
uint8_t cnt1,cnt2, cntBack, work_star1, work_star2, work_char1, work_char2, work_int1, work_int2, work_int3, work_int4, work_float1, work_float2; //--рабочие регисты
int16_t v1,v2,v3,v4; //--Выводимые регистры int
char vChar1,vChar2; //--Выводимые символы
bool blink;
//--------------------------------------------
void setup() {pinMode(pinControl,OUTPUT);}
//--------------------------------------------
void loop() {
//======Системная часть
blink=!blink; digitalWrite(pinControl,blink);
cntBack++; if(cntBack>50) {cntBack=0; eventBack=1;} else eventBack=0; //--Формирование флага фоновой задачи
//======Фоновая задача №1
if(eventBack){
//++++ Блок инициализации и контроля дисплея begin(). Параметры ->lcd,id,col,row,addr;
switch(z1.dir){default: case 0: Wire.begin(); RT_HW_Lcd_hd44780.device_setID(1,z1,16,2,addrLCD); break; case 1: break; case 2: RT_HW_Lcd_hd44780.begin(z1); break;}
//++++ Подготовка параметров для вывода на дисплей (события event каждые 100 мс)
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_star1++; if(work_star1 > 3) {work_star1=0; star1.run=2; }}
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_star2++; if(work_star2 > 9) {work_star2=0; star2.run=2; }}
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_int1++; if(work_int1 > 5) {work_int1=0; int1.run=2; v1=v1+7; if(v1>127) v1=0;}}
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_int2++; if(work_int2 > 7) {work_int2=0; int2.run=2; v2=v2+1; if(v2>40) v2=0;}}
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_int3++; if(work_int3 > 9) {work_int3=0; int3.run=2; v3=v3+1; if(v3>20) v3=0;}}
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_int4++; if(work_int4 >12) {work_int4=0; int4.run=2; v4=v4+1; if(v4>10) v4=0;}}
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_char1++; if(work_char1 > 5) {work_char1=0; char1.run=2; vChar1='1'+cnt1; cnt1++; if(cnt1>10) cnt1=0;}}
if(RT_HW_Lcd_hd44780.prt[1]->event) {work_char2++; if(work_char2 >10) {work_char2=0; char2.run=2; vChar2='A'+cnt2; cnt2++; if(cnt2>10) cnt2=0;}}
//++++ Блоки вывода мерцающих символов. Параметры ->lcd,id,col,row,signF,signS
switch(star1.dir){default: case 0:RT_HW_Lcd_hd44780.setID_char(1,star1, 1,1,'B','*',' '); break; case 1:break; case 2:RT_HW_Lcd_hd44780.print_char(star1); break;};
switch(star2.dir){default: case 0:RT_HW_Lcd_hd44780.setID_char(1,star2, 1,2,'B','#',' '); break; case 1:break; case 2:RT_HW_Lcd_hd44780.print_char(star2); break;};
//++++ Блоки вывода меняющихся символов. Параметры ->lcd,id,col,row
switch(char1.dir){default: case 0:RT_HW_Lcd_hd44780.setID_char(1,char1,16,1); break; case 1:break; case 2:RT_HW_Lcd_hd44780.print_char(char1,vChar1); break;};
switch(char2.dir){default: case 0:RT_HW_Lcd_hd44780.setID_char(1,char2,16,2); break; case 1:break; case 2:RT_HW_Lcd_hd44780.print_char(char2,vChar2); break;};
//++++ Блоки вывода меняющихся int16 с заголовками. Параметры ->lcd,id,col,row,aligHead,lenHead,head,aligVal,modeVal,lenVal
switch(int1.dir) {default: case 0:RT_HW_Lcd_hd44780.setID_int16(1,int1, 2,1,'L',3,"t1=",'L','D',3); break; case 1:break; case 2: RT_HW_Lcd_hd44780.print_int16(int1,v1); break;};
switch(int2.dir) {default: case 0:RT_HW_Lcd_hd44780.setID_int16(1,int2, 8,1,'L',3,"h1=",'L','H',3); break; case 1:break; case 2: RT_HW_Lcd_hd44780.print_int16(int2,v2); break;};
switch(int3.dir) {default: case 0:RT_HW_Lcd_hd44780.setID_int16(1,int3, 2,2,'L',3,"t2=",'L','T',2); break; case 1:break; case 2: RT_HW_Lcd_hd44780.print_int16(int3,v3); break;};
switch(int4.dir) {default: case 0:RT_HW_Lcd_hd44780.setID_int16(1,int4, 8,2,'L',3,"h2=",'L','b',4); break; case 1:break; case 2: RT_HW_Lcd_hd44780.print_int16(int4,v4); break;};
} //--END if(eventBack)
//====================================================
} //--END LOOP
============================
Результатом сами очень довольны.
Тест в примерах библиотеки.