Привет All !
Требуется помощь клуба... Проблема в следующем: при чтении I2C EEPROMки иногда считывается вместо нормального значения 0xFF... причем если потом еще раз прочесть этот же адрес, то приходит валидное значение... Память 24lc256, подключена к пику 16F877A к выводам RC3=SCL, RC4=SDA, подтянута к питанию +5В резисторами на 4.7к Запись и чтение осуществляется программной реализацией вне прерывания, при этом прерывания разрешены... Тактовая пика - 20МГц... Где могут быть зарыты грабли?
-------------------- Программная реализация I2C (HiTech C 8.01PL3) ------ void random_write(unsigned char dev_adr, unsigned int mem_adr, unsigned char dat) { i2c_start(); i2c_out_byte(0xa0 | (dev_adr << 1)); i2c_nack(); i2c_out_byte((mem_adr >> 8) & 0xff); // high unsigned char of memory address i2c_nack(); i2c_out_byte(mem_adr & 0xff); // low unsigned char of mem address i2c_nack(); i2c_out_byte(dat); // and finally the data i2c_nack(); i2c_stop(); delay_ms(6); // allow for the programming of the eeprom }
unsigned char random_read(unsigned char dev_adr, unsigned int mem_adr) { unsigned char y; i2c_start(); i2c_out_byte(0xa0 | (dev_adr << 1)); i2c_nack(); i2c_out_byte((mem_adr >> 8) & 0xff); i2c_nack(); i2c_out_byte(mem_adr & 0xff); i2c_nack(); i2c_start(); // no intermediate stop i2c_out_byte(0xa1 | (dev_adr << 1)); // read operation i2c_nack(); y = i2c_in_byte(); i2c_stop(); return(y); }
// Common I2C Routines
unsigned char i2c_in_byte(void) { unsigned char i_byte, n; i2c_high_sda(); for (n=0; n<8; n++) { i2c_high_scl(); if (SDA_PIN) { i_byte = (i_byte << 1) | 0x01; // msbit first } else { i_byte = i_byte << 1; } i2c_low_scl(); } return(i_byte); }
void i2c_out_byte(unsigned char o_byte) { unsigned char n; for(n=0; n<8; n++) { if(o_byte & 0x80) { i2c_high_sda(); } else { i2c_low_sda(); } i2c_high_scl(); i2c_low_scl(); o_byte = o_byte << 1; } i2c_high_sda(); }
void i2c_nack(void) { i2c_high_sda(); // data at one i2c_high_scl(); // clock pulse i2c_low_scl(); }
void i2c_ack(void) { i2c_low_sda(); // bring data low and clock i2c_high_scl(); i2c_low_scl(); i2c_high_sda(); }
void i2c_start(void) { i2c_low_scl(); i2c_high_sda(); i2c_high_scl(); // bring SDA low while SCL is high i2c_low_sda(); i2c_low_scl(); }
void i2c_stop(void) { i2c_low_scl(); i2c_low_sda(); i2c_high_scl(); i2c_high_sda(); // bring SDA high while SCL is high // idle is SDA high and SCL high }
void i2c_high_sda(void) { // bring SDA to high impedance SDA_DIR = 1; delay_uc(3); }
void i2c_low_sda(void) { SDA_PIN = 0; SDA_DIR = 0; // output a hard logic zero delay_uc(3); }
void i2c_high_scl(void) { SCL_DIR = 0; // high impedance SCL_PIN = 1; delay_uc(3); }
void i2c_low_scl(void) { SCL_PIN = 0; SCL_DIR = 0; delay_uc(3); }
-------------------------------------------------------------------------
До встречи, Alex.