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] 1Wire + termometr maxima.

omicronNs 03 Mar 2010 18:27 1114 0
REKLAMA
  • #1 7778793
    omicronNs
    Poziom 21  
    Witam. Jako że nie chcę korzystać z gotowców, postanowiłem spróbować napisać obsługę dla transmisji 1Wire. Naskrobałem coś takiego:


    Funkcje obsługi "1wire.h":
    
    #include <moje/moje.h>						//Załącz potrzebne biblioteki
    #define DDR1W DDRD							//Rejestry specjalne portu wykorzystywanego do komunikacji 1wire
    #define PORT1W PORTD						//...
    #define PIN1W PIND							//...
    #define DQ_MASK 0x01						//Gotowa maska pinu DQ
    #define INITDQ PORT1W&=~(DQ_MASK);			//Initializacja rejestru PORTx portu wykorzystywanego do komunikacji 1wire (stan niski)
    #define DQOUT DDR1W|=(DQ_MASK);				//Ustaw DQ jako wyjście
    #define DQIN DDR1W&=~(DQ_MASK);				//Ustaw DQ jako wejście
    
    u08 init1w(void)							//Initializacja transmisji (wyślij "RESET" i jeśli jest "PRESENCE PULSE" zwraca 0)
    {
    	u08 ret;
    	INITDQ
    	DQOUT
    	_delay_us(600);
    	DQIN
    	_delay_us(70);
    	ret = (PIN1W&(DQ_MASK));
    	_delay_us(200);							//Czekaj na zwolnienie linii
    	return ret;								//Zwróć wynik poprawności initializacji (0 jeśli ok, 1 jeśli brak odpowiedzi)
    }
    
    void sendbyte(u08 data)						//Wyślij bajt danych
    {
    	u08 licznik;
    	INITDQ
    	for(licznik=0;licznik!=8;licznik++)	//Wykonaj 8 razy
    	{
    		if((1<<licznik)&(data))			//Sprawdź bit danej o numerze "licznik"
    		{									//Jeśli jeden:
    			DQOUT
    			_delay_us(10);
    			DQIN
    			_delay_us(90);
    		}									//Jeśli zero:
    		else
    		{
    			DQOUT
    			_delay_us(90);
    			DQIN
    			_delay_us(10);
    		}
    		_delay_us(50);
    	}
    	_delay_us(100);
    }
    
    u08 recivebyte(void)						//Odbierz bajt danych
    {
    	u08 licznik, data=0;
    	INITDQ
    	for(licznik=0;licznik!=8;licznik++)	//Wykonaj 8 razy
    	{
    		DQOUT
    		_delay_us(2);
    		DQIN
    		_delay_us(10);
    		if(PIN1W&DQ_MASK)					//Sprawdź odebrany bit, jeśli 1 ustaw odpowiedni bit zmiennej data, jeśli 0 nic nie rób
    			data|=(1<<licznik);
    		_delay_us(35);						//Czekaj na zwolnienie linii
    	}
    	_delay_us(100);
    	return data;							//Zwróć odebrane dane
    }
    


    I proste ciało programu:

    
    #include "1wire.h"
    
    ISR(INT0_vect)
    {
    	init1w();
    	sendbyte(0xCC);
    	sendbyte(0x44);
    	_delay_ms(200);
    	_delay_ms(200);
    	_delay_ms(200);
    	_delay_ms(200);
    	_delay_ms(200);
    	init1w();
    	sendbyte(0xCC);
    	sendbyte(0xBE);
    	recivebyte();
    	PORTB=recivebyte();
    }
    
    int main(void)
    {
    	DDRB=0xFF;
    	PORTB=0x00;
    	PORTD|=(1<<2);
    	GICR|=(1<<INT0);
    	MCUCR|=(1<<ISC01);
    	sei();
    	while(1);
    }
    


    W pliku moje.h załączone są wszystkie niezbędne pliki, oraz definicje typów zmiennych:

    
    typedef unsigned char      u08; // 8 bitów bez znaku (int8_t)
    typedef          char      s08; // 8 bitów ze znakiem (uint8_t)
    typedef unsigned short     u16; // 16 bitów bez znaku (int16_t)
    typedef          short     s16; // 16 bitów ze znakiem (uint16_t)
    typedef unsigned long      u32; // 32 bity bez znaku (int32_t)
    typedef          long      s32; // 32 bity ze znakiem (uint32_t)
    typedef unsigned long long u64; // 64 bity bez znaku (int64_t)
    typedef          long long s64; // 64 bity ze znakiem (uint64_t)
    


    Linia DQ znajduje się na PD0.

    Sama obsługa typu odbierz bajt wyślij bajt wydają mi się w porządku, za to mam wrażenie że odbieram nie ten bajt co trzeba. Przy zmianie temperatury dostaję co prawda inne wyniki starszego bajtu, lecz młodszy bajt zawsze jest taki sam(10101010) oraz nie pasują one do tego czym powinny być. Rzekome bity znaku nie są takie same. Podam przykładowe odczyty z portu b (starszych bajtów, bo młodszy taki sam) np dla 20st: 11011010, 21st: 01101101, 22st: 01101110, 23st: 10110111. Aha no i cały ten grajdołek na razie istnieje tylko w symulatorze Proteusa.

    Nie mam pojęcia co to za dziwadła. Z góry dzięki za ewentualną pomoc.

    Dodano po 35 [minuty]:

    Ustawiony był za krótki czas opóźnienia pomiędzy odczytem poszczególnych bitów w funkcji recivebyte() zmiana z 35 na 50 pomogła. Zamykam.
  • REKLAMA
REKLAMA