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

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

Всем спасибо за замечания. Кроме упомянутых, исправлена еще пара логических ошибок и недочетов. Добавлена очистка чипа. Актуальная версия:

 

#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 = 0);
    uint8_t   pageSize() {return _pageSize;}
    uint16_t  maxAddress() {return _maxaddr;}
    void      erase(uint8_t tmpl = 0);
  private:
    uint8_t  _i2cAddr;
    uint16_t  _maxaddr = 65535;
    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)/sizeof(sz[0])); 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("Memory dump of "); Serial.print(pgs);Serial.println(" pages:");
  if (pgs == 0) pgs = _maxaddr / _pageSize;
  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'); 
}

void i2cEEPROM::erase(uint8_t tmpl){
  uint8_t arr[_maxaddr]; 
  for (uint16_t i = 0; i<_maxaddr; i++){
    arr[i] = tmpl;
  }
  write(0, arr, _maxaddr);
}

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);
  i2c.erase();
  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() {}

 

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

Если делаете return из под if, то else не нужен. Красивее выйдет.

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

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

sadman41 пишет:
Если делаете return из под if, то else не нужен.

Это логично. Спасибо. У себя поправил. Перевыкладывать из-за косметики не буду пока.