avr-gcc i 1wire - ponownie

May 18, 2007 6 Replies

Witam,



Teraz przysiad³em siê do oprogramowania i testowania 1wire. I mam problem, otó¿ tak± mam procedurê g³ówn±: <code>



for (;;) { for (tmp=0;tmp<8;tmp++) ds_nr[tmp] = 0x00; if (ow_reset() == 0) { ow_write_byte(0x33); // read rom for (tmp=0;tmp<8;tmp++) ds_nr[tmp] = ow_read_byte(); lcd_setPos(2,0); lcd_str_P((prog_char*)PSTR("1W_RESET=0")); } else { lcd_setPos(2,0); lcd_str_P((prog_char*)PSTR("1W_RESET=1")); }



lcd_setPos(1,0); for (tmp=0;tmp<8;tmp++) lcd_hex_byte(ds_nr[tmp]);



delay1ms(5);



} </code>



I z ds_nr mam same 0x08, co do czasów resetu i pozosta³ych my¶lê ¿e s± dobre (na przyk³adnaie uk³adu reaguje) ale z odczytem mam ju¿ g³upoty :/



Mo¿e zjadzie siê osoba co mog³a rzuciæ by okiem: <code unit="1wire.c">



void ow_delay(uint16_t t) { while (t>0) { // ~250ns asm volatile("nop"::); asm volatile("nop"::); // ~250ns asm volatile("nop"::); asm volatile("nop"::); // ~250ns asm volatile("nop"::); asm volatile("nop"::); // ~250ns asm volatile("nop"::); asm volatile("nop"::); // + --- " --- = 1us



--t; } }



void ow_write_bit(uint8_t bit) {



DDR(OW_PORT) |= 1 << OW_PIN; // port=OUT PORT(OW_PORT) &= ~(1 << OW_PIN); // port=0 ow_delay(3); // poczekaj chwile i: if (bit != 0) { // je¶li ma byæ wystawiona 1 to port=1 je¶li nie to port pozostanie w "0" PORT(OW_PORT) |= 1 << OW_PIN; } ow_delay(70); // poczekaj az ramka bitu moze sie zakonczyc (t>60us) DDR(OW_PORT) &= ~(1 << OW_PIN); // port=IN PORT(OW_PORT) |= 1 << OW_PIN; // port=1 }



uint8_t ow_read_bit(void) { static uint8_t tmp;



PORT(OW_PORT) &= ~(1 << OW_PIN); // port=0 DDR(OW_PORT) |= 1 << OW_PIN; // port=OUT // prze³acz port=0 ow_delay(3); PORT(OW_PORT) &= ~(1 << OW_PIN); //port=IN ow_delay(7); // poczekaj na slave'a az przejmie kontorle i:



tmp = PIN(OW_PORT) & (1<<OW_PIN); // odczytaj stan



ow_delay(80); // poczekaj na bezpieczny czas zakonczenia trnasmisji bitu



return tmp; }



// -------------------------------------- // -------------------------------------- // -------- funkcje g³ówne // -------------------------------------- // --------------------------------------



void ow_init(void) { DDR(OW_PORT) &= ~(1 << OW_PIN); PORT(OW_PORT) |= 1 << OW_PIN; }



uint8_t ow_reset(void) { uint8_t tmp;



DDR(OW_PORT) |= 1 << OW_PIN; PORT(OW_PORT) &= ~(1 << OW_PIN); // 1W - RESET PULSE ow_delay(500); // delay 500us // teraz przelacz port na wejscie i sprawdz czy cos sie dziej DDR(OW_PORT) &= ~(1 << OW_PIN); // port=IN PORT(OW_PORT) |= 1 << OW_PIN; // port=1 (pull-up) ow_delay(30); // poczekaj az slave przjemie kontorle nad linia i sci±gnie j± do masy tmp = PIN(OW_PORT) & (1 << OW_PIN); // odczytaj je¶lo tmp=0 to jest co¶ na



1w :) // jeszcze sobie poczekamy... ow_delay(500); return tmp; }

void ow_write_byte(uint8_t data) { uint8_t tmp; for (tmp=0;tmp<8;tmp++) { ow_write_bit(data & 0x01); data >>= 1; } }



uint8_t ow_read_byte(void) { uint8_t tmp, tmp2=0; for (tmp=0;tmp<8;tmp++) { tmp2 |= (ow_read_bit() << tmp); } return tmp; } </code>


Z not± w rêce sprawdzi³em 2x ow_write_bit i ow_read_bit czy s± dobrze i czasy s± te¿ w granicach tak wiêc nie mam ju¿ pomys³u. A znowu kopiowanie czyjego¶ kodu nie spacjalnie lubiê, "bo" preferujê siê czego¶ nauczyæ. Aha F_CPU=8MHz i MCU=attiny2313


Jaki masz zegar? Wnioskuje, ze 8MHz? Moze lepiej skorzystac z delay z biblioteki standardowej gcc?

^^^^^^^^^^^^^ A tu chyba ma byc DDR, a nie port. Bo tak wystawiasz silne 0 na magistrale i nie dajesz mozliwosci wymuszenia stanu przez slave 1-wire.

Troche za krotko, bezpieczniej bedzie poczekac z 15us, bo 1-wire co prawda szybciej zwykle wystawia wartosc, ale nie zapominaj, ze szyna pracuje z pull-upem i potrzebuje troche czasu na przejscie z 0 do 1.

Bezpieczniej bedzie czekac az pojawi sie ponownie "1". To ma tez ta kozysc, ze mozesz skrocic czas transmisji bitu "1", co ci przyspieszy cala transmisje po 1-wire.

To nie blad, ale mozna zastosowac maly myk. Wpisujac 0 do port, wystawianie 0 lub 1 na 1-wire bedzie polegalo po prostu na przelaczaniu tylko DDR. Czyli DDR 1->out, na wyjsciu masz 0, jesli chcesz 1 to DDR=0 i szyna jest w stanie "1" utrzymywanym przez zewnetrzny pull=up.

Tu musisz poczekac az szyna po 0 wroci do 1, inaczej pierwsze transmisje po 1-wire moga trafic jeszcze na presence pulse.

Dodaj male opoznienie. Bo write_bit konczy sie szybko i jesli wystawia "0" to szyna przed nastepnym bitem moze nie zdazyc wrocic do "1".

Tutaj analogicznie, read_bit nie czekasz az szyna wroci do "1" i jesli ds dluzej trzyma niz 80us szyne to masz kaszane.

no fakt (ju¿ pó¼no jak pisa³em)... ale to i tak nic nie zmieni³o wci±¿ to samo (0x08 odczytuje :/ - sprawdzia³m na bascomie czy uk³ad dobry - dzia³a)

Widzia³em to w innych modu³ach które podgl±da³em.

Poprawi³em to i kod wrzuci³em na serwer:

formatting link
Jeszcze raz jutro porównam z innym kodem (g³ównie czasy).

TMF masz browarka u mnie :) za b³±d. I moim problemem jednak by³y czasy za d³ugie zbytnio opiera³em siê na wyliczeniach czasu ,a przecie¿ wywo³anie ow_delay, dekrementacja czasu, warunek sprawdzenia t>0 to dodatkowe takty tak wiêc czasy skróci³em mocno i dzia³a :)) jak kto¶ chêtny to siê podziele kodem. Sprawdzny kod na ds2401, ds2405 i ds1990. Sprawdza³em tylko komendê 0x33 ale z innymi te¿ powinno dzia³±æ.

