буфер по умолчанию в библиотеке wire

okta
Offline
Зарегистрирован: 10.01.2015

В библиотеке wire буфер выставлен 32 байта. Но при попытке записать массив в 32 байта  во внешнюю i2c eeprom - т.е. всю страницу записать пытаюсь (у меня сейчас AT24C32 - судя по datasheet там можно сразу страницами по 32 байта записывать) - из 32 байт пишется 30. Делаю так:

#include <Wire.h>

#define memAdr 0x50

void setup() {
  Wire.begin();
  Serial.begin(9600);
  byte dat[32];
  for(byte i=0;i<32;i++){
    dat[i]=110-i;
  }
  Wire.beginTransmission(memAdr);
  Wire.write(0);   // Hba
  Wire.write(0);   // Lba
  Wire.write(dat,32);
  Wire.endTransmission();
  delay(20);
}

Посмотрел код библиотеки - там функциями write в буфер загонятеся (int)адрес ячейки памяти (как раз те самые не достающие 2 байта), а потом данные. Это у меня библиотека кривая, или так и должно быть и я что-то не понимаю? Код из библиотеки:

// must be called in:
// slave tx event callback
// or after beginTransmission(address)
size_t TwoWire::write(uint8_t data)
{
  if(transmitting){
  // in master transmitter mode
    // don't bother if buffer is full
    if(txBufferLength >= BUFFER_LENGTH){
      setWriteError();
      return 0;
    }
    // put byte in tx buffer
    txBuffer[txBufferIndex] = data;
    ++txBufferIndex;
    // update amount in buffer   
    txBufferLength = txBufferIndex;
  }else{
  // in slave send mode
    // reply to master
    twi_transmit(&data, 1);
  }
  return 1;
}

// must be called in:
// slave tx event callback
// or after beginTransmission(address)
size_t TwoWire::write(const uint8_t *data, size_t quantity)
{
  if(transmitting){
  // in master transmitter mode
    for(size_t i = 0; i < quantity; ++i){
      write(data[i]);
    }
  }else{
  // in slave send mode
    // reply to master
    twi_transmit(data, quantity);
  }
  return quantity;
}

Вобщем, кто уже с этим боролся? Я пока увеличил буфер в TWI и в WIRE, но это какое-то кривое решение - малоли как другие библиотеки использующие I2C эти константы используют... Можно, конечно, напрямую из TWI функции подергать... Но тогда уж проще под себя пилить, под конкретную задачу. А хочется готовой универсальности :)

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

Что-то мне подсказывает, что буфер в себя включает в том числе адрес. Двухбайтный.

okta
Offline
Зарегистрирован: 10.01.2015

Yarik.Yar пишет:

Что-то мне подсказывает, что буфер в себя включает в том числе адрес. Двухбайтный.

Спасибо, Кэп! Некст тайм читаем плз дальше первых двух строк :)

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

На здоровье.

Нет, либа не кривая. С чего бы ей быть кривой? Просто создатели выставили размер буфера в 32 байта. 

Если что-то непонятно - обратитесь к спецификациям интерфейса, узнайте, что и как, как передача происходит и прочее.

"Теперь ваша душенька довольна?"©

okta
Offline
Зарегистрирован: 10.01.2015

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

Я перефразирую вопрос. Просто увеличив буфера... о как :) я кроме как на расход памяти вроде как ни на что не влияю. Кто-то же внешнюю eeprom использовал совместно с другими i2c? Или все побайтово пишут в память? Пока у меня ощущение, что 32 выбрано как в анекдоте, про то как считают программисты - 34 "нечетное" :)

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

Yarik.Yar пишет:

Просто создатели выставили размер буфера в 32 байта. 

Нет никакого ограничения. Что по кайфу, то и делайте с размером буфера.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

okta пишет:

if(txBufferLength >= BUFFER_LENGTH){ setWriteError(); return 0; } }

Ты чего хотел-то? На этих строчках последние два байта из переданных тобой как байты данных и обрежутся. Буфер в Wire общий для адреса и для данных, так что - как есть: максимум, что ты сможешь передать - это 30 байт данных. Все вызовы write - это просто запись во внутренний буфер (ну да ты знаешь, раз код смотрел), актуальная передача - по endTransmission, такой вот механизм избран.

Так что выход один - увеличивать буфер, других вариантов не видно.

З.Ы. Ты ещё не видел косяков в стандартной либе Ethernet - там вообще прямо в комментарии сказано, что код не работает так, как надо :)))) Я уже привык :)

 

 

 
 
 

 

 

 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Уважаемые, а какой теоретически-возможный предел размера буфера Wire? 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Очевидно, он может превышать размер оперативной памяти.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

andriano пишет:

Очевидно, он может превышать размер оперативной памяти.

Это понятно. Но так-же очевидно, что разраб установил такой дефолтный предел не потому, что дальше 31 считать не умел. Был же какой-то смысл в этом ограничении?

sadman41
Offline
Зарегистрирован: 19.10.2016

Надо спросить у Nicholas Zambetti. Может у него номер дома - 32,

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Rumata пишет:

Это понятно. Но так-же очевидно, что разраб установил такой дефолтный предел не потому, что дальше 31 считать не умел. Был же какой-то смысл в этом ограничении?

Вообще-то при объеме памяти контроллера 2к экономить приходится каждый байт. Очевидно, что если при подключении Wire памяти больше не останется, это никого не устроит. Поэтому 32 байта - результат компромисса. В принципе, посмотрите тип переменных, которыми описывается дина/заполнение буфера. Если они двухбайтовые, то скорее всего, единственное ограничение указано в сообщении №8.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

