i2c przez lpt - mały problem...

witam, robię sobie układzik komunikujący się z kompem za pomocą i2c, napisałem cos, co wg mnie powinno działac, i okazuje sie ze jednak nie działa. piszę w Borland C++ Builderze, a układ docelowy to Atmega8. układ "slave" działa poprawnie z innym układem, dane są przesyłane poprawnie i ogolnie wszystko ok. funkcje uSDA, uSCL, cSDA. cSCL działają poprawnie (testowane diodkami), wiec wysjcia są aktywne, problem w tym ze gdy proboje wysłac ządane dane, to slave na nie nie reaguje, tzn nie reaguje za polecenie:

TWI_start(); TWI_write(adres); TWI_write(data0); TWI_write(data1); TWI_stop();

przy tak zdeklarowanych funkcjach: (podejrzewam błędy w sekwencjach, ale naprawde nie potrafie ich znalezc...)

/*założenia data0-SDA out strobe-SCL out select-SDA in paperout-SCL in

*/

BYTE inportb(UINT portid) { unsigned char value; __asm mov edx,portid __asm in al,dx __asm mov value,al return value; }

void outportb(UINT portid,BYTE value) { __asm mov edx,portid __asm mov al,value __asm out dx,al }

void uSDA(char data) { if(data) outportb(0x378,0x01); else outportb(0x378,0x00); Sleep(1); }

void uSCL(char data) { if(data) outportb(0x37A,0x00); else outportb(0x37A,0x01); Sleep(1); }

bool cSDA() { bool out; out=(inportb(portid+0x01) & 0x10); return out; }

bool cSCL() { bool out; out=(inportb(portid+0x01) & 0x20); return out; }

void TWI_start() //jest ok { uSDA(1); //ustaw SDA uSCL(1); //ustaw SCL uSDA(0); //zeruj SDA }

