Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

problem z odczytem temperatury z 1wire za pomoca 4xDS1820

lukasb9 03 Jul 2006 01:10 1586 2
  • #1
    lukasb9
    Level 28  
    Pokładałem sobie urzadzonko które ma czytac z czterech ds-ów temperature, wszystkie cztery sa na jednej magistrali z zasilaniem osobnym, (trzy kable) wyswietlacze na których ma byc pokazana temperatura to zwykłe 7-mio segmentowe led-y, multipleksowane w przerwaniu od timera (przerwanie działa tylko w momentach kiedy ds czeka naprzykład na impuls strobujacy z procesora i odwrotnie, stad nie przeszkadzxa w transmisji po 1wire) i wszystko niby jest ok ale... jak podłacze wiecej jak 2 ds-y to całosc sie psuje, co któras transmisja to odczyt samych jedynek z magistrali, przy podłaczeniu 4 ds-ów to juz sie nieda zobaczyc temperatury tak czesto sa te złe odczyty.... zmieniałem opornik podciagajacy, próbowałem delikatnie filtrowac magistrale i nic...bład jest w programie , załaczam listing z nadzieja ze ktos cos znajdzie, to mój pierwszy program w C prosze o wyrozumiałosc, zapomniał bym, numery ds-ów sa zapisane w eepromie atmegi8 która całoscia steruje



    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    unsigned char tablica[18];

    unsigned char tablica2[32];
    unsigned char licznik;
    void selectchar (unsigned char numchar);
    void zapisz1w (unsigned char rozkaz);
    void czytaj1w(void);
    unsigned char odbierz(void);


    void wait1w (unsigned char time)
    {
    do
    {asm("NOP");}
    while(--time);
    }


    void wait480us(void)
    {TIMSK |= _BV(0);
    unsigned char zt1;
    unsigned char zt;
    for (zt=15;zt>0;zt--)
    {for(zt1=20;zt1!=0;zt1--)
    asm("NOP");}
    TIMSK &= ~_BV(0);}



    void wait415us (void)
    {TIMSK |= _BV(0);
    unsigned char zt1;
    unsigned char zt;
    for (zt=14;zt>0;zt--)
    {for(zt1=20;zt1!=0;zt1--)
    asm("NOP");}
    TIMSK &= ~_BV(0);}


    unsigned char reset1w()
    {unsigned char stan;
    TIMSK |= _BV(0);
    stan = 0;
    DDRC |= _BV(2);
    wait480us();
    DDRC &= ~_BV(2);
    wait1w(49);
    if bit_is_clear(PINC,PC2)
    stan = 1;
    wait415us();
    if bit_is_clear(PINC,PC2)
    stan = 0;
    TIMSK &= ~_BV(0);
    return stan;}








    void wyslij (unsigned char znak)
    {
    if (znak)
    {
    DDRC |= _BV(2); //sciagnij wyjscie 1wire do masy
    wait1w(5);
    DDRC &= ~_BV(2); //zwolnij linie 1wire
    TIMSK |= _BV(0); //zezwolenie na przerwania od timera
    wait1w(44);
    TIMSK &= ~_BV(0); //wylaczenie obslugi przerwania od timera
    DDRC &= ~_BV(2); //zwolnij linie 1wire
    }
    else
    {
    DDRC |= _BV(2); //sciagnij wyjscie 1wire do masy
    TIMSK |= _BV(0); //zezwolenie na przerwania od timera
    wait1w(54);
    TIMSK &= ~_BV(0); //wylaczenie obslugi przerwania od timera
    DDRC &= ~_BV(2); //zwolnij linie 1wire
    }}







    void zapiseeproma (void)
    {
    unsigned char flag;
    unsigned char i;
    extern unsigned char tablica2[32];
    flag = 0;
    EEARH = 0;
    unsigned char slot;
    if bit_is_clear(PIND,PD2)
    {slot = 0;
    flag = 1;}
    if bit_is_clear(PIND,PD1)
    {slot = 8;
    flag = 1;}
    if bit_is_clear(PIND,PD0)
    {slot = 16;
    flag = 1;}
    if bit_is_clear(PINC,PC5)
    {slot = 24;
    flag = 1;}


    if (flag == 1)
    {


    if (reset1w()) //reset magistrali
    {
    zapisz1w(0x33); //rzadanie o przedstawienie pastylki
    for(i=(0+slot);i<(8+slot);i++) //8 razy odczytaj i zapisz bajt z układu do eeproma
    {
    do //petla nieskonczona
    {} //czeka az dostane zezwolenie na zapis
    while(bit_is_set(EECR,EEWE)); //eeproma

    EEARL = i;
    EEDR=odbierz(); //odbierz bajt z 1wire
    EECR = 0b00000100;
    EECR = 0b00000110;
    }}

    EECR = 0b00000000;





    }
    for (i=0;i<32;i++)
    {

    do //petla nieskonczona
    {} //czeka az dostane zezwolenie na odczyt
    while(bit_is_set(EECR,EEWE)); //eeproma


    EEAR = i;
    EECR |= 0b00000001;
    tablica2[i]=EEDR;}

    }
    ///////////////////////////////////////////
    ///////////////////////////////////////////
    ///////////////////////////////////////////
    int main(void)
    {
    extern unsigned char tablica2[32];
    unsigned char adres;
    unsigned char temporary;
    extern unsigned char tablica[18];
    unsigned char temperatura;
    unsigned char liczniczek;

    DDRD = 0b11111111; //konfiguracja portów PD3,4,5,6,7 jako wyjsciowy
    DDRB = 0b00011111; //konfiguracja portów PB0,1,2,3,4 jako wyjsciowy (podciagniecie do jeden)
    DDRC = 0b00100011; //konfiguracja portu C jako wyjsciowy
    PORTC |=0b00100011; //ustawienie pinów C0, i C2 na jedynke
    PORTD |=0b00000111;
    zapiseeproma ();
    TCCR0 = 0b00000100; //konfiguracja preskalera dla timera 0 na 1024
    TCNT0 = 0b11111000; //załaduj do rejestru timera liczbe 245 (przerwaniepo 10 impulsach)
    TIMSK |= _BV(0); //LOKALNE ZEZWOLENIE NA PRZERWANIE "0"
    SREG |= _BV(7); //GLOBALNE ZEZWOLENIE NA OBSLUGE PRZERWAN
    do
    {
    liczniczek++;
    if(liczniczek==4)
    liczniczek=0;

    if (reset1w()) //sprawdź czy na magistrali sa jakies urzadzenia
    {
    zapisz1w(0xCC); //zapisz do ds-a polecenie skip rom
    zapisz1w(0x44); //poczatek konwersji dla wszystkich czujników

    if bit_is_set(PINC,PC2) //poczekaj na zakonczenie konwersji A/D
    {
    reset1w(); //reset ds-a - jasna sprawa
    zapisz1w(0x55); //zapisz do ds-a polecenie match rom

    //tablica[18]=17;
    //tablica[17]=17;
    if(liczniczek == 0)
    {temporary = 0;
    for (adres=0;adres<8;adres++)
    zapisz1w(tablica2[adres]);}
    if(liczniczek == 1)
    {temporary = 4;
    for (adres=8;adres<16;adres++)
    zapisz1w(tablica2[adres]);}
    if(liczniczek == 2)
    {temporary = 9;
    for (adres=16;adres<24;adres++)
    zapisz1w(tablica2[adres]);}
    if(liczniczek == 3)
    {temporary = 13;
    for (adres=24;adres<32;adres++)
    zapisz1w(tablica2[adres]);}

    zapisz1w(0xBE); //zapisz do ds-a zadanie odczytu temperatury
    }

    temperatura = odbierz();

    if(temperatura < 255)
    {tablica[temporary+1]=(temperatura/20);
    tablica[temporary+2]=(temperatura-(20*(temperatura/20)))/2;
    tablica[temporary+3]=16;
    tablica[temporary+4]=12;}
    else
    {tablica[temporary+1]=14;
    tablica[temporary+2]=18;
    tablica[temporary+3]=18;
    tablica[temporary+4]=17;}


    }
    else
    {for (temporary=0;temporary<17;temporary++)
    tablica[temporary]=19;}

    }
    while(1);
    return 0;
    }
    ///////////////////////////////////////////
    ///////////////////////////////////////////
    ///////////////////////////////////////////









    void selectchar (unsigned char numchar)
    {switch(numchar){
    case 0:
    PORTD = 0b11000000;
    PORTB = 0b00001111;
    break;
    case 1:
    PORTD = 0b01000000;
    PORTB = 0b00000010;
    break;
    case 2:
    PORTD = 0b01000000;
    PORTB = 0b00011101;
    break;
    case 3:
    PORTD = 0b01000000;
    PORTB = 0b00010111;
    break;
    case 4:
    PORTD = 0b11000000;
    PORTB = 0b00010010;
    break;
    case 5:
    PORTD = 0b10000000;
    PORTB = 0b00010111;
    break;
    case 6:
    PORTD = 0b10000000;
    PORTB = 0b00011111;
    break;
    case 7:
    PORTD = 0b01000000;
    PORTB = 0b00000011;
    break;
    case 8:
    PORTD = 0b11000000;
    PORTB = 0b00011111;
    break;
    case 9:
    PORTD = 0b11000000;
    PORTB = 0b00010111;
    break;
    //case 10:
    //PORTD = 0b11000000;
    //PORTB = 0b00011011;
    //break;
    //case 11:
    //PORTD = 0b10000000;
    //PORTB = 0b00011110;
    //break;
    case 12:
    PORTD = 0b10000000;
    PORTB = 0b00001101;
    break;
    //case 13:
    //PORTD = 0b01000000;
    //PORTB = 0b00011110;
    //break;
    case 14:
    PORTD = 0b10000000;
    PORTB = 0b00011101;
    break;
    //case 15:
    //PORTD = 0b10000000;
    //PORTB = 0b00011001;
    //break;
    case 16:
    PORTD = 0b11000000;
    PORTB = 0b00010001;
    break;
    case 17:
    PORTD = 0b00000000;
    PORTB = 0b00000000;
    break;
    case 18:
    PORTD = 0b00000000;
    PORTB = 0b00011000;
    break;
    case 19:
    PORTD = 0b00000000;
    PORTB = 0b00010000;
    break;
    }}







    void zapisz1w (unsigned char rozkaz)
    {
    unsigned char i;
    for(i=0;i<8;i++)
    {
    wyslij(rozkaz&0x01);
    rozkaz>>=1;
    }}
    unsigned char odbierz(void)
    {
    unsigned char bitna1w;
    unsigned char i;
    unsigned char bajt;
    bajt=0;
    for (i=0;i<8;i++)
    {
    bitna1w =1; //ustaw wstepnie bit
    DDRC |= _BV(2); //sciagnij wyjscie 1wire do masy
    wait1w(1);
    DDRC &= ~_BV(2); //zwolnij linie 1wire
    wait1w(6);
    if bit_is_clear(PINC,PC2) //jesli pastylka sciagneła linie to
    bitna1w = 0; //odczytany bit jest zerem, jesli nie to jeden
    TIMSK |= _BV(0);
    wait1w(44);
    TIMSK &= ~_BV(0);
    if(bitna1w) bajt |= 0x01<<i;
    }
    return bajt; //no i zwróc to co odczytałes
    }






    SIGNAL(SIG_OVERFLOW0)
    {
    extern unsigned char tablica[18];
    extern unsigned char licznik;
    TCNT0 = 0b11110000;
    PORTD = 0b00000000;
    PORTB = 0b00000000;
    licznik++;


    PORTD |= _BV(4);
    PORTD &= ~_BV(4);
    if (licznik==17)
    licznik = 0;

    if (licznik<9)
    {
    PORTD &= ~_BV(5);
    PORTD |= _BV(3);
    }
    else
    {
    PORTD &= ~_BV(3);
    PORTD |= _BV(5);
    }



    selectchar (tablica[licznik+1]);

    }
  • #2
    zumek
    Level 39  
    Z krótkiej lektury Twojego kodu wynika jedno - nie znasz "zasady działania" DS18B20 :(
    Za pomocą rozkazu 1wire 0x33(READ ROM) , nie można odczytać ID , jeśli na linii jest >1 układ.Do tego służy rozkaz 0xF0(SEARCH ROM).Po wtóre , sprawdzanie stanu magistrali 1wire , by wykryć koniec konwersji , nic nie da. Procek musi "zapytać" czy konwersja dobiegła końca , odczytując 1 bit z magistrali 1wire ... itd :(

    Piotrek
  • #3
    lukasb9
    Level 28  
    A wiec... dziekuje za odpowiedź:) teraz małe sprostowanie, nie uzywam układów DS18B20 tylko DS1820, odczyt ID pastylki przeprowadzam jednorazowo, zwierajac jedna z czterech zworek na płytce podłaczajac tylko jeden czujnik i właczajac układ co powoduje zapis ID do EEPROMA, czynnosc ta powtarzam 4 razy dla czterech ds-ów za kazdym razem przykładajac tylko jeden do magistrali, kiedy juz wszystkie sa zapisane w EEPROMIE zdejmuje zworke i odpalam układ, teraz cały program pobiera numery seryjne z EEPROMA polecenia READ ROM (0x33) uzyłem tylko w miejscu programowania EEPROMA a to wykonuje sie tylko raz i w załozeniu z jednym ds-em na magistrali nie rozumiem jeszcze tylko tego czekania na koniec konwersji zaraz sprawdze w nocie wydawało mi sie ze układy na czas konwersji zwieraja magistrale i wystapienie na niej stanu "1" oznacza koniec konwersji wszystkich układów