andriano пишет:

Вообще-то при объеме памяти контроллера 2к экономить приходится каждый байт. Очевидно, что если при подключении Wire памяти больше не останется, это никого не устроит. Поэтому 32 байта - результат компромисса. В принципе, посмотрите тип переменных, которыми описывается дина/заполнение буфера. Если они двухбайтовые, то скорее всего, единственное ограничение указано в сообщении №8.

Да, спасибо, уже вроде теоретически разобрался с этим вопросом. На ЕСП проблема дефицита SRAM не так остро стоит, как на AVR. Но в любом случае, мне под мои задачи восьмибитной длины буфера хватит. Завтра потестирую с AT24C32 на ds3231.

5N62V
Offline
Зарегистрирован: 25.02.2016

okta пишет:

В библиотеке wire буфер выставлен 32 байта. Но при попытке записать массив в 32 байта  во внешнюю i2c eeprom - т.е. всю страницу записать пытаюсь (у меня сейчас AT24C32 - судя по datasheet там можно сразу страницами по 32 байта записывать) - из 32 байт пишется 30. ...

Вобщем, кто уже с этим боролся? Я пока увеличил буфер в TWI и в WIRE, но это какое-то кривое решение - малоли как другие библиотеки использующие I2C эти константы используют... 

Вы сами себе создали проблему , и теперь героически пытаетесь ее решить. Я буквально вчера писал библиотеку для ЕЕПРОМки у которой страница 64 байта, и никаких трудностей не встретил.

//________________________________________________________________________________________EEPROM WRITE PAGE 
uint8_t EEPROMwritePage(const unsigned int address, uint8_t* buf, const uint8_t len) {
    uint8_t cs = 0;
    EEPROMsendAddr(address);
    for (uint8_t i = 0; i < len; i++) {
        uint8_t b = *(buf + i);
        Wire.write(b); cs |= b;
    }
    Wire.endTransmission();
    return cs;
}
//________________________________________________________________________________________EEPROM APPLY TO DEVICE AND SET ADDR
void EEPROMsendAddr(unsigned int address) {
    Wire.beginTransmission(EEPROM_I2C_ADDR);
    Wire.write((address >> 8) & 0xFF);
    Wire.write((address & 0xFF));
}

 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019
// Wire.h:

#define I2C_BUFFER_LENGTH 128

По умолчанию

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

а завтра ты поставишь новую версию IDE, забудешь про свои правки и будешь до крови мучительно долго чесать плешь на затылке, не понимая, что произошло, "ведь токашто всё работало".  Ситуация усугубится еще и тем, что, накатив опять старую рабочую версию IDE, ошибки не уйдут, ибо ты просто затёр все свои исправления.  Останется только искать по хозяйственным крепкую табуретку и скользкое ароматное мыло. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

5N62V пишет:

 Я буквально вчера писал библиотеку для ЕЕПРОМки у которой страница 64 байта, и никаких трудностей не встретил.

//________________________________________________________________________________________EEPROM WRITE PAGE 
uint8_t EEPROMwritePage(const unsigned int address, uint8_t* buf, const uint8_t len) {
    uint8_t cs = 0;
    EEPROMsendAddr(address);
    for (uint8_t i = 0; i < len; i++) {
        uint8_t b = *(buf + i);
        Wire.write(b); cs |= b;
    }
    Wire.endTransmission();
    return cs;
}
//________________________________________________________________________________________EEPROM APPLY TO DEVICE AND SET ADDR
void EEPROMsendAddr(unsigned int address) {
    Wire.beginTransmission(EEPROM_I2C_ADDR);
    Wire.write((address >> 8) & 0xFF);
    Wire.write((address & 0xFF));
}

 

твой код нерабочий при len>30.

Особенно порадовала строчка cs |= b

на случайных данных, ты в 99% случаев будешь возвращать число, близкое или равное 0xFF.

если это должна быть типа контрольная сумма (чего?) то решение не просто неудачное, а феерический facepalm. 

5N62V
Offline
Зарегистрирован: 25.02.2016

DetSimen пишет:

твой код нерабочий при len>30.

Вообще-то вчерась успешно таким образом писал куски по 68 байт. Специально брал больше страницы, чтоб проверить работу нескольких обращений к данной фукции. 

Но скорее всего у Вас есть аргументы. :)

DetSimen пишет:

Особенно порадовала строчка cs |= b

на случайных данных, ты в 99% случаев будешь возвращать число, близкое или равное 0xFF.

если это должна быть типа контрольная сумма (чего?) то решение не просто неудачное, а феерический facepalm. 

ага, чушь написал. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

5N62V пишет:

Вообще-то вчерась успешно таким образом писал куски по 68 байт. 

Какие ваши доказательства? 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

DetSimen пишет:

а завтра ты поставишь новую версию IDE, забудешь про свои правки и будешь до крови мучительно долго чесать плешь на затылке, не понимая, что произошло, "ведь токашто всё работало". 

Если это мне, то 128 стоит по умолчанию в Wire.h из СДК ESP32 версии 1.0.4. Я ничего не правлю в чужих библиотеках ))

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019
uint8_t EEPROMwritePage(const unsigned int address, void* buf, const size_t len)

Так, мне кажется более универсально было бы

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ну, если речь за ESP32, тада я беру всё сказанное взат. 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

На гите есть библа для FRAM. Пример порадовал 8-D

#include "FM24I2C.h"

FM24I2C fm(0x57);

