Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

DS18b20 + lcd + atmega 32 programowany w c

09 Mar 2007 22:45 3262 4
  • Poziom 16  
    Przepraszam odrazu że poruszam temat wałkowany 1000 a moze i wiecej razy. Niestety jednak niepotrafie sobie sam poradzić dlatego prosze was o pomoc.

    Termometr wyswietla mi cały czas temp -0.02

    Niemam pojecia dlaczego


    Ds jest zasilany ciągle (nie przez iwire) a środkowa noga zwarta przez rezystor podciągający (4,7k) do zasilania.
    podłączyłem go do 0 pina portu d

    Niewiem czy przez przypadek nie spaliłem dallasa podłączając na odwrót polaryzacje ale nie wydaje mi się poniewaz 2 dallas reaguje tak samo .
    Moze macie jakiś sposobik co by szybko sprawdzic dallasa ?

    Jeżeli ktoś byłby tak miły i zobaczył mój kod...
    Oscylator ustawiłem na 4MHz

    Code:

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    //
    #define klaw PORTC
    #define oklaw PINC
    #define dklaw DDRC

    #define LCD  PORTA
    #define DLCD DDRA
    #define E  3
    #define RS  2
    //
    #define SET_E   LCD |= _BV(E)
    #define CLR_E   LCD &= ~_BV(E)
    //
    #define SET_RS  LCD |= _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)

    #define DQ 1

    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)

    #define IN_DQ PIND & _BV(DQ)

    //ENABLE_INT0_FLAGING;
    unsigned char temper1, temper2, dana=1, dana1;


    // procedura opóźniająca o (5+5*t)* 0,25 us dla 4MHz kwarcu
    void delay(int t)
    {
    do{asm("nop");}while(--t);
    }

    void delay_ms(unsigned int ms)
    {
       unsigned int i;
          for (i=0;i<ms;i++)
           {
                 delay(800);
                 asm volatile ("WDR");
       }
    }
    //obsługa klawiatury mtrycowej 4x4
    prog_char tz[4][4]=   {
                     {'D','C','B','A'},
                   {'#','9','6','3'},
                   {'0','8','5','2'},
                   {'*','7','4','1'}
                                   };                

    int i=1000;
    char bufor[17];
    char tabc[3];
    //tabc[1]=tz[1][1];

    char przycisk()
    {
    unsigned char row,col,k; // lokalne zmienne pomocnicze
    unsigned char m=0x01; // maska do wyboru rzędu

    for(row=0;row<4;row++) //4 rzędy
       {
       //dklaw=m; //wybór rzędu przez zmianę kierunku
       klaw=~m;
       k=0xEF; //odczyt kolumn
       for(col=0;col<4;col++) // 4 kolumny
          {
          if(oklaw==(~m&k)) // sprawdzanie czy kolumna = 0
             {
             //dklaw=0xF0; // wszystkie rzędy - wyjście(wykrycie naciśnięcia dowolnego przyc.)
             klaw=0xF0;
           return(tabc[0]=pgm_read_byte(&tz[row][col])); // pobieramy kod klawisza z tablicy w pamięci programu
             }
          k<<=1;
         k++; // kolejna kolumna na pozycję 0
          }
       m<<=1; // kolejny rząd jako wyjście
       }
    //dklaw=0xF0;
    klaw=0xF0;
    return (tabc[0]='e'); // czyżby nic nie wciśnięto ?
    }

    //koniec obsługi klawiatyry




    // pcodedura zapisu bajtu do wyświetlacza LCD
    // bez rozróżnienia instrukcja/dana
    void write_to_lcd(char x)
    {
    SET_E; // ustaw na E stan wysoki
    LCD = ((LCD & 0x0F) | (x & 0xF0)); // zapis pierwszej połówki bajtu
    CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    SET_E; // ustaw na E stan wysoki
    LCD = ((LCD & 0x0F) | ((x & 0x0F) << 4)); // zapis drugiej połowki bajtu
    CLR_E; // opadające zbocze na E -> zapis do wyświetlacza
    delay_ms(1); // czekaj 1ms
    }

    // procedura zapisu instrukcji do wyświetlacza LCD
    void write_command(char x)
    {
    CLR_RS; // niski stan na RS -> zapis instrukcji
    write_to_lcd(x); // zapis do LCD
    }

    // procedura zapisu danej do wyświetlacza LCD
    void write_char(char x)
    {
    SET_RS; // wysoki stan na RS -> zapis danej
    write_to_lcd(x); // zapis do LCD
    }

    // procedura zapisu tekstu do wyświetlacza LCD
    void write_text(char * s)
    {
    while(*s) // do napotkania 0
      {
      write_char(*s); // zapisz znak wskazywany przez s na LCD
      s++; // zwiększ s (przygotuj nastepny znak)
      }
    }

    // USTAWIANIE KURSORA W ZADANYM MIEJSCU
    void lcd_xy(unsigned char w, unsigned char k)
    {
     write_command((w*0x40+k)|0x80);
    }

    // procedura inicjalizacji wyświetlacza LCD
    void lcd_init(void)
    {
    delay_ms(15); // czekaj 15ms na ustabilizowanie się napięcia zasilającego
    CLR_E; // E = 0
    CLR_RS; // RS = 0
    char i; // zmianna licznikowa
    for(i = 0; i < 3; i++) // trzykrotne powtórzenie bloku instrukcji
      {
      SET_E; // E = 1
      LCD &= 0x3F; //
      CLR_E; // E = 0
      delay_ms(5); // czekaj 5ms
      }
    SET_E; // E = 1
    LCD &= 0x2E; //
    CLR_E; // E = 0
    delay_ms(1); // czekaj 1ms
    write_command(0x28); // interfejs 4-bity, 2-linie, znak 5x7
    write_command(0x08); // wyłącz LCD, kursor i miganie
    write_command(0x01); // czyść LCD
    write_command(0x06); // bez przesuwania w prawo
    write_command(0x0C); // włącz LCD, bez kursora i mrugania
    }

     // OBSLUGA 1 WIRE


    // procedura reset
    void ow_reset(void)
    {
    CLR_DQ; // stan niski na linii 1wire
    delay(255); //
    delay(119); // opóźnienie ok 480us
    //delay(1);
    SET_DQ;// stan wysoki na linii 1wire
    delay(255); //
    delay(119); // opóźnienie ok 480 us
    }
    // procedura zapisu bitu na linię 1wire
    void ow_write_bit(char b)
    {
    cli(); // zablokowanie przerwań
    CLR_DQ; // stan niski na linii 1wire
    delay(7); // opóźnienie 10us
    if(b) SET_DQ; // jeśli parametr jest niezerowy to ustaw stan wysoki na linii
    delay(80); // opóźnienie 100us
    SET_DQ; // stan wysoki na linii 1wire
    sei(); // odblokowanie pzrerwań
    }

    char ow_read_bit(void)
    {
    cli();
    CLR_DQ;
    delay(1);
    SET_DQ;
    delay(11);
    sei();
    if(IN_DQ) return 1; else return 0;
    }

    unsigned char ow_read_byte(void)
    {
    unsigned char i;
    unsigned char value = 0;
    for (i=0;i<8;i++)
    {
    if(ow_read_bit()) value|=0x01<<i;
    delay(6);
    }
    return(value);
    }

    void ow_write_byte(char val)
    {
    unsigned char i;
    unsigned char temp;
    for (i=0; i<8; i++)
    {
    temp = val >> i;
    temp &= 0x01;
    ow_write_bit(temp);
    }
    delay(5);
    }


    void USART_Transmit( unsigned char data )
    {
       /* Wait for empty transmit buffer */
       while ( !( UCSRA & (1<<UDRE)) );
       /* Put data into buffer, sends the data */
       UDR = data;
    }

    // Zapis temperatury na wyswietlaczu
    void write_temp( short int t)
    {
       char s, d, j;
       
       if (t < 0)   
       {
       lcd_xy(1,0);
       write_text("-");
       t = -t;
       }
           
       s = t/100;
       d = (t-(s*100))/10;
       j = t-(s*100+d*10);
       USART_Transmit(s+48);
       USART_Transmit(d+48);
       USART_Transmit('.');
       USART_Transmit(j+48);
       USART_Transmit(32);
       write_char(s+48);
       write_char(d+48);
       write_text(".");
       write_char(j+48);
    }
       
      short int odczytaj_temp(void)

    {
             char temp1, temp2;
           short int tmp1, ulamek, t;
                   
          ow_reset();
            ow_write_byte(0xcc);           // pomin czytanie nr
            ow_write_byte(0x44);          // nakaz pomiar temperatury
            delay_ms(800);                // czekaj na przetworzenie 800 dla 12 bitow
          ow_reset();
          ow_write_byte(0xcc);           // pomin czytanie nr
          ow_write_byte(0xbe);           // zadaj odczytania temperatury
           temp1 = ow_read_byte();    // pierwszy bajt mlodszy
            temp2 = ow_read_byte();    // drugi bajt starszy
           
          tmp1 = temp1;                      // w tmp1 bedziemy trzymac czesc ulamkowa
                    tmp1 &= 0x0f;            // wycinamy niepotrzebne bity HHHH
                    temp1 >>= 4;             // przesuwamy HHHH w prawo wycinamy LLLL
                    temp2 <<= 4;             // wycinamy 4 niepotrzebne bity znaku
                    t = temp1 | temp2;     // laczymy i w t mamy czesc calkowita
                if (t > 127)              // gdy temperatura jest ujemna
                       {                       // musimy przeliczyc wynik
                            t =(255 - t);       // przeliczamy czesc calkowita
                            tmp1 =( 15 - tmp1);    // przeliczamy czesc ulamkowa       
                       
                   }       
                ulamek = tmp1 * 625;        // ulamek o warosciach do 10000
                    tmp1 = ulamek / 1000;      // tmp1 musi byc w granicach od 0 do 9
                    if (tmp1 ==10) tmp1 = 0;
                t=(t*10)+(tmp1-1);
                 
          return(t);
    }

    // program główny
    int main(void)
    {
    short int tm;

    GIMSK=1<<INT0;         //włącz przerwanie zewnętrzne INT0
    MCUCR=0x02;            //przerwania INT0 wyzwalane narastajacym zboczem
    // konfiguracja portów we/wy

    DLCD = 0xFF;
    LCD = 0xFF;
    dklaw = 0x0F;
    klaw = 0xF0;
    sei();

    // inicjalizacja LCD
    lcd_init();
    // zapisz na LCD przykładowy tekst
    write_command(0x01); // czyść LCD
    /*write_text("Ala ma kota :D");
    write_command(0xC0);

    itoa(i,bufor,10);
    write_text(bufor);

    //write_text(tz);
    // petla nieskończona*/
    lcd_xy(0,0);
    write_text("temperatura:");
    int e=0;
    while(1)
    {

    char bufor1[33];
    tm = odczytaj_temp();
    lcd_xy(1,2);
    write_temp(tm);
    itoa(e,bufor1,10);
    lcd_xy(1,10);
    write_text(bufor1);
    delay_ms(20);
    e++;
    //return (0);     
    }   
    return 0;
    }






    SIGNAL(SIG_INTERRUPT0)
    {


    przycisk();

    {
    if(tabc[0]=='3'||tabc[0]=='6'||tabc[0]=='9'||tabc[0]=='#'||tabc[0]=='A'||tabc[0]=='B'||tabc[0]=='C'||tabc[0]=='D')
       {
       i--;
       write_command(0x1C);
       }
       else
       {
       i++;
       write_command(0x18);
       }



    write_command(0xC0);
    write_text("              ");

    itoa(i,bufor,10);
    write_command(0xC0);
    write_text(bufor);
    write_text(" ");
    write_text(tabc);
    }


    }


    Dzieki za rady...

    P.S
    Po czytanie wielu tematów na temat ds18b20 doszłem do wniosku coby stworzyć oddzielny temacik gdzie by była skarbnica wiedzy poniewaz wiele osób pyta o podstawy takie jak obsługa iwire lub procedurki do dsa.
    Wiele milej było by to wszystko znależć w 1 temacie.
    Jezeli ktoś by zechciał mi pomóc to moze byśmy zredagoowali jakiś taki post nadający się do doklejenia z podstawowymi procedurkami.
  • Poziom 39  
    domelfm napisał:
    ...Termometr wyswietla mi cały czas temp -0.02

    Niemam pojecia dlaczego

    No to zaraz podam Ci , pierwszy powód ;)
    domelfm napisał:
    ...podłączyłem go do 0 pina portu d

    Tiaaaa.... a w kodzie ...
    Code:

    /*...*/
    #define DQ 1

    #define SET_DQ DDRD &= ~_BV(DQ)
    #define CLR_DQ DDRD |= _BV(DQ)

    #define IN_DQ PIND & _BV(DQ)
    /*...*/

    domelfm napisał:

    Dzieki za rady...

    Nie ma za co ;)
    Natomiast za "nad-komentarze" i "niezgodność" z kanonami sztuki programowania w C , dostanie Ci się :shii: od kol. JacekCz :D

    Piotrek
  • Poziom 16  
    Cze...

    Takie dorobne przeoczenie ale i taki efekt ten sam...
    Teraz zmieniłem sobie na portb pin 0.

    Code:

    #define DQ 0

    #define SET_DQ DDRB &= ~_BV(DQ)
    #define CLR_DQ DDRB |= _BV(DQ)

    #define IN_DQ PINB & _BV(DQ)
  • Poziom 12  
    Witam.

    Po pierwsze sprawdź dokładnie czy Twoja funkcja odczytu temperatury poprawnie konwertuje wynik (nie wydaje mi się ale mogę się mylić). Sprawdź też komunikację z DSem - opóźnienia przy transmisji i czy delay_ms(800) rzeczywiście daje 800ms opóźnienia. Funkcja ta zwraca -2 (co odpowiada temp. -0.2 jak rozumiem) dla wartości odczytanej z czujnika 0xFFFF. Bawiłem się kiedyś DSami i miałem podobny efekt - często dostawałem same FFki - problem związany był właśnie z funkcją delay(us).
  • Poziom 12  
    zumek napisał:

    Natomiast za "nad-komentarze" i "niezgodność" z kanonami sztuki programowania w C , dostanie Ci się :shii: od kol. JacekCz :D

    To ja się wtrącę, żeby nie było, że tylko JacekCz krytykuje :D. Bo niestety ma on absolutną rację.
    Oczywiście kod wygląda na "CTRL+C -> CTRL+V" z kursu http://mikrokontrolery.net/avr_kursy.htm - stąd tyle komentarzy. Jak zwykle razi (nad)używanie #define. I tu poprę kolegę JacekCz - lepiej żeby kursu wogóle nie było, niżby miał uczyć złego stylu. Niestety to specyfika polskich kursów. Dlatego czasem warto pomęczyć się i poszukać anglojęzycznych...
    Czy tak trudno nauczać korzystania z sympatycznej i nadzorowanej przez kompilator funkcji inline?? Efekt ten sam a ileż zalet...

    domelfm napisał:
    Po czytanie wielu tematów na temat ds18b20 doszłem do wniosku coby stworzyć oddzielny temacik gdzie by była skarbnica wiedzy poniewaz wiele osób pyta o podstawy takie jak obsługa iwire lub procedurki do dsa.

    Zamiast tego proponuję stworzyć oddzielny temat zajmujący się prostowaniem głupot (przepraszam za wyrażenie ale inaczej sie nie da...) wypisywanych w kursach C na uC...

    Pozdrawiam,
    Zenek[/b]