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

problem z komunikacją atmega32 i eeprom 24c64a (i2c)

Gryllen 10 Lis 2006 19:18 2526 1
REKLAMA
  • #1 3209837
    Gryllen
    Poziom 12  
    Posty: 19
    Pomógł: 2
    Witam.

    Mam dość denerwujący z magistralą i2c. Nie udało mi się jeszcze odczytać zadnej wartości z pamięci poprawnie. Przeczytałem dośc dużo tematów tutaj na forum ale żaden z pomysłów tam przedstawionych mi nie pomógł. Ale przejde może do konkretów.

    Rezystory podciągające mam 5k1 dobrze wlutowane, pamięć odpowiada wszystkimi potwierdzeniami prawidłowo ale pomimo tego widzę ciągle to nieszczęsne FF.

    Wkleje poniżej kod którego używam w C. Gdyby ktoś światły byłby mi w stanie pomóc byłbym niesamowicie wdzięczny.

    pliki nagłówkowe
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "rs232_pooling.h"
    #include <util/delay.h>


    funkcja inicjująca twi
    void i2ceepromInit(void)
    {
    	cli();
    	//podlaczenie rezystorow podciagajacych
    	//PORTC |= _BV(0);
    	//PORTC |= _BV(1);
    	//ustawienie wartosci przesylu
    	TWSR &= ~(_BV(TWPS1));
    	TWSR &= ~(_BV(TWPS0));
    	TWBR = 72;  // mialo byc 100kHz 
    	//wlaczenie TWI
    	TWCR |= _BV(TWEN);
    	//wyzerowanie znacznika TWIE
    	TWCR &= ~(_BV(TWIE));
    	sei();
    }


    funkcja zapisu do pamięci
    void i2ceepromWriteByte(int address, unsigned char data)
    {
    	unsigned char SLA_W= 0xA0 ; //adres przesuniety plus bit mowiacy o zapisie :)
    	//wysylamy START
    	TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //ustawianie twen niepotrzebne bo zrobilismy to w init
    	//czekamy na ACK od pamieci
    	while(!(TWCR & (1<<TWINT)) );
    	TWCR &= ~( (1<<TWSTA)|(1<<TWINT) ); //poprawka po doczytaniu elektrody
    	//TWCR &= 0b01011111; 
    	//sprawdzamy zawartosc TWSR maskujac bity preskalera
    	USART_uchar_send(TWSR & 0xf8);
    	
    
    	//wysylamy adres wybranego urzadzenia
    	TWDR =SLA_W;
    	//rozpoczynamy transmisje adresu
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na potwierdzenie odbiory SLA_W przez pamiec
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy odebrane zostalo ACK
    	USART_uchar_send(TWSR & 0xf8);
    	
    
    	//teraz przesylamy adres komorki ktora chcemy zapisywac w dwoch partiach
    	//najpierw przesylamy starsza czesc adresu czyli 5 waznych bitow
    	//datasheet at24c324/64a p. 11 
    	TWDR = (address>>8) ;
    	//wysylamy dane 
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na otrzymanie ACK/NACK
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy otrzymalismy ACK 
    	USART_uchar_send(TWSR & 0xf8);
    	
    	//teraz przesylamy adres komorki ktora chcemy zapisywac w dwoch partiach 
    	TWDR = address;
    	//wysylamy dane 
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na otrzymanie ACK/NACK
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy otrzymalismy ACK 
    	USART_uchar_send(TWSR & 0xf8);
    	
    	
    	//przeslanie nowej wartosci komorki
    	TWDR = data;
    	//wysylamy dane 
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na otrzymanie ACK/NACK
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy otrzymalismy ACK 
    	USART_uchar_send(TWSR & 0xf8);
    
    
    	//nadajemy STOP
    	TWCR = (1<<TWSTO) | (1<<TWINT);	
    
    	_delay_loop_2(40000);
    }


    odczyt z pamięci typ random read
    unsigned char i2ceepromReadByte(int address)
    {	
    	unsigned char output;
    	//jest to typ random read 
    	unsigned char SLA_W=0xa0 ; //adres przesuniety plus bit mowiacy o zapisie :)
    	//wysylamy START
    	TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //ustawianie twen niepotrzebne bo zrobilismy to w init
    	//czekamy na ACK od pamieci
    	while(!(TWCR & (1<<TWINT)) );
    	TWCR &= ~( (1<<TWSTA)|(1<<TWINT) ); 
    	//sprawdzamy zawartosc TWSR maskujac bity preskalera
    	USART_uchar_send(TWSR & 0xf8);
    
    	//wysylamy adres wybranego urzadzenia
    	TWDR =SLA_W;
    	//rozpoczynamy transmisje adresu
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na potwierdzenie odbiory SLA_W przez pamiec
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy odebrane zostalo ACK
    	USART_uchar_send(TWSR & 0xf8);
    
    	//teraz przesylamy adres komorki ktora chcemy zapisywac w dwoch partiach
    	//najpierw przesylamy starsza czesc adresu czyli 5 waznych bitow
    	//datasheet at24c324/64a p. 11 
    	TWDR = (address>>8) ;
    	//wysylamy dane 
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na otrzymanie ACK/NACK
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy otrzymalismy ACK 
    	USART_uchar_send(TWSR & 0xf8);
    
    	//teraz przesylamy adres komorki ktora chcemy zapisywac w dwoch partiach 
    	TWDR = address;
    	//wysylamy dane 
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na otrzymanie ACK/NACK
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy otrzymalismy ACK 
    	USART_uchar_send(TWSR & 0xf8);
    	
    	_delay_loop_2(40000);	
    	
    	//koniec "dummy read"
    
    	//wysyłamy START
    	TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //ustawianie twen niepotrzebne bo zrobilismy to w init
    	//czekamy na ACK od pamieci
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy zawartosc TWSR maskujac bity preskalera
    	USART_uchar_send(TWSR & 0xf8);
    
    	//przygotowujemy SLA_R
    	unsigned char SLA_R=0xa1 ;
    	//wysylamy adres wybranego urzadzenia
    	TWDR =SLA_R;
    	//rozpoczynamy transmisje adresu
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	//czekamy na potwierdzenie odbioru SLA_R przez pamiec
    	while(!(TWCR & (1<<TWINT)) );
    	//sprawdzamy czy odebrane zostalo ACK
    	USART_uchar_send(TWSR & 0xf8);//x40
    	
    	//odbieramy dane
    	//odebranie tylko jednego bajtu gdy inaczej dajemy tutaj TWEA=1
    	TWCR = (1<<TWINT) | (0<<TWEA) | (1<<TWEN);
    	//czekamy na potwierdzenie
    	while(!(TWCR & (1<<TWINT)) );
    	//zapis odebranych danych
    	output=(unsigned char)TWDR;
    	//sprawdzamy co zostalo odebrane
    	USART_uchar_send(TWSR & 0xf8);
    
    
    	//wysylamy STOP
    	TWCR = (1<<TWSTO) | (1<<TWINT);
    
    	return output;
    }
    



    głowny program:
    int main(void)
    {
    	
    	i2ceepromInit();
    	USARTinit();
    	unsigned char temp,output;
    
    	i2ceepromWriteByte(100,0);
    	output=i2ceepromReadByte(100);
    	USART_uchar_send(output);
    	
    	/*unsigned char i;
    	for (i=100;i<110;i++)
    	{
    		i2ceepromWriteByte(i,0);
    	}
    	for(i=100;i<110;i++)
    	{
    		output=i2ceepromReadByte(i);
    		//USART_uchar_send(output);
    	}*/
    	return 0;
    }
    


    wyniki wysylam sobei przez rs232, takze w ten sposob patrzylem czy wszsytkie ACK dochodza

    to co odbieram na terminalu na PC:

    08 18 28 28 28 08 18 28 28 10 40 58 FF

    z tego co widze to wszystko "wygląda" dobrze, ale co z tego skoro nie działa jak trzeba, to ostatnie nieszczęsne FF

    Proszę o pomoc w miarę możliwości badź sugestie co zrobić
  • REKLAMA
  • #2 3210006
    Pituś Bajtuś
    Poziom 28  
    Posty: 934
    Pomógł: 137
    Ocena: 10
    Tutaj : EEPROM znajdują sie procedurki dla pamięci na I2C oraz sprzętowego TWI w ATmedze32.
REKLAMA