void setup() {
  Wire.begin();
  Serial.begin(9600);
  char str1[]="12345678901234567890";
  char str2[]="qwertyuiopasdfghjklzxcvbnm";
  int a1=0x00;
  int a2=0x40;
  fm.pack(a1,str1,strlen(str1)+1);
  delay(5);
  fm.pack(a2,str2,strlen(str2)+1);
  delay(5);
  char buf[80];
  fm.unpack(a2,buf,strlen(str2)+1);
  Serial.println(str2);
  fm.unpack(a1,buf,strlen(str1)+1);
  Serial.println(str1);
}

void loop() {
  // put your main code here, to run repeatedly:

}

 

5N62V
Offline
Зарегистрирован: 25.02.2016

DetSimen пишет:

Какие ваши доказательства? 

То есть к рабочему коду надо еще прилагать доказательства? :))

Вот мой черновик, я сначала добился чтоб работал этот код. 

#include <Wire.h>

#define EEPROM_I2C_ADDR 0x57
#define EEADR_WPNO 0x40
#define EEPROM_DATA_ADDR 0x5800
#define EEPROM_DATA_CS_ADDR 0x7000

#define PAGE_SIZE 64

struct _parameters {
  int a;
  int b;
  int c;
  int d;
  int e;
  int f;
  int g;
  int h;
  int k;
  int l;
  int m;
  int n;
  int o;
  int p;
  int q;
  int r;
  int s;
  void incr() {
    a += 12; b += 13; c += 15; s += 14;
  }
};

_parameters parameters;
_parameters temp = {0};

void setup()
{
  Wire.begin();

  SerialUSB.begin(115200);
  delay(3000);

}


void loop()
{
  temp.incr();
  parameters = temp;
  uint8_t* ptr = (uint8_t*)&parameters;
  //EEPROM_write_parameters();
  EEPROMwriteByteSeq(EEPROM_DATA_ADDR, sizeof(parameters), ptr);
  delay(10);
  memset(ptr, 0, sizeof(parameters));
  //bool flag = EEPROM_read_parameters();
  //SerialUSB.println(flag?"OK":"BAD");

  EEPROMreadByteSeq(EEPROM_DATA_ADDR, sizeof(parameters), ptr);
  SerialUSB.print(parameters.a); SerialUSB.print( " "); SerialUSB.print(parameters.b); SerialUSB.print( " "); SerialUSB.print(parameters.c); SerialUSB.print( " "); SerialUSB.println(parameters.s);
  delay(10);
  SerialUSB.println(EEPROMreadByte(EEPROM_DATA_ADDR + PAGE_SIZE));


  delay(1000);
}

void EEPROMreadByteSeq(unsigned int address, uint32_t len, uint8_t *buf) {
  EEPROMsendAddr(address);
  Wire.endTransmission();
  for (uint8_t i = 0; i < len; i++) {
    Wire.requestFrom(EEPROM_I2C_ADDR, 1);
    *(buf + i) = Wire.read();
  }
}

byte EEPROMreadByte(unsigned int address)
{
  byte read_data = 0;
  EEPROMsendAddr(address);
  Wire.endTransmission();
  Wire.requestFrom(EEPROM_I2C_ADDR, 1);
  read_data = Wire.read();
  return read_data;
}
//________________________________________________________________________________________EEPROM WRITE BYTE
void EEPROMwriteByte(unsigned int address, byte data)
{
  EEPROMsendAddr(address);
  Wire.write(data);
  Wire.endTransmission();
}

void EEPROMwriteByteSeq(unsigned int address, uint32_t len, uint8_t* buf) {
  if (len == 0) return;
  if (len <= 64)EEPROMwritePage(address, buf, len);
  else {
    uint8_t pages = len / PAGE_SIZE;
    if (len - pages * PAGE_SIZE != 0) pages++;
    uint32_t remainedBytes = len;
    for (uint8_t i = 0; i < pages; i++) {
      if (remainedBytes >= PAGE_SIZE) {
        EEPROMwritePage(address, buf + i * PAGE_SIZE , PAGE_SIZE);
        address += PAGE_SIZE; remainedBytes -= PAGE_SIZE;
      }
      else EEPROMwritePage(address, buf + (pages - 1)* PAGE_SIZE, remainedBytes);

    }
  }
}


void EEPROMwritePage(unsigned int address, uint8_t *buf, uint8_t len ) {
  EEPROMsendAddr(address);
  for (uint8_t i = 0; i < len; i++) Wire.write(*(buf + i));
  Wire.endTransmission();
  delay(5);
}

void EEPROMsendAddr(unsigned int address) {
  Wire.beginTransmission(EEPROM_I2C_ADDR);
  Wire.write((address >> 8) & 0xFF);
  Wire.write((address & 0xFF));
}

В монитор выдается: 

12 13 15 14
14
24 26 30 28
28
36 39 45 42
42
48 52 60 56
56
60 65 75 70
70
72 78 90 84
84
84 91 105 98
98
96 104 120 112
112
108 117 135 126
126
120 130 150 140
140
132 143 165 154
154
144 156 180 168
168
156 169 195 182
182
168 182 210 196
196
180 195 225 210
210
192 208 240 224
224
204 221 255 238
238

Я сделал вывод что код рабочий. В проекте он тоже заработал так, как я предполагал. 

5N62V
Offline
Зарегистрирован: 25.02.2016

Кстати, вот этот кусок : 

uint8_t pages = len / PAGE_SIZE;
if (len - pages * PAGE_SIZE != 0) pages++;

