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

[atmega8] [c] Problem z odczytem z urządzeń 1-wire

y0yster 30 Sty 2009 18:54 1523 6
REKLAMA
  • #1 6078018
    y0yster
    Poziom 19  
    Witam,

    Ostatnio zacząłem sobie pisać funkcje służące komunikacji przez 1 wire.

    Nie wiem dlaczego, ale nie działa mi odczyt :/

    Staram się odczytać temperaturę od DS18B20.

    Dodam, że próbowałem już różnych timingów przy odczycie, ale nic to nie dało.

    Oto kod:

    
    void onewire_init( void)
    {
    	//ustawienie lini na "0"
    	cbi( onewire_port, onewire_line);
    }
    
    //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    
    unsigned char onewire_reset( void)
    {
    
    	//ustawienie lini jako wyjscie
    	//mamy na lini stan "0"	
    	sbi( onewire_ddr, onewire_line);
    	
    	//stan ma trwac prze minimum 480 us
    	//my dajemy 490us
    	_delay_us( 200);
    	_delay_us( 200);
    	_delay_us( 90);
    
    	//teraz zmieniamy sie na wejscie
    	//mamy na lini stan "1"
    	cbi( onewire_ddr, onewire_line);
    
    	//UWAGA 1
    
    	//czekamy 100 us
    	_delay_us( 100);
    
    	if( bit_is_clear( onewire_pin, onewire_line) )
    	{
    
    		//odczekujemy minimum 480 us
    		//u nas bedzie to 490 us
    		//ale jest to czas od puntku UWAGA 1
    		//wiec czekamy jeszcze 390 us
    
    		_delay_us( 200);
    		_delay_us( 190);
    
    		//zwracamy 1, poniewaz wykrylismy urzadzenie onewire
    		return 1;
    	}
    
    	//niedoczekalismy sie urzadzenie dlatego zwracamy 0 i uciekamy
    	return 0;
    }
    
    //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    
    void onewire_write( unsigned char dane)
    {
    
    
    	//procedura wysylki 1 bajtu
    	//single byte :P
    	for( unsigned char i = 0; i < 8; i++)
    	{
    		//przestawiamy sie na wyjscie
    		//na lini jest "0"
    		sbi( onewire_ddr, onewire_line);
    
    		//czekamy chwilke
    		_delay_us( 5);
    
    		//wysylamy jeden bit z danej
    		//poczynajac od najmlodszego, najmniej znaczacego
    		//jesli jest to 1
    		if( ((dane >> i) & 1) )
    			//ustawiamy linie na wejscie, a
    			//stan lini to "1"
    			cbi( onewire_ddr, onewire_line);
    		//jesli NIE jest to 1, czyli 0, to
    		//stan lini to dalej "0"		
    
    		//czekamy
    		_delay_us( 75);
    
    		//teraz ustawiamy stan lini na "1"
    		cbi( onewire_ddr, onewire_line);
    
    		//odczekujemy chwileczke
    		_delay_us( 3);
    		//zaczynamy transmisje nastepnego bitu.......		
    	}
    }
    
    //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
    
    unsigned char onewire_read( void)
    {
    	unsigned char dane = 0;
    
    	for( unsigned char i = 0; i < 8; i++)
    	{
    		//przestawiamy sie na wyjscie
    		//na lini jest "0"
    		sbi( onewire_ddr, onewire_line);
    
    		//czekamy chwilke
    		_delay_us( 30);
    
    		//przestawiamy sie na wejscie
    		//na lini bedzie "1"
    		cbi( onewire_ddr, onewire_line);
    
    		//teraz urzadzenie daje "0" lub "1"
    
    		//malutkie opoznienie
    		_delay_us( 10);
    
    		dane |= ((onewire_pin >> onewire_line) & 1) << i;
    
    		//odczekujemy do konca
    		_delay_us( 70);
    
    		//zaczynamy odbior kolejnego bitu.......		
    	}
    
    	return dane;
    }
    


    A to wewnątrz głównego programu.

    
    	if( onewire_reset())
    	{
    
    		sbi( PORTD, PD6);
    
    		onewire_write( 0xCC);
    
    		onewire_write( 0x44);
    
    		_delay_ms( 200);
    		_delay_ms( 200);
    		_delay_ms( 200);
    		_delay_ms( 200);
    		_delay_ms( 200);
    
    		onewire_reset();
    
    		onewire_write( 0xCC);
    		onewire_write( 0xBE);
    
    		i_raz = onewire_read();
    		i_dwa = onewire_read();
    
    	}
    
  • REKLAMA
  • #2 6079162
    marenc
    Poziom 24  
    Sprawdź timingi sprzętem ... oscyloskop lub analizator stanów logicznych ;)
  • REKLAMA
  • #3 6080252
    y0yster
    Poziom 19  
    Niestety nie posiadam takowego sprzętu :/

    Symuluję program w Proteusie. Dodam, że program napisany w bascomie działa ok. Sprawdzałem tam timingi i są prawie identyczne. Zgadzają się stany "0" i "1", małe różnice są co do długości trwania tych impulsów.

    Ale niestety przy odczycie dostaję tylko Same "1" i małe skoki na "0". Więc coś nie gra. Myślę, że jest to związane z procedurami zapisu do 1-wire, ale według mnie wszystko jest ok, może ktoś podsunie jakąś myśl ?

    Pozdrawiam.
  • #4 6080326
    marenc
    Poziom 24  
    Z tego co kojarzę, to odpowiedź czujnika 0xffffffff sygnalizuje jego uszkodzenie...

    W załączniku moje procedury... kiedyś działały, ale nie są optymalne... możesz porównać ;)
  • REKLAMA
  • #5 6080499
    y0yster
    Poziom 19  
    Twój kod działa.

    Teraz przeanalizuję co i jak. Ale zauważyłem, że odbierasz dane taką samą metodą jak Doliński ze swojej książki o uC :P.

    Pewnie pies jest pogrzebany gdzieś w timingach :/

    Pozdrawiam.

    --edit

    Tak, doszedłem do tego, że nie można zrobić wszystkiego w jednej pętli z jednym if'em, tak jak ttego chciałem. Niby wszystko tak samo, a jednak różnie :/. Przetestowałem na różnych timingach i działa tylko w taki sposób jak ty to masz zrobione.

    Troszkę teraz kombinuję z konwersją temperatury :/. W twoim kodzie niestety nie jest to zrobione poprawne, ponieważ dla -1 zwraca -0.

    Pozdrawiam.
  • REKLAMA
  • #6 6087611
    marenc
    Poziom 24  
    Witam, kod był tylko do testów i aktualnie w wolnej chwili zamierzam zająć się napisaniem nowych bibliotek.

    Wiem, że jest różnica pomiędzy delay_ms i delay_us ... znaczy, że są inaczej interpretowane dla tych samych wartości czasowych...
    np. delay_ms(0.1) i delay_us(100) nie dają tego samego odstępu czasowego ;)

    Kod napisany na podstawie dokumentacji czujnika, kilku opracowań w necie oraz pomocy(z timingami - nie miałem jeszcze oscyloskopu) na tym forum.
  • #7 6088773
    y0yster
    Poziom 19  
    Problem został rozwiązany, wszystko gra.

    Należało poprawić funkcję do zapisu, w której trzeba było stworzyć dwa oddzielne bloki dla wysyłania "0" i "1". Zostało to zrealizowane przez stworzenie 2 oddzielnych funkcji dla "0" i "1".

    Pozdrawiam.
REKLAMA