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

Jak wyświetlić temperaturę z DS18B20 na LCD w AVR-GCC?

Ganz 14 Gru 2005 23:46 5393 2
REKLAMA
  • #1 2084432
    Ganz
    Poziom 17  
    Posty: 299
    Pomógł: 10
    Ocena: 1
    Walczę właśnie z DS18B20. Mój procek to AT90S2313 na płytce ZL1AVR, a kwarc 8 MHz. 1-Wire wychodzi tam na pin nr 3 portu D, a pin VCC DS18B20 jest podłączony do 5V. Port B służy do obsługi wyświetlacza. (To info dla tych co nie znają ZL1AVR ;-) ) Program pisałem w AVR-GCC na podstawie informacji ze strony www.mikrokontrolery.net i książki "Mikrokontrolery AVR w Praktyce" Radosława Dolińskiego.

    Problem mój polega na tym, że nie za bardzo wiem jak wyświelić temperaturę zmierzoną przez DS 18B20. Nie wiem, czy problem polega na tym, że źle odczytuję (np. źle dobrane opóźnienia/odstępy), czy źle wypisuję (było kilka koncepcji, ale żadna nie wypaliła więc wyciąłem fragmenty kodu odpowiadające za wyślwietlanie temperatury). Jeśli ktoś ma jakieś pomysły na to jak wypisać na LCD temperaturę w oparciu o moje funcje lub zweryfikować moje funcje odpowiedzialne za obsługę 1-Wire (szczególnie opóźnenia i funkcję ow_read_bit) to prosze o pomoc.

    Jeszcze jedno. Co musiałbym zmienić w algorytmie, aby umóżliwić sobie pracę z DS18S20?

    P.S. Funkcje do obsługi LCD są przetestowane więc powinny być ok.

    
    
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/delay.h>
    #include <avr/signal.h>
    // Zmienne do obslugi LCD ******************************************************************
    unsigned char row = 0;
    unsigned char column = 0;
    unsigned char lcd_rs = 2;   //definicja bitu portu dla linii RS
    unsigned char lcd_e = 3;    //definicja bitu portu dla linii E
    unsigned char CR = 0x0a;    //definicja znaku CR (przejście do nowej linii)
    //******************************************************************************************
    #define DQ 3
    #define CLR_DQ DDRD |= _BV(DQ)
    #define SET_DQ DDRD &= ~_BV(DQ)
    #define IN_DQ PIND & _BV(DQ)
    
    
    const unsigned char tau = 10.38;     //przybliżony przelicznik argumentu na ms
    // Funkcje do obslugi LCD******************************************************************
    void wait(unsigned long w) //procedura wytracania czasu
    {                   
     unsigned char tp;
     for(;w>0;w--)
     {
      for(tp=255;tp!=0;tp--);
     }
    }
    
    void lcd_send_i(unsigned char instruction) //zapisz instrukcję sterującą do LCD
    {
     PORTB = (PORTB & 0xFB); //cbi(PORTB,lcd_rs);
     PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
     PORTB = ((PORTB & 0x0f) | (instruction & 0xf0));  //przygotuj starszy półbajt do LCD
     asm("nop");                       //wymagane wydłużenie impulsu
     asm("nop");
     asm("nop");
     PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e); impuls strobujący
     wait(10L);                      //czekaj na gotowość LCD ok. 100us
     PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
     PORTB = ((PORTB & 0x0f) | ((instruction & 0x0f)<<4));//przygotuj młodszy półbajt do LCD
     asm("nop");
     asm("nop");
     asm("nop");
     PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e);
     wait(10L);                      //czekaj na gotowość LCD ok. 100us
    }
    
    void lcd_send_d(char data)           //zapisz daną do LCD
    {
     PORTB = (PORTB | 0x04); //sbi(PORTB,lcd_rs);
     PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
     PORTB = ((PORTB & 0x0f) | (data & 0xf0));   //przygotuj starszy półbajt do LCD
     asm("nop");                       //wymagane wydłużenie impulsu
     asm("nop");
     asm("nop");
     PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e);                 //impuls strobujący
     wait(10L);                      //czekaj na gotowość LCD
     PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
     PORTB = ((PORTB & 0x0f) | ((data & 0x0f)<<4)); //przygotuj młodszy półbajt do LCD
     asm("nop");
     asm("nop");
     asm("nop");
     PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e);      impuls strobujący
     wait(10L);                      //czekaj na gotowość LCD
    }
    
    void write(char string)    //procedura umieszcza znak na wyświetlaczu
    {
     lcd_send_d(string);            //wyświetl znak na LCD
     if(++column==16)          //czy bieżąca kolumna mieści się na wyświetlaczu?
     {                          
      column=0;                //jeśli nie, to ustaw początkową...
      if(++row==2)           //i przejdź do nowego wiersza
      {
       row=0;       //jeśli nowy wiersz jest poza wyświetlaczem, ustaw początkowy
      }
     }
    }
    
    void lcd_clr(void)                //czyść ekran
    {
     lcd_send_i(0x01);      //polecenie czyszczenia ekranu dla kontrolera LCD
     wait(1.64*tau);    //rozkaz 0x01 wykonuje się 1.64ms
     row = 0;
     column = 0;
    }
    
    void lcd_xy(unsigned char w, unsigned char k)    //ustaw współrzędne kursora
    {
     lcd_send_i((w*0x40+k)|0x80);  //standardowy rozkaz sterownika LCD 
    } //ustawiający kursor w określonych współrzędnych}
    
    void write_text(char * s)
    {
     while(*s) // do napotkania 0
      {
      lcd_send_d(*s); // zapisz znak wskazywany przez s na LCD
      s++; // zwiększ s (przygotuj nastepny znak)
       //if (++column==16) 
       //{
       // lcd_xy(1,0);
       //}
      }
    }
    //1-Wire*********************************************************************************
    void delay_us(unsigned char us)
    {
     do
     {
      asm("nop");
     } while(--us!=0);
    }
    
    void ow_reset(void) //reset 1-Wire
    {
     CLR_DQ; // stan niski na linii 1wire
     delay_us(255);
     delay_us(255);
     delay_us(255); // opóźnienie ok 480us
     SET_DQ;// stan wysoki na linii 1wire
     delay_us(255);
     delay_us(255);
     delay_us(255); // opóźnienie ok 480us
    }
    
    void ow_write_bit(unsigned char bit) // zapisu bitu na linię 1wire
    {
     CLR_DQ; // stan niski na linii 1wire
     delay_us(20); // opóźnienie 11us
     if(bit) SET_DQ; // jeśli parametr jest niezerowy to ustaw stan wysoki na linii
     delay_us(119); // opóźnienie 100us
     SET_DQ; // stan wysoki na linii 1wire
    }
    
    void ow_write_byte(unsigned char value)
    {
     unsigned char i;
     unsigned char temp;
     for (i=0; i<8; i++)
     {
     temp = value >> i;
     temp &= 0x01;
     ow_write_bit(temp);
     }
     delay_us(10);
    }
    
    unsigned char ow_read_bit(void)
    {
     CLR_DQ;
     delay_us(1);
     SET_DQ;
     delay_us(27);
     if(IN_DQ) return 1; else return 0;
     //Moze cos dodac - delay
    }
    
    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_us(12);
     }
     return(value);
    }
    
    //****************************************************************************************
    int main(void)
    {
     // Inicjalizacja LCD ********************************************************************
     unsigned char i;
    
     DDRB = 0xFF; //PORTB - wy
     PORTB = 0x03;   //port z podciąganiem
     DDRD |= _BV(3);
     DDRD |= _BV(4);
     PORTD |= _BV(DQ);
     
     //>>>>>>>>>>>>>>>>>>   inicjacja wyświetlacza LCD   <<<<<<<<<<<<<<<<<<<<<<
     wait(45*tau);        //opóźnienie ok. 45ms dla ustabilizowania się napięcia
                            //zasilania LCD (katalogowo min. 15 ms)
                            //lcd_rs już wcześniej było ustawione w stanie "0"
     for(i=0;i<3;i++)       //3-krotne wysłanie 3-
     {
      PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
      PORTB=((PORTB&0x0f)|0x30); //wyślij 3- do LCD
      asm("nop");
      asm("nop");
      asm("nop");
      PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e);                 //impuls strobujący
      wait(5*tau);      //ok. 5ms
     }
     PORTB = (PORTB | 0x08); //sbi(PORTB,lcd_e);
     PORTB=(PORTB&0x0f)|0x20;  //wyślij 2- do LCD
     asm("nop");               //wymagane wydłużenie impulsu
     asm("nop");
     asm("nop");
     PORTB = (PORTB & 0xF7); //cbi(PORTB,lcd_e);                 //impuls strobujący
     wait(10L);        //od tego momentu można sprawdzać gotowość LCD
                         //w tym programie nie będzie sprawdzania gotowości
    
     lcd_send_i(0x28);     //interfejs 4-bitowy, 2 linie, znak 5x7
     lcd_send_i(0x08);     //wyłącz LCD, wyłącz kursor, wyłącz mruganie
     lcd_send_i(0x01);     //czyść LCD
     wait(1.64*tau);   //wymagane dla instrukcji czyszczenia ekranu opóźnienie
     lcd_send_i(0x06);     //bez przesuwania w prawo
     
     lcd_send_i(0x0c);   //włącz LCD, włącz kursor, włącz mruganie
     //*******************************************************************************************
     char msb, lsb, temp;
     unsigned char d1, d2;
     char znaki[17] = {192,249,164,176,153,146,130,248,128,144};
     
     while(1)
     {
      wait(5000);
      ow_reset();
      ow_write_byte(0xCC);
      ow_write_byte(0x44);
      _delay_ms(250);
      _delay_ms(250);
      _delay_ms(250);
      _delay_ms(250);
      _delay_ms(250);
      _delay_ms(250);
      ow_reset();
      ow_write_byte(0xCC);
      ow_write_byte(0xBE);
      lsb = ow_read_byte();
      msb = ow_read_byte();
    
      lsb = lsb >> 4;
      msb &= 0x07;
      msb = msb << 4;
      temp = lsb | msb;
      d2 = temp / 10;
      d1 = temp % 10;
     // WYSWIETLANIE
      wait(2000);
     }
    }
    
    
  • REKLAMA
  • #3 2085170
    Ganz
    Poziom 17  
    Posty: 299
    Pomógł: 10
    Ocena: 1
    Anderian napisał:
    google Twoim przyjacielem nawet na 64kb/s ;P
    http://www.siwawi.arubi.uni-kl.de/avr_projects/tempsensor/


    Mówisz tak bo masz w domu 512 ;P. Dzięki za linka, ale ja chciałbym sklepać coś sam tym bardziej, że mam prawie gotowy program (przynajmniej mi się tak wydaje) ;).
REKLAMA