Я сначала написал так: uint8_t pages = len/PAGE_SIZE + (len%PAGE_SIZE)? 1:0;

Но чей-то  условие не работало. Что не так?

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

если это код для STM, то вполне вероятно, что он работает как надо. Моё замечание касается AVR

GarryC
Offline
Зарегистрирован: 08.08.2016

А это передайте громадный привет создателям С с их неявными (и не очевидными) приоритетами операций, ваш код будет исполняться, как (len / PAGE_SIZE + (len % PAGE_SIZE)) ? 1:0 с очевидным результатом 1 либо 0 :)

Очевидное решение - поставить скобки len / PAGE_SIZE + ((len % PAGE_SIZE) ? 1:0, но, к счастью, есть более правильное решение (len + PAGE_SIZE - 1) / PAGE_SIZE.

5N62V
Offline
Зарегистрирован: 25.02.2016

GarryC пишет:

 есть более правильное решение (len + PAGE_SIZE - 1) / PAGE_SIZE.

Семен Семеныч! :) я ж это даже где-то применял, но забыл, что обидно :) Благодарю!

Rumata пишет:

uint8_t EEPROMwritePage(const unsigned int address, void* buf, const size_t len)

Так, мне кажется более универсально было бы

100% согласен! Спасибо за подсказку. Ведь можно и строки на еепромке хранить! 

 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Набросал класс для записи/чтения любых объектов (пока кроме литералов) любых размеров в i2c EEPROM. Пока физически в наличии только ат24с32. На днях проверю с ат24с256 (там другой размер страницы). Пока не понимаю, как реализовать автоопределение, поэтому выбор через соответствующий дефайн. Работает на ESP32 с I2C_BUFFER_LENGTH 128. По идее должна и с 32 нормально работать на AVR. 

Корифеи, если не лень, потыкайте пожалуйста  в ошибки

#include "Wire.h"
#define EEPROM_I2C_ADDR 0x57

#define AT24C32
//#define AT24C64
//#define AT24C128
//#define AT24C256
//#define AT24C512
#ifdef AT24C32
#define maxaddr   4095
#define pageSize  32
#endif
#ifdef AT24C64
#define maxaddr   8191
#define pageSize  32
#endif
#ifdef AT24C128
#define maxaddr   16383
#define pageSize  64
#endif
#ifdef AT24C256
#define maxaddr   32768
#define pageSize  64
#endif
#ifdef AT24C512
#define maxaddr   65535
#define pageSize  64
#endif


class i2cEEPROM {
  public:
    i2cEEPROM(uint8_t addr) {_i2cAddr = addr;}
    //~i2cEEPROM();
    uint16_t write(uint16_t addr, void* buf, size_t len);  // Запись в EEPROM. 
    uint16_t read(uint16_t addr, void* buf, size_t len);
    void printDump(uint16_t pages);

  private:
    uint8_t  _i2cAddr;
    uint16_t  pageWrite(uint16_t addr, void* buf, size_t len);
    uint16_t  pageRead(uint16_t addr, void* buf, size_t len);
    uint16_t  firstPageAddr(uint16_t page);
};


uint16_t i2cEEPROM::write(uint16_t addr, void* buf, size_t len) {
  if ((addr + len) > maxaddr) return 0;
  uint16_t thisPage = addr / pageSize;
  uint16_t count = 0;
  if (thisPage == (addr + len) / pageSize) {
    count = pageWrite(addr, buf, len);
    return count;
  }
  else {
    count = pageWrite(addr, buf, firstPageAddr(thisPage + 1) - addr);
    thisPage++;
    while ((len - count) > pageSize) {
      count += pageWrite(firstPageAddr(thisPage), (uint8_t*)buf + count, pageSize);
      thisPage++;
    }
    count += pageWrite(firstPageAddr(thisPage), (uint8_t*)buf + count, len - count);
  }
  return count;
}


uint16_t i2cEEPROM::read(uint16_t addr, void* buf, size_t len) {
  if ((addr + len) > maxaddr) return 0;
  //uint8_t* dat = (uint8_t*)buf;
  uint16_t ctr = 0;

  if (len <= I2C_BUFFER_LENGTH - 2) {
    ctr = pageRead(addr, buf, len);
    return ctr;
  }
  else {
    uint16_t twiPages = 0;
    while ((len - ctr) > (I2C_BUFFER_LENGTH - 2)) {
      ctr += pageRead(addr + ((I2C_BUFFER_LENGTH - 2) * twiPages), (uint8_t*)buf + ctr, (I2C_BUFFER_LENGTH - 2));
      twiPages++;
    }
    ctr += pageRead(addr + ((I2C_BUFFER_LENGTH - 2) * twiPages), (uint8_t*)buf + ctr, len - ctr);
  }
  return ctr;
}


uint16_t i2cEEPROM::pageWrite(uint16_t addr, void* buf, size_t len) {
  uint16_t ctr = 0;
  Wire.beginTransmission(_i2cAddr);
  Wire.write(addr >> 8);
  Wire.write(addr & 0xFF);
  for (uint8_t i = 0; i < len; i++) {
    ctr += Wire.write(*((uint8_t*)buf) + i);
  }
  Wire.endTransmission();
  delay(5);
  return ctr;
}


uint16_t i2cEEPROM::pageRead(uint16_t addr, void* buf, size_t len) {
  uint8_t* dat = (uint8_t*)buf;
  Wire.beginTransmission(_i2cAddr);
  Wire.write(addr >> 8);
  Wire.write(addr & 0xFF);
  Wire.endTransmission(false);
  Wire.requestFrom(_i2cAddr, len);
  for (uint8_t i = 0; i < len; i++) {
    *(dat + i) = Wire.read();
  }
  Wire.endTransmission();
  return len;
}

