Код: Выделить всё
#pragma once
namespace EEPROM_AT24C
{
enum class EEType { AT24C01=0, AT24C02=1, AT24C04=2, AT24C08=3, AT24C16=4,
AT24C32=5, AT24C64=6, AT24C128=7, AT24C256=8, AT24C512=9, AT24CM01=10, AT24CM02=11 };
struct EEParams
{
uint32_t size;
uint32_t page_size;
};
static constexpr EEParams AllParams[12] = //Объём памяти и размер страницы для всех чипов 24Cxx
{ {128,8}, {256,8}, {512,16}, {1024*1,16}, {1024*2,16},
{1024*4,38}, {1024*8,32}, {1024*16,64}, {1024*32,64}, {1024*65,128}, {1024*128,256}, {1024*256,256} };
template<typename TI2C, typename TDelay, EEType eeType, uint8_t HW_ADR>
class EE_24C
{
public:
_inline_ constexpr EE_24C(){};
static _inline_ bool ReadByte(uint16_t adr, uint8_t *data)
{
if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24CM01))
{ //Микросхемы с двухбайтовой адресацией + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>16)&0x3)<<1);
return TI2C::ReadReg(new_adr,(uint16_t)adr, data, (uint8_t)1);
}
else if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24C32))
{ //Микросхемы с двухбайтовой адресацией
return TI2C::ReadReg(hw_adr,(uint16_t)adr, data, (uint8_t)1);
}
else if constexpr(uint32_t(eeType)<=uint32_t(EEType::AT24C02))
{ //Микросхемы с однобайтовой адресацией
return TI2C::ReadReg(hw_adr,(uint8_t)adr, data, (uint8_t)1);
}
else
{ //Микросхемы с адресацией 1 байт + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>8)&0x3)<<1);
return TI2C::ReadReg(new_adr,(uint8_t)adr, data, (uint32_t)1);
}
}
static _inline_ bool WriteByte(uint16_t adr, uint8_t data)
{
if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24CM01))
{ //Микросхемы с двухбайтовой адресацией + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>16)&0x3)<<1);
return TI2C::WriteReg(new_adr,(uint16_t)adr, &data, (uint8_t)1);
}
else if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24C32))
{ //Микросхемы с двухбайтовой адресацией
return TI2C::WriteReg(hw_adr,(uint16_t)adr, &data, (uint8_t)1);
}
else if constexpr(uint32_t(eeType)<=uint32_t(EEType::AT24C02))
{ //Микросхемы с однобайтовой адресацией
return TI2C::WriteReg(hw_adr,(uint8_t)adr, &data, (uint8_t)1);
}
else
{ //Микросхемы с адресацией 1 байт + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>8)&0x3)<<1);
return TI2C::WriteReg(new_adr,(uint8_t)adr, &data, (uint8_t)1);
}
}
static _inline_ bool ReadData(uint32_t adr, uint8_t *data, uint32_t length)
{
if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24CM01))
{ //Микросхемы с двухбайтовой адресацией + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>16)&0x3)<<1);
return TI2C::ReadReg(new_adr,(uint16_t)adr, data, (uint32_t)length);
}
else if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24C32))
{ //Микросхемы с двухбайтовой адресацией
return TI2C::ReadReg(hw_adr, (uint16_t)adr, data, (uint32_t)length);
}
else if constexpr(uint32_t(eeType)<=uint32_t(EEType::AT24C02))
{ //Микросхемы с однобайтовой адресацией
return TI2C::ReadReg(hw_adr,(uint8_t)adr, data, (uint8_t)length);
}
else
{ //Микросхемы с адресацией 1 байт + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>8)&0x3)<<1);
return TI2C::ReadReg(new_adr,(uint8_t)adr, data, (uint32_t)length);
}
}
static _inline_ bool WriteData(uint32_t adr, uint8_t *data, uint32_t length)
{
if( (((uint32_t)adr) + ((uint32_t)length)) > eeparams.size) return false;
uint32_t page_shift = adr&(eeparams.page_size-1);
//Шаг 1: Запись начального кусочка
uint32_t data2write = length<(eeparams.page_size-page_shift) ? length : (eeparams.page_size-page_shift);
if(!WriteDataInOnePage(adr,data,data2write)) return false;
length -= data2write;
adr+=data2write;
data+=data2write;
//Шаг 2: Запись остальных страниц (они уже выровнены)
while(length)
{
TDelay::template Delay_ms<5>(); //Ждать пока предыдущая страница не запишется
data2write = length<eeparams.page_size ? length : eeparams.page_size;
if(!WriteDataInOnePage(adr,data,data2write)) return false;
length -= data2write;
adr+=data2write;
data+=data2write;
}
return true;
}
private:
static constexpr uint8_t hw_adr=0xA0+((HW_ADR&0x7)<<1);
static constexpr EEParams eeparams = AllParams[uint32_t(eeType)];
static _inline_ bool WriteDataInOnePage(uint32_t adr, uint8_t *data, uint32_t length)
{
if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24CM01))
{ //Микросхемы с двухбайтовой адресацией + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>16)&0x3)<<1);
return TI2C::WriteReg(new_adr,(uint16_t)adr, data, (uint32_t)length);
}
else if constexpr (uint32_t(eeType)>=uint32_t(EEType::AT24C32))
{ //Микросхемы с двухбайтовой адресацией
if constexpr(eeparams.page_size>255)
return TI2C::WriteReg(hw_adr,(uint16_t)adr, data, (uint32_t)length);
else
return TI2C::WriteReg(hw_adr,(uint16_t)adr, data, (uint8_t)length);
}
else if constexpr(uint32_t(eeType)<=uint32_t(EEType::AT24C02))
{ //Микросхемы с однобайтовой адресацией
return TI2C::WriteReg(hw_adr,(uint8_t)adr, data, (uint8_t)length);
}
else
{ //Микросхемы с адресацией 1 байт + биты в HW_ADR
uint8_t new_adr = hw_adr + (((adr>>8)&0x3)<<1);
return TI2C::WriteReg(new_adr,(uint8_t)adr, data, (uint8_t)length);
}
}
};
} // namespace EEPROM_AT24C