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
funkcja inicjująca twi
funkcja zapisu do pamięci
odczyt z pamięci typ random read
głowny program:
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ć
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ć