logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[AVR][AVR-GCC] Programowe I2C, problem z potwierdzeniem

KubeqZ 23 Lut 2011 12:57 1322 0
REKLAMA
  • #1 9191477
    KubeqZ
    Poziom 16  
    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.

    #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 :
    [AVR][AVR-GCC] Programowe I2C, problem z potwierdzeniem

    ------------------------------------------------------------------
    edit: Problem rozwiązany, kod poprawny, to Proteus pokazuje głupoty jak jest podpięty oscyloskop..
  • REKLAMA
REKLAMA