Почему ломаю? Схема один в один как у ТС, только катоды через ULN. Секундомер на двух регистрах работает на любых из трех. Изменение таймера с двух на три проходит, а дальше затык. Программа последняя, приведенная в топике, один в один, не работает с теми же симптомами. Буду дальше разбираться.
Сильно помогло бы, если в программе велосипед в лупе привели бы образец как цифру выводить.
Не очень понял почему такой щенячий восторг. Число 666 пишется нормально, но если попробовать записать другое число, с разными цифрами, то все - засвечивается абракадабра. Посмотрел еще раз внимательно на велосипед. Центральная ось рисуется не на центральном регистре, а на крайних.
Не очень понял почему такой щенячий восторг. Число 666 пишется нормально, но если попробовать записать другое число, с разными цифрами, то все - засвечивается абракадабра. Посмотрел еще раз внимательно на велосипед. Центральная ось рисуется не на центральном регистре, а на крайних.
ты скетч опубликуешь или будешь продолжать мосг ебать?
Ну, Вас просили ещё подробности об индикаторе и схему подключения. И кстати, я не понял фразы "работает на любых двух регистрах", поясните. Также не пноял "не показывает нормально". - а как показывает?
Не за что, только заметьте, я дважды (здесь и здесь) просил Вас дать мне подробности об индикаторе (например ссылку на товар у продавца или модель) и схему. Вы игнорировали. дали, давно б разобрались. Хотя и лучше, что Вы сами всё раскопали. Это полезнее, чем если бы я за Вас это сделал.
Виртуальные экраны это вот что такое. Вот представьте ради-часы или автомагнитолу - у этих устройств частенько один и тот ;е экран используется для разных целей. То показывает время, то частоту радиостанции, то настройки громкости и баланса и т.п. в зависимости от нажатия каких-то кнопок.
Гораздо проще скзать, что к одному физическому экрану у меня привязано N виртуальных. На каждую функцию свой собственный виртуальный экран. Тогда допустим, часы ничего не проверяют, а тупо выводят время на свой собственный экран всегда. Тоже самое термометр ничего не проверяет, а просто всегда выводит температуру на свой собственный экран. То есть всё упростилось. Всё выглядит так, как будто у них в вправду собственные экраны. Они (часы или термометр) вообще-то понятия не имеют и знать не хотят, что именно сейчас показывается на реальном экране - они выводят свои данные на виртуальный экран и не парятся ни о чём.
Ну и есть функция, которая по каким-то нажатиям кнопок или ещё по каким командам, просто переключает физический экран с одного виртуального на другой.
Вот допустим, Вы посмотрели температуру. Затем экран переключился на время. Но термометр каждую минуту исправно пишет новую температуру на свой виртуальный экранчик, которого никто видит. Затем Вы нажимаете кнопку, физически экран переходит с виртуального экрана часов на виртуальных экран термометра и Вы видите новую, текущую температуру (он же её в виртуальном экране регулярно обновлял). При этом ни часы, ни термометр не знают о том, что Вы переключали физический экран с одного виртуального на другой - они вообще про физический экран ничего не знают - они пишут в свои виртуальные и спят спокойно.
Концепция понятна?
реализуется это гораздо проще и короче, чем объясняется. Виртуальный экран - это просто переменная типа нашей numberToShow - своя для каждой функции. А переключатель - это программа из трёх строк, которая определяет какую из этих "numberToShow" отображать на физическом экране. Вот и вся реализация.
Ещё вопрос о функции вывода на печать на реальный дисплей.
Получается, что при таком подходе приходится полностью весь дисплей обновлять (перерисовывать/перепечатывать) на каждом такте/раз в N-тактов? Или как быть? У меня сейчас в проекте данные обновляются на дисплее только если они изменились. При подходе с виртуальными дисплеями такое реализуемо?
Не хотелось мудрсвовать но ладно. Есть код прикладной. Ну тот когда надо поменять контент программы сообщения, место и порядок надписей. А есть все остальное. Остальное тоже не однородно. Работа с виртуальными экранами это уровень обработки данных. Что то похожее на String. Может в большой упаковке, а может в виде рассыпи отдельных функций и структуры приведённой вышн. А есть канальный уровень. Это код который эти данные забрасывать уже на чип дисплея.
Не хочу показаться камнем без острых углов, но я все же не совсем понял как канальный уровень поймёт, что на прикладном уровне произошли изменения в отображаемой информации и надо дисплей перерисовать?
Как я это вижу? Флаг - «Что то изменилось, надо бы перерисовать дисплей». Его же можно и в примере с меняющимися часами и температурой использовать для смены «кадра». Не?
Ну вспомни библиотеку для лсд1602 и2с. Там гибрид. Что туда напечатано. То на экран и отправлено. Но если сделать промежуточный объект. И туда печатать. Конечно на экране ничего нет. Что бы было надо создавать ещё объект который будет настраивать канал и2с и чип дисплея. А когда надо показать то даётся команда отправить этот виртуальный дисплей на отображение реального.
Все зависит от задачи, я предпочитаю сохранять данные от разных функций в памяти, а уже отдельная часть логики решает что и когда выводить.
PS. Мало с дисплеями работал, а меню вообще страдание, все таки железка которая сама решает как жить программируется проще. Впрочем дело вкуса.
Я iic не использую, мне и так пинов хватает.
Собственно заинтересовала идея виртуальных дисплеев, но не хочется на каждом такте дисплей перерисовывать. А так как в программировании я ещё как котёнок, хотелось бы у более опытных участников форума узнать по максимуму.
Информация с датчиков приходит асинхроно. Да и датчиков море. Вот и приходится хранить все данные. Вдруг вот как раз их надо показать на экране. А так напечатал на экране значение и забыл. Нужный экран всегда готов к показу. Код упрощается. Да и по памяти перерасход не большой.
Вы что ему таймер ломаете? Если нормально при одинаковых цифрах, то похоже ...
В общем, хотите разговора, а не флуда, подробности об индикаторе, схему подклюучения и скетч в студию.
Почему ломаю? Схема один в один как у ТС, только катоды через ULN. Секундомер на двух регистрах работает на любых из трех. Изменение таймера с двух на три проходит, а дальше затык. Программа последняя, приведенная в топике, один в один, не работает с теми же симптомами. Буду дальше разбираться.
Сильно помогло бы, если в программе велосипед в лупе привели бы образец как цифру выводить.
Программа с велосипедом работает.
Программа с велосипедом работает.
О-О////
Не очень понял почему такой щенячий восторг. Число 666 пишется нормально, но если попробовать записать другое число, с разными цифрами, то все - засвечивается абракадабра. Посмотрел еще раз внимательно на велосипед. Центральная ось рисуется не на центральном регистре, а на крайних.
Не очень понял почему такой щенячий восторг. Число 666 пишется нормально, но если попробовать записать другое число, с разными цифрами, то все - засвечивается абракадабра. Посмотрел еще раз внимательно на велосипед. Центральная ось рисуется не на центральном регистре, а на крайних.
ты скетч опубликуешь или будешь продолжать мосг ебать?
В смысле сделать копию любого скетча для трехрегистрового индикатора из этой темы? Могу даже пины воткнуть в те же адреса. Тоже мысль.
Для двух разрядного все работают, для трех ни один.
Центральная ось рисуется не на центральном регистре, а на крайних.
Интересно девки пляшут. У велосипеда должна быть центральная ось в центре, а по краям педали крутятся в противофазе.
И в центровом регистре тоже педали крутятся без оси. Но больше всего смущает цифра 666.
001
//
002
//
003
// Определение пинов для сегментов
004
// (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
005
#define PIN_A 7
006
#define PIN_B 9
007
#define PIN_C 5
008
#define PIN_D 3
009
#define PIN_E 2
010
#define PIN_F 8
011
#define PIN_G 6
012
#define PIN_DP 4
013
014
#define PIN_DIG0 15
015
#define PIN_DIG1 16
016
#define PIN_DIG2 14
017
018
//
019
// Определение масок для сегментов
020
//
021
#define MASK_A (1 << 0)
022
#define MASK_B (1 << 1)
023
#define MASK_C (1 << 2)
024
#define MASK_D (1 << 3)
025
#define MASK_E (1 << 4)
026
#define MASK_F (1 << 5)
027
#define MASK_G (1 << 6)
028
#define MASK_DP (1 << 7)
029
030
//
031
// Определение цифр через маски сегментов
032
//
033
#define D0 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F)
034
#define D1 (MASK_B | MASK_C)
035
#define D2 (MASK_A | MASK_B | MASK_G | MASK_D | MASK_E)
036
#define D3 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_G)
037
#define D4 (MASK_B | MASK_C | MASK_G | MASK_F)
038
#define D5 (MASK_A | MASK_C | MASK_D | MASK_F | MASK_G)
039
#define D6 (MASK_A | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
040
#define D7 (MASK_A | (MASK_B | MASK_C))
041
#define D8 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
042
#define D9 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_F | MASK_G)
043
044
045
046
//
047
// Функция устанавливает по маске - параметру (HIGH-горит, LOW-не горит)
048
//
049
void
setRawSegments(
const
int8_t mask) {
050
digitalWrite(PIN_A, mask & MASK_A);
051
digitalWrite(PIN_B, mask & MASK_B);
052
digitalWrite(PIN_C, mask & MASK_C);
053
digitalWrite(PIN_D, mask & MASK_D);
054
digitalWrite(PIN_E, mask & MASK_E);
055
digitalWrite(PIN_F, mask & MASK_F);
056
digitalWrite(PIN_G, mask & MASK_G);
057
digitalWrite(PIN_DP, mask & MASK_DP);
058
}
059
060
//
061
// Функция устанавливает все сегменты для цифры-параметра (HIGH-горит, LOW-не горит)
062
//
063
void
setSegments(
const
int8_t digit) {
064
static
const
uint8_t all_digits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 };
065
setRawSegments(all_digits[digit]);
066
}
067
068
//
069
// Функция зажигает цифру d в позиции pos
070
// При этом ставит пин соответсвующий позиции pos в LOW
071
//
072
void
showDigit(
const
uint8_t d,
const
uint8_t pos) {
073
static
const
uint8_t all_postions[] = { PIN_DIG0, PIN_DIG1};
074
for
(register uint8_t i = 0; i <
sizeof
(all_postions) /
sizeof
(all_postions[0]); i++) {
075
digitalWrite(all_postions[i], pos != i);
076
}
077
setSegments(d);
078
}
079
volatile unsigned numberToShow =68;
080
// #define PRESACLER (1 << CS11) // Соответствует делителю частоты 8
081
//#define TICKS ((uint16_t)(65536ul - 20000ul)) // Оставляет 20000 тиков до переполнения
082
#define PRESACLER (1<<CS11)|(1<<CS10) // Соответствует делителю частоты 64
083
#define TICKS ((uint16_t)(65536ul - 1666ul)) // Оставляет 1666 тиков до переполнения ( 64*1666/16000 == 6,664 миллисекунды)
084
085
086
087
//
088
// Инициализация таймера. делается один раз
089
//
090
void
setupTimer2(
void
) {
091
PRR &= ~(1 << PRTIM1);
// Убедимся, что таймер 1 не отключен
092
TCCR1A = 0;
// Установим Normal режим
093
TCCR1B = PRESACLER;
// Установим делитель частоты
094
TCNT1 = TICKS;
// Установим счётчик
095
TIMSK1 |= (1 << TOIE1);
// Разрешим прерывание по переполнению
096
TIFR1 = 1;
// Очистим Очистим флаг прерывания (если он взведён)
097
}
098
099
//
100
// Обработка прерывания по переполнению
101
//
102
ISR(TIMER1_OVF_vect) {
103
TCNT1 = TICKS;
// Установим счётчик для следующего прерывания
104
//
105
// Покажем очередную цифру, как мы это делали раньше
106
//
107
static
uint8_t currentDigit = 0;
108
109
const
uint8_t digitToShow = (currentDigit) ? numberToShow / 10 : numberToShow % 10;
110
showDigit(digitToShow, currentDigit);
111
currentDigit = (currentDigit + 1) % 2;
// В следующий раз показываем другую цифру
112
113
114
}
115
116
//
117
// Всё, что выше - это своя жизнь. От основной программы требуется только
118
// положить число для показа в numberToShow и оно будет показываться.
119
// Больше основная программа ни о чём не заботится
120
//
121
///////////////////////////////////////////////////////////////////////////////////
122
123
void
setup
() {
124
setupTimer2();
125
pinMode(2, OUTPUT);
126
pinMode(3, OUTPUT);
127
pinMode(4, OUTPUT);
128
pinMode(5, OUTPUT);
129
pinMode(6, OUTPUT);
130
pinMode(7, OUTPUT);
131
pinMode(8, OUTPUT);
132
pinMode(9, OUTPUT);
133
pinMode(14, OUTPUT);
134
pinMode(15, OUTPUT);
135
pinMode(16, OUTPUT);
136
}
137
138
139
//
140
// Здесь реализован простейший секундомер
141
//
142
void
loop
() {
143
static
int8_t counter = 0;
144
numberToShow = counter;
// теперь это число будет показываться
145
counter = (counter + 1) % 100;
146
delay(1000);
147
}
001
#define PIN_A 7
002
#define PIN_B 9
003
#define PIN_C 5
004
#define PIN_D 3
005
#define PIN_E 2
006
#define PIN_F 8
007
#define PIN_G 6
008
#define PIN_DP 4
009
010
#define PIN_DIG0 14
011
#define PIN_DIG1 15
012
#define PIN_DIG2 16
013
//
014
// Определение пинов для сегментов
015
// (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
016
017
//
018
#define PRESACLER (1<<CS11)|(1<<CS10) // Соответствует делителю частоты 8
019
#define TICKS ((uint16_t)(65536ul - 1666ul)) // Оставляет 20000 тиков до переполнения
020
021
022
023
//
024
// Определение пинов для цифр
025
// (поставьте Ваши пины, у меня мелкий экран и плохо видно какие там у Вас)
026
//
027
028
//
029
// Определение масок для сегментов
030
//
031
#define MASK_A (1 << 0)
032
#define MASK_B (1 << 1)
033
#define MASK_C (1 << 2)
034
#define MASK_D (1 << 3)
035
#define MASK_E (1 << 4)
036
#define MASK_F (1 << 5)
037
#define MASK_G (1 << 6)
038
#define MASK_DP (1 << 7)
039
040
//
041
// Определение цифр через маски сегментов
042
//
043
#define D0 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F)
044
#define D1 (MASK_B | MASK_C)
045
#define D2 (MASK_A | MASK_B | MASK_G | MASK_D | MASK_E)
046
#define D3 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_G)
047
#define D4 (MASK_B | MASK_C | MASK_G | MASK_F)
048
#define D5 (MASK_A | MASK_C | MASK_D | MASK_F | MASK_G)
049
#define D6 (MASK_A | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
050
#define D7 (MASK_A | (MASK_B | MASK_C))
051
#define D8 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_E | MASK_F | MASK_G)
052
#define D9 (MASK_A | MASK_B | MASK_C | MASK_D | MASK_F | MASK_G)
053
054
volatile unsigned numberToShow = 0;
055
056
//
057
// Функция устанавливает по маске - параметру (HIGH-горит, LOW-не горит)
058
//
059
void
setRawSegments(
const
int8_t mask) {
060
digitalWrite(PIN_A, mask & MASK_A);
061
digitalWrite(PIN_B, mask & MASK_B);
062
digitalWrite(PIN_C, mask & MASK_C);
063
digitalWrite(PIN_D, mask & MASK_D);
064
digitalWrite(PIN_E, mask & MASK_E);
065
digitalWrite(PIN_F, mask & MASK_F);
066
digitalWrite(PIN_G, mask & MASK_G);
067
digitalWrite(PIN_DP, mask & MASK_DP);
068
}
069
070
//
071
// Функция устанавливает все сегменты для цифры-параметра (HIGH-горит, LOW-не горит)
072
//
073
void
setSegments(
const
int8_t digit) {
074
static
const
uint8_t all_digits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9};
075
setRawSegments(all_digits[digit]);
076
}
077
078
//
079
// Функция зажигает цифру d в позиции pos
080
// При этом ставит пин соответсвующий позиции pos в LOW
081
//
082
void
showDigit(
const
uint8_t d,
const
uint8_t pos) {
083
static
const
uint8_t all_postions[] = { PIN_DIG0, PIN_DIG1, PIN_DIG2 };
084
for
(register uint8_t i = 0; i <
sizeof
(all_postions) /
sizeof
(all_postions[0]); i++) {
085
digitalWrite(all_postions[i], pos != i);
086
}
087
setSegments(d);
088
}
089
090
//
091
// Инициализация таймера. делается один раз
092
//
093
void
setupTimer2(
void
) {
094
PRR &= ~(1 << PRTIM1);
// Убедимся, что таймер 1 не отключен
095
TCCR1A = 0;
// Установим Normal режим
096
TCCR1B = PRESACLER;
// Установим делитель частоты
097
TCNT1 = TICKS;
// Установим счётчик
098
TIMSK1 |= (1 << TOIE1);
// Разрешим прерывание по переполнению
099
TIFR1 = 1;
// Очистим Очистим флаг прерывания (если он взведён)
100
}
101
//
102
// Обработка прерывания по переполнению
103
//
104
ISR(TIMER1_OVF_vect) {
105
TCNT1 = TICKS;
// Установим счётчик для следующего прерывания
106
//
107
// Покажем очередную цифру, как мы это делали раньше
108
//
109
static
uint8_t currentDigit ;
110
uint8_t digitToShow ;
111
if
(currentDigit == 0) digitToShow = numberToShow / 100;
112
else
if
(currentDigit == 1) digitToShow = (numberToShow % 100) / 10;
113
else
digitToShow = numberToShow % 10;
114
showDigit(digitToShow, currentDigit);
115
currentDigit = (currentDigit + 1)%3;
// В следующий раз показываем другую цифру
116
117
}
118
119
//
120
// Всё, что выше - это своя жизнь. От основной программы требуется только
121
// положить число для показа в numberToShow и оно будет показываться.
122
// Больше основная программа ни о чём не заботится
123
//
124
///////////////////////////////////////////////////////////////////////////////////
125
126
127
void
setup
() {
128
setupTimer2();
129
// ... задайте все pinMode как раньше
130
pinMode(2, OUTPUT);
131
pinMode(3, OUTPUT);
132
pinMode(4, OUTPUT);
133
pinMode(5, OUTPUT);
134
pinMode(6, OUTPUT);
135
pinMode(7, OUTPUT);
136
pinMode(8, OUTPUT);
137
pinMode(9, OUTPUT);
138
pinMode(14, OUTPUT);
139
pinMode(15, OUTPUT);
140
pinMode(16, OUTPUT);
141
142
143
144
}
145
146
//
147
// я считаю, что нулевая цмфра слева (единицы), а первая справа (десятки)
148
// если у Вас по-другому - поменяйте.
149
//
150
void
loop
() {
151
152
153
numberToShow = 123;
154
155
}
//
156
//
Первый код с секундомером работает на любых двух регистрах. Второй если цифры одинаковые, показывает нормально, если разные - нет.
Ну, Вас просили ещё подробности об индикаторе и схему подключения. И кстати, я не понял фразы "работает на любых двух регистрах", поясните. Также не пноял "не показывает нормально". - а как показывает?
На любых - программно менял номера пинов. Таким образом проверял что все подключено правильно.
Почти все сегменты светятся, но с разной яркостью.
В велосипеде , вроде бы, сегменты высвечиваются наооборот.
Из того что пробовал. Если принудительно в функции, которую обрабатывает таймер, написать цифру в каком-нибудь сегменте - исправно пишет.
Разобрался. Общий катод, поэтому в соответствующем месте надо ставить 1, а не 0.
Перетащил из обработчика в лоор , поставил большой делай, сразу увидел.
Спасибо ЕвгенийП за науку.
Не за что, только заметьте, я дважды (здесь и здесь) просил Вас дать мне подробности об индикаторе (например ссылку на товар у продавца или модель) и схему. Вы игнорировали. дали, давно б разобрались. Хотя и лучше, что Вы сами всё раскопали. Это полезнее, чем если бы я за Вас это сделал.
И это тоже заметил. Работающий секундомер заставлял в этом сомневаться.
Виртуальные экраны это вот что такое. Вот представьте ради-часы или автомагнитолу - у этих устройств частенько один и тот ;е экран используется для разных целей. То показывает время, то частоту радиостанции, то настройки громкости и баланса и т.п. в зависимости от нажатия каких-то кнопок.
Гораздо проще скзать, что к одному физическому экрану у меня привязано N виртуальных. На каждую функцию свой собственный виртуальный экран. Тогда допустим, часы ничего не проверяют, а тупо выводят время на свой собственный экран всегда. Тоже самое термометр ничего не проверяет, а просто всегда выводит температуру на свой собственный экран. То есть всё упростилось. Всё выглядит так, как будто у них в вправду собственные экраны. Они (часы или термометр) вообще-то понятия не имеют и знать не хотят, что именно сейчас показывается на реальном экране - они выводят свои данные на виртуальный экран и не парятся ни о чём.
Ну и есть функция, которая по каким-то нажатиям кнопок или ещё по каким командам, просто переключает физический экран с одного виртуального на другой.
Вот допустим, Вы посмотрели температуру. Затем экран переключился на время. Но термометр каждую минуту исправно пишет новую температуру на свой виртуальный экранчик, которого никто видит. Затем Вы нажимаете кнопку, физически экран переходит с виртуального экрана часов на виртуальных экран термометра и Вы видите новую, текущую температуру (он же её в виртуальном экране регулярно обновлял). При этом ни часы, ни термометр не знают о том, что Вы переключали физический экран с одного виртуального на другой - они вообще про физический экран ничего не знают - они пишут в свои виртуальные и спят спокойно.
Концепция понятна?
реализуется это гораздо проще и короче, чем объясняется. Виртуальный экран - это просто переменная типа нашей numberToShow - своя для каждой функции. А переключатель - это программа из трёх строк, которая определяет какую из этих "numberToShow" отображать на физическом экране. Вот и вся реализация.
Ну, мы до этого ещё доберёмся если интересно.
Мне интересна реализация в примере, если можно.
ну это ж тривиально, не?
несколько структур
{
char Line1[16];
char Line2[16];
}
и актуальный указатель для вывода одной из них. Сам не догадаешь?
То есть так банально? Потом на реальном дисплее просто печатать обе эти линии, при необходимости?
Я думал что то по мудрее....
Ещё вопрос о функции вывода на печать на реальный дисплей.
Получается, что при таком подходе приходится полностью весь дисплей обновлять (перерисовывать/перепечатывать) на каждом такте/раз в N-тактов? Или как быть? У меня сейчас в проекте данные обновляются на дисплее только если они изменились. При подходе с виртуальными дисплеями такое реализуемо?
несколько структур
А в случае семисегментника, так и несколько чисел :)
Не хотелось мудрсвовать но ладно. Есть код прикладной. Ну тот когда надо поменять контент программы сообщения, место и порядок надписей. А есть все остальное. Остальное тоже не однородно. Работа с виртуальными экранами это уровень обработки данных. Что то похожее на String. Может в большой упаковке, а может в виде рассыпи отдельных функций и структуры приведённой вышн. А есть канальный уровень. Это код который эти данные забрасывать уже на чип дисплея.
Не хочу показаться камнем без острых углов, но я все же не совсем понял как канальный уровень поймёт, что на прикладном уровне произошли изменения в отображаемой информации и надо дисплей перерисовать?
Как я это вижу? Флаг - «Что то изменилось, надо бы перерисовать дисплей». Его же можно и в примере с меняющимися часами и температурой использовать для смены «кадра». Не?
Ну вспомни библиотеку для лсд1602 и2с. Там гибрид. Что туда напечатано. То на экран и отправлено. Но если сделать промежуточный объект. И туда печатать. Конечно на экране ничего нет. Что бы было надо создавать ещё объект который будет настраивать канал и2с и чип дисплея. А когда надо показать то даётся команда отправить этот виртуальный дисплей на отображение реального.
BOOM, никак - это просто разные вещи. Канальному уровню вообще пофиг чего там отображается - его дело данные гнать.
Все зависит от задачи, я предпочитаю сохранять данные от разных функций в памяти, а уже отдельная часть логики решает что и когда выводить.
PS. Мало с дисплеями работал, а меню вообще страдание, все таки железка которая сама решает как жить программируется проще. Впрочем дело вкуса.
Я iic не использую, мне и так пинов хватает.
Собственно заинтересовала идея виртуальных дисплеев, но не хочется на каждом такте дисплей перерисовывать. А так как в программировании я ещё как котёнок, хотелось бы у более опытных участников форума узнать по максимуму.
Информация с датчиков приходит асинхроно. Да и датчиков море. Вот и приходится хранить все данные. Вдруг вот как раз их надо показать на экране. А так напечатал на экране значение и забыл. Нужный экран всегда готов к показу. Код упрощается. Да и по памяти перерасход не большой.
Данные хранить надо в любом случае. Как их можно забывать?