Chyba uda³o mi siêdopie¶ciæ czasy tak ¿e mi dzia³aj± wszystkie uk³±dy jakie mam i przy zmianie kwarcu zmieniam tylko ilo¶æ nop'ów w ow_delay()

Ok. ¼róde³ko tutaj:

formatting link
tylko serwer "zasrywa" strone reklamami :/ troche

Jakies info o licencji na jakiej to udostepniasz dodaj, bo takie czasy, ze strach cos sciagac z netu :) Dobra robota, tylko dodaj jeszcze SearchROM i MatchROM (to drugie latwe do zaimplementowania). Bo bez tego trudno z tego korzystac. No i jesli chce ci sie bawic przerob te wymuszanie stanow tak, zeby wystarczylo zmieniac DDR, bez PORT, zawsze to pare bajtow mozna zaoszczedzic. Ale gratuluje roboty.

Skoro wrzuci³em to rób co chcesz :) nie mam nic przeciwko :))

Sam napisz :)) i wklej kawa³ek kodu tutaj :)) do doklejej do tego co ju¿ jest :))

EEE tak jest przej¿y¶ciej, wiem mo¿na zmieniæ g³ównie ow_write_bit() na troche szybsz± ale i tak narazie u¿ywam du¿ych procesorów (m48, m32, m8535, ,a do tiny2313 z obs³ug± lcd wejdzie i zostanie jeszcze ze 600b wolnego :)) )

dziêkuje :))

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required