// Печатаем на экран содержимое EEPROM для визуального контроля
void i2cEEPROM::printDump(uint16_t pgs){
  Serial.print('\n'); 
  Serial.print("Page size: "); Serial.println(pageSize);
  Serial.print("Memory dump of "); Serial.print(pgs);Serial.println(" pages:");
  for (uint8_t r = 0; r < pgs; r++) {    
    Serial.print(r, HEX); Serial.print(": ");
    uint16_t addr = r * pageSize;
    Wire.beginTransmission(_i2cAddr);
    Wire.write(addr >> 8);
    Wire.write(addr & 0xFF);
    Wire.endTransmission(false);
    Wire.requestFrom((int)_i2cAddr, (int)pageSize);
      for(uint8_t i = 0; i < pageSize; i++){
        Serial.print(Wire.read(), HEX); Serial.print(" ");
      }
    Serial.print('\n');
  } 
  Serial.print('\n'); 
}


uint16_t i2cEEPROM::firstPageAddr(uint16_t page) {
  return (page * pageSize);
}



void setup() {
  Wire.begin();
  Serial.begin(115200);
  i2cEEPROM i2c(EEPROM_I2C_ADDR);
  uint8_t ts[350];
  uint8_t dta = 0;
  for (uint16_t i = 0; i < sizeof(ts); i++) {
    ts[i] = dta++; if (dta> 255) dta = 0;
  }
  uint16_t address = 10;
  Serial.print("Write to EEPROM: ");
  Serial.println(i2c.write(address, &ts, sizeof(ts)));
  uint8_t rs[350];
  Serial.print("Read from EEPROM: ");
  Serial.println(i2c.read(address, &rs, sizeof(rs)));
  for (uint16_t i = 0; i < sizeof(rs); i++) {
  if ((i+1)%30) {Serial.print(rs[i]); Serial.print(" ");}
  else Serial.println(rs[i]);
  }
  i2c.printDump(16);
}


void loop() {}

Результат

Write to EEPROM: 350
Read from EEPROM: 350
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 
Page size: 32
Memory dump of 16 pages:
0: 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 
1: 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 
2: 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 
3: 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 
4: 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 
5: 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 
6: B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 
7: D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 
8: F6 F7 F8 F9 FA FB FC FD FE FF 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 
9: 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 
A: 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 
B: 56 57 58 59 5A 5B 5C 5D 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
C: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
D: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
E: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
F: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Если я правильно помню, в eeprom размер страницы зависит от объёма и прописан в дпташитах, введите define в скетче с объёмом и от него считайте.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

andycat пишет:
Если я правильно помню, в eeprom размер страницы зависит от объёма и прописан в дпташитах, введите define в скетче с объёмом и от него считайте.

Ну так ровно это сейчас уже и сделано. 

 

В строке 95 ошибка. должно быть

    ctr += Wire.write(*(((uint8_t*)buf) + i));

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Rumata пишет:
Корифеи, если не лень, потыкайте пожалуйста  в ошибки
Про правило пяти Вы наверное не знали.  https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%BE_%D1%82%D1%80%D1%91%D1%85_(C%2B%2B)#%D0%9F%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D0%BE_%D0%BF%D1%8F%D1%82%D0%B8

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

qwone пишет:
Про правило пяти Вы наверное не знали.

Да, с этим нужно что-то делать

5N62V
Offline
Зарегистрирован: 25.02.2016

Rumata пишет:

 Пока не понимаю, как реализовать автоопределение, поэтому выбор через соответствующий дефайн. 

Я не в курсе можно ли реализовать такое .  Для флешек есть там какие-то идентификаторы 3х байтовые, JEDEC ID . В нем зашифрован производитель, тип и объем, по поводу архитектуры не уверен. Для еепромок - не знаю есть ли такое. Поэтому дефайн - скорее всего единственный выход.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Rumata пишет:

Да, с этим нужно что-то делать

чтобы формально соблюсти Пухово бестолковое правило, укажи вручную, какие ненужные конструкторы неявно создавать НЕ надо.  И какие надо тоже укажи.

class TAnalogSelector : public TCustomSensor {
protected:
	uint8_t			FPin;

	TAnalogSelector() = delete;
	TAnalogSelector(TAnalogSelector &) = delete;
	TAnalogSelector(TAnalogSelector&&) = delete;

public:

	TAnalogSelector(\
		const uint8_t AAnalogPin, \
		const uint16_t AValues[],
		const uint8_t ASize\
	) :TCustomSensor::TCustomSensor(), FSize(ASize) {

 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

DetSimen пишет:

чтобы формально соблюсти Пухово бестолковое правило, укажи вручную, какие ненужные конструкторы неявно создавать НЕ надо.  И какие надо тоже укажи.

Если честно, я не уверен, что кроме конструктора инициализации тут что-то еще может быть востребовано. Даже роль деструктора в данном классе и реальных сценариях применения мне не совсем очевидна. Но, для формального следования правилам можно сделать. Потом))

Кстати, добавил работу с литералами. Если кому интересно, могу выложить.

На днях должны приплыть fm24cl64. Там нет страниц и не требуется 5 миллис для внутричиповых процедур записи. Вот красота то будет 

Logik
Offline
Зарегистрирован: 05.08.2014

5N62V пишет:

Rumata пишет:

 Пока не понимаю, как реализовать автоопределение, поэтому выбор через соответствующий дефайн. 

