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

PCF8583 + Atmega32: Błąd daty 31 grudnia zmieniającej się na 41 stycznia

tokarz 04 Sie 2007 11:19 1407 4
REKLAMA
  • #1 4144836
    tokarz
    Poziom 18  
    Posty: 349
    Pomógł: 17
    Ocena: 19
    Witam,

    na Atmedze32 i PCF8583 zbudowałem zegarek z kalendarzem wyświetlającym dni i miesiące. Mam problem w momencie, gdy ustawię 31. grudnia. Po przekroczeniu godziny "0", miesiąc zmienia się na 01, natomiast dni na 41. Pozostałe miesiące przeskakują normalnie. Co może być nie tak ?
    Oto fragment kodu:
    1) funkcja wyświetlająca czas i datę na LCD
    
    void wyswietlczas(void)      //procedura wyświetlania czasu na LCD
    {
     unsigned char zp;    
    lcdxy(0,0);				
     pbufi2c=&bufi2c[2];      // ustaw bufor w pozycji godzin
     zp=*pbufi2c--;                //pobierz godziny
     nalcd((zp&0xf0)>>4,zp);     //wyświetl godziny
     piszznak(':');
     zp=*pbufi2c--;                //pobierz minuty
     nalcd((zp&0xf0)>>4,zp);     //wyświetl minuty
     piszznak(':');
     zp=*pbufi2c;                //pobierz sekundy
     nalcd((zp&0xf0)>>4,zp);     //wyświetl sekundy
     piszznak(' ');
     pbufi2c=&bufi2c[3];         //ustaw wskaźnik bufora na pozycje dni
     zp=*pbufi2c++;              //pobierz dzien
     nalcd((zp&0xf0)>>4,zp);     //wyświetl dzien
     piszznak('-');
     zp=*pbufi2c;              //pobierz miesiac
     nalcd((zp&0x10)>>4,zp);     //wyświetl miesiac
    }
    

    2) funkcja nalcd()
    
    void nalcd(unsigned char zn1, unsigned char zn2)
    {                  //umieszczenie czasu na LCD z jednoczesną konwersją na ASCII
     piszznak(zn1+0x30);    //dodanie 0x30 realizuje prostą konwersję liczby na ASCII
     piszznak((zn2&0x0f)+0x30);
    }
    

    3) funkcja piszznak()
    
    void piszznak(char znak)     //procedura umieszcza znak na wyświetlaczu
    {
     piszdlcd(znak);             //wyświetl znak na LCD
    }


    Dodam, że funkcja piszdlcd() na pewno dziala, bo wyświetlam nią też inne komunikaty na LCD.

    Pozdrawiam.

    Dodano po 31 [minuty]:

    Mam jeszcze jedno pytanie. Problemem było dla mnie zamienienie liczbowej postaci miesięcy na trzyliterowy skrót. Rozwiązałem to tak:
    
    void wyswietlczas(void)      //procedura wyświetlania czasu na LCD
    {
     unsigned char zp;           //zmienna pomocnicza
     char *miesiace[12]={
                    PSTR("sty"),
                    PSTR("lut"),
                    PSTR("mar"),
                    PSTR("kwi"),
    				PSTR("maj"),
    				PSTR("cze"),
    				PSTR("lip"),
    				PSTR("sie"),
    				PSTR("wrz"),
    				PSTR("paz"),
    				PSTR("lis"),
    				PSTR("gru")
                   };
     
     lcdxy(0,0);				 // wyposrodkowanie godziny i daty (0,2), gdy nie ma sekund
     pbufi2c=&bufi2c[2];
     zp=*pbufi2c--;                //pobierz godziny
     nalcd((zp&0xf0)>>4,zp);     //wyświetl godziny
     piszznak(':');
     zp=*pbufi2c--;                //pobierz minuty
     nalcd((zp&0xf0)>>4,zp);     //wyświetl minuty
     piszznak(':');
     zp=*pbufi2c;                //pobierz sekundy
     nalcd((zp&0xf0)>>4,zp);     //wyświetl sekundy
     piszznak(' ');
     piszznak(' ');
     pbufi2c=&bufi2c[3];         //ustaw wskaźnik bufora na pozycje dnia
     zp=*pbufi2c++;              //pobierz dzien
     nalcd((zp&0xf0)>>4,zp);     //wyświetl dzien
     piszznak('-');
    
     zp=*pbufi2c;              //pobierz miesiac
     //nalcd((zp&0x10)>>4,zp);     //wyświetl miesiac w postaci liczbowej
     int indeks1, indeks2;		// wyswietlanie miesiaca w postaci trzyliterowego skrotu
     indeks1 = (zp&0x10)>>4;   // badam pierwsza cyfre okreslajaca miesiac
     indeks2 = zp&0x0f;          // bvadam druga cyfre okreslajaca miesiac
     if(indeks1 == 0)      // jezeli pierwsza jest rowna 0
     {
    	if(indeks2 == 1)          // a druga 1 to chodzi o styczen
    		pisztekst(miesiace[0]);    // wyswietlam sty
    	else if(indeks2 == 2)	
    		pisztekst(miesiace[1]);
    	else if(indeks2 == 3)	
    		pisztekst(miesiace[2]);
    	else if(indeks2 == 4)	
    		pisztekst(miesiace[3]);
    	else if(indeks2 == 5)	
    		pisztekst(miesiace[4]);
    	else if(indeks2 == 6)	
    		pisztekst(miesiace[5]);
    	else if(indeks2 == 7)	
    		pisztekst(miesiace[6]);
    	else if(indeks2 == 8)	
    		pisztekst(miesiace[7]);
    	else if(indeks2 == 9)	
    		pisztekst(miesiace[8]);	
      }
      else if(indeks1 == 1)       // jezeli pierwsza cyfra wynosi 1
      {
    	if(indeks2 == 0)   // a druga 0 to chodzi o pazdziernik
    		pisztekst(miesiace[9]); // wyswietlam pazdziernik
    	else if(indeks2 == 1)
    		pisztekst(miesiace[10]);
    	else if(indeks2 == 2)
    		pisztekst(miesiace[11]);
      }
    }
    

    Rozwiązanie to działa, ale jak widać funkcja jest bardzo długa. Wpadłem na pomysł, że mogę zamienić wartość BCD odczytaną z PCF-a na DEC lub HEX i wtedy zorganizować to tak:
    
    int indeks;
    tutaj jakas konwersja na DEC czy HEX
    pisztekst(miesiace[indeks]);
    trzyliterowego skrotu pobranego z tablicy miesiace[12]
    

    Niestety nie wiem jak dokonać sprawnie konwersji, czy ktoś mógłby mi pomoc z tym ? BCD do DEC lub BCD do HEX.

    Pozdrawiam.
  • REKLAMA
  • Pomocny post
    #2 4144968
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #3 4145086
    tokarz
    Poziom 18  
    Posty: 349
    Pomógł: 17
    Ocena: 19
    W funkcji wyswietlczas() zamieniłem:
    
    nalcd((zp&0xf0)>>4,zp);
    

    na
    
    nalcd((zp&0x30)>>4,zp);
    
    , dzieki czemu przy koniunkcji pomijam zapis roku w tym rejestrze. Dzięki za odpowiedź. Z miesiącami nie miałem tego problemu, ponieważ miałem:
    
    nalcd((zp&0x10)>>4,zp);
    
    , więc przy koniunkcji wykluczałem dane dotyczące dnia tygodnia.
    Dzięki za pomoc. Może wiesz jak napisać konwersję BCD do HEX lub DEC ? W internecie szukałem trochę, ale jakoś nic nie mogłem znaleźć.

    Pozdrawiam.
  • REKLAMA
  • Pomocny post
    #4 4145164
    Konto nie istnieje
    Poziom 1  
  • #5 4155556
    tokarz
    Poziom 18  
    Posty: 349
    Pomógł: 17
    Ocena: 19
    Konwersja działa wyśmienicie. Rozwiązanie jakże proste, a skuteczne.
    Dzięki za pomoc.

    Swoją drogą, teraz chcę uruchomić DS18S20 na tej Atmedze. Czy macie jakieś gotowce ? Ja w necie szukałem czegokolwiek, ale zazwyczaj kod jest albo w Bascomie, albo w C, tylko że zupełnie nieprzydatny (wykorzystujący "milion" plików nagłówkowych niedostępnych w WinAVR, wyświetlający wyniki na LED 7-segmentowych, itd.).
    Czy macie coś na LCD, co mógłbym przerobić na swój sposób ?

    Pozdrawiam.
REKLAMA