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

Atmega32 PCF8583 DS18b20 co 3 sekunda dłuższa

lokii 09 Lip 2009 10:39 2000 13
  • #1 6757492
    lokii
    Poziom 13  
    Witam, wiem, ze postów na temat tych układów jest masa, ale nie udało mi sie znaleźć rozwiązania.

    Problem:

    Zbudowałem układ, który ma pełnić rolę sterownika akwarium, wyposażony w rtc i czujnik ds18b20.

    Zaprogramowałem odczyt temperatury i czasu(sprzętowe TWI) oraz obsługę wyświetlacza.

    Aktualnie podczas pracy układu co 3 sekunda wyświetlana na wyświetlaczu wydaje mi się dłuższa od pozostałych.

    Blokowo postaram sie przedstawić kod programu:

    przerwanie od PCF - int0
    {
    ustawiam flage przerwanie=1
    }
    
    funkcja main
    {
    
    for(;;)
    
    if (przerwanie==1)
    {
    odczyt z PCF i wyswietlanie na LCD
    
    przerwanie=0;
    
    
    }
    
    obsługa DS18b20 (_delay_ms(750)) + wyświetlanie na LCD
    
    }


    Wydaje mi się, że jest to spowodowane oczekiwaniem 750ms na konwersję temperatury.

    Proszę o podpowiedź jak zrealizować poprawnie obsługę tych układów.
  • #2 6758378
    Kolek
    Poziom 25  
    Pokaż cały kod bo z tego ciężko mi cokolwiek wywnioskować.
  • #3 6758426
    lokii
    Poziom 13  
    #include <avr/io.h>
    #include <util/delay.h>
    #include <HD44780.c>
    #include <stdlib.h>
    #include <makra.h>
    #include <DS18B20.c>
    #include <twi.c>
    #include <avr/interrupt.h>
    
    
    #define zegar 0xA0 
    
    
    
    int przerwanie=0;
    
    
    void INT0_inicjacja(void) 
    { 
     
      MCUCR = 0b00000001;     
      GICR = 0b01000000;   
    } 
    
    
    
    ISR(INT0_vect)   
    	{ 
    		przerwanie=1;
    	}
    
    
    
    
    
    int main (void) 
    
    { 
    
    //Porty: PC0(SCL) PC1(SDA)  ->  wejścia TWI 
    
    DDRC =0b00000010;
    PORTC =0b00000001;
     
        
    unsigned char sprawdz;
    char temp1=0, temp2=0;
    float temp=0;
    
    INT0_inicjacja(); 
    sei();
    
    LCD_Initalize();
    LCD_Clear(); 
    TWI_inicjacja(); 
    TWI_zapis(zegar,0x00,0b00000000); // ustawienie początkowe zegara pcf8583 (zerowanie)
    
    
    
    for(;;)
    {
    
    if (przerwanie==1)
    
    {
    
    volatile unsigned char czas[6] ={0,}; // zerowanie wszystkich elementów tablicy 
    unsigned char czasPCF8583 =0;
    unsigned char buf2;
    unsigned char buf3;
    unsigned char buf4;
    unsigned char buf5;
    unsigned char buf6;
    unsigned char buf7;
    
    
    
        czasPCF8583 =TWI_odczyt(zegar,0x04); 
        czas[0] =(czasPCF8583 & 0b00110000) >> 4;   // dziesatki_godzin          
        czas[1] =czasPCF8583 & 0b00001111;      // godziny 
        czasPCF8583 =TWI_odczyt(zegar,0x03); 
        czas[2] =czasPCF8583 >> 4;             // dziesatki_minut 
        czas[3] =czasPCF8583 & 0b00001111;      // minuty 
        czasPCF8583 =TWI_odczyt(zegar,0x02); 
        czas[4] =czasPCF8583 >> 4;             // dziesatki_sekund 
        czas[5] =czasPCF8583 & 0b00001111;      // sekundy
    	
    	
    	buf2=(czas[0]+0x30);
    	buf3= (czas[1]+0x30);	
    	buf4= (czas[2]+0x30);	
    	buf5= (czas[3]+0x30);	
    	buf6= (czas[4]+0x30);		
    	buf7= (czas[5]+0x30);	
    
    	
    	LCD_GoTo(0, 0);
    	LCD_WriteData(buf2);
    	LCD_GoTo(1, 0);
    	LCD_WriteData(buf3);
    	
    	LCD_GoTo(3, 0);
    	LCD_WriteData(buf4);
    	LCD_GoTo(4, 0);
    	LCD_WriteData(buf5);
    	
    	LCD_GoTo(6, 0);
    	LCD_WriteData(buf6);
    	LCD_GoTo(7, 0);
    	LCD_WriteData(buf7);
    	
    	przerwanie=0;
    }	
    
    
    
    
    	
    	sprawdz=RESET_PULSE();
    
    	if(sprawdz==1)
    	{
    	send_byte(0xCC);
    	send_byte(0x44);
    	_delay_ms(750);
    	
    	sprawdz=RESET_PULSE();
    	
    	send_byte(0xCC);
    	send_byte(0xBE);
    	
    	temp1=read_byte();
    	temp2=read_byte();
    	
    	sprawdz=RESET_PULSE();
    	
    	temp = zamien_temp(temp2,temp1);
    	
    	dtostrf(temp, 3, 1, buf);
    	
    	 LCD_GoTo(0, 1);
    	 LCD_WriteText("T:");
    	 LCD_WriteText(buf);
    	 LCD_WriteText(" ");
    	
    	
    	
    
    		}
    	}
    }
  • Pomocny post
    #4 6758688
    H0miczek
    Poziom 20  
    nie zagłebiajac sie w kod, wydaje mi sie ze to jest ten delay_ms. ma prawo wystepowac cos takiego ze siedzisz w delay'u to juz sie zmienil czas ale minie spory kawałek sekundy zanim odswiezysz wyswietlacz..
    na test usun delay'a, jak pomoze to zrob to czekanie na timerze
  • #5 6758749
    Kolek
    Poziom 25  
    Dlaczego nie umieściłeś tego fragmentu w funkcji przerwania (ISR(INT0_vect) {} ) tylko zmieniasz i sprawdzasz flagę ?
    {
    
    volatile unsigned char czas[6] ={0,}; // zerowanie wszystkich elementów tablicy
    unsigned char czasPCF8583 =0;
    unsigned char buf2;
    unsigned char buf3;
    unsigned char buf4;
    unsigned char buf5;
    unsigned char buf6;
    unsigned char buf7;
    
    
    
        czasPCF8583 =TWI_odczyt(zegar,0x04);
        czas[0] =(czasPCF8583 & 0b00110000) >> 4;   // dziesatki_godzin         
        czas[1] =czasPCF8583 & 0b00001111;      // godziny
        czasPCF8583 =TWI_odczyt(zegar,0x03);
        czas[2] =czasPCF8583 >> 4;             // dziesatki_minut
        czas[3] =czasPCF8583 & 0b00001111;      // minuty
        czasPCF8583 =TWI_odczyt(zegar,0x02);
        czas[4] =czasPCF8583 >> 4;             // dziesatki_sekund
        czas[5] =czasPCF8583 & 0b00001111;      // sekundy
       
       
       buf2=(czas[0]+0x30);
       buf3= (czas[1]+0x30);   
       buf4= (czas[2]+0x30);   
       buf5= (czas[3]+0x30);   
       buf6= (czas[4]+0x30);      
       buf7= (czas[5]+0x30);   
    
       
       LCD_GoTo(0, 0);
       LCD_WriteData(buf2);
       LCD_GoTo(1, 0);
       LCD_WriteData(buf3);
       
       LCD_GoTo(3, 0);
       LCD_WriteData(buf4);
       LCD_GoTo(4, 0);
       LCD_WriteData(buf5);
       
       LCD_GoTo(6, 0);
       LCD_WriteData(buf6);
       LCD_GoTo(7, 0);
       LCD_WriteData(buf7);
       
       przerwanie=0;
    }    
  • #6 6758757
    dawid512
    Poziom 32  
    Kolek Gdyby tak zrobił to uc w najgorszym wypadku mógłby się restartować. Pamiętaj że przerwanie powinno być jak najkrótsze. Sposób ze sprawdzaniem flagi jest jak najbardziej poprawny. Moim zdaniem problem polega na tym że na lcd wyświetlasz czas w momencie wystąpienia przerwania( co sekundę). Spróbuj wyświetlać czas na bieżąco.
  • #7 6758946
    Kolek
    Poziom 25  
    Dawid nie wydaje mi się, napisałem kiedyś właśnie prosty zegar gdzie w funkcji przerwania od wewnętrznego licznika wykonuje się minimum 100 cykli + opóźnienie 150ms i nic się złego nie dzieje. Fakt że miejsce w pamięci na wektor przerwania jest niewielkie, ale C to nie assembler i kompilator jakoś to sobie ułoży.
  • #8 6759318
    lokii
    Poziom 13  
    No to sprawa się poprawia jak wyrzuce _delay_ms(750).

    Tle tylko, że z dokumentacji ds18b20 wynika że te 750 ms jest potrzebne na konwersje temperatury.

    Po wyrzuceniu linijki z opoźnieniem, temperatura jest mierzona poprawnie.

    Powiedzcie mi za tem czy to opoźnienie jest potrzebne czy nie?
  • #9 6759414
    pempek
    Poziom 10  
    U mnie też działa bez tego opóźnienia :)
  • #10 6759436
    lokii
    Poziom 13  
    ok pempek tylko, że jak coś jest napisane w datasheet to chyba jest potrzebne?
  • #11 6760110
    janbernat
    Poziom 38  
    Przecież to tak musi być.
    750ms- to 3/4 sekundy.
    A jest to konieczne do odczytu DS.
    A jeszcze obsługa LCD.
    Odczytuj czas co 5s.

    Dodano po 3 [minuty]:

    Albo jak napisał HOmiczek- przerwanie od timera- jak masz jakiś wolny.
  • #12 6760435
    elektryk2000
    Specjalista urządzeń chłodniczych
    lokii napisał:
    No to sprawa się poprawia jak wyrzuce _delay_ms(750).

    Tle tylko, że z dokumentacji ds18b20 wynika że te 750 ms jest potrzebne na konwersje temperatury.

    Po wyrzuceniu linijki z opoźnieniem, temperatura jest mierzona poprawnie.

    Powiedzcie mi za tem czy to opoźnienie jest potrzebne czy nie?


    Ja od kilku lat nie daję żadnych opóźnień i wszystko działa, tylko DS'y podłączam na trzech przewodach każdy, +5, GND i sygnał.
  • #13 6761473
    lokii
    Poziom 13  
    no fakt działa tylko pytanie czy to sie nie zemści w późniejszym czasie, spróbuje tez wersji z timerem, wydaje mi sie to pewniejsze.
  • #14 6762183
    ksarim
    Poziom 15  
    DS18B20 potrzebuje 750ms do konwersji temperatury. Jak nie dajecie tego opóźnienia to otrzymujecie temperaturę nie z danego pomiaru a z wcześniejszego pomiaru(zakładając że odpytujemy czujnik o temperaturę w odstępach czasu co najmniej 750ms). Jeżeli komuś to nie robi różnicy to oczywiście nie musi dawać opóźnień.
REKLAMA