Я не в курсе можно ли реализовать такое .  Для флешек есть там какие-то идентификаторы 3х байтовые, JEDEC ID . В нем зашифрован производитель, тип и объем, по поводу архитектуры не уверен. Для еепромок - не знаю есть ли такое. Поэтому дефайн - скорее всего единственный выход.

Автоопределение реализуемо. За одну команду записи не может записатся больше одной страницы. Даже если передано больше. Через это св-во делать.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Logik пишет:

За одну команду записи не может записатся больше одной страницы. Даже если передано больше. 

а как eeprom должен сигнализировать записалось или нет?

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Logik пишет:

Автоопределение реализуемо. За одну команду записи не может записатся больше одной страницы. Даже если передано больше. Через это св-во делать.

В принципе, можно записать uint16_t  в 0x1F и попытаться прочитать. Если успех - значит 128 или 256. А вот как определить полный объем чипа? Он и пишет и читает кольцом

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

andycat пишет:

m должен сигнализировать записалось или нет?

С еепром главный вопрос не это, а КУДА записалось

Logik
Offline
Зарегистрирован: 05.08.2014

Rumata пишет:

Logik пишет:

Автоопределение реализуемо. За одну команду записи не может записатся больше одной страницы. Даже если передано больше. Через это св-во делать.

В принципе, можно записать uint16_t  в 0x1F и попытаться прочитать. Если успех - значит 128 или 256. 

да. пишем допустим 1КБ неспеша нулями. Потом одной командой пытаемся записать 1КБ 0х01. Читаем сколько реально прописалось - это страница

Rumata пишет:

 А вот как определить полный объем чипа? Он и пишет и читает кольцом

тоже просто. Пишем по адресу 0 допустим 0х00. Далее через 1КБ (или 2КБ, какой минимальный обем на подозрении в общем) пишем допустим 0х01. После каждого раза проверяем адрес 0. Если уже не 0 а 0х01 - пошли по кругу

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

все это конечно реально, и опытным путем да, определить наверное можно и размер страницы и чипа, только возникает одна проблема - если в EEPROM уже есть нужные данные, затирать их экспериментом очень не хочется. Так что надежнее изначально говорить программе что мы втыкаем в устройство.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Logik пишет:

да. пишем допустим 1КБ неспеша нулями. Потом одной командой пытаемся записать 1КБ 0х01. Читаем сколько реально прописалось - это страница

Rumata пишет:

 А вот как определить полный объем чипа? Он и пишет и читает кольцом

тоже просто. Пишем по адресу 0 допустим 0х00. Далее через 1КБ (или 2КБ, какой минимальный обем на подозрении в общем) пишем допустим 0х01. После каждого раза проверяем адрес 0. Если уже не 0 а 0х01 - пошли по кругу

1. Писать страницами не вариант. Там же что-то уже записано может быть. Определение размера страницы легко записью одного int-а >255 определить. Если на 0х1F страница заканчивается, то запись произойдет в 0x1f 0x00. А прочитается из  0x1f 0x20. 

2. Хороший вариант. Попробую. 

Logik
Offline
Зарегистрирован: 05.08.2014

Все что в памяти было - прощаю ;)

Проблема определения параметров еепрома актуальна при первом запуске или после перепайки еепрома. В обоих случаях содержимое не валидно. После определения найденные значения сохраняем в энергонезависимой памяти, на следующих ребутах берем оттуда. Я когда ФС писал, то по команде форматирования это делал. Сохранял в нулевую страницу, вместе с всякой всячиной типа смещения страницы, содержащей начало таблицы файлов и т.д. По этим данным считал хеш, потом его же тоже сохранял в нулевой странице. При ребуте проверял хеш, если ОК - все параметры валидны, если не ОК - форматируем.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Logik пишет:

Проблема определения параметров еепрома актуальна при первом запуске или после перепайки еепрома. 

Если паяешь в достаточно трезвом виде, до эта задача представляет сугубо академический интерес

Сделал, посмотрите, если не трудно ))

Функция: 


void i2cEEPROM::selfTest(){
  //tnx 2 Logik
  uint8_t b0 = read8(0);                            // Save first byte
  uint8_t bn;                 
  uint8_t testVal = 123;
  uint16_t sz[] = {2047, 4095, 8191, 16383, 32767, 65535};
  uint16_t mp[] = {16, 32, 32, 64, 64, 64};  
  write8(0, 0);                                     // Set first bype to 0
  for (uint8_t i = 0; i<sizeof(sz); i++){
    bn = read8(sz[i]+1);                            // Save test byte
    write8(sz[i]+1, testVal);                       // Trying to write bype to first "out of range" address
    if (read8(0) != 0 || read8(sz[i]+1)!=testVal){  // Test write failed
      _maxaddr = sz[i];
      _pageSize = mp[i];
      write8(0, b0);                                // Restore 0 byte     
      return;
    }
    else {                                          // Trying next size
      write8(sz[i]+1, bn);                          // Restore test byte
    }
  }
}

 

Все целиком:

#include "Wire.h"
#define EEPROM_I2C_ADDR 0x57


