Doskonale rozumiem, że I2C było wiele razy już omawiane na tym forum, lecz męczę się z tym od 3 dni.. Symuluję w Proteusie poniżej podany kod, lecz po przeslaniu 8 bitów, nie otrzymuję potwierdzenia (linia SDA mimo że puszczona nie zostaje obniżona przez EEPROM ( 24LC512 ) ), oczywiscie linie sa podciagniete do zasilania przez rezystory.
Daną do EEPROM'a (zapis 0 pod adres 0) wysyłam w sposób zgodny z datasheetem:
Niestety pomimo tak dużego opóźnienia (10ms) nie otrzymuję potwierdzenia od EEPROM'u.. Proteus wyswietla ostrzeżenie "Stop detected part way through receiving data byte" , a oto przebiegi :
------------------------------------------------------------------
edit: Problem rozwiązany, kod poprawny, to Proteus pokazuje głupoty jak jest podpięty oscyloskop..
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define ACK 1
#define NACK 0
#define bSDA PD5
#define bSCL PD6
#define TWI_DDR_SDA DDRD
#define TWI_PORT_SDA PORTD
#define TWI_PIN_SDA PIND
#define TWI_DDR_SCL DDRD
#define TWI_PORT_SCL PORTD
#define SCL_1() cbi(TWI_DDR_SCL, bSCL)
#define SCL_0() sbi(TWI_DDR_SCL, bSCL)
#define SDA_1() cbi(TWI_DDR_SDA, bSDA)
#define SDA_0() sbi(TWI_DDR_SDA, bSDA)
#define RELEASE_SDA() cbi(TWI_DDR_SDA, bSDA)
#define TWI_SW_DELAY 10
void i2c_soft_init(void)
{
cbi(TWI_DDR_SDA,bSDA);
cbi(TWI_PORT_SDA,bSDA);
cbi(TWI_DDR_SCL,bSCL);
cbi(TWI_PORT_SCL,bSCL);
}
void i2c_soft_start(void)
{
RELEASE_SDA();
SCL_1();
_delay_ms(TWI_SW_DELAY);
SDA_0();
_delay_ms(TWI_SW_DELAY);
SCL_0();
_delay_ms(TWI_SW_DELAY);
}
void i2c_soft_stop(void)
{
SDA_0();
_delay_ms(TWI_SW_DELAY);
SCL_1(); //scl do gory
_delay_ms(TWI_SW_DELAY);
SDA_1(); //sda do gory
_delay_ms(TWI_SW_DELAY);
}
uint8_t i2c_soft_send_data(uint8_t data)
{
register uint8_t i;
for (i = 0; i <= 7; i++) {
if (data & 0x80) {
SDA_1();_delay_ms(TWI_SW_DELAY);
} else {
SDA_0();
}
_delay_ms(TWI_SW_DELAY);
SCL_1();
_delay_ms(TWI_SW_DELAY);
SCL_0();
_delay_ms(TWI_SW_DELAY);
data = data << 1;
}
RELEASE_SDA();
_delay_ms(TWI_SW_DELAY);
SCL_1();
_delay_ms(TWI_SW_DELAY);
if(bit_is_set(TWI_PIN_SDA, bSDA)) {
SCL_0();
_delay_ms(TWI_SW_DELAY);
return 0; //Acknowledge NOT received
}
SDA_0();
SCL_0();
_delay_ms(TWI_SW_DELAY);
return 1;
}
uint8_t i2c_soft_receive_data(uint8_t ack)
{
uint8_t i, data;
RELEASE_SDA();
data = 0;
for (i = 0; i <= 7; i++) {
SCL_1();
_delay_ms(TWI_SW_DELAY);
data <<= 1;
if (bit_is_set (TWI_PIN_SDA, bSDA))
data++;
SCL_0();
_delay_ms(TWI_SW_DELAY);
}
if (!ack) {
SDA_1(); /*Set NO ACK*/
} else {
SDA_0(); /*Set ACK*/
}
SCL_1();
_delay_ms(TWI_SW_DELAY);
SCL_0();
_delay_ms(TWI_SW_DELAY);
return data;
}Daną do EEPROM'a (zapis 0 pod adres 0) wysyłam w sposób zgodny z datasheetem:
i2c_soft_start();
i2c_soft_send_data(0xA0);
i2c_soft_send_data(0);
i2c_soft_send_data(0);
i2c_soft_send_data(0);
i2c_soft_stop();Niestety pomimo tak dużego opóźnienia (10ms) nie otrzymuję potwierdzenia od EEPROM'u.. Proteus wyswietla ostrzeżenie "Stop detected part way through receiving data byte" , a oto przebiegi :
------------------------------------------------------------------
edit: Problem rozwiązany, kod poprawny, to Proteus pokazuje głupoty jak jest podpięty oscyloskop..