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

DS18B20 na ATmega32 (PD3) nie wykrywa obecności czujnika – diagnostyka połączenia

pgp 09 Kwi 2006 22:15 2499 4
REKLAMA
  • #1 2511002
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Hej. Implementuje DS18B20 na Atmega32 (na nóżce PD3)

    Oto funkcja resetująca linię one wire :

    unsigned char ow_reset(void) // reset lini one wire
    {
    unsigned char presence;
    sbi(DDRD,3); //DQ = 0; //pull DQ line
    delay(767); // leave it low // wystawienie na czas 480us "0" na linię 1w przez uC
    cbi(DDRD,3);//DQ = 1; // allow line to //powrót lini 1w do trybu wejścia
    delay(111); // wait for presence pulse(pochodzący od DS-a) //czekamy na ustabilizowanie lini
    if(bit_is_clear(PIND,3)) presence=0; //odczytujemy co wystawił na linię DS
    if(bit_is_set(PIND,3)) presence=1; //get presence

    delay(661); // wait for end
    return(presence); // presence signal
    } // 0=presence, 1 = no part


    fragment main() :

    DDRD=0x00; //port D - we
    PORTD=0; //bez podciągania


    kwarc - 8 MHz
    funkcja opóźniająca:


    void delay(unsigned char tau) //czeka ok (5+5*tau)*T, gdzie T to cykl zegara
    { //u nas T=1/8*10^6=125ns
    unsigned char tau2=tau;
    do
    asm("nop"); //wstawka asemblerowa
    while(--tau2!=0);
    }




    wywołanie funkcji resetujacej daje w odpowiedzi 1.
    Sprawdziłem napięcia na lini PD3. Jeśli DDRD=0 to napięcie wynosi 4,96, a jesli ustawię post w tryb wyjściowy (DDRD=1) to 0,03 V. (sprawdziłem to pisząc krótkie programiki przełączające tryb we na wy). Czyżby walnięty czujnik ?

    Dodano po 2 [godziny] 6 [minuty]:

    Hmmm. Wymieniłem czujnik i nadal to samo... Czyli coś nie tak w programie ... Pomóżcie !
  • REKLAMA
  • #2 2515943
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Okazuje się że tak jak wiele kolegów pisało - problem leży w dokłądnym odmierzaniu czasy dla one wire... To co na zwykłym AVR chodzi wolniej to na ATmedze chodzi szybciej - nie do końca wiem dlaczego tak jest... Ale dopiero pomiary oscyloskopowe pomogły wyznaczyć dokładne interwały czasowe... no i temperaturka się ładnie mierzy...
  • REKLAMA
  • #3 2517656
    maly35
    Poziom 14  
    Posty: 91
    Pomógł: 6
    Ocena: 2
    Mógłbyś napisać teraz poprawną procedurkę delay, tzn. ewentualnie już z wartościami bo też się męczę z DS18B20. dzieki
  • REKLAMA
  • #4 2518203
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Jasne, program sprawdzony na ATmega 32, rezonator 8 MHz.

    void delay(unsigned int tau)
    {
    unsigned int tau2=tau;
    do
    { asm("nop"); //wstawka asemblerowa
    }
    while(--tau2);
    }

    unsigned char ow_reset(void) // reset lini one wire
    {
    unsigned char presence=1;
    sbi(DDRD,3); //DQ = 0; //pull DQ line
    delay(245); // leave it low // wystawienie na czas 490us "0" na linię 1w przez uC
    cbi(DDRD,3); //DQ = 1; // allow line to //powrót lini 1w do trybu wejścia
    delay(40); // wait for presence pulse(pochodzący od DS-a) //czekamy na ustabilizowanie lini
    if(bit_is_clear(PIND,3)) presence=0; //odczytujemy co wystawił na linię DS
    //get presence

    delay(190); // wait for end
    return(presence); // presence signal
    } // 0=presence, 1 = no part

    ///---------------------------------------------------------

    // READ_BIT - reads a bit from the one-wire bus. The delay
    // required for a read is 15us, so the DELAY routine won't work.
    // We put our own delay function in this routine in the form of a
    // for() loop.
    unsigned char read_bit(void)
    {
    unsigned char i,presence;
    sbi(DDRD,3); //DQ = 0; // pull DQ low to start timeslot
    cbi(DDRD,3);//DQ = 1; // then return high
    delay(7); // delay 15us from start of timeslot
    if(bit_is_clear(PIND,3)) presence=0;
    if(bit_is_set(PIND,3)) presence=1;
    return(presence); // return value of DQ line
    }
    ///---------------------------------------------------------

    void write_bit(char bitval) //WRITE_BIT - writes a bit to the one-wire bus, passed in bitval.
    {
    sbi(DDRD,3); //DQ = 0; // pull DQ low to start timeslot
    if(bitval==1) cbi(DDRD,3); //DQ =1; // return DQ high if write 1
    delay(50); // hold value for remainder of timeslot - delay 104us
    cbi(DDRD,3);//DQ = 1;
    }

    ///---------------------------------------------------------

    unsigned char read_byte(void) // READ_BYTE - reads a byte from the one-wire bus
    {
    unsigned char i;
    unsigned char value = 0;
    for (i=0;i<8;i++)
    {
    if(read_bit()) value|=0x01<<i; // reads byte in, one byte at a time and then
    delay(47); // shifts it left wait for rest of timeslot
    }
    return(value);
    }

    ///---------------------------------------------------------

    void write_byte(char val) // WRITE_BYTE - writes a byte to the one-wire bus.
    {
    unsigned char i;
    unsigned char temp;
    for (i=0; i<8; i++) // writes byte, one bit at a time
    {
    temp = val>>i; // shifts val right 'i' spaces
    temp &= 0x01; // copy that bit to temp
    write_bit(temp); // write bit in temp into
    }
    delay(51);
    }

    ///---------------------------------------------------------

    void Read_Temperature(void)
    {
    char tmp[10];
    char temp_lsbyte,temp_msbyte;
    int k;
    if(ow_reset()) {lcdxy(0,0); printf("cisza");}
    else
    {
    write_byte(0xCC); //Skip ROM
    write_byte(0x44); // Start Conversion
    delay(51);
    ow_reset();
    write_byte(0xCC); // Skip ROM
    write_byte(0xBE); // Read Scratch Pad
    lcdxy(0,0);
    for (k=0;k<9;k++){tmp[k]=read_byte();}
    printf("DAT=%X%X%X%X%X",tmp[8],tmp[7],tmp[6],tmp[5],tmp[4],tmp[3],tmp[2],tmp[1],tmp[0]);
    temp_msbyte = tmp[1]; // Sign byte + lsbit
    temp_lsbyte = tmp[0]; // Temp data plus lsb
    if (temp_msbyte <= 0x80){temp_lsbyte = (temp_lsbyte/2);} // shift to tmp whole degree
    temp_msbyte = temp_msbyte & 0x80; // mask all but the sign bit
    if (temp_msbyte >= 0x80) {temp_lsbyte = (~temp_lsbyte)+1;} // twos complement
    if (temp_msbyte >= 0x80) {temp_lsbyte = (temp_lsbyte/2);}// shift to tmp whole degree
    if (temp_msbyte >= 0x80) {temp_lsbyte = ((-1)*temp_lsbyte);} // add sign bit
    lcdxy(1,0);
    printf( "TempC=%d C", (int)temp_lsbyte ); // print temp. C
    temperature=temp_lsbyte;
    }
    }


    ______________________________


    zmienna temperature to w moim programie zmienna globalna przechowująca wartość odczytanej temperatury.

    Dodano po 1 [minuty]:

    funkcje są ściągnięte z noty katalogowej Dallasa. używam czujnika DS1820.
  • #5 3102954
    Kubbaz
    Poziom 26  
    Posty: 1237
    Pomógł: 9
    Ocena: 30
    Witam

    Ponieważ chcę podłączyć iButton DS1996 - pamięć 64kb na 1-wire do mojego uC ATMEGA8 (z kwarcem zewnętrznym 8MHz), to czy zadziałały by twoje funkcje w C ?? tj.:
    ow_reset(void);
    read_bit(void);
    

    itp. no oprócz tej do pomiaru temperatury, bo jej bym nie potrzebował ...
REKLAMA