class i2cEEPROM {
  public:
    i2cEEPROM(uint8_t addr) {_i2cAddr = addr; selfTest();}
    //~i2cEEPROM();
    uint16_t  write(uint16_t addr, void* buf, size_t len);  // Запись в EEPROM. 
    uint8_t   write8(uint16_t addr, uint8_t dat);
    uint8_t   write16(uint16_t addr, uint16_t dat);
    uint8_t   write32(uint16_t addr, uint32_t dat);
    uint16_t  read(uint16_t addr, void* buf, size_t len);
    uint8_t   read8(uint16_t addr);
    uint16_t  read16(uint16_t addr);
    uint32_t  read32(uint16_t addr);
    void      printDump(uint16_t pages);
    uint8_t   pageSize() {return _pageSize;}
    uint16_t  maxAddress() {return _maxaddr;}
  private:
    uint8_t  _i2cAddr;
    uint16_t  _maxaddr;
    uint8_t   _pageSize;
    void      selfTest();
    uint16_t  pageWrite(uint16_t addr, void* buf, size_t len);
    uint16_t  pageRead(uint16_t addr, void* buf, size_t len);
    uint16_t  firstPageAddr(uint16_t page);
};


void i2cEEPROM::selfTest(){
  //tnx 2 Logik
  uint8_t b0 = read8(0);                            // Save first byte
  uint8_t bn;                 
  uint8_t testVal = 123;
  uint16_t sz[] = {2047, 4095, 8191, 16383, 32767, 65535};
  uint16_t mp[] = {16, 32, 32, 64, 64, 64};  
  write8(0, 0);                                     // Set first bype to 0
  for (uint8_t i = 0; i<sizeof(sz); i++){
    bn = read8(sz[i]+1);                            // Save test byte
    write8(sz[i]+1, testVal);                       // Trying to write bype to first "out of range" address
    if (read8(0) != 0 || read8(sz[i]+1)!=testVal){  // Test write failed
      _maxaddr = sz[i];
      _pageSize = mp[i];
      write8(0, b0);                                // Restore 0 byte     
      return;
    }
    else {                                          // Trying next size
      write8(sz[i]+1, bn);                          // Restore test byte
    }
  }
}



uint16_t i2cEEPROM::write(uint16_t addr, void* buf, size_t len) {
  if ((addr + len) > _maxaddr) return 0;
  uint16_t thisPage = addr / _pageSize;
  uint16_t count = 0;
  if (thisPage == (addr + len) / _pageSize) {
    count = pageWrite(addr, buf, len);
    return count;
  }
  else {
    count = pageWrite(addr, buf, firstPageAddr(thisPage + 1) - addr);
    thisPage++;
    while ((len - count) > _pageSize) {
      count += pageWrite(firstPageAddr(thisPage), (uint8_t*)buf + count, _pageSize);
      thisPage++;
    }
    count += pageWrite(firstPageAddr(thisPage), (uint8_t*)buf + count, len - count);
  }
  return count;
}


uint8_t i2cEEPROM::write16(uint16_t addr, uint16_t dat) {
  if ((addr + sizeof(dat)) > _maxaddr) return 0;
  uint16_t thisPage = addr / _pageSize;
  uint8_t count = 0;
  if (thisPage == (addr + sizeof(dat)) / _pageSize) {
    count = pageWrite(addr, &dat, sizeof(dat));
    return count;
  }
  else {
    count = pageWrite(addr, &dat, firstPageAddr(thisPage + 1) - addr);
    thisPage++;
    count += pageWrite(firstPageAddr(thisPage), &dat + count, sizeof(dat) - count);
  }
  return count;
}


uint8_t i2cEEPROM::write32(uint16_t addr, uint32_t dat) {
  if ((addr + sizeof(dat)) > _maxaddr) return 0;
  uint16_t thisPage = addr / _pageSize;
  uint8_t count = 0;
  if (thisPage == (addr + sizeof(dat)) / _pageSize) {
    count = pageWrite(addr, &dat, sizeof(dat));
    return count;
  }
  else {
    count = pageWrite(addr, &dat, firstPageAddr(thisPage + 1) - addr);
    thisPage++;
    count += pageWrite(firstPageAddr(thisPage), &dat + count, sizeof(dat) - count);
  }
  return count;
}


uint8_t i2cEEPROM::write8(uint16_t addr, uint8_t dat) {
  if (addr > _maxaddr) return 0;
    uint8_t count = pageWrite(addr, &dat, sizeof(dat));
    return count;
}


uint16_t i2cEEPROM::read(uint16_t addr, void* buf, size_t len) {
  if ((addr + len) > _maxaddr) return 0;
  uint16_t ctr = 0;

  if (len <= I2C_BUFFER_LENGTH - 2) {
    ctr = pageRead(addr, buf, len);
    return ctr;
  }
  else {
    uint16_t twiPages = 0;
    while ((len - ctr) > (I2C_BUFFER_LENGTH - 2)) {
      ctr += pageRead(addr + ((I2C_BUFFER_LENGTH - 2) * twiPages), (uint8_t*)buf + ctr, (I2C_BUFFER_LENGTH - 2));
      twiPages++;
    }
    ctr += pageRead(addr + ((I2C_BUFFER_LENGTH - 2) * twiPages), (uint8_t*)buf + ctr, len - ctr);
  }
  return ctr;
}


uint8_t i2cEEPROM::read8(uint16_t addr) {
  Wire.beginTransmission(_i2cAddr);
  Wire.write(addr >> 8);
  Wire.write(addr & 0xFF);
  Wire.endTransmission(false);
  Wire.requestFrom(_i2cAddr, sizeof(uint8_t));
  uint8_t ret  = Wire.read();
  Wire.endTransmission();
  return ret;
}