void TWI_stop() { uSDA(0); //zeruj SDA uSCL(1); //ustaw SCL uSDA(1); //ustaw SDA }

char TWI_write(char data) { char ack=0;

for(int i=0;i<8;i++) { uSCL(0); //zeruj SCL uSDA(data<<7-i&&0x80); //ustaw bit SDA uSCL(1);//ustaw SCL while(!cSCL()); }

uSCL(0); //zeruj SCL uSDA(1); //ustaw bit SDA uSCL(1); //ustaw SCL if(cSDA()) ack=1; //jesli SDA=1, ack =1 uSCL(0); //zeruj SCL uSDA(1); //ustaw bit SDA

return ack; }

char TWI_read(UINT portid,char ack) { char data; uSCL(1); //ustaw SCL while(!cSCL()); //czekaj aż SCL=1 for(int i=0;i<8;i++) { uSCL(1); //ustaw SCL if(cSDA()) data |= (1 << i); uSCL(0); //zeruj SCL } uSDA(ack); //ustaw bit SDA uSDA(0); //zeruj bit SDA uSCL(1); //ustaw SCL uSCL(0); //zeruj SCL return data; }

Reply to
nuclear2001
Loading thread data ...

[ ciach ]

  1. "__asm mov edx,portid" sugeruje, że robisz pod Windows. I zakładasz, że możesz tak sobie pisać i czytać po portach IO? I że absolutnie nie potrzebujesz sterownika do tego? Hint -> np.
    formatting link

  1. Czy program jest _dokładnie_ taki, jak na listingu? Jak tak, to brakuje opóźnień - pamiętaj, że max dla zwykłego I2C to ~400kHz a przy dłuższych kablach i obsłudze programowej bezpieczniej będzie ~100kHz. Tak ciasne pętle na współczesnych procach pewnie generują sygnały po kilka MHz...

Widzę, że bazujesz na "przytrzymywaniu" bitu SCL przez wolniejsze urządzenie ale ono może po prostu nie zdążyć przyblokować SCLa...

Reply to
Pawel Kraszewski
  1. "__asm mov edx,portid" sugeruje, że robisz pod Windows. I zakładasz, że możesz tak sobie pisać i czytać po portach IO? I że absolutnie nie potrzebujesz sterownika do tego? Hint -> np.
    formatting link
    fakt, zapomniałem dodas ze uzywam sterownika "userport.sys", i sterownaie poszczegolnymi pinami portu działa (testowane ledami)

  1. Czy program jest _dokładnie_ taki, jak na listingu? Jak tak, to brakuje opóźnień - pamiętaj, że max dla zwykłego I2C to ~400kHz a przy dłuższych kablach i obsłudze programowej bezpieczniej będzie ~100kHz. Tak ciasne pętle na współczesnych procach pewnie generują sygnały po kilka MHz...

Widzę, że bazujesz na "przytrzymywaniu" bitu SCL przez wolniejsze urządzenie ale ono może po prostu nie zdążyć przyblokować SCLa...

ok, wprowadze ządane opoznienia i zobacze co to da..

Reply to
nuclear2001

heh, na szybkiego zmieniłem funkcje tak:

void uSDA(char data) { Sleep(1); if(data) outportb(0x378,0x01); else outportb(0x378,0x00); Sleep(1); } void uSCL(char data) { Sleep(1); if(data) outportb(0x37A,0x00); else outportb(0x37A,0x01); Sleep(1); }

i patrzac na diodki to cos na liniach sie dzieje, nawet podobne, ale slave nadal nie odpowiada...

Reply to
nuclear2001

zmieniłem jeszcze tą funkcję

har TWI_write(char data) { char ack=0;

for(int i=0;i<8;i++) { uSCL(0); //zeruj SCL uSDA(data & (1 << (7-i))); //ustaw bit SDA

uSCL(1);//ustaw SCL while(!cSCL()); }

uSCL(0); //zeruj SCL uSDA(1); //ustaw bit SDA uSCL(1); //ustaw SCL if(cSDA()) ack=1; //jesli SDA=1, ack =1 uSCL(0); //zeruj SCL uSDA(1); //ustaw bit SDA

return ack; }

i ogladajac ten przebieg, wszystko sie wydaje być ok, poza tym ze slave nie wystawia ack, oraz nie reaguje... teraz juz nie rozumiem co moze byc nie tak...

Reply to
nuclear2001

Użytkownik "nuclear2001" snipped-for-privacy@poczta.onet.pl> napisał w wiadomości news:fl3u3b$jqh$ snipped-for-privacy@news.onet.pl...

Dostajesz ACK po wysłaniu adresu? Może za szybko program leci? Poza tym u mnie zawsze sekwencja startu jest: sda(1) scl(1) // te dwie linijki na wszelki wypadek, czasem nie dawałem bo to załatwia stop sda(0) scl(0)

a wysyłanie bitów: sda(bit) scl(1) scl(0)

Michał

Reply to
invalid unparseable

hm, nagle zaczeło wszystko działac, chociaz nic nie zmieniałem, chyba slave sie wieszał... no dobra, z tym sobie poradziłem, dane są odbierane, nie było potrzeba zadnych opóżnien nawet ;] problem w tym ze gdy chce zrobić cos w rodzaju

TWI_start(); TWI_write(adr); TWI_write(0x28); TWI_write(0xFF); TWI_stop(); TWI_start(); TWI_write(adr); TWI_write(0x29); TWI_write(0xFF); TWI_stop();

to układ odbiera tylko tą drugą transmisję... w czym moze być problem? nieodpowiednio zakończona transmisja nr1 ? ale przeciez konczy sie warunkiem stopu...

Reply to
nuclear2001

dobra, sam sobie odpowiem, wszystko juz działa zupełnie bez zarzutu, jednak małe opoznienie musi byc ;) dziekuje wszystkim za pomoc;]

Reply to
nuclear2001

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.