Код (сокращенный, полностью в архиве):
eeprom.c
- Код: Выделить всё • Развернуть
- uint8_t eeprom_read(uint16_t address, void* buf, uint16_t count)
 {
 uint8_t *b = buf;
 I2C_START;
 uint8_t ack = i2c_write(EEPROM_ADDRESS);
 if (ack) {
 I2C_STOP;
 return ack;
 }
 ack = i2c_write(address >> 8);
 if (ack) {
 I2C_STOP;
 return ack;
 }
 ack = i2c_write(address & 0xFF);
 if (ack) {
 I2C_STOP;
 return ack;
 }
 I2C_STOP;
 I2C_START;
 ack = i2c_write(EEPROM_ADDRESS | 1);
 if (ack) {
 I2C_STOP;
 return ack;
 }
 while (count) {
 *b = i2c_read(count > 1);
 b++;
 count--;
 }
 I2C_STOP;
 return ack;
 }
 uint8_t eeprom_write(uint16_t address, void* buf, uint16_t count)
 {
 uint8_t *b = buf;
 uint8_t ack = 0;
 while (count) {
 PORTC ^= 2;
 uint8_t nbytes = 64 - (address & 63);
 if (nbytes > count) nbytes = count;
 uint8_t attempts = 100;
 while (attempts--) {
 I2C_START;
 ack = i2c_write(EEPROM_ADDRESS);
 if (!ack) break;
 else I2C_STOP;
 }
 if (ack) {
 return ack;
 }
 ack = i2c_write(address >> 8);
 if (ack) {
 I2C_STOP;
 return ack;
 }
 ack = i2c_write(address & 0xFF);
 if (ack) {
 I2C_STOP;
 return ack;
 }
 count -= nbytes;
 while (nbytes) {
 ack = i2c_write(*b);
 if (ack) {
 I2C_STOP;
 return ack;
 }
 b++;
 nbytes--;
 }
 I2C_STOP;
 address += nbytes;
 }
 uint8_t attempts = 100;
 while (attempts--) {
 I2C_START;
 uint8_t ack = i2c_write(EEPROM_ADDRESS);
 I2C_STOP;
 if (!ack) break;
 }
 return ack;
 }
test.c:
- Код: Выделить всё • Развернуть
- uint8_t buf[8] = {
 1, 2, 3, 4, 5, 6, 7,
 };
 FILE serial = FDEV_SETUP_STREAM(fputchar, NULL, _FDEV_SETUP_WRITE);
 int main(void)
 {
 stdout = &serial;
 UBRRH = 0;
 UBRRL = 197;
 DDRD = (1 << 1); // TXD
 DDRC = 2; // debug
 UCSRB = (1 << TXEN);
 if (eeprom_write(0, buf, 8)) printf("WRITE FAIL!\n\n");
 if (!eeprom_read(0, buf, 8)) {
 printf("%02X ", buf[0]);
 printf("%02X ", buf[1]);
 printf("%02X ", buf[2]);
 printf("%02X ", buf[3]);
 printf("%02X ", buf[4]);
 printf("%02X ", buf[5]);
 printf("%02X ", buf[6]);
 printf("%02X\n", buf[7]);
 }
 for(;;);
 }
Чтение проходит нормально. ПЗУ поставил с записанными данными, в терминале их вижу. А новые не записываются. Когда пытаюсь писать не 8 байт, а больше, по импульсам на ноге PORTC.1 вижу, что цикл записи страницы занимает ровно столько времени, сколько нужно для вывода 67 байт (адрес I2c, 2 байта адреса памяти, 64 байта данных). По идее оно должно быть больше, так как ПЗУ после стоп-бита нужно до 5 мс для записи данных.
Подтяжку на шине I2C проверил. Нога WP притянута к земле. Что я делаю не так?


 
 