uint16_t i2cEEPROM::read16(uint16_t addr) {
  Wire.beginTransmission(_i2cAddr);
  Wire.write(addr >> 8);
  Wire.write(addr & 0xFF);
  Wire.endTransmission(false);
  Wire.requestFrom(_i2cAddr, 2);
  uint16_t ret = 0;
  for (uint8_t i = 0; i < 2; i++) {
    *((uint8_t*)&ret + i) = Wire.read();
  }
  Wire.endTransmission();
  return ret;
}


uint32_t i2cEEPROM::read32(uint16_t addr) {
  Wire.beginTransmission(_i2cAddr);
  Wire.write(addr >> 8);
  Wire.write(addr & 0xFF);
  Wire.endTransmission(false);
  Wire.requestFrom(_i2cAddr, 4);
  uint32_t ret = 0;
  for (uint8_t i = 0; i < 4; i++) {
    *((uint8_t*)&ret + i) = Wire.read();
  }
  Wire.endTransmission();
  return ret;
}



uint16_t i2cEEPROM::pageWrite(uint16_t addr, void* buf, size_t len) {
  uint16_t ctr = 0;
  Wire.beginTransmission(_i2cAddr);
  Wire.write(addr >> 8);
  Wire.write(addr & 0xFF);
  for (uint8_t i = 0; i < len; i++) {
    ctr += Wire.write(*(((uint8_t*)buf) + i));
  }
  Wire.endTransmission();
  delay(5);
  return ctr;
}


uint16_t i2cEEPROM::pageRead(uint16_t addr, void* buf, size_t len) {
  uint8_t* dat = (uint8_t*)buf;
  Wire.beginTransmission(_i2cAddr);
  Wire.write(addr >> 8);
  Wire.write(addr & 0xFF);
  Wire.endTransmission(false);
  Wire.requestFrom(_i2cAddr, len);
  for (uint8_t i = 0; i < len; i++) {
    *(dat + i) = Wire.read();
  }
  Wire.endTransmission();
  return len;
}

// Печатаем на экран содержимое EEPROM для визуального контроля
void i2cEEPROM::printDump(uint16_t pgs){
  Serial.print('\n'); 
  Serial.print("Page size: "); Serial.println(_pageSize);
  Serial.print("Memory dump of "); Serial.print(pgs);Serial.println(" pages:");
  for (uint8_t r = 0; r < pgs; r++) {    
    Serial.print(r, HEX); Serial.print(": ");
    uint16_t addr = r * _pageSize;
    Wire.beginTransmission(_i2cAddr);
    Wire.write(addr >> 8);
    Wire.write(addr & 0xFF);
    Wire.endTransmission(false);
    Wire.requestFrom((int)_i2cAddr, (int)_pageSize);
      for(uint8_t i = 0; i < _pageSize; i++){
        Serial.print(Wire.read(), HEX); Serial.print(" ");
      }
    Serial.print('\n');
  } 
  Serial.print('\n'); 
}


uint16_t i2cEEPROM::firstPageAddr(uint16_t page) {
  return (page * _pageSize);
}



void setup() {
  Wire.begin();
  Serial.begin(115200);
  Serial.print('\n'); 
  i2cEEPROM i2c(EEPROM_I2C_ADDR);
  Serial.print("Max address: "); Serial.println(i2c.maxAddress());
  Serial.print("Page size: "); Serial.println(i2c.pageSize());
  Serial.print('\n'); 
  uint8_t ts[350];
  uint8_t dta = 0;
  for (uint16_t i = 0; i < sizeof(ts); i++) {
    ts[i] = dta++; if (dta> 255) dta = 0;
  }
  uint16_t address = 20;
  Serial.print("Write to EEPROM: ");
  Serial.println(i2c.write(address, &ts, sizeof(ts)));
  uint8_t rs[350];
  Serial.print("Read from EEPROM: ");
  Serial.println(i2c.read(address, &rs, sizeof(rs)));
  for (uint16_t i = 0; i < sizeof(rs); i++) {
  if ((i+1)%30) {Serial.print(rs[i]); Serial.print(" ");}
  else Serial.println(rs[i]);
  }
  Serial.print('\n');  
  i2c.write8(405, 123);
  Serial.println(i2c.read8(405));
  i2c.write16(400, 16000);
  Serial.println(i2c.read16(400));
  i2c.write32(420, 1234567);
  Serial.println(i2c.read32(420)); 
  uint32_t tt= 12345678;
  i2c.write(440, &tt, sizeof(tt));
  Serial.println(i2c.read32(440));   
  i2c.printDump(16);
}


void loop() {}

 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Про еепром и ребуты не додумал, ага

sadman41
Offline
Зарегистрирован: 19.10.2016

В первом фрагменте строка 9 что делает?

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

sadman41 пишет:
В первом фрагменте строка 9 что делает?

Спасибо, не выспался сегодня(( Поправил

sadman41
Offline
Зарегистрирован: 19.10.2016

Пока не наблюдаю исправлений. sizeof не возвращает размер массива в айтемах, он работает с байтами. А в Вашем массиве двубайтовые айтемы. Поставьте println(i), посмотрите до скольки досчитает.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

sadman41 пишет:
Пока не наблюдаю исправлений. sizeof не возвращает размер массива в айтемах, он работает с байтами. А в Вашем массиве двубайтовые айтемы. Поставьте println(i), посмотрите до скольки досчитает.

да я знаю, затупил просто. У себя уже поправил. Через пару часов обновлю тут. С телефона не очень. Поделил на размер элемента, как дОлжно

Logik
Offline
Зарегистрирован: 05.08.2014

for (uint8_t i = 0; i< sizeof(sz)/sizeof(sz[0])

Вроде похоже.