Ну а что вы "гуру" не объясните болезному , что он пытается писать на суржике Си, ничего общего не имеющего ни с ООП ни с плюсами. А уж если "цЫфровые автоматы" это попытка создать конечный автомат тогда абма...
Я читал однако. Вы счас что его засыпали фекалиями, если вам очевидно что человек болен. Любите издеваться над жЫвотными, иголочками тыкать...
ты зачем Винни больным жывотным обозвал?
он не болен - это его нормально-стабильное состояние: вилкой ни себе, ни соседу не тыкает в глаз, пишет в код всякое. а, кто не писал всякое? - ткните в него вилкой!
Да судя по коду - онанизм с частичной специализацией, не более того. Зачем оно в том виде, в котором есть - хз. Квон, похоже, не совсем понимает, зачем нужна частичная специализация. Пусть развлекается, чо уж там.
Квон, ты напрасно уверен в том, что я наезжаю на тебя. Используешь слова типа "обсирать". Это не так, поверь. Мне реально симпатичны твоё усердие и старание, и мне приятно тебе помочь. Пока моя помощь состоит только в демонстрации факта наличия ошибок (уверен с их сутью ты и сам разберёшься). Но если какая-то из ошибок непонятна, не стесняйся спрашивать - я всегда объясню и помогу.
C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = unsigned char]':
C:\Qwone\test\test.ino:33:22: warning: invalid conversion from 'const unsigned char*' to 'uint8_t* {aka unsigned char*}' [-fpermissive]
In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0,
from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233,
from sketch\test.ino.cpp:1:
c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:164:6: note: initializing argument 1 of 'void eeprom_write_byte(uint8_t*, uint8_t)'
void eeprom_write_byte (uint8_t *__p, uint8_t __value);
^~~~~~~~~~~~~~~~~
C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = unsigned int]':
C:\Qwone\test\test.ino:45:21: warning: invalid conversion from 'const unsigned int*' to 'uint16_t* {aka unsigned int*}' [-fpermissive]
In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0,
from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233,
from sketch\test.ino.cpp:1:
c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:169:6: note: initializing argument 1 of 'void eeprom_write_word(uint16_t*, uint16_t)'
void eeprom_write_word (uint16_t *__p, uint16_t __value);
^~~~~~~~~~~~~~~~~
C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = long unsigned int]':
C:\Qwone\test\test.ino:57:22: warning: invalid conversion from 'const long unsigned int*' to 'uint32_t* {aka long unsigned int*}' [-fpermissive]
In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0,
from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233,
from sketch\test.ino.cpp:1:
c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:174:6: note: initializing argument 1 of 'void eeprom_write_dword(uint32_t*, uint32_t)'
void eeprom_write_dword (uint32_t *__p, uint32_t __value);
^~~~~~~~~~~~~~~~~~
C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = float]':
C:\Qwone\test\test.ino:69:22: warning: invalid conversion from 'const float*' to 'float*' [-fpermissive]
In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0,
from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233,
from sketch\test.ino.cpp:1:
c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:179:6: note: initializing argument 1 of 'void eeprom_write_float(float*, float)'
void eeprom_write_float (float *__p, float __value);
^~~~~~~~~~~~~~~~~~
Скетч использует 3166 байт (9%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 200 байт (9%) динамической памяти, оставляя 1848 байт для локальных переменных. Максимум: 2048 байт.
вопрос можно? Реально в твоём коде кнопки добавить двойное-тройное нажатие, хотя бы двойное
Можно, хоть титановый велосипед. Просто я считаю, что в нормально спроектированном меню это не желательно. Где-то я Гайверовские кнопки подключал. Используйте их.
вопрос можно? Реально в твоём коде кнопки добавить двойное-тройное нажатие, хотя бы двойное
Можно, хоть титановый велосипед. Просто я считаю, что в нормально спроектированном меню это не желательно. Где-то я Гайверовские кнопки подключал. Используйте их.
пробовал, бывают сбои, на твоём коде за всё время отработки (ТАМ УЖЕ ЗА 800 СТРОК) одной программы ни одного сбоя )))
Правда сын посмотрев мой код изрёк - такое впечатление, что писали как минимум три программиста, ...
я жеж просто заимствую код...естественно - сборная солянка )))
Вот и я об этом. Лучше меньше, да надежней. Я к этому варианту меню пришел не сразу. И обработка кнопок с минимумом тоже не сразу. И да скорее обменял долгое нажатие на повторное нажатие. Вот сейчас ковыряюсь с EEPROM. Тоже неплохо выйдет. Вот только интерфейс команд класса и некоторая защита от идиота.
/**/
#include "aaa.h"
byte* adr1 = (byte*)0;
int num = 10;
void setup() {
Serial.begin(9600);
aaa<byte> a(adr1);
Serial.print('\n');
for (int i = 0; i < num; i++) {
Serial.print(a[i]); Serial.print(' ');
}
Serial.print('\n');
for (int i = 0; i < num; i++) {
Serial.print(a[i] = a[i] + 1); Serial.print(' ');
}
Serial.print('\n');
}
void loop() {
}
небольшой омак. Три виртуальных экрана.
//---кнопки----------------------------- typedef void (*pDo)(); class Cl_btn { protected: byte pin; bool state; unsigned long past; void set(bool s) { state = s; past = millis(); if (s == true) Do(); } public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } }; Cl_btn BtnS(/*пин*/2); //кнопка 1 Cl_btn BtnU(/*пин*/3); //кнопка 2 Cl_btn BtnD(/*пин*/4); //кнопка 3 #include "lcd2004_i2c.h" qGTX display1(LCD_W, LCD_H); qGTX display2(LCD_W, LCD_H); qGTX display3(LCD_W, LCD_H); //-------------------------------- void setup() { BtnS.init(); BtnU.init(); BtnD.init(); lcd.init(); lcd.backlight(); lcd.show(display1); display1 << xy_t(0, 0) << F("Virtual screen 1"); display2 << xy_t(1, 1) << F("Virtual screen 2"); display3 << xy_t(2, 2) << F("Virtual screen 3"); BtnS.Do = [] {lcd.show(display1);}; BtnU.Do = [] {lcd.show(display2);}; BtnD.Do = [] {lcd.show(display3);}; } void loop() { BtnS.run(); BtnU.run(); BtnD.run(); }lcd2004_i2c.h
/*lcd2004_i2c.h*/ //.h---------------------------- #ifndef LCD2004_I2C_H #define LCD2004_I2C_H //--класс обработки данных ------------------------------------------ class Cl_lcd2004_i2c; struct xy_t { uint8_t x, y; explicit xy_t(int _x, int _y) : x(_x), y(_y) {} }; class qGTX: public Print { friend class Cl_lcd2004_i2c; protected: uint8_t *buffer; uint8_t W, H, posX, posY; public: qGTX(uint8_t w, uint8_t h) { if (w == 0) w = 1; if (h == 0) h = 1; W = w; H = h; buffer = new uint8_t[W * H]; clear(); } ~qGTX() { delete[] buffer; } inline size_t write(uint8_t value) { if (posX < W && posY < H) { buffer[posY * W + posX] = value; posX++; } return 1; } void setCursor(byte x, byte y) { if (x > W) x = W; else posX = x; if (y > H) x = H; else posY = y; } void clear() { for (byte i = 0; i < W * H; i++) buffer[i] = 0x20; posX = 0; posY = 0; } }; template <typename T> qGTX & operator << (qGTX &s,const T n) { s.print(n); return s; } template <> qGTX & operator << <struct xy_t>(qGTX &s, const struct xy_t n) { s.setCursor(n.x, n.y); return s; } //-- канальный класс Cl_lcd2004_i2c----------------------------------------- #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 // размеры экрана #define LCD_W 20 #define LCD_H 4 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd2004_i2c { protected: uint8_t adr; uint8_t _backlightval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; public: Cl_lcd2004_i2c(uint8_t a): adr(a) {} void init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _backlightval = LCD_NOBACKLIGHT; expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); } // подсветку вкл/выкл void backlight(void) { _backlightval = LCD_BACKLIGHT; expanderWrite(0); } void noBacklight(void) { _backlightval = LCD_NOBACKLIGHT; expanderWrite(0); } // отправить информацию из qGTX на экран void show(const qGTX &obj) { line(0); for (byte i = 0; i < obj.W; i++ )out(obj.buffer[i]); line(1); for (byte i = obj.W; i < 2 * obj.W; i++ )out(obj.buffer[i]); line(2); for (byte i = 2 * obj.W; i < 3 * obj.W; i++ )out(obj.buffer[i]); line(3); for (byte i = 3 * obj.W; i < 4 * obj.W; i++ )out(obj.buffer[i]); } private: /*внутрение функции*/ void line(byte l) { switch (l) { case 0: command(LCD_SETDDRAMADDR + 0x00); break; case 1: command(LCD_SETDDRAMADDR + 0x40); break; case 2: command(LCD_SETDDRAMADDR + 0x14); break; case 3: command(LCD_SETDDRAMADDR + 0x54); break; } } inline void out(uint8_t value) { send(value, Rs); } /*команды низкоуровневого управления*/ inline void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data | _backlightval)); Wire.endTransmission(); } void pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } }; //.cpp---------------------------- //qGTX display(20, 4); Cl_lcd2004_i2c lcd(0x3F);//0x27 #endifНемного переформатировал программу
/**/ #include "qwonelib.h" //------------------- struct data_t { // некая пользовательская структура byte bData; int iData; float fData; }; byte index = 0; const byte max_index = 10; data_t EEMEM adr1[max_index]; // размещение ее в EEPROM byte setting_index = 0; const byte max_setting_index = 5; void setting(byte in) { static const PROGMEM data_t adr2[max_setting_index] = { // набор констант для пользовательской функции {100, 1000, 10.10} // 0 комплект настроек , {101, 1001, 10.11} // 1 комплект настроек , {102, 1002, 10.12} // 2 комплект настроек , {103, 1003, 10.13} // 3 комплект настроек , {104, 1004, 10.14} // 4 комплект настроек }; (eeRef <byte>) (&adr1[in].bData) = (pgmRef<byte>) (&adr2[setting_index].bData); // загрузка байтовой части (eeRef <int>) (&adr1[in].iData) = (pgmRef<int>) (&adr2[setting_index].iData); // загрузка интовой части (eeRef <float>)(&adr1[in].fData) = (pgmRef<float>)(&adr2[setting_index].fData); // загрузка флоат части } #include "menu.h" //---------------------------------------- void setup() { menu_init(); while (1) { menu_run(); } } void loop() {}Cl_btn.h
/*Cl_btn.h*/ #ifndef Cl_btn_h #define Cl_btn_h //Cl_btn.h-------------------------------- typedef void (*pDo)(); class Cl_btn { public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init(); void run(); protected: void set(bool s); byte pin; bool state; unsigned long past; }; //Cl_btn.cpp-------------------------------- void Cl_btn::set(bool s) { state = s; past = millis(); if (s == true) Do(); } void Cl_btn::init() { pinMode(pin, INPUT_PULLUP); set(false); } void Cl_btn::run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } #endiflcd2004_i2c.h
/*lcd2004_i2c.h*/ //.h---------------------------- #ifndef LCD2004_I2C_H #define LCD2004_I2C_H //--класс обработки данных ------------------------------------------ // xy.h------------------------------------ class Cl_lcd2004_i2c; class xy { // класс задание позиции public: int x, y; explicit xy(): x(0), y(0) {} explicit xy(int _x, int _y): x(_x), y(_y) {} }; // xy.cpp------------------------------------ // qGTX.h------------------------------------ class qGTX: public Print { // класс графической обработки данных friend class Cl_lcd2004_i2c; friend qGTX operator+(const qGTX &obj, xy pos); friend qGTX operator+(const qGTX &obj1, const qGTX &obj2); // наложение на 1-й 2-го friend qGTX operator*(const qGTX &obj1, const qGTX &obj2); // горизонтальная склейка friend qGTX operator/(const qGTX &obj1, const qGTX &obj2); // вертикальная склейка protected: uint8_t *buffer; public: uint8_t W, H; int posX, posY; qGTX(uint8_t w, uint8_t h); qGTX(const qGTX &obj); qGTX(qGTX &&obj); qGTX & operator=(const xy& pos); qGTX& operator=(const qGTX& obj); qGTX& operator=(qGTX&& obj) ; qGTX& operator +=(const xy& pos); qGTX& operator +=(const qGTX& obj); qGTX& operator *=(const qGTX& obj); qGTX& operator /=(const qGTX& obj); ~qGTX(); inline size_t write(uint8_t c); void copy(uint8_t *d1, uint8_t *d2, int len); void setCursor(uint8_t x, uint8_t y); void clear(); void put(int x, int y, uint8_t c); uint8_t get(int x, int y) const ; }; // qGTX.cpp------------------------------------ qGTX::qGTX(uint8_t w, uint8_t h) { W = (w == 0) ? 1 : w; H = (h == 0) ? 1 : h; posX = posY = 0; buffer = new uint8_t[W * H]; clear(); } qGTX::qGTX(const qGTX &obj) {// конструктор копирования W = obj.W, H = obj.H, posX = obj.posX, posY = obj.posY; buffer = new uint8_t[W * H]; copy(buffer, obj.buffer, W * H); } qGTX::qGTX(qGTX &&obj) { // конструктор копирования c перемещением buffer = obj.buffer, W = obj.W, H = obj.H, posX = obj.posX, posY = obj.posY; obj.buffer = nullptr; } qGTX& qGTX::operator=(const xy& pos) { posX = (pos.x < W) ? pos.x : W; posY = (pos.y < H) ? pos.y : H; return *this; } qGTX& qGTX::operator=(const qGTX& obj) { // копирование по левой ссылке if (&obj == this) return *this; delete[] buffer; W = obj.W; H = obj.H; posX = obj.posX, posY = obj.posY; buffer = new uint8_t[W * H]; copy(buffer, obj.buffer, W * H); return *this; } qGTX& qGTX::operator=(qGTX&& obj) { // копирование по правой ссылке if (&obj == this) return *this; delete[] buffer; W = obj.W, H = obj.H, posX = obj.posX, posY = obj.posY, buffer = obj.buffer; obj.buffer = nullptr; return *this; } qGTX& qGTX::operator +=(const xy& pos) { posX += pos.x; posY += pos.y; return *this; } qGTX& qGTX::operator +=(const qGTX& obj) { for (int j = 0; j < obj.H; j++) for (int i = 0; i < obj.W; i++) put(i + posX, j + posY, obj.get(i, j)); posX += obj.W; //posY += obj.H-1; return *this; } qGTX::~qGTX() { delete[] buffer; } size_t qGTX::write(uint8_t c) { if (c == '\n') { posX = 0; posY = (posY < H) ? (posY + 1) : H; return 1; } if (posX < W && posY < H) { buffer[posY * W + posX] = c; posX++; } return 1; } void qGTX::copy(uint8_t *d1, uint8_t *d2, int len) { for (int i = 0; i < len; i++) d1[i] = d2[i]; } void qGTX::setCursor(uint8_t x, uint8_t y) { *this = xy(x, y); } void qGTX::clear() { for (uint8_t i = 0; i < W * H; i++) buffer[i] = 0x20; posX = posY = 0; } void qGTX::put(int x, int y, uint8_t c) { // поместить чар if (x < 0 || x >= W) return; if (y < 0 || y >= H) return; buffer[x + W * y] = c; } uint8_t qGTX::get(int x, int y) const { // извлеч чар if (x < 0 || x >= W) return 0x20; if (y < 0 || y >= H) return 0x20; return buffer[x + W * y]; } qGTX operator+(const qGTX &obj, xy pos) { //перемещение на шаг qGTX out(obj); return out += pos; } qGTX operator+(const qGTX &obj1, const qGTX &obj2) { // наложение на 1-й 2-го qGTX out(obj1); return out += obj2; } template <typename TT> qGTX & operator << (qGTX & obj, const TT& n) { obj.print(n); return obj; } template <> qGTX & operator << <xy>(qGTX &obj, const xy& pos) { return obj = pos; } template <> qGTX & operator << <qGTX>(qGTX &obj1, const qGTX& obj2) { return obj1 += obj2; } // Cl_lcd2004_i2c.h------------------------------------ //канальный класс #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 // размеры экрана #define LCD_W 20 #define LCD_H 4 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd2004_i2c { // класс канала передачи public: Cl_lcd2004_i2c(uint8_t a): adr(a) {} void init(); // иницирование void backlight(void); // подсветка вкл void noBacklight(void); // подсветка выкл void show(const qGTX &obj); // отправить информацию из qGTX на экран private: /*внутрение функции*/ inline void out(uint8_t value); inline void command(uint8_t value); void send(uint8_t value, uint8_t mode); void write4bits(uint8_t value); void expanderWrite(uint8_t _data); void pulseEnable(uint8_t _data); protected: uint8_t adr; uint8_t _backlightval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; }; // Cl_lcd2004_i2c.cpp------------------------------------ void Cl_lcd2004_i2c::init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _backlightval = LCD_NOBACKLIGHT; expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); } void Cl_lcd2004_i2c::backlight(void) { _backlightval = LCD_BACKLIGHT; expanderWrite(0); } void Cl_lcd2004_i2c::noBacklight(void) { _backlightval = LCD_NOBACKLIGHT; expanderWrite(0); } void Cl_lcd2004_i2c::show(const qGTX &obj) { command(LCD_SETDDRAMADDR + 0x00); for (uint8_t i = 0; i < obj.W; i++ )out(obj.buffer[i]); command(LCD_SETDDRAMADDR + 0x40); for (uint8_t i = obj.W; i < 2 * obj.W; i++ )out(obj.buffer[i]); command(LCD_SETDDRAMADDR + 0x14); for (uint8_t i = 2 * obj.W; i < 3 * obj.W; i++ )out(obj.buffer[i]); command(LCD_SETDDRAMADDR + 0x54); for (uint8_t i = 3 * obj.W; i < 4 * obj.W; i++ )out(obj.buffer[i]); } void Cl_lcd2004_i2c::out(uint8_t value) { send(value, Rs); } void Cl_lcd2004_i2c::command(uint8_t value) { send(value, 0); } void Cl_lcd2004_i2c::send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void Cl_lcd2004_i2c::write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void Cl_lcd2004_i2c::expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data | _backlightval)); Wire.endTransmission(); } void Cl_lcd2004_i2c::pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } //qGTX display(LCD_W, LCD_H); Cl_lcd2004_i2c lcd(0x3F);//0x27 #endifmenu.h
/*menu.h*/ #ifndef MENU_H #define MENU_H #include "Cl_btn.h" Cl_btn BtnS(/*пин*/2); //кнопка селект Cl_btn BtnU(/*пин*/3); //кнопка верх Cl_btn BtnD(/*пин*/4); //кнопка вниз //--------------- меню--------------------------------------------- #include "lcd2004_i2c.h" void goPage(byte p); // перейти на страницу p void menu_init(); // инициализировать меню void menu_run(); // текущая работа // обозначение страницы меню - что делает const byte page0 = 0;//гашение экрана const byte page1 = 10;//ноказ настроек const byte page2 = 20;//поменять индекс устройства const byte page3 = 30;//изменение байтовой части const byte page4 = 40;//изменение интовой части const byte page5 = 50;//изменение флоат части const byte page6 = 60; //сброс настроек byte page; unsigned long past; void goPage(byte p) { past = millis(); page = p; qGTX display(LCD_W, LCD_H); switch (page) { case page0: BtnS.Do = [] {goPage(page1);}; BtnU.Do = [] {goPage(page1);}; BtnD.Do = [] {goPage(page1);}; lcd.noBacklight(); break; case page1: BtnS.Do = [] {goPage(page2);}; BtnU.Do = [] {}; BtnD.Do = [] {}; lcd.backlight(); display << xy(0, 0) << F("info:"); display << xy(0, 1) << F(" byte(") << index << F(")=") << (eeRef <byte>)(&adr1[index].bData); // вывод байтовой части display << xy(0, 2) << F(" int(") << index << F(")=") << (eeRef <int>) (&adr1[index].iData); // вывод интовой части display << xy(0, 3) << F("float(") << index << F(")=") << (eeRef <float>)(&adr1[index].fData); // вывод флоат части break; case page2: BtnS.Do = [] {goPage(page3);}; BtnU.Do = [] { if (index < (max_index - 1))index++; goPage(page2); }; BtnD.Do = [] { if (index > 0)index--; goPage(page2); }; display << xy(0, 0) << F("set index:") << index; break; case page3: BtnS.Do = [] {goPage(page4);}; BtnU.Do = [] { if ((eeRef <byte>)(&adr1[index].bData) <= 200)(eeRef <byte>)(&adr1[index].bData) += 10; goPage(page3); }; BtnD.Do = [] { if ((eeRef <byte>)(&adr1[index].bData) >= 50)(eeRef <byte>)(&adr1[index].bData) -= 10; goPage(page3); }; display << xy(0, 0) << F("set byte(") << index << F(")=") << (eeRef <byte>)(&adr1[index].bData); // вывод байтовой части break; case page4: BtnS.Do = [] {goPage(page5);}; BtnU.Do = [] { if ((eeRef <int>)(&adr1[index].iData) <= 2000)(eeRef <int>)(&adr1[index].iData) += 100; goPage(page4); }; BtnD.Do = [] { if ((eeRef <int>)(&adr1[index].iData) >= 500)(eeRef <int>)(&adr1[index].iData) -= 100; goPage(page4); }; display << xy(0, 0) << F("set int(") << index << ")=" << (eeRef <int>) (&adr1[index].iData); // вывод интовой части break; case page5: BtnS.Do = [] {goPage(page6);}; BtnU.Do = [] { if ((eeRef <float>)(&adr1[index].fData) <= 20.30)(eeRef <float>)(&adr1[index].fData) += 1.01; goPage(page5); }; BtnD.Do = [] { if ((eeRef <float>)(&adr1[index].fData) >= 5.05)(eeRef <float>)(&adr1[index].fData) -= 1.01; goPage(page5); }; display << xy(0, 0) << F("set float(") << index << F(")=") << (eeRef <float>)(&adr1[index].fData); // вывод флоат части break; case page6: BtnS.Do = [] {goPage(page1);}; BtnU.Do = [] { if (setting_index < (max_setting_index - 1))setting_index++; setting(index); goPage(page6); }; BtnD.Do = [] { if (setting_index > 0)setting_index--; setting(index); goPage(page6); }; display << xy(0, 0) << F("setting(") << setting_index << F(")"); display << xy(0, 1) << F(" byte(") << index << F(")=") << (eeRef <byte>)(&adr1[index].bData); // вывод байтовой части display << xy(0, 2) << F(" int(") << index << F(")=") << (eeRef <int>) (&adr1[index].iData); // вывод интовой части display << xy(0, 3) << F("float(") << index << F(")=") << (eeRef <float>)(&adr1[index].fData); // вывод флоат части break; } lcd.show(display); } void menu_init() { BtnS.init(); BtnU.init(); BtnD.init(); lcd.init(); goPage(page1); } void menu_run() { BtnS.run(); BtnU.run(); BtnD.run(); switch (page) { case page0: break; default: if (millis() - past >= 10000)goPage(page0);// если долго не щелкают по кнопкам то погасить экран break; } } #endifqwonelib.h
/*qwonelib.h*/ #ifndef QWONELIB_H #define QWONELIB_H //pgmRef.h------------------------------------------- #include <avr/pgmspace.h> template <typename TT> struct pgmRef { // шаблон ссылка на PROGMEM uint8_t* adr; pgmRef( const TT *_adr); void setNewAdr(const TT *_adr); TT operator*() const ; operator TT() const ; }; //pgmRef.cpp------------------------------------------- template <typename TT> pgmRef<TT>::pgmRef( const TT *_adr): adr((uint8_t*)_adr) {} template <typename TT> void pgmRef<TT>::setNewAdr(const TT *_adr) { adr = (uint8_t*)_adr; } template <typename TT> TT pgmRef<TT>::operator*() const { TT data; uint8_t* p = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(TT); i++) p[i] = pgm_read_byte(adr + i); return data; } template <typename TT> pgmRef<TT>::operator TT() const { return **this; } //eeRef.h ---------------------------------------------- #include <avr/eeprom.h> template <typename TT> class eeRef { // шаблон ссылка на EEROM protected: uint8_t* adr; public: eeRef( const TT* _adr); void setNewAdr(const TT* _adr); TT operator*() const ; operator TT() const; //Assignment/write members. eeRef& operator=( const eeRef &ref ); eeRef& operator=( TT data ); eeRef& operator +=( TT data ); eeRef& operator -=( TT data ); eeRef& operator *=( TT data ); eeRef& operator /=( TT data ); eeRef& operator ^=( TT data ); eeRef& operator %=( TT data ); eeRef& operator &=( TT data ); eeRef& operator |=( TT data ); eeRef& operator <<=( TT data ); eeRef& operator >>=( TT data ); eeRef& update( TT data ); /** Prefix datacrement/decrement **/ eeRef& operator++(); eeRef& operator--(); /** Postfix datacrement/decrement **/ TT operator++ (int); TT operator-- (int); }; //eeRef.cpp------------------------- template <typename TT> eeRef<TT>::eeRef( const TT *_adr): adr((uint8_t*)_adr) {} template <typename TT> void eeRef<TT>::setNewAdr(const TT *_adr) { adr = (uint8_t*)_adr; } template <typename TT> TT eeRef<TT>::operator*() const { TT data; uint8_t* p = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(TT); i++) p[i] = eeprom_read_byte(adr + i); return data; } template <typename TT> eeRef<TT>::operator TT() const { return **this; } template <typename TT> eeRef<TT>& eeRef<TT>::operator=(const eeRef<TT> &ref ) { return *this = *ref; } template <typename TT> eeRef<TT>& eeRef<TT>::operator=( TT data ) { uint8_t* p = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(TT); i++) if ( p[i] != eeprom_read_byte(adr + i)) eeprom_write_byte(adr + i, p[i]); return *this; } template <typename TT> eeRef<TT>& eeRef<TT>::operator +=( TT data ) { return *this = **this + data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator -=( TT data ) { return *this = **this - data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator *=( TT data ) { return *this = **this * data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator /=( TT data ) { return *this = **this / data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator ^=( TT data ) { return *this = **this ^ data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator %=( TT data ) { return *this = **this % data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator &=( TT data ) { return *this = **this & data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator |=( TT data ) { return *this = **this | data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator <<=( TT data ) { return *this = **this << data; } template <typename TT> eeRef<TT>& eeRef<TT>::operator >>=( TT data ) { return *this = **this >> data; } template <typename TT> eeRef<TT>& eeRef<TT>::update( TT data ) { return data != *this ? *this = data : *this; } template <typename TT> eeRef<TT>& eeRef<TT>::operator++() { return *this += 1; } template <typename TT> eeRef<TT>& eeRef<TT>::operator--() { return *this -= 1; } template <typename TT> TT eeRef<TT>::operator++ (int) { TT ret = **this; return ++(*this), ret; } template <typename TT> TT eeRef<TT>::operator-- (int) { TT ret = **this; return --(*this), ret; } #endifНу и зарисовки по Морзе
/**/ //------------------------------------------------- const byte st_none = 0; const byte st_next = 1; const byte st_dot = 2; const byte st_dush = 3; const byte st_pause_dot = 4; const byte st_pause_dush = 5; class cMorse { protected: String buffer; unsigned int ii; byte pin; unsigned long past; unsigned long time; unsigned long dot_time; byte state, next_state; void set( byte s); public: cMorse(byte p); void init(unsigned long t = 300); void run(); void play(String msg); }; void cMorse::set(byte s) { state = s; past = millis(); while (state == st_next) { char tmp = buffer[ii++]; switch (tmp) { case '.': state = st_dot; break; case '-': state = st_dush; break; case ' ': state = st_pause_dush; break; case '\0': state = st_none; break; } } switch (state) { case st_none: Serial.print(F("OK")); break; case st_next: break; case st_dot: Serial.print(F(".")); digitalWrite(pin, HIGH); time = dot_time; next_state = st_pause_dot; break; case st_dush: Serial.print(F("-")); digitalWrite(pin, HIGH); time = dot_time * 3; next_state = st_pause_dot; break; case st_pause_dot: digitalWrite(pin, LOW); time = dot_time; next_state = st_next; break; case st_pause_dush: Serial.print(F(" ")); digitalWrite(pin, LOW); time = dot_time * 3; next_state = st_next; break; } } cMorse::cMorse(byte p) : pin(p) {} void cMorse::init(unsigned long t) { dot_time = t; ii = 0; set(st_none); pinMode(pin, OUTPUT); } void cMorse::run() { if (state != st_none && millis() - past >= time) set(next_state); } void cMorse::play(String msg) { buffer = msg; ii = 0; set(st_next); } cMorse Morse(/*пин*/13); //----------- кнопка ------------------------ typedef void (*pDo)(); class Cl_Btn { protected: byte pin; unsigned long past; bool state; void set(bool s) { past = millis(); state = s; if (s == true)Do(); } public: pDo Do = [] {}; Cl_Btn(byte p): pin(p) {} void init() { pinMode(pin, INPUT_PULLUP); set(false); } void run() { if (millis() - past >= 100) { switch (state) { case false : if (!digitalRead(pin)) set(true); break; case true : if (digitalRead(pin)) set(false); break; } } } }; Cl_Btn Btn(/*пин*/2);// кнопка void setup() { Serial.begin(9600); Morse.init(100);//0.1 секунды длит точки Btn.init(); Btn.Do = [] { Serial.println(); Morse.play(F("... --- ... "));// сообщение SOS }; } void loop() { Morse.run(); Btn.run(); }для читабельности кода на слух пауза между буквами должна быть 1.5 паузы между точками и тире
Жду код заветной кнопки, то-есть, кнопка работающая на PCINT
А что, в лисапете нету?
А что, в лисапете нету?
в лисапете калидоре булгахтеры...
страна русской дислексии - тьфу!
для читабельности кода на слух пауза между буквами должна быть 1.5 паузы между точками и тире
для читабельности кода на слух пауза между буквами должна быть 1.5 паузы между точками и тире
три многовато видимо
А что, в лисапете нету?
не знаю )))
ВЫ же знаете, мы радисты и пятерные клики различаем, а там что-то с двойными и одинарными проблема, или я так понял
для читабельности кода на слух пауза между буквами должна быть 1.5 паузы между точками и тире
три многовато видимо
вроде бы стандарт был 1 - 3 - 7 ?
возможно, но точка точно маловато, совсем всё сливается
не знаю )))
...проблема, или я так понял
не читал, но осуждаю(с)
- садись! пять по геноциду здравого смысла!
Ну а что вы "гуру" не объясните болезному , что он пытается писать на суржике Си, ничего общего не имеющего ни с ООП ни с плюсами. А уж если "цЫфровые автоматы" это попытка создать конечный автомат тогда абма...
Досикус, наверное стоит хотя бы первую страницу проглядеть по диагонали, прежде чем включать босса, как всегда, и начинать предъявами сыпать?
Я читал однако.
Вы счас что его засыпали фекалиями, если вам очевидно что человек болен.
Любите издеваться над жЫвотными, иголочками тыкать...
ты зачем Винни больным жывотным обозвал?
он не болен - это его нормально-стабильное состояние: вилкой ни себе, ни соседу не тыкает в глаз, пишет в код всякое. а, кто не писал всякое? - ткните в него вилкой!
/*EEPROM_qLib.ino*/ #include "EEPROM_qLib.h" float *const adr1 = 0; //float *const adr2 = (float*)((uint8_t*)adr1 + 2 * sizeof(float)); const PROGMEM float f_adr = {12.34}; void setup() { /*Serial.begin(9600); Serial.println((int)adr2); Serial.println((EERef<float>)adr1 = (pgmRef<float>)&f_adr);*/ (EERef<float>)adr1 = (pgmRef<float>)&f_adr; } void loop() { }EEPROM_qLib.h
/*EEPROM_qLib.h*/ #ifndef EEPROM_qLib_h #define EEPROM_qLib_h //pgmRef.h------------------------------------------- #include <avr/pgmspace.h> template <typename TT> class pgmRef { // шаблон ссылка на PROGMEM protected: uint8_t* _adr; public: explicit pgmRef(const TT* adr): _adr((uint8_t*)adr) {} TT read(); operator TT() { return read(); } }; //pgmRef.cpp------------------------------------------- template <typename TT> TT pgmRef<TT>::read() { TT data; uint8_t* pdata = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(TT); i++) pdata[i] = pgm_read_byte(_adr + i); return data; } template <> uint8_t pgmRef<uint8_t>::read() { uint8_t data = pgm_read_byte(_adr); return data; } // EERef.h------------------------------------ #include <avr/eeprom.h> template <typename TT> class EERef { protected: uint8_t* _adr; public: explicit EERef(const TT* adr): _adr((uint8_t*)adr) {} EERef& write(const TT& data); EERef& write(TT&& data); TT read(); operator TT() { return read(); } EERef& operator=(const EERef& ref ) { return write(ref); } EERef& operator=(const TT& in ) { return write(in); } EERef& operator +=(const TT& in ) { return write(read() + in); } EERef& operator -=(const TT& in ) { return write(read() - in); } EERef& operator *=(const TT& in ) { return write(read() * in); } EERef& operator /=(const TT& in ) { return write(read() / in); } EERef& operator ^=(const uint8_t& in) { return write(read() ^ in); } EERef& operator %=(const uint8_t& in ) { return write(read() % in); } EERef& operator &=(const uint8_t& in ) { return write(read() & in); } EERef& operator |=(const uint8_t& in ) { return write(read() | in); } EERef& operator <<=(const uint8_t& in ) { return write(read() << in); } EERef& operator >>=(const uint8_t& in ) { return write(read() >> in); } /** Prefix increment/decrement **/ EERef& operator++() { return write(read() += 1); } EERef& operator--() { return write(read() -= 1); } /** Postfix increment/decrement **/ EERef& operator++ (int) { TT ret = read(); write(read() += 1); return ret; } EERef& operator-- (int) { TT ret = read(); write(read() -= 1); return ret; } }; // EERef.cpp------------------------------------ template <typename TT> EERef<TT>& EERef<TT>::write(const TT& data) { uint8_t* pdata = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(TT); i++) if (pdata[i] != eeprom_read_byte(_adr + i)) eeprom_write_byte(_adr + i, pdata[i]); return *this; } template <> EERef<uint8_t>& EERef<uint8_t>::write(const uint8_t& data) { if (data != eeprom_read_byte(_adr)) eeprom_write_byte(_adr, data); return *this; } template <typename TT> EERef<TT>& EERef<TT>::write(TT&& data) { uint8_t* pdata = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(TT); i++) { if (pdata[i] != eeprom_read_byte(_adr + i)) eeprom_write_byte(_adr + i, pdata[i]); } return *this; } template <> EERef<uint8_t>& EERef<uint8_t>::write(uint8_t&& data) { if (data != eeprom_read_byte(_adr)) eeprom_write_byte(_adr, data); return *this; } template <typename TT> TT EERef<TT>::read() { TT data = 0; uint8_t* pdata = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(TT); i++) pdata[i] = eeprom_read_byte(_adr + i); return data; } template <> uint8_t EERef<uint8_t>::read() { uint8_t data = eeprom_read_byte(_adr); return data; } #endifя запретил разговаривать с болезными - сразу в пропасть!
/**/ float *adr1 = (float*)4; // размещение ее в EEPROM float *adr2 = (float*)8; #include "EEPROM_qLib.h" const PROGMEM float adr[4] = {1.3, 2.3, 2.7, 4.3}; void setup() { Serial.begin(9600); EERef<float> aaa(adr1); aaa =pgmRef<float>(&adr[0]); Serial.println(aaa); EERef<float> bbb(adr2); bbb =pgmRef<float>(&adr[1]); Serial.println(bbb); } void loop() { }EEPROM_qLib.h
/*EEPROM_qLib.h*/ #ifndef EEPROM_qLib_h #define EEPROM_qLib_h //pgmRef.h--------------------------------- #include <avr/pgmspace.h> template <typename T> class pgmRef { protected: const uint8_t* _adr; public: pgmRef() = delete; explicit pgmRef(const T* adr); operator T(); // read }; //pgmRef.cpp--------------------------------- template <typename T> pgmRef<T>::pgmRef(const T* adr): _adr((uint8_t*)adr) {} template <typename T> pgmRef<T>::operator T() { T data; uint8_t* p = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(T); i++) p[i] = pgm_read_byte(_adr + i); return data; } /*uint8_t*/ template <> pgmRef<uint8_t>::pgmRef(const uint8_t* adr): _adr(adr) {} template <> pgmRef<uint8_t>::operator uint8_t() { return pgm_read_byte(_adr); } // EERef.h------------------------------------ #include <avr/eeprom.h> template <typename T> class EERef { protected: uint8_t* _adr; public: EERef() = delete; explicit EERef(const T* adr); EERef(const EERef& other) = delete; operator T(); // read EERef& operator=(const T& data); // write EERef& operator=(const EERef& other); // write }; // EERef.cpp------------------------------------ template <typename T> EERef<T>::EERef(const T* adr): _adr((uint8_t*)adr) {} template <typename T> EERef<T>::operator T() { T data; uint8_t* p = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(T); i++) { p[i] = eeprom_read_byte(_adr + i); } return data; } template <typename T> EERef<T>& EERef<T>::operator=(const T& data) { uint8_t* p = (uint8_t*)&data; for (uint8_t i = 0; i < sizeof(T); i++) if (p[i] != eeprom_read_byte(_adr + i)) eeprom_write_byte(_adr + i, p[i]); return *this; } template <typename T> EERef<T>& EERef<T>::operator=(const EERef<T>& other) { if (this != &other) { *this = other; } return *this; } /*uint8_t*/ template <> EERef<uint8_t>::EERef(const uint8_t* adr): _adr((uint8_t*)adr) {} template <> EERef<uint8_t>::operator uint8_t() { return eeprom_read_byte(_adr); } template <> EERef<uint8_t>& EERef<uint8_t>::operator=(const uint8_t& data) { eeprom_write_byte(_adr, data); return *this; } template <> EERef<uint8_t>& EERef<uint8_t>::operator=(const EERef<uint8_t>& other) { if (this != &other) { *this = other; } return *this; } //--------------------------------- #endif/**/ #include "aaa.h" //----------------------- void setup() { Serial.begin(9600); aaa<String> a(F("9912345789")); Serial.println(a); aaa<float> b(12.56); Serial.println(b); } void loop() {aaa.h
/*aaa.h*/ #ifndef AAA_H #define AAA_H //aaa.h------------------------- template <typename T> class aaa { protected: uint8_t* pData; public: aaa() = delete; aaa(const T& d); ~aaa(); operator T(); aaa& operator=(const T& d); aaa& operator=(const aaa& other); aaa& read(); aaa& write(const T& d); }; //aaa.cpp------------------------- template <typename T> aaa<T>::aaa(const T& d): pData(new uint8_t[sizeof(T)]) { uint8_t* p =(uint8_t*)&d; for (uint8_t i = 0; i < sizeof(T); i++) pData[i] = p[i]; } template <typename T> aaa<T>::~aaa() { delete[] pData; } template <typename T> aaa<T>::operator T() { T data; uint8_t* p =(uint8_t*) &data; for (uint8_t i = 0; i < sizeof(T); i++) p[i] = pData[i]; return data; } template <typename T> aaa<T>& aaa<T>::operator=(const T& d) { uint8_t* p = &d; for (uint8_t i = 0; i < sizeof(T); i++) pData[i] = p[i]; return *this; } template <typename T> aaa<T>& aaa<T>::operator=(const aaa<T>& other) { if (this != &other) this = other; return *this; } template <typename T> aaa<T>& aaa<T>::read() { return *this; } template <typename T> aaa<T>& aaa<T>::write(const T& d) { return *this = d; } /*uint8_t*/ template <> aaa<uint8_t>::aaa(const uint8_t& d): pData(new uint8_t) {} template <> aaa<uint8_t>::~aaa<uint8_t>() { delete pData; } template <> aaa<uint8_t>::operator uint8_t() { return *pData; } template <> aaa<uint8_t>& aaa<uint8_t>::operator=(const uint8_t& d) { *pData = d; return *this; } template <> aaa<uint8_t>& aaa<uint8_t>::operator=(const aaa<uint8_t>& other) { if (this != &other) *this = other; return *this; } template <> aaa<uint8_t>& aaa<uint8_t>::read() { return *this; } template <> aaa<uint8_t>& aaa<uint8_t>::write(const uint8_t& d) { return *this = d; } /*String*/ #define STRING_SIZE 16 template <> aaa<String>::aaa(const String& d): pData(new uint8_t[STRING_SIZE]) { uint8_t len = (d.length() <= STRING_SIZE) ? d.length() : STRING_SIZE; uint8_t i = 0; for (; i < len; i++) { pData[i] = d[i]; } } template <> aaa<String>::~aaa() { delete[] pData; } template <> aaa<String>::operator String() { String data = ""; data.reserve(STRING_SIZE); for (uint8_t i = 0; i < STRING_SIZE; i++) { uint8_t d = pData[i]; if (d == 0) break; data += (char)d; } return data; } template <> aaa<String>& aaa<String>::operator=(const String& d) { uint8_t len = (d.length() <= STRING_SIZE) ? d.length() : STRING_SIZE; uint8_t i = 0; for (; i < len; i++) pData[i] = d[i]; return *this; } template <> aaa<String>& aaa<String>::operator=(const aaa<String>& other) { if (this != &other) *this = other; return *this; } template <> aaa<String>& aaa<String>::read() { return *this; } template <> aaa<String>& aaa<String>::write(const String& d) { return *this = d; } #endifА теперь тоже самое но с записью EEPPROM
/**/ #include "aaa.h" const String* adr1 = (String*)0; // адресс ячеек для записи String const float* adr2 = (float*)(&adr1 + STRING_SIZE);// адресс ячеек для записи float //----------------------- void setup() { Serial.begin(9600); aaa<String> a(adr1); a = String(F("temp String 1234567890")); Serial.println(a); aaa<float> b(adr2); b = 12.14; Serial.println(b); aaa<String> c(adr1); Serial.println(c); aaa<float> d(adr2); Serial.println(d); } void loop() { }aaa.h
/*aaa.h*/ #ifndef AAA_H #define AAA_H //aaa.h------------------------- #include <avr/eeprom.h> template <typename T> class aaa { protected: uint8_t* pData; public: aaa() = delete; explicit aaa(const T* adr); operator T(); aaa& operator=(const T& d); aaa& operator=(const aaa& other); aaa& read(); aaa& write(const T& d); }; //aaa.cpp------------------------- template <typename T> aaa<T>::aaa(const T* adr): pData((uint8_t*)adr) {} template <typename T> aaa<T>::operator T() { T data; uint8_t* p = (uint8_t*) &data; for (uint8_t i = 0; i < sizeof(T); i++) p[i] = eeprom_read_byte(pData + i); return data; } template <typename T> aaa<T>& aaa<T>::operator=(const T& d) { uint8_t* p = (uint8_t*)&d; for (uint8_t i = 0; i < sizeof(T); i++) eeprom_write_byte(pData + i, p[i]); return *this; } template <typename T> aaa<T>& aaa<T>::operator=(const aaa<T>& other) { if (this != &other) this = other; return *this; } template <typename T> aaa<T>& aaa<T>::read() { return *this; } template <typename T> aaa<T>& aaa<T>::write(const T& d) { return *this = d; } /*uint8_t*/ template <> aaa<uint8_t>::operator uint8_t() { uint8_t d = eeprom_read_byte(pData); return d; } template <> aaa<uint8_t>& aaa<uint8_t>::operator=(const uint8_t& d) { eeprom_write_byte(pData, d); return *this; } template <> aaa<uint8_t>& aaa<uint8_t>::operator=(const aaa<uint8_t>& other) { if (this != &other) *this = other; return *this; } template <> aaa<uint8_t>& aaa<uint8_t>::read() { return *this; } template <> aaa<uint8_t>& aaa<uint8_t>::write(const uint8_t& d) { return *this = d; } /*String*/ #define STRING_SIZE 16 template <> aaa<String>::operator String() { String data = ""; data.reserve(STRING_SIZE); for (uint8_t i = 0; i < STRING_SIZE; i++) { uint8_t d = eeprom_read_byte(pData + i); if (d == 0) break; data += (char)d; } return data; } template <> aaa<String>& aaa<String>::operator=(const String& d) { uint8_t len = (d.length() <= STRING_SIZE) ? d.length() : STRING_SIZE; uint8_t i = 0; for (; i < len; i++) eeprom_write_byte(pData + i, d[i]); eeprom_write_byte(pData + i, 0); return *this; } template <> aaa<String>& aaa<String>::operator=(const aaa<String>& other) { if (this != &other) *this = other; return *this; } template <> aaa<String>& aaa<String>::read() { return *this; } template <> aaa<String>& aaa<String>::write(const String& d) { return *this = d; } #endifшаблон только с явной специализаций.
/**/ //aaa.h------------------------ template <typename T> class aaa { protected: T data; public: ~aaa(); aaa(); aaa(T d); aaa(const aaa& other); aaa(aaa&& other) noexcept; aaa& operator=(const aaa& other); aaa& operator=(aaa&& other) noexcept ; // operator byte(); }; //aaa.cpp------------------------ /*общее*/ // отсутсвуют /*byte*/ template <> aaa<byte>::~aaa() {} template <> aaa<byte>::aaa(): data(0) {} template <> aaa<byte>::aaa(byte d): data(d) {} template <> aaa<byte>::aaa(const aaa<byte>& other): data(other.data) {} template <> aaa<byte>::aaa(aaa<byte>&& other): data(other.data) {} template <> aaa<byte>& aaa<byte>::operator=(const aaa<byte>& other) { data = other.data; return *this; } template <> aaa<byte>& aaa<byte>::operator=(aaa<byte>&& other) { data = other.data; return *this; } // template <> aaa<byte>::operator byte() { return data; } //------------------------ void setup() { Serial.begin(9600); aaa<byte> a(5); aaa<byte> b(a); aaa<byte> c; c = b; Serial.println(c); } void loop() { }А что допустимo в качестве T ? Кроме byte, конечно.
А что допустимo в качестве T ? Кроме byte, конечно.
Вопрос с подковыркой, насколько я понимаю, мельком взглянув на код? ;)
Интересуюсь.
А что допустимo в качестве T ? Кроме byte, конечно.
Вопрос с подковыркой, насколько я понимаю, мельком взглянув на код? ;)
а в фиге вместо косточки стриптиз? )))
Интересуюсь.
Да судя по коду - онанизм с частичной специализацией, не более того. Зачем оно в том виде, в котором есть - хз. Квон, похоже, не совсем понимает, зачем нужна частичная специализация. Пусть развлекается, чо уж там.
А что допустимo в качестве T ? Кроме byte, конечно.
template <> aaa<char*>::operator char*() { return data; }ПС:https://metanit.com/cpp/tutorial/5.15.php
Опять квона бьют...
А теперь тоже самое но с записью EEPPROM
Семё-ё-ён Семёныч ...
Пух, ну ты же взрослый мужик, претендуешь на какие-то знания, ну что же ты творишь?
Вот это что такое?
Давай напечатаем твои адреса.
#include "aaa.h" const String* adr1 = (String*)0; // адресс ячеек для записи String const float* adr2 = (float*)(&adr1 + STRING_SIZE);// адресс ячеек для записи float //----------------------- void setup() { Serial.begin(57600); Serial.println((uint16_t)adr1); Serial.println((uint16_t)adr2); } void loop() { } ///////////////////////// // В МОНИТОРЕ // // 0 // 310Ты точно этого хотел? Может, вот так надо было?
#include "aaa.h" const String* adr1 = (String*)0; // адресс ячеек для записи String const float* adr2 = (float*)((byte *)adr1 + STRING_SIZE);// адресс ячеек для записи float //----------------------- void setup() { Serial.begin(57600); Serial.println((uint16_t)adr1); Serial.println((uint16_t)adr2); } void loop() { } ///////////////////////// // В МОНИТОРЕ // // 0 // 16Так должно быть?
Но, если сделать так, то не проходит твой тест. Почти твой - я лишь переместил число раньше строки и само число поменял. Смотри сам:
#include "aaa.h" const String* adr1 = (String*)0; // адресс ячеек для записи String const float* adr2 = (float*)((byte *)adr1 + STRING_SIZE);// адресс ячеек для записи float //----------------------- void setup() { Serial.begin(57600); aaa<float> b(adr2); b = -12345678; Serial.println(b); aaa<String> a(adr1); a = String(F("temp String 1234567890")); Serial.println(a); aaa<String> c(adr1); Serial.println(c); aaa<float> d(adr2); Serial.println(d); } void loop() { } ///////////////////////// // В МОНИТОРЕ // // -12345678.00 // temp String 1234 // temp String 1234 // -12345600.00Видишь, что число переврано? Твоя строка его затирает!
Опять квона бьют...
за то, что двойное нажатие к кнопке не приделал?
разобрался с <char*>
/**/ #include "aaa.h" //------------------------ void setup() { Serial.begin(9600); aaa<byte> a(5); aaa<byte> b(a); aaa<byte> c; c = b; Serial.println(c); aaa<char*> aa; aa="qwerty"; Serial.println(aa); } void loop() { }aaa.h
/*aaa.h*/ #ifndef AAA_H #define AAA_H //aaa.h------------------------ template <typename T> class aaa { protected: T data; public: ~aaa(); aaa(); aaa(T d); aaa(const aaa& other); aaa(aaa&& other) noexcept; aaa& operator=(const aaa& other); aaa& operator=(aaa&& other) noexcept ; // operator T() const; }; //aaa.cpp------------------------ /*общее*/ // отсутсвуют /*byte*/ template <> aaa<byte>::~aaa() {} template <> aaa<byte>::aaa(): data(0) {} template <> aaa<byte>::aaa(byte d): data(d) {} template <> aaa<byte>::aaa(const aaa<byte>& other): data(other.data) {} template <> aaa<byte>::aaa(aaa<byte>&& other): data(other.data) {} template <> aaa<byte>& aaa<byte>::operator=(const aaa<byte>& other) { data = other.data; return *this; } template <> aaa<byte>& aaa<byte>::operator=(aaa<byte>&& other) { data = other.data; return *this; } // template <> aaa<byte>::operator byte() const{ return data; } /* char* */ template <> aaa<char*>::~aaa() { delete[] data; } template <> aaa<char*>::aaa(): data(nullptr) {} template <> aaa<char*>::aaa(char* d) : data(new char[strlen(d) + 1]) { strcpy(data, d); } template <> aaa<char*>::aaa(const aaa<char*>& other) : data(new char[strlen(other.data) + 1]) { strcpy(data, other.data); } template <> aaa<char*>::aaa(aaa<char*> && other): data(other.data) { data = other.data; other.data = nullptr; } template <> aaa<char*>& aaa<char*>::operator=(const aaa<char*>& other) { if (this == &other)return *this; char* tmp = new char[strlen(other.data) + 1]; strcpy(tmp, other.data); delete[] data; data = tmp; return *this; } template <> aaa<char*>& aaa<char*>::operator=(aaa<char*>&& other) { if (this == &other)return *this; delete[] data; data = other.data; other.data = nullptr; return *this; } // template <> aaa<char*>::operator char*() const{ return data; } #endifПС: А это чисто поржать https://www.youtube.com/watch?v=XZEi0bzrMfY
очередной набросок
/**/ //eeprom_Ref.h--------------------------------- #include <avr/eeprom.h> template <typename T> class eeprom_Ref { protected: const T* adr; public: ~eeprom_Ref(); eeprom_Ref() = delete; explicit eeprom_Ref(const T* a); eeprom_Ref(const eeprom_Ref& other) = delete; eeprom_Ref(eeprom_Ref&& other) = delete; eeprom_Ref& operator=(const eeprom_Ref& other); eeprom_Ref& operator=(eeprom_Ref&& other) noexcept ; // operator T() const; eeprom_Ref& operator=(const T& data); }; //eeprom_Ref.cpp--------------------------------- /*все*/ template <typename T> eeprom_Ref<T>::~eeprom_Ref() {} /* uint8_t*/ template <> eeprom_Ref<uint8_t>::eeprom_Ref(const uint8_t* a): adr(a) {} template <> eeprom_Ref<uint8_t>::operator uint8_t() const { return eeprom_read_byte (adr); } template <> eeprom_Ref<uint8_t>& eeprom_Ref<uint8_t>::operator=(const uint8_t& data) { eeprom_write_byte (adr, data); return *this; } /* uint16_t*/ template <> eeprom_Ref<uint16_t>::eeprom_Ref(const uint16_t* a): adr(a) {} template <> eeprom_Ref<uint16_t>::operator uint16_t() const { return eeprom_read_word(adr); } template <> eeprom_Ref<uint16_t>& eeprom_Ref<uint16_t>::operator=(const uint16_t& data) { eeprom_write_word(adr, data); return *this; } /* uint32_t*/ template <> eeprom_Ref<uint32_t>::eeprom_Ref(const uint32_t* a): adr(a) {} template <> eeprom_Ref<uint32_t>::operator uint32_t() const { return eeprom_read_dword(adr); } template <> eeprom_Ref<uint32_t>& eeprom_Ref<uint32_t>::operator=(const uint32_t& data) { eeprom_write_dword(adr, data); return *this; } /* float*/ template <> eeprom_Ref<float>::eeprom_Ref(const float* a): adr(a) {} template <> eeprom_Ref<float>::operator float() const { return eeprom_read_float ((const float *)adr); } template <> eeprom_Ref<float>& eeprom_Ref<float>::operator=(const float& data) { eeprom_write_float(adr, data); return *this; } //--------------------------------- const uint8_t* adr1 = (uint8_t*)0; const uint16_t* adr2 = (uint16_t*)10; const float* adr3 = (float*)20; void setup() { Serial.begin(9600); eeprom_Ref<uint8_t> aaa(adr1); aaa = 10; Serial.println(aaa); eeprom_Ref<uint16_t> bbb(adr2); bbb = 100 + aaa; Serial.println(bbb); eeprom_Ref<float> ccc(adr3); ccc = 12.34; Serial.println(ccc); } void loop() { }очередной набросок
C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = unsigned char]': C:\Qwone\test\test.ino:33:22: warning: invalid conversion from 'const unsigned char*' to 'uint8_t* {aka unsigned char*}' [-fpermissive] In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0, from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233, from sketch\test.ino.cpp:1: c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:164:6: note: initializing argument 1 of 'void eeprom_write_byte(uint8_t*, uint8_t)' void eeprom_write_byte (uint8_t *__p, uint8_t __value); ^~~~~~~~~~~~~~~~~ C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = unsigned int]': C:\Qwone\test\test.ino:45:21: warning: invalid conversion from 'const unsigned int*' to 'uint16_t* {aka unsigned int*}' [-fpermissive] In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0, from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233, from sketch\test.ino.cpp:1: c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:169:6: note: initializing argument 1 of 'void eeprom_write_word(uint16_t*, uint16_t)' void eeprom_write_word (uint16_t *__p, uint16_t __value); ^~~~~~~~~~~~~~~~~ C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = long unsigned int]': C:\Qwone\test\test.ino:57:22: warning: invalid conversion from 'const long unsigned int*' to 'uint32_t* {aka long unsigned int*}' [-fpermissive] In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0, from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233, from sketch\test.ino.cpp:1: c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:174:6: note: initializing argument 1 of 'void eeprom_write_dword(uint32_t*, uint32_t)' void eeprom_write_dword (uint32_t *__p, uint32_t __value); ^~~~~~~~~~~~~~~~~~ C:\Qwone\test\test.ino: In member function 'eeprom_Ref<T>& eeprom_Ref<T>::operator=(const T&) [with T = float]': C:\Qwone\test\test.ino:69:22: warning: invalid conversion from 'const float*' to 'float*' [-fpermissive] In file included from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/USBAPI.h:25:0, from C:\Arduino\arduino-1.8.10\hardware\arduino\avr\cores\arduino/Arduino.h:233, from sketch\test.ino.cpp:1: c:\arduino\arduino-1.8.10\hardware\tools\avr\avr\include\avr\eeprom.h:179:6: note: initializing argument 1 of 'void eeprom_write_float(float*, float)' void eeprom_write_float (float *__p, float __value); ^~~~~~~~~~~~~~~~~~ Скетч использует 3166 байт (9%) памяти устройства. Всего доступно 32256 байт. Глобальные переменные используют 200 байт (9%) динамической памяти, оставляя 1848 байт для локальных переменных. Максимум: 2048 байт.очередной набросок
/**/ //aaa.h----------------------- template <typename T> class aaa { protected: T* pointer; public: ~aaa(); aaa() = delete; explicit aaa(T* p); aaa(const aaa& other); aaa(aaa&& other) noexcept; aaa& operator=(const aaa& other); aaa& operator=(aaa&& other) noexcept ; // aaa& operator=(const T data); aaa operator[] (const int index); operator T(); }; //aaa.cpp----------------------- /*общее*/ // отсутсвуют /*byte*/ template <> aaa<byte>::~aaa() {} template <> aaa<byte>::aaa(byte* p): pointer(p) {} template <> aaa<byte>::aaa(const aaa<byte>& other): pointer(other.pointer) {} template <> aaa<byte>::aaa(aaa<byte>&& other): pointer(other.pointer) {} template <> aaa<byte>& aaa<byte>::operator=(const aaa<byte>& other) { pointer = other.pointer; return *this; } template <> aaa<byte>& aaa<byte>::operator=(aaa<byte>&& other) { pointer = other.pointer; return *this; } // template <> aaa<byte>& aaa<byte>::operator=(const byte data) { pointer[0] = data; return *this; } template <> aaa<byte> aaa<byte>::operator[] (const int index) { aaa other(pointer + index); return other; } template <> aaa<byte>::operator byte() { return pointer[0]; } //----------------------- #define num 10 void setup() { byte Array[num]; aaa<byte> a(Array); a = 14; Serial.begin(9600); Serial.println(a); Serial.println(a[6] = a + 3); } void loop() { }очередной набросок
/**/ //aaa.h----------------------- template <typename T> class aaa { protected: T* pointer; public: ~aaa(); aaa() = delete; explicit aaa(T* p); aaa(const aaa& other); aaa(aaa&& other) noexcept; aaa& operator=(const aaa& other); aaa& operator=(aaa&& other) noexcept ; // aaa& operator=(const T data); aaa operator[] (const int index); operator T(); }; //aaa.cpp----------------------- /*общее*/ // отсутсвуют /*byte*/ template <> aaa<byte>::~aaa() {} template <> aaa<byte>::aaa(byte* p): pointer(p) {} template <> aaa<byte>::aaa(const aaa<byte>& other): pointer(other.pointer) {} template <> aaa<byte>::aaa(aaa<byte>&& other): pointer(other.pointer) {} template <> aaa<byte>& aaa<byte>::operator=(const aaa<byte>& other) { pointer = other.pointer; return *this; } template <> aaa<byte>& aaa<byte>::operator=(aaa<byte>&& other) { pointer = other.pointer; return *this; } // template <> aaa<byte>& aaa<byte>::operator=(const byte data) { pointer[0] = data; return *this; } template <> aaa<byte> aaa<byte>::operator[] (const int index) { aaa other(pointer + index); return other; } template <> aaa<byte>::operator byte() { return pointer[0]; } //----------------------- #define num 10 void setup() { byte Array[num]; aaa<byte> a(Array); a = 14; Serial.begin(9600); Serial.println(a); Serial.println(a[6] = a + 3); } void loop() { }вопрос можно? Реально в твоём коде кнопки добавить двойное-тройное нажатие, хотя бы двойное
пробовал, бывают сбои, на твоём коде за всё время отработки (ТАМ УЖЕ ЗА 800 СТРОК) одной программы ни одного сбоя )))
Правда сын посмотрев мой код изрёк - такое впечатление, что писали как минимум три программиста, ...
я жеж просто заимствую код...естественно - сборная солянка )))
Вот и я об этом. Лучше меньше, да надежней. Я к этому варианту меню пришел не сразу. И обработка кнопок с минимумом тоже не сразу. И да скорее обменял долгое нажатие на повторное нажатие. Вот сейчас ковыряюсь с EEPROM. Тоже неплохо выйдет. Вот только интерфейс команд класса и некоторая защита от идиота.
/**/ #include "aaa.h" byte* adr1 = (byte*)0; int num = 10; void setup() { Serial.begin(9600); aaa<byte> a(adr1); Serial.print('\n'); for (int i = 0; i < num; i++) { Serial.print(a[i]); Serial.print(' '); } Serial.print('\n'); for (int i = 0; i < num; i++) { Serial.print(a[i] = a[i] + 1); Serial.print(' '); } Serial.print('\n'); } void loop() { }aaa.h
/* aaa.h */ #ifndef AAA_H #define AAA_H //aaa.h----------------------- #include <avr/eeprom.h> template <typename T> class aaa { protected: T* pointer; public: ~aaa(); aaa() = delete; explicit aaa(T* p); aaa(const aaa& other); aaa(aaa&& other) noexcept; aaa& operator=(const aaa& other); aaa& operator=(aaa&& other) noexcept ; // aaa& operator=(const T data); aaa operator[] (const int index); operator T(); }; //aaa.cpp----------------------- /*общее*/ // отсутсвуют /*byte*/ template <> aaa<byte>::~aaa() {} template <> aaa<byte>::aaa(byte* p): pointer(p) {} template <> aaa<byte>::aaa(const aaa<byte>& other): pointer(other.pointer) {} template <> aaa<byte>::aaa(aaa<byte>&& other): pointer(other.pointer) {} template <> aaa<byte>& aaa<byte>::operator=(const aaa<byte>& other) { pointer = other.pointer; return *this; } template <> aaa<byte>& aaa<byte>::operator=(aaa<byte>&& other) { pointer = other.pointer; return *this; } // template <> aaa<byte>& aaa<byte>::operator=(const byte data) { eeprom_write_byte(pointer, data); return *this; } template <> aaa<byte> aaa<byte>::operator[](const int index) { aaa<byte> other(pointer + index); return other; } template <> aaa<byte>::operator byte() { return eeprom_read_byte(pointer); } #endifПС: И да я совмещаю .h c .cpp для удобства выкладки на форуме.
Промежуточный вариант
/**/ #include "eeprom_Ref.h" float* adr1 = (float*)0; int num = 10; void setup() { Serial.begin(9600); eeprom_Ref<float> a(adr1); Serial.print('\n'); for (int i = 0; i < num; i++) { Serial.print(a[i]); Serial.print(' '); } Serial.print('\n'); for (int i = 0; i < num; i++) { Serial.print(a[i] = a[i] + 1.23); Serial.print(' '); } Serial.print('\n'); } void loop() { }eeprom_Ref.h
/* eeprom_Ref.h */ #ifndef EEPROM_REF_H #define EEPROM_REF_H //eeprom_Ref.h----------------------- #include <avr/eeprom.h> template <typename T> class eeprom_Ref { protected: T* pointer; public: ~eeprom_Ref(); eeprom_Ref() = delete; explicit eeprom_Ref(T* p); eeprom_Ref(const eeprom_Ref& other); eeprom_Ref(eeprom_Ref&& other) noexcept; eeprom_Ref& operator=(const eeprom_Ref& other); eeprom_Ref& operator=(eeprom_Ref&& other) noexcept ; // eeprom_Ref& operator=(const T data); eeprom_Ref operator[] (const int index); operator T(); }; //eeprom_Ref.cpp----------------------- /*общее*/ // отсутсвуют /*byte*/ template <> eeprom_Ref<byte>::~eeprom_Ref() {} template <> eeprom_Ref<byte>::eeprom_Ref(byte* p): pointer(p) {} template <> eeprom_Ref<byte>::eeprom_Ref(const eeprom_Ref<byte>& other): pointer(other.pointer) {} template <> eeprom_Ref<byte>::eeprom_Ref(eeprom_Ref<byte>&& other): pointer(other.pointer) {} template <> eeprom_Ref<byte>& eeprom_Ref<byte>::operator=(const eeprom_Ref<byte>& other) { pointer = other.pointer; return *this; } template <> eeprom_Ref<byte>& eeprom_Ref<byte>::operator=(eeprom_Ref<byte>&& other) { pointer = other.pointer; return *this; } // template <> eeprom_Ref<byte>& eeprom_Ref<byte>::operator=(const byte data) { eeprom_write_byte(pointer, data); return *this; } template <> eeprom_Ref<byte> eeprom_Ref<byte>::operator[](const int index) { eeprom_Ref<byte> other(pointer + index); return other; } template <> eeprom_Ref<byte>::operator byte() { return eeprom_read_byte(pointer); } /* uint16_t*/ template <> eeprom_Ref<uint16_t>::~eeprom_Ref() {} template <> eeprom_Ref<uint16_t>::eeprom_Ref(uint16_t* p): pointer(p) {} template <> eeprom_Ref<uint16_t>::eeprom_Ref(const eeprom_Ref<uint16_t>& other): pointer(other.pointer) {} template <> eeprom_Ref<uint16_t>::eeprom_Ref(eeprom_Ref<uint16_t>&& other): pointer(other.pointer) {} template <> eeprom_Ref<uint16_t>& eeprom_Ref<uint16_t>::operator=(const eeprom_Ref<uint16_t>& other) { pointer = other.pointer; return *this; } template <> eeprom_Ref<uint16_t>& eeprom_Ref<uint16_t>::operator=(eeprom_Ref<uint16_t>&& other) { pointer = other.pointer; return *this; } // template <> eeprom_Ref<uint16_t>& eeprom_Ref<uint16_t>::operator=(const uint16_t data) { eeprom_write_word(pointer, data); return *this; } template <> eeprom_Ref<uint16_t> eeprom_Ref<uint16_t>::operator[](const int index) { eeprom_Ref<uint16_t> other(pointer + index); return other; } template <> eeprom_Ref<uint16_t>::operator uint16_t() { return eeprom_read_word(pointer); } /* uint32_t*/ template <> eeprom_Ref<uint32_t>::~eeprom_Ref() {} template <> eeprom_Ref<uint32_t>::eeprom_Ref(uint32_t* p): pointer(p) {} template <> eeprom_Ref<uint32_t>::eeprom_Ref(const eeprom_Ref<uint32_t>& other): pointer(other.pointer) {} template <> eeprom_Ref<uint32_t>::eeprom_Ref(eeprom_Ref<uint32_t>&& other): pointer(other.pointer) {} template <> eeprom_Ref<uint32_t>& eeprom_Ref<uint32_t>::operator=(const eeprom_Ref<uint32_t>& other) { pointer = other.pointer; return *this; } template <> eeprom_Ref<uint32_t>& eeprom_Ref<uint32_t>::operator=(eeprom_Ref<uint32_t>&& other) { pointer = other.pointer; return *this; } // template <> eeprom_Ref<uint32_t>& eeprom_Ref<uint32_t>::operator=(const uint32_t data) { eeprom_write_dword(pointer, data); return *this; } template <> eeprom_Ref<uint32_t> eeprom_Ref<uint32_t>::operator[](const int index) { eeprom_Ref<uint32_t> other(pointer + index); return other; } template <> eeprom_Ref<uint32_t>::operator uint32_t() { return eeprom_read_dword(pointer); } /* float*/ template <> eeprom_Ref<float>::~eeprom_Ref() {} template <> eeprom_Ref<float>::eeprom_Ref(float* p): pointer(p) {} template <> eeprom_Ref<float>::eeprom_Ref(const eeprom_Ref<float>& other): pointer(other.pointer) {} template <> eeprom_Ref<float>::eeprom_Ref(eeprom_Ref<float>&& other): pointer(other.pointer) {} template <> eeprom_Ref<float>& eeprom_Ref<float>::operator=(const eeprom_Ref<float>& other) { pointer = other.pointer; return *this; } template <> eeprom_Ref<float>& eeprom_Ref<float>::operator=(eeprom_Ref<float>&& other) { pointer = other.pointer; return *this; } // template <> eeprom_Ref<float>& eeprom_Ref<float>::operator=(const float data) { eeprom_write_float(pointer, data); return *this; } template <> eeprom_Ref<float> eeprom_Ref<float>::operator[](const int index) { eeprom_Ref<float> other(pointer + index); return other; } template <> eeprom_Ref<float>::operator float() { return eeprom_read_float(pointer); } #endifПохоже почти получилось создать реферальный класс на EEPROM
/**/ #include "eeprom_Ref.h" int* adr1 = (int*)0; float* adr2 = (float*)50; void setup() { Serial.begin(9600); eeprom_int a(adr1); a[5] = 5; Serial.println(a[5]); eeprom_float b(adr2); b[1] = 5.33; Serial.println(b[1]); } void loop() { }eeprom_Ref.h
/* eeprom_Ref.h */ #ifndef EEPROM_REF_H #define EEPROM_REF_H //Ref.h----------------------- #include <avr/eeprom.h> template <typename T> class Ref { protected: T* pointer; void set(T data); T get(); public: ~Ref(); Ref() = delete; Ref(T* a); Ref(const Ref& other) = delete; Ref(Ref&& other); Ref& operator=(const Ref& other) = delete; Ref& operator=(Ref&& other); // operator T(); Ref& operator=(T&& d); Ref& operator=(const T& d); Ref operator[] (const int index); }; typedef Ref<byte> eeprom_byte; typedef Ref<int> eeprom_int; typedef Ref<uint16_t> eeprom_uint16_t; typedef Ref<uint32_t> eeprom_uint32_t; typedef Ref<float> eeprom_float; //Ref.cpp----------------------- /*byte*/ template <> void Ref<byte>::set(byte data) { eeprom_write_byte(pointer, data); } template <> byte Ref<byte>::get() { return eeprom_read_byte(pointer); } /* int */ template <> void Ref<int>::set(int data) { eeprom_write_word((uint16_t*)pointer, (uint16_t)data); } template <> int Ref<int>::get() { return eeprom_read_word((uint16_t*)pointer); } /* uint16_t*/ template <> void Ref<uint16_t>::set(uint16_t data) { eeprom_write_word(pointer, data); } template <> uint16_t Ref<uint16_t>::get() { return eeprom_read_word(pointer); } /* uint32_t*/ template <> void Ref<uint32_t>::set(uint32_t data) { eeprom_write_dword(pointer, data); } template <> uint32_t Ref<uint32_t>::get() { return eeprom_read_dword(pointer); } /* float*/ template <> void Ref<float>::set(float data) { eeprom_write_float(pointer, data); } template <> float Ref<float>::get() { return eeprom_read_float(pointer); } /*общее*/ template <typename T> Ref<T>::~Ref() {} template <typename T> Ref<T>::Ref(T* a): pointer(a) {} template <typename T> Ref<T>::Ref(Ref<T>&& other) { set(other.get()); } template <typename T> Ref<T>& Ref<T>::operator=(Ref<T>&& other) { set(other.get()); return *this; } template <typename T> Ref<T>::operator T() { return get(); } template <typename T> Ref<T>& Ref<T>::operator=(T&& d) { set(d); return *this; } template <typename T> Ref<T>& Ref<T>::operator=(const T& d) { set(d); return *this; } template <typename T> Ref<T> Ref<T>::operator[] (const int index) { return Ref<T>(pointer + index); } #endifСледующая доработка класса. И да шаблон класса почему-то на два файла .h и .cpp не делится, а точнее не компилируется
/**/ #include "eeprom_Ref.h" int* adr1 = (int*)0; float* adr2 = (float*)50; const float adr3[] PROGMEM = {0.23,12.34, 13.45, 14.56}; void setup() { Serial.begin(9600); eeprom_int a(adr1); a[5] = 5; Serial.println(a[5]); eeprom_float b(adr2); b[1] = 5.33; Serial.println(b[1]); pgm_float c(adr3); Serial.println(c[2]); } void loop() { }eeprom_Ref.h
/* Ref.h */ #ifndef EEPROM_REF_H #define EEPROM_REF_H //Ref.h----------------------- #include <Arduino.h> #include <avr/eeprom.h> template <typename T> class Ref { protected: T* pointer; void set(T data); T get(); public: ~Ref(); Ref() = delete; Ref(T* a); Ref(const Ref& other) = delete; Ref(Ref&& other); Ref& operator=(const Ref& other) = delete; Ref& operator=(Ref&& other); // operator T(); Ref& operator=(T&& d); Ref& operator=(const T& d); Ref operator[] (const int index); }; //Ref.cpp----------------------- /* uint8_t */ template <> void Ref<uint8_t>::set(uint8_t data) { eeprom_write_byte(pointer, data); } template <> uint8_t Ref<uint8_t>::get() { return eeprom_read_byte(pointer); } /* int */ template <> void Ref<int>::set(int data) { eeprom_write_word((uint16_t*)pointer, (uint16_t)data); } template <> int Ref<int>::get() { return eeprom_read_word((uint16_t*)pointer); } /* uint16_t*/ template <> void Ref<uint16_t>::set(uint16_t data) { eeprom_write_word(pointer, data); } template <> uint16_t Ref<uint16_t>::get() { return eeprom_read_word(pointer); } /* uint32_t*/ template <> void Ref<uint32_t>::set(uint32_t data) { eeprom_write_dword(pointer, data); } template <> uint32_t Ref<uint32_t>::get() { return eeprom_read_dword(pointer); } /* float*/ template <> void Ref<float>::set(float data) { eeprom_write_float(pointer, data); } template <> float Ref<float>::get() { return eeprom_read_float(pointer); } /*общее*/ template <typename T> Ref<T>::~Ref() {} template <typename T> Ref<T>::Ref(T* a): pointer(a) {} template <typename T> Ref<T>::Ref(Ref<T>&& other) { pointer = other.pointer; } template <typename T> Ref<T>& Ref<T>::operator=(Ref<T>&& other) { if (pointer != other.pointer) set(other.get()); return *this; } template <typename T> Ref<T>::operator T() { return get(); } template <typename T> Ref<T>& Ref<T>::operator=(T&& d) { set(d); return *this; } template <typename T> Ref<T>& Ref<T>::operator=(const T& d) { set(d); return *this; } template <typename T> Ref<T> Ref<T>::operator[] (const int index) { return Ref<T>(pointer + index); } using eeprom_int = Ref<int> ; using eeprom_uint8_t = Ref<uint8_t>; using eeprom_uint16_t = Ref<uint16_t>; using eeprom_uint32_t = Ref<uint32_t>; using eeprom_float = Ref<float>; //pRef.h----------------------------- #include <avr/pgmspace.h> template <typename T> class pRef { protected: const T* pointer; T get(); public: ~pRef(); pRef() = delete; pRef(const T* a); pRef(const pRef& other) = delete; pRef(pRef&& other); pRef& operator=(const pRef& other) = delete; pRef& operator=(pRef&& other); // operator T(); pRef operator[] (const int index); }; //pRef.cpp----------------------------- /*uint8_t*/ template <> uint8_t pRef<uint8_t>::get() { return pgm_read_byte(pointer); } /* int */ template <> int pRef<int>::get() { return pgm_read_word((uint16_t*)pointer); } /* uint16_t*/ template <> uint16_t pRef<uint16_t>::get() { return pgm_read_word(pointer); } /* uint32_t*/ template <> uint32_t pRef<uint32_t>::get() { return pgm_read_dword(pointer); } /* float*/ template <> float pRef<float>::get() { return pgm_read_float(pointer); } /*общее*/ template <typename T> pRef<T>::~pRef() {} template <typename T> pRef<T>::pRef(const T* a): pointer(a) {} template <typename T> pRef<T>::pRef(pRef<T>&& other) : pointer(other.pointer) {} template <typename T> pRef<T>& pRef<T>::operator=(pRef<T>&& other) { pointer = other.pointer; return *this; } template <typename T> pRef<T>::operator T() { return get(); } template <typename T> pRef<T> pRef<T>::operator[] (const int index) { return pRef<T>(pointer + index); } //------------------------------------------------- using pgm_int = pRef<int>; using pgm_uint8_t = pRef<uint8_t>; using pgm_uint16_t = pRef<uint16_t>; using pgm_uint32_t = pRef<uint32_t>; using pgm_float = pRef<float>; #endifОрганизовал на основе этого класса меню и посмотрел как выглядит он в этой комбинации
/**/ // 10 устройств с данными uint8_t,int,float #include "eeprom_Ref.h" byte index = 0; const byte max_index = 10; uint8_t* eeprom_b = (uint8_t*)(100); int* eeprom_i = (int*) ((int)eeprom_b + max_index*sizeof(uint8_t)); float* eeprom_f = (float*) ((int)eeprom_i + max_index*sizeof(int)); eeprom_uint8_t eeprom_B(eeprom_b); eeprom_int eeprom_I(eeprom_i); eeprom_float eeprom_F(eeprom_f); byte setting_index = 0; const byte max_setting_index = 5; static const PROGMEM uint8_t pgm_b[] = {100,101,102,103,104}; static const PROGMEM int pgm_i[] = {1000,1001,1002,1003,1004}; static const PROGMEM float pgm_f[] = {10.10,10.11,10.12,10.13,10.14}; pgm_uint8_t pgm_B(pgm_b); pgm_int pgm_I(pgm_i); pgm_float pgm_F(pgm_f); #include "menu.h" //---------------------------------------- void setup() { menu_init(); while (1) { menu_run(); } } void loop() {}Cl_btn.h
/*Cl_btn.h*/ #ifndef Cl_btn_h #define Cl_btn_h //Cl_btn.h-------------------------------- typedef void (*pDo)(); class Cl_btn { public: Cl_btn(byte p): pin(p) {} pDo Do = [] {}; void init(); void run(); protected: void set(bool s); byte pin; bool state; unsigned long past; }; //Cl_btn.cpp-------------------------------- void Cl_btn::set(bool s) { state = s; past = millis(); if (s == true) Do(); } void Cl_btn::init() { pinMode(pin, INPUT_PULLUP); set(false); } void Cl_btn::run() { if (millis() - past >= 100) switch (state) { case false: if (!digitalRead(pin))set(true); break; case true: if (digitalRead(pin))set(false); if (millis() - past >= 300)set(false); break; } } #endifeeprom_Ref.h
/* eeprom_Ref.h */ #ifndef EEPROM_REF_H #define EEPROM_REF_H //Ref.h----------------------- #include <Arduino.h> #include <avr/eeprom.h> template <typename T> class Ref { protected: T* pointer; void set(T data); T get(); public: ~Ref(); Ref() = delete; Ref(T* a); Ref(const Ref& other) = delete; Ref(Ref&& other); Ref& operator=(const Ref& other) = delete; Ref& operator=(Ref&& other); // operator T(); Ref& operator=(T&& d); Ref& operator=(const T& d); Ref operator[] (const int index); Ref& operator +=(T&& d); Ref& operator -=(T&& d); }; //Ref.cpp----------------------- /* uint8_t */ template <> void Ref<uint8_t>::set(uint8_t data) { eeprom_write_byte(pointer, data); } template <> uint8_t Ref<uint8_t>::get() { return eeprom_read_byte(pointer); } /* int */ template <> void Ref<int>::set(int data) { eeprom_write_word((uint16_t*)pointer, (uint16_t)data); } template <> int Ref<int>::get() { return eeprom_read_word((uint16_t*)pointer); } /* uint16_t*/ template <> void Ref<uint16_t>::set(uint16_t data) { eeprom_write_word(pointer, data); } template <> uint16_t Ref<uint16_t>::get() { return eeprom_read_word(pointer); } /* uint32_t*/ template <> void Ref<uint32_t>::set(uint32_t data) { eeprom_write_dword(pointer, data); } template <> uint32_t Ref<uint32_t>::get() { return eeprom_read_dword(pointer); } /* float*/ template <> void Ref<float>::set(float data) { eeprom_write_float(pointer, data); } template <> float Ref<float>::get() { return eeprom_read_float(pointer); } /*общее*/ template <typename T> Ref<T>::~Ref() {} template <typename T> Ref<T>::Ref(T* a): pointer(a) {} template <typename T> Ref<T>::Ref(Ref<T>&& other) { pointer = other.pointer; } template <typename T> Ref<T>& Ref<T>::operator=(Ref<T>&& other) { if (pointer != other.pointer) set(other.get()); return *this; } template <typename T> Ref<T>::operator T() { return get(); } template <typename T> Ref<T>& Ref<T>::operator=(T&& d) { set(d); return *this; } template <typename T> Ref<T>& Ref<T>::operator=(const T& d) { set(d); return *this; } template <typename T> Ref<T> Ref<T>::operator[] (const int index) { return Ref<T>(pointer + index); } template <typename T> Ref<T>& Ref<T>::operator +=(T&& d) { set(get() + d); return *this; } template <typename T> Ref<T>& Ref<T>::operator -=(T&& d) { set(get() - d); return *this; } using eeprom_int = Ref<int> ; using eeprom_uint8_t = Ref<uint8_t>; using eeprom_uint16_t = Ref<uint16_t>; using eeprom_uint32_t = Ref<uint32_t>; using eeprom_float = Ref<float>; //pRef.h----------------------------- #include <avr/pgmspace.h> template <typename T> class pRef { protected: const T* pointer; T get(); public: ~pRef(); pRef() = delete; pRef(const T* a); pRef(const pRef& other) = delete; pRef(pRef&& other); pRef& operator=(const pRef& other) = delete; pRef& operator=(pRef&& other); // operator T(); pRef operator[] (const int index); }; //pRef.cpp----------------------------- /*uint8_t*/ template <> uint8_t pRef<uint8_t>::get() { return pgm_read_byte(pointer); } /* int */ template <> int pRef<int>::get() { return pgm_read_word((uint16_t*)pointer); } /* uint16_t*/ template <> uint16_t pRef<uint16_t>::get() { return pgm_read_word(pointer); } /* uint32_t*/ template <> uint32_t pRef<uint32_t>::get() { return pgm_read_dword(pointer); } /* float*/ template <> float pRef<float>::get() { return pgm_read_float(pointer); } /*общее*/ template <typename T> pRef<T>::~pRef() {} template <typename T> pRef<T>::pRef(const T* a): pointer(a) {} template <typename T> pRef<T>::pRef(pRef<T>&& other) : pointer(other.pointer) {} template <typename T> pRef<T>& pRef<T>::operator=(pRef<T>&& other) { pointer = other.pointer; return *this; } template <typename T> pRef<T>::operator T() { return get(); } template <typename T> pRef<T> pRef<T>::operator[] (const int index) { return pRef<T>(pointer + index); } //------------------------------------------------- using pgm_int = pRef<int>; using pgm_uint8_t = pRef<uint8_t>; using pgm_uint16_t = pRef<uint16_t>; using pgm_uint32_t = pRef<uint32_t>; using pgm_float = pRef<float>; #endiflcd2004_i2c.h
/*lcd2004_i2c.h*/ #ifndef LCD2004_I2C_H #define LCD2004_I2C_H // xy.h------------------------------------ class Cl_lcd2004_i2c; class xy { // класс задание позиции public: int x, y; explicit xy(): x(0), y(0) {} explicit xy(int _x, int _y): x(_x), y(_y) {} }; // xy.cpp------------------------------------ // GTX.h------------------------------------ class GTX : public Print { friend class Cl_lcd2004_i2c; protected: uint8_t W, H; uint8_t* buffer; int posX, posY; public: ~GTX(); GTX(); GTX(uint8_t w, uint8_t h); GTX(const GTX& other) = delete; GTX(GTX&& other ); GTX& operator=(const GTX& other) = delete; GTX& operator=(GTX&& other); // void clear(); void setCursor(uint8_t x, uint8_t y); inline size_t write(uint8_t c); template <typename T> GTX& operator<< (T n); }; // GTX.cpp------------------------------------ GTX::~GTX() { delete[] buffer; } GTX::GTX() : W(1), H(1), buffer(new uint8_t[1]) { buffer[0] = ' '; } GTX::GTX(uint8_t w, uint8_t h) : W(w), H(h), buffer(new uint8_t[W * H]), posX(0), posY(0) { clear(); } GTX::GTX(GTX&& other ) : W(other.W), H(other.H), buffer(other.buffer), posX(0), posY(0) { other.buffer = nullptr; } GTX& GTX::operator=(GTX&& other) { W = other.W, H = other.H, buffer = other.buffer, other.buffer = nullptr, posX = 0, posY = 0; return *this; } // void GTX::clear() { memset(buffer, 0x20, W * H); posX = posY = 0; } void GTX::setCursor(uint8_t x, uint8_t y) { posX = x; posY = y; } size_t GTX::write(uint8_t c) { if (c == '\n') { posX = 0; posY = (posY < H) ? (posY + 1) : H; return 1; } if (posX < W && posY < H) { buffer[posY * W + posX] = c; posX++; } return 1; } template<> GTX& GTX::operator<< (xy n) { posX = n.x; posY = n.y; return *this; } template <typename T> GTX& GTX::operator<< ( T n) { this->print(n); return *this; } // Cl_lcd2004_i2c.h------------------------------------ //канальный класс #include <Wire.h> // команды #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // флаги для режима ввода дисплея #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // флаги для управления включением / выключением дисплея #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // флаги для отображения / сдвига курсора #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // флаги для набора функций #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // флаги для управления подсветкой #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 // размеры экрана #define LCD_W 20 #define LCD_H 4 #define En B00000100 // Бит разрешения #define Rw B00000010 // Чтение / запись бит #define Rs B00000001 // Бит выбора регистра class Cl_lcd2004_i2c { // класс канала передачи public: Cl_lcd2004_i2c(uint8_t a): adr(a) {} void init(); // иницирование void backlight(void); // подсветка вкл void noBacklight(void); // подсветка выкл void show(const GTX &obj); // отправить информацию из qGTX на экран private: /*внутрение функции*/ inline void out(uint8_t value); inline void command(uint8_t value); void send(uint8_t value, uint8_t mode); void write4bits(uint8_t value); void expanderWrite(uint8_t _data); void pulseEnable(uint8_t _data); protected: uint8_t adr; uint8_t _backlightval; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; }; // Cl_lcd2004_i2c.cpp------------------------------------ void Cl_lcd2004_i2c::init() { Wire.begin(); write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(4500); // wait min 4.1ms write4bits(0x03 << 4); delayMicroseconds(150); write4bits(0x02 << 4); delay(50); _backlightval = LCD_NOBACKLIGHT; expanderWrite(_backlightval); // сбросить расширение и выключить подсветку (бит 8 = 1) // режим работы дисплея 4-х битный интерфейс ,две строки,5х8 точек _displayfunction = LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS; command(LCD_FUNCTIONSET | _displayfunction); // режим контроля дисплей вкл, курсор не мигает,дисплей не мигает _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; command(LCD_DISPLAYCONTROL | _displaycontrol); // режим ввода текста в память-начинать слева с движением в право _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); } void Cl_lcd2004_i2c::backlight(void) { _backlightval = LCD_BACKLIGHT; expanderWrite(0); } void Cl_lcd2004_i2c::noBacklight(void) { _backlightval = LCD_NOBACKLIGHT; expanderWrite(0); } void Cl_lcd2004_i2c::show(const GTX &obj) { command(LCD_SETDDRAMADDR + 0x00); for (uint8_t i = 0; i < obj.W; i++ )out(obj.buffer[i]); command(LCD_SETDDRAMADDR + 0x40); for (uint8_t i = obj.W; i < 2 * obj.W; i++ )out(obj.buffer[i]); command(LCD_SETDDRAMADDR + 0x14); for (uint8_t i = 2 * obj.W; i < 3 * obj.W; i++ )out(obj.buffer[i]); command(LCD_SETDDRAMADDR + 0x54); for (uint8_t i = 3 * obj.W; i < 4 * obj.W; i++ )out(obj.buffer[i]); } void Cl_lcd2004_i2c::out(uint8_t value) { send(value, Rs); } void Cl_lcd2004_i2c::command(uint8_t value) { send(value, 0); } void Cl_lcd2004_i2c::send(uint8_t value, uint8_t mode) { uint8_t highnib = value & 0xf0; write4bits((highnib) | mode); uint8_t lownib = (value << 4) & 0xf0; write4bits((lownib) | mode); } void Cl_lcd2004_i2c::write4bits(uint8_t value) { expanderWrite(value); pulseEnable(value); } void Cl_lcd2004_i2c::expanderWrite(uint8_t _data) { Wire.beginTransmission(adr); Wire.write((int)(_data | _backlightval)); Wire.endTransmission(); } void Cl_lcd2004_i2c::pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high delayMicroseconds(1); // enable pulse must be >450ns expanderWrite(_data & ~En); // En low delayMicroseconds(50); // commands need > 37us to settle } //GTX display(LCD_W, LCD_H); Cl_lcd2004_i2c lcd(0x3F);//0x27 #endifmenu.h
/*menu.h*/ #ifndef MENU_H #define MENU_H #include "Cl_btn.h" Cl_btn BtnS(/*пин*/2); //кнопка селект Cl_btn BtnU(/*пин*/3); //кнопка верх Cl_btn BtnD(/*пин*/4); //кнопка вниз //--------------- меню--------------------------------------------- #include "lcd2004_i2c.h" void goPage(byte p); // перейти на страницу p void menu_init(); // инициализировать меню void menu_run(); // текущая работа // обозначение страницы меню - что делает const byte page0 = 0;//гашение экрана const byte page1 = 10;//ноказ настроек const byte page2 = 20;//поменять индекс устройства const byte page3 = 30;//изменение байтовой части const byte page4 = 40;//изменение интовой части const byte page5 = 50;//изменение флоат части const byte page6 = 60; //сброс настроек byte page; unsigned long past; void goPage(byte p) { past = millis(); page = p; GTX display(LCD_W, LCD_H); switch (page) { case page0: BtnS.Do = [] {goPage(page1);}; BtnU.Do = [] {goPage(page1);}; BtnD.Do = [] {goPage(page1);}; lcd.noBacklight(); break; case page1: BtnS.Do = [] {goPage(page2);}; BtnU.Do = [] {}; BtnD.Do = [] {}; lcd.backlight(); display << xy(0, 0) << F("info:"); display << xy(0, 1) << F(" byte(") << index << F(")=") << (eeprom_B[index]); // вывод байтовой части display << xy(0, 2) << F(" int(") << index << F(")=") << (eeprom_I[index]); // вывод интовой части display << xy(0, 3) << F("float(") << index << F(")=") << (eeprom_F[index]); // вывод флоат части break; case page2: BtnS.Do = [] {goPage(page3);}; BtnU.Do = [] { if (index < (max_index - 1))index++; goPage(page2); }; BtnD.Do = [] { if (index > 0)index--; goPage(page2); }; display << xy(0, 0) << F("set index:") << index; break; case page3: BtnS.Do = [] {goPage(page4);}; BtnU.Do = [] { if (eeprom_B[index] <= 200)eeprom_B[index] += 10 ; goPage(page3); }; BtnD.Do = [] { if (eeprom_B[index] >= 50)eeprom_B[index] -= 10; goPage(page3); }; display << xy(0, 0) << F("set byte(") << index << F(")=") << (eeprom_B[index]); // вывод байтовой части break; case page4: BtnS.Do = [] {goPage(page5);}; BtnU.Do = [] { if (eeprom_I[index] <= 2000)eeprom_I[index] += 100; goPage(page4); }; BtnD.Do = [] { if (eeprom_I[index] >= 500)eeprom_I[index] -= 100; goPage(page4); }; display << xy(0, 0) << F("set int(") << index << ")=" << (eeprom_I[index]); // вывод интовой части break; case page5: BtnS.Do = [] {goPage(page6);}; BtnU.Do = [] { if (eeprom_F[index] <= 20.30)eeprom_F[index] += 1.01; goPage(page5); }; BtnD.Do = [] { if (eeprom_F[index] >= 5.05) eeprom_F[index] -= 1.01; goPage(page5); }; display << xy(0, 0) << F("set float(") << index << F(")=") << (eeprom_F[index]); // вывод флоат части break; case page6: BtnS.Do = [] {goPage(page1);}; BtnU.Do = [] { if (setting_index < (max_setting_index - 1)) { setting_index++; eeprom_B[index] = pgm_B[setting_index]; eeprom_I[index] = pgm_I[setting_index]; eeprom_F[index] = pgm_F[setting_index]; } goPage(page6); }; BtnD.Do = [] { if (setting_index > 0) { setting_index--; eeprom_B[index] = pgm_B[setting_index]; eeprom_I[index] = pgm_I[setting_index]; eeprom_F[index] = pgm_F[setting_index]; } goPage(page6); }; display << xy(0, 0) << F("setting(") << setting_index << F(")"); display << xy(0, 1) << F(" byte(") << index << F(")=") << (eeprom_B[index]); // вывод байтовой части display << xy(0, 2) << F(" int(") << index << F(")=") << (eeprom_I[index]); // вывод интовой части display << xy(0, 3) << F("float(") << index << F(")=") << (eeprom_F[index]); // вывод флоат части break; } lcd.show(display); } void menu_init() { BtnS.init(); BtnU.init(); BtnD.init(); lcd.init(); goPage(page1); } void menu_run() { BtnS.run(); BtnU.run(); BtnD.run(); switch (page) { case page0: break; default: if (millis() - past >= 10000)goPage(page0);// если долго не щелкают по кнопкам то погасить экран break; } } #endifПодброшу еще один вариант Меню на LCD Keypad Shield с текстами на 5 песенок размещенных в PROGMEM
/*mmenuPgmKeyShield*/ //------------------------------------------ void func_P(byte n, const char * title, ... ); void txtPage1(byte n);// текст стр 1 void txtPage2(byte n);// текст стр 2 void txtPage3(byte n);// текст стр 3 void txtPage4(byte n);// текст стр 4 void txtPage5(byte n);// текст стр 5 //Cl_analog.h-------------------------------- typedef void (*pDo)() ;// тип -функция обработчик class Cl_analog { public: pDo Do_Right , Do_Up, Do_Down, Do_Left , Do_Select; Cl_analog() = delete; Cl_analog(byte _pin); /**/ void init(); void run(); protected: static const byte sNone = 0; static const byte sRight = 1; static const byte sUp = 2; static const byte sDown = 3; static const byte sLeft = 4; static const byte sSelect = 5; const byte pin; byte state; uint32_t past; void set(byte s); byte read(); }; //Cl_analog.cpp-------------------------------- Cl_analog::Cl_analog(byte p): pin(p) {} /**/ void Cl_analog::set(byte s) { state = s; past = millis(); switch (state) { case sNone: break; case sRight: Do_Right(); break; case sUp: Do_Up(); break; case sDown: Do_Down(); break; case sLeft: Do_Left(); break; case sSelect: Do_Select(); break; } } byte Cl_analog::read() { int value = analogRead(pin); if (value < 110) return sRight; else if (value < 200) return sUp; else if (value < 400) return sDown; else if (value < 600) return sLeft; else if (value < 800) return sSelect; else return sNone; } void Cl_analog::init() { Do_Right = Do_Up = Do_Down = Do_Left = Do_Select = [] {}; set(sNone); } void Cl_analog::run() { if (past - millis() >= 100) { byte s = read(); switch (state) { case sNone: if (s != state)set(s); break; default: if (s == sNone)set(sNone); if (millis() - past >= 300)set(sNone); break; } } } Cl_analog Keys(/*пин*/A0); //menu------------------------------------------------------------- #include <LiquidCrystal.h> LiquidCrystal lcd(/*RS*/8,/*Enable*/9,/*DB4*/4,/*DB5*/5,/*DB6*/6,/*DB7*/7); const byte pageN = 0;// погасить экран const byte page0 = 5;// главный экран const byte page0a = 6; const byte page1 = 10;// страница 1 const byte page1a = 11; const byte page2 = 20;// страница 2 const byte page2a = 21; const byte page3 = 30;// страница 3 const byte page3a = 31; const byte page4 = 40;// страница 4 const byte page4a = 41; const byte page5 = 50;// страница 5 const byte page5a = 51; byte page; // текущая страница uint32_t past;// крайний millis() смены отображения int line, maxLine;// текущая строка и мах кол-во строк void goPage(byte p) { page = p; past = millis(); lcd.clear(); switch (page) { case pageN:// погасить экран lcd.noDisplay(); Keys.Do_Right = [] {goPage(page0);}; Keys.Do_Up = [] {goPage(page0);}; Keys.Do_Down = [] {goPage(page0);}; Keys.Do_Left = [] {goPage(page0);}; Keys.Do_Select = [] {goPage(page0);}; break; case page0: // страница 0 lcd.display(); Keys.Do_Left = [] {}; Keys.Do_Right = [] {goPage(page1);}; Keys.Do_Up = [] {goPage(page0a);}; Keys.Do_Down = [] {goPage(page0a);}; Keys.Do_Select = [] {goPage(page0a);}; case page0a: lcd.print("Songs"); break; case page1:// страница 1 Keys.Do_Left = [] {goPage(page0);}; Keys.Do_Right = [] {goPage(page2);}; Keys.Do_Up = [] { if (line > 0) --line; goPage(page1a); }; Keys.Do_Down = [] { if (line < (maxLine - 2)) ++line; goPage(page1a); }; line = 0; case page1a: txtPage1(line); lcd.setCursor(0, 1); txtPage1(line + 1); break; case page2:// страница 2 Keys.Do_Left = [] {goPage(page1);}; Keys.Do_Right = [] {goPage(page3);}; Keys.Do_Up = [] { if (line > 0) --line; goPage(page2a); }; Keys.Do_Down = [] { if (line < (maxLine - 2)) ++line; goPage(page2a); }; line = 0; case page2a: txtPage2(line); lcd.setCursor(0, 1); txtPage2(line + 1); break; case page3:// страница 3 Keys.Do_Left = [] {goPage(page2);}; Keys.Do_Right = [] {goPage(page4);}; Keys.Do_Up = [] { if (line > 0) --line; goPage(page3a); }; Keys.Do_Down = [] { if (line < (maxLine - 2)) ++line; goPage(page3a); }; line = 0; case page3a: txtPage3(line); lcd.setCursor(0, 1); txtPage3(line + 1); break; case page4:// страница 4 Keys.Do_Left = [] {goPage(page3);}; Keys.Do_Right = [] {goPage(page5);}; Keys.Do_Up = [] { if (line > 0) --line; goPage(page4a); }; Keys.Do_Down = [] { if (line < (maxLine - 2)) ++line; goPage(page4a); }; line = 0; case page4a: txtPage4(line); lcd.setCursor(0, 1); txtPage4(line + 1); break; case page5:// страница 5 Keys.Do_Left = [] {goPage(page4);}; Keys.Do_Right = [] {}; Keys.Do_Up = [] { if (line > 0) --line; goPage(page5a); }; Keys.Do_Down = [] { if (line < (maxLine - 2)) ++line; goPage(page5a); }; line = 0; case page5a: txtPage5(line); lcd.setCursor(0, 1); txtPage5(line + 1); break; } } void initMenu() { lcd.begin(16, 2); goPage(page0); Keys.init(); } void runMenu() { Keys.run(); if (page != pageN && millis() - past >= 3000)goPage(pageN); } //---------------------------------------- void func_P(byte n, const char * title, ... ) { va_list ap; const char * message; int i = 0; va_start( ap, title ); if (n == i)lcd.print((const __FlashStringHelper *)title); message = va_arg( ap, const char * ); while (message) { ++i; if (n == i) lcd.print((const __FlashStringHelper *)message); message = va_arg( ap, const char *); } va_end( ap ); } void txtPage1(byte n) { // текст стр 1 maxLine = 15; func_P( n, PSTR("1-Jingle bells"), PSTR("Dashing through the snow,"), PSTR("in a one - horse open sleigh."), PSTR("O'er the fields we go,"), PSTR("laughing all the way."), PSTR("Bells on bobtails ring,"), PSTR("making spirits bright."), PSTR("What fun it is to ride and sing"), PSTR("a sleighing song tonight."), PSTR(""), PSTR("Oh! Jingle bells, jingle bells,"), PSTR("jingle all the way."), PSTR("Oh what fun it is to ride"), PSTR("in a one-horse open sleigh. Hey!"), PSTR("---end---"), 0 //<-- конец ); } void txtPage2(byte n) { // текст стр 2 maxLine = 19; func_P( n, PSTR("2-Canoa virou"), PSTR("A canoa virou"), PSTR("Por deixa-la virar"), PSTR("Foi por causa do Indiozinho"), PSTR("Que nao soube remar"), PSTR("Se eu fosse um peixinho"), PSTR("E soubesse nadar"), PSTR("Eu tirava o Indiozinho"), PSTR("Do fundo do mar"), PSTR(""), PSTR("A canoa virou"), PSTR("Por deixa-la virar"), PSTR("Foi por causa da Julia"), PSTR("Que nao soube remar"), PSTR("Se eu fosse um peixinho"), PSTR("E soubesse nadar"), PSTR("Eu tirava a Julia"), PSTR("Do fundo do mar"), PSTR("---end---"), 0 //<-- конец ); } void txtPage3(byte n) { // текст стр 3 maxLine = 6; func_P( n, PSTR("3-Sapo Cururu"), PSTR("Sapo Cururu na beira do rio"), PSTR("Quando o sapo canta, ô maninha, E porque tem frio"), PSTR("A mulher do sapo, deve estar la dentro"), PSTR("Fazendo rendinha, ô maninha, para o casamento"), PSTR("---end---"), 0 //<-- конец ); } void txtPage4(byte n) { // текст стр 4 maxLine = 19; func_P( n, PSTR("4-Baratinha"), PSTR("A barata diz que tem"), PSTR("Sete saias de filo"), PSTR("E mentira da barata"), PSTR("Ela tem E uma so"), PSTR("Ra ra ra, ro ro ro"), PSTR("Ela tem E uma so"), PSTR("Ra ra ra, ro ro ro"), PSTR("Ela tem E uma so"), PSTR(""), PSTR("A barata diz que tem"), PSTR("Um anel de formatura"), PSTR("E mentira da barata"), PSTR("Ela tem a casca dura"), PSTR("Ra ra ra, ro ro ro"), PSTR("Ela tem a casca dura"), PSTR("Ra ra ra, ro ro ro"), PSTR("Ela tem a casca dura"), PSTR("---end---"), 0 //<-- конец ); } void txtPage5(byte n) { // текст стр 5 maxLine = 16; func_P( n, PSTR("5 - Dona Aranha"), PSTR(""), PSTR("A Dona Aranha subiu pela parede"), PSTR("veio a chuva forte e a derrubou"), PSTR("Ja passou a chuva, o sol ja vem surgindo"), PSTR("e a Dona Aranha continua a subir"), PSTR("Ela E teimosa e desobediente"), PSTR("sobe, sobe, sobe e nunca esta contente"), PSTR(""), PSTR("A Dona Aranha desceu pela parede"), PSTR("veio a chuva forte e a derrubou"), PSTR("Ja passou a chuva, o sol ja vem surgindo"), PSTR("e a Dona Aranha continua a descer"), PSTR("Ela E teimosa e desobediente"), PSTR("desce, desce, desce e nunca esta contente"), PSTR("-- -end-- -"), 0 //<-- конец ); } //---------------------------------------- void setup() { Serial.begin(9600); initMenu(); } void loop() { runMenu(); }