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

AVR/ATMEGA8 - Jak wyświetlić dane z DS18B20 na segmentowym LED?

GOTHAM 06 Paź 2013 20:13 4593 4
  • #1 12816181
    GOTHAM
    Poziom 14  
    Witam,

    Pisząc swój własny program chciałem wypróbować gotowy kod. Moim źródłem jest ( "Obsługa interfejsu 1-wire " Cezarego Klimasza ). Jednak napotkałem 2 problemy.

    1. Kompilator zgłasza mi ostrzenie " implicit declaration of function 'dtostrf' "
    2. W przykładzie podano bibliotekę do obsługi wyswietlacza lcd. Jednak ja chce zrealizować wyświetlanie na segmentowym led i tutaj moje pytanie. Czy jest jakaś biblioteka ułatwiająca obsługę wyświetlacza segmentowego led?
  • #3 12826454
    GOTHAM
    Poziom 14  
    Ad1. Znalazłem rozwiązanie mojego problemu.

    Ad2. Niestety nie znalazłem tego czego szukałem, samo stworzenie tablicy i wyświetlenie tego co napisze nie jest problemem najgorzej z wyświetleniem otrzymanej temperatury poniżej zaprezentuje kawałek kodu.

    
     fTemperature=(float)(cTemperatureL+(cTemperatureH<<8))/16;
    	  
    dtostrf(fTemperature,1,1,cStringBuffer);            //konwersja float do stringa
    	                                                         //ustawienie w pozycji 0,0
    	                                                          //wyswietlenie temp
    _delay_ms(200);                                 //nastepny pomiar za 200 ms
    	 
    	 len = strlen(cStringBuffer); 
    


    strlen podaje mi ilość znaków o wartości 4 czyli temperatura ma wygląd XX.X .
    wszystko jest ładnie jeśli wyświetlam na lcd temperaturę zawartą w cStringBuffer ale jak wyciągnac z tego wyniku poszczególne znaki tak żeby móc nimi operować co jest potrzebne do wyświetlenie na segmentowym wyświetlaczu led.
  • #4 12827231
    GanzConrad
    Poziom 25  
    operuj na zmiennych typu uint8_t (osobno część całkowita, osobno dziesiętna), wówczas nie będziesz musiał marnować kodu na float i jego konwersję, co jest " trochę nieoptymalne".
    poszukaj w sieci bibliotek Petera Danneggera - będzie szybciej.
    poszperaj w postach na forum, było już chyba wszystko na temat tego czujnika.
  • #5 12835124
    GOTHAM
    Poziom 14  
    GanzConrad napisał:
    operuj na zmiennych typu uint8_t (osobno część całkowita, osobno dziesiętna), wówczas nie będziesz musiał marnować kodu na float i jego konwersję, co jest " trochę nieoptymalne".
    poszukaj w sieci bibliotek Petera Danneggera - będzie szybciej.
    poszperaj w postach na forum, było już chyba wszystko na temat tego czujnika.


    Wydaje mi się że unit8_t nie pomoże tutaj. Nie wyświetli otrzymanej temperatury jak to robi biblioteka do wyświetlacza lcd gdzie wystarczy jedno polecenie.

    Poniżej wkleiłem kod swojego termometru nie jak liczbę po przecinku uzyskać.

    /* Szkielet prostego programu dla avr-gcc */
    
    // #define F_CPU 1000000L
    #include <stdio.h>
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    #include <string.h>        
    #include <avr/interrupt.h>
    
    
    #define PIN_1WIRE  1
    #define PORT_1WIRE PINB
    
    
    #define OUT_1WIRE_LOW    PORT_1WIRE &= ~(1<<PIN_1WIRE);
    #define OUT_1WIRE_HIGH   PORT_1WIRE |= 1<<PIN_1WIRE;
    #define DIR_1WIRE_IN     DDRB&=~(1<<PIN_1WIRE);
    #define DIR_1WIRE_OUT    DDRB|=1<<PIN_1WIRE;
    
    /*
    #define OUT_1WIRE_LOW    PORT_1WIRE = PORT_1WIRE & ~(1<<PIN_1WIRE);
    #define OUT_1WIRE_HIGH   PORT_1WIRE = PORT_1WIRE | 1<<PIN_1WIRE;
    #define DIR_1WIRE_IN     DDRB = DDRB & ~(1<<PIN_1WIRE);
    #define DIR_1WIRE_OUT    DDRB = DDRB | 1<<PIN_1WIRE;
    */
    char cStringBuffer[8];  //zmienna potrzebna przy konwersji temperatury
    
    int LED[13]; 
    int segment[4];
    int liczba_znakow;
    int segmentlicz;
    int len;
    int napis;
    int cyfra;
    int dziesiatki;
    int pierwsza;
    int value;
    int temp_fraction;
    //#define LED_1   0x06; // 0000 0110
    //#define LED_2   0x5b; // 0101 1011
    //#define LED_3   0x4f; // 0100 1111
    //#define LED_4   0x66; // 0110 0110
    //#define LED_5   0x6d; // 0110 1101
    //#define LED_6   0x7d; // 0111 1101
    //#define LED_7   0x07; // 0000 0111
    //#define LED_8   0x7f; // 0111 1111
    //#define LED_9   0x67; // 0110 0111
    //#define LED_0   0x3f; // 0011 1111
    
    //#define segment_1 0x01; // 0000 0001
    
    
    unsigned char uc1Wire_ResetPulse(void)
    
    {     
         unsigned char ucPresenceImpulse;
    	 
    	 OUT_1WIRE_LOW;              //ustaw port w stan niski
    	 DIR_1WIRE_OUT;              //kierunek pinu na: wyjście
    	 _delay_us(500);               //odczekanie 500us
    	 DIR_1WIRE_IN;               //kierunek pinu na:wejscie
    	 _delay_us(45);                //odczekanie 45us
    	 
    	 if (bit_is_clear(PORT_1WIRE, PIN_1WIRE))             //sprawdzamy poziom linii
    	     ucPresenceImpulse=1;                             //1 - odebrano bit PRESENCE,
    	else
    	     ucPresenceImpulse=0;                             //0 - stan nieaktywnosci
    		 
    	_delay_us(470);                                         //odczekanie przez mastera 470us
    	
    	return ucPresenceImpulse;                             //zwracamy wartosc do funkcji
    	
    }
    	 
    
    //Funkcja wysyla na magistrale pojedynczy bit
    void v1Wire_SendBit(char cBit)
    {
    
         DIR_1WIRE_OUT;                                      //ustawianie kierunku pin na wyjscie
         _delay_us(5);
    
         if(cBit==1)
             DIR_1WIRE_IN;                                   //zwolnienie magistrali, pin na wejscie
    		 
    	_delay_us(80);                                         //przetrzymanie - wyslanie zera
    	DIR_1WIRE_IN;                                    
    	
    }
    	
    	
    //Funckaj odbiera bit z magistrali
    unsigned char uc1Wire_ReadBit(void)
    {
    
        unsigned char ucBit;
    	
    	DIR_1WIRE_OUT;                                                 //kierunek pinu na wyjscie
    	_delay_us(2);                                                    //odczekanie 2us
    	DIR_1WIRE_IN;                                                  //zwolnienie magistrali
    	_delay_us(15);                                                   //odczekanie 15us
    	
    	
    	if(bit_is_set(PORT_1WIRE, PIN_1WIRE))
    	        ucBit=1;                                               //odbior wartosci "1"
    			
    		else
    		   
    		    ucBit=0;                                               //odbior wartosci "0"
    			
    	return(ucBit);                                                 //zwrocienie wartosci
    	
    	
    }
    
    
    //Funkcja wysyla bajt na magistrale
    void v1Wire_SendByte(char ucByteValue)
    {
    
         unsigned char ucCounter;                                       //zmienna licznikowa
    	 unsigned char ucValueToSend;                                   //wartosc do wysylania
    	 
    	 for (ucCounter=0; ucCounter<8; ucCounter++)                   //wysylanie bitow pojedynczo
    	 {
    	 
    	    ucValueToSend = ucByteValue>>ucCounter;                    //przesuniecie bitowe w prawo
    		ucValueToSend &= 0x01;                                     //skopiowanie bitu
    		v1Wire_SendBit(ucValueToSend);                             //wysylanie bitu na magistrale
    		
    	 }
    	 _delay_us(100);                                                 //odczekanie 100us
    }
    
    
    //Funckaj odbiera bajt z magistrali
    unsigned char uv1Wire_ReadByte(void)
    {
    
       unsigned char ucCounter;                                        //zmienna licznikowa
       unsigned char ucReadByte = 0;                                   //odczytana wartosc
       
       for (ucCounter=0;ucCounter<8;ucCounter++)                      //petla wykonywana 8 razy
       {
       
             if  (uc1Wire_ReadBit())                                   //odczyt po jednym bicie
    		       ucReadByte|=0x01<<ucCounter;
    		 _delay_us(15);                                              //odczekanie 15us
    		 
    	}
    	
    	return(ucReadByte);                                            //zwrot wartosci
    	
    }
    
    
    //funckja wyswietlania na led
    int wyswietl(void)
    {
    
    
     
    //cyfra[1] = (int)value%10;
    
    //cyfra[2]=((int)value/10)%10;
    
    
    
    
    
    
    
    for(liczba_znakow=0;liczba_znakow<=3;liczba_znakow++)
    
    
    
    
    
    {
    
    dziesiatki=((int)value/10)%10;
    
    
    
    
    
    PORTC = segment[1];
    PORTD = ~LED[pierwsza= (int)value%10];
    _delay_ms(50);
    
    
    
    PORTC = segment[2];
    
    PORTD = ~LED[dziesiatki];	
    //_delay_ms(20); 
    
    
    
    
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    return 0;
    
    }
    
    int czyscekran (void)
    
    {
    
    
    PORTC = 0x0f;
    
    PORTD = 0x00;
    
    
    
    
    return 0;
    
    }
    
    
    
    
    
    
    
    
    
    int main(void)
    {
      
        
    
    
      
      
      
      
      
      
      
      
      
      
      
      unsigned char ucReset;
      char cTemperatureH=0, cTemperatureL=0;
      float fTemperature=0;
      //char napis;
      
      
      
      //unsigned char i,n;
      
    
      
    LED[0] = 0x3f; // 0011 1111
    LED[1] = 0x06; // 0000 0110
    LED[2] = 0x5b; // 0101 1011
    LED[3] = 0x4f; // 0100 1111
    LED[4] = 0x66; // 0110 0110
    LED[5] = 0x6d; // 0110 1101
    LED[6] = 0x7d; // 0111 1101
    LED[7] = 0x07; // 0000 0111
    LED[8] = 0x7f; // 0111 1111
    LED[9] = 0x67; // 0110 0111
    LED[10] = 0x40;   // Symbol '-'
    LED[11] = 0x00;   // puste
    LED[12] = 0x80;   // przecinek "," symbol  
    
    
    
    
    
    segment[0] = 0xfe;
    segment[1] = 0xfd;
    segment[2] = 0xfb;
    segment[3] = 0xf7;  
      
      
      /* Wszystkie linie portu D będą wyjściami */
       DDRD = 0xFF;  /* 0xFF binarnie 1111 1111 */
       
       /* Wszystkie linie portu C będą wyjściami */
       DDRC = 0xFF;  /* 0xFF binarnie 1111 1111 */
      
      
      
      
      
      
      
      /* Tutaj wpisujemy instrukcje naszego  programu */
      
      
      
      
      
      
      
      for(;;)                                                             //nieskonczona petla
      {   
      
       
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	ucReset=uc1Wire_ResetPulse();                                     //impuls resetu
    	
    	if (ucReset==1)
    	
        {
    	
    	  v1Wire_SendByte(0xCC);                                         //SKIP ROM
    	  v1Wire_SendByte(0x44);                                         //CONVERT T
    	  _delay_ms(750);                                                //odczekaj 750ms - czas konwersji
    	  ucReset=uc1Wire_ResetPulse();                                  //wysylanie impulsu reset
    	  v1Wire_SendByte(0xCC);                                         //SKIP ROM
    	  v1Wire_SendByte(0xBE);                                         //READ SCRATCHPAD
    	  cTemperatureL=uv1Wire_ReadByte();                              //odczytanie LSB
    	  cTemperatureH=uv1Wire_ReadByte();                              //odczytnie MSB
    	  ucReset=uc1Wire_ResetPulse();                                  //zwolnienie magistrali
    	  
    	  fTemperature=(float)(cTemperatureL+(cTemperatureH<<8))/16;
    	  temp_fraction=(cTemperatureL+(cTemperatureH<<8))/16;
    	  dtostrf(fTemperature,1,1,cStringBuffer);                      //konwersja float do stringa
    	                                                                 //ustawienie w pozycji 0,0
    	   value = fTemperature;                                                              //wyswietlenie temp
    	  _delay_ms(200);                                               //nastepny pomiar za 200 ms
    	 
    	 
      
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 
    	 //napis = cStringBuffer;
    	 len = strlen(cStringBuffer); 
    	
    	wyswietl();
      
    	}
    	else                                                            //jesli nie wykryto PRESENCE_PULSE
    	{
    	                                                             //pozycja 0,0 na LCD
    	//wyswietl();			                                    //napis  "cisza"
    	}
    	
       
       
       
       
       
       
       
       }
       
     }
      
      
      
      
      
      
      
REKLAMA