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.

[atmega32][c]Zegar sterujący-porównywanie czasu

10 Lis 2010 16:37 2106 13
  • Poziom 16  
    Witam.Mam problem z funkcjami w dwu kanałowym zegarze sterującym gdzie muszę porównywać czas bieżący z ustawionym czasem włączenia i czasem wyłączenia niezależnie jednego i drugiego kanału. Napisałem coś takiego opierając się na warunkach if ale nie chodziło to prawidłowo bo raz zadziałało a raz nie a i kodu było sporo. Mam z tym duży kłopot bo to ostatni człon mojego programu a ja nie potrafię wymyślić sensownej definicji którą mógłbym zastosować dlatego proszę o pomoc może ktoś z większym doświadczeniem podpowie jak coś takiego zdefiniować.To cześć kodu odczytującego z PCF8583 czas bieżący i zapisane w nim czasy nastaw.
    Code:

    {
             PCF8583=TWI_read(zegar,0x06);      
               pcf_mc[1] = PCF8583 >> 4;            //dziesiatki miesięc                           
               pcf_mc[0] = PCF8583 & 0x0F;            //jednostki miesięcy      
             PCF8583=TWI_read(zegar,0x05);      
             pcf_dni[1] = PCF8583 >> 4;            //dziesiatki dni          
               pcf_dni[0] = PCF8583 & 0x0F;         //jednostki dni
               PCF8583=TWI_read(zegar,0x04);       
    ;         pcf_godz[1] = PCF8583 >> 4;            //dziesiatki godzin          
               pcf_godz[0] = PCF8583 & 0x0F;          //jednostki godzin
               PCF8583=TWI_read(zegar,0x03);      
             pcf_min[1] = PCF8583 >> 4;            //dziesiatki          
               pcf_min[0] = PCF8583 & 0x0F;         //jednostki minut
               PCF8583=TWI_read(zegar,0x02);      
             pcf_sec[1] = PCF8583 >> 4;            //dziesiatki          
               pcf_sec[0] = PCF8583 & 0x0F;         //jednostki sekund
             //--------------------------------------------------------------odczyt nastaw timerów
             PCF8583=TWI_read(zegar,0x08);         //czas włącz kanał 1      
             godz_timer[0] = PCF8583;
             PCF8583=TWI_read(zegar,0x09);   
             min_timer[0] = PCF8583;
             PCF8583=TWI_read(zegar,0x0a);         //czas wyłącz kanał 1
             godz_timer[1] = PCF8583;
             PCF8583=TWI_read(zegar,0x0B);   
             min_timer[1] = PCF8583;
             PCF8583=TWI_read(zegar,0x0C);         //czas włącz kanał 2      
             godz_timer[2] = PCF8583;
             PCF8583=TWI_read(zegar,0x0D);   
             min_timer[3] = PCF8583;
             PCF8583=TWI_read(zegar,0x0E);         //czas wyłącz kanał 2
             godz_timer[4] = PCF8583;
             PCF8583=TWI_read(zegar,0x0F);   
             min_timer[4] = PCF8583;
               IRQ==0;

             m=((pcf_mc[1]*10)+(pcf_mc[0]));
             d=((pcf_dni[1]*10)+(pcf_dni[0]));
             y=2010;
             pcf_dzien=(d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7;//numer dnia tygodnia
  • Poziom 26  
    1. Kod mógł nie działać prawidłowo, bo zajęty mikrokontroler mógł zwyczajnie przegapić równość minut. Pytanie co ile sprawdzasz czas? Można by ustawić jakieś widełki zamiast konkretnej godziny.
    2. Najlepiej wykorzystać alarm zaszyty w RTC i wyjście INT. Postępujesz następująco:
    - ustawiasz 1 alarm w RTC. Konfigurujesz przerwanie zewnętrzne i mikrokontroler możne robić co chce, nawet przejść w Power Down.
    - jeśli czas zrówna się z wpisanym wystąpi przerwanie więc nie ma mowy by to przegapisz
    - robisz co potrzeba i nastawiasz 2 czas itd.
  • Poziom 16  
    Mógłbym gdyby PCF tylko włączał coś o określonej godzinie a ja potrzebuję by włączył kanał 1 o np;18:00 i wyłączył o 03:00 i analogicznie włączył kanał 2 o np;21:00 i wyłączył o 09:00 sterując poprzez optotriaki urządzeniami pracującymi w sieci 230V.
  • Poziom 38  
    Zapewne interesuje cię czas z dokładnością 1 minuta wystarczy? A może i godzina? Ustaw alarm tak by zgłaszał się co minutę (godzinę) w przerwaniu porównanie i zrób co należy.
  • Poziom 16  
    Dokładność czasu 1minuta to standard przy takich zegarach...na if-ach robiłem najpierw sprawdzanie co godzinę czy Tgodz_pcf==Tgodz_kanal_t1_t2_t3_t4 jeżeli tak to sprawdzałem analogicznie minuty i jeżeli znowu tak to sprawdzałem który czas nastawy "pasuje" do czasu bierzącego. To trochę zakręcone i sam się w tym gubiłem dlatego szukam innego bardziej przejrzystego rozwiązania.
    dodane;
    na chwilę obecną kombinuje z takim kodem [zbędne linie kodu usunąłem] ale co z tego wyjdzie?...
    Code:

    if(IRQ==1)//--------------------------------------------------------odczyt czasu,daty oraz nastaw timerów
           {
             PCF8583=TWI_read(zegar,0x06);      
               pcf_mc_1 = PCF8583 >> 4;            //dziesiatki miesięc               
               pcf_mc_0 = PCF8583 & 0x0F;            //jednostki miesięcy   
             PCF8583=TWI_read(zegar,0x05);      
             pcf_dni_1 = PCF8583 >> 4;            //dziesiatki dni          
               pcf_dni_0 = PCF8583 & 0x0F;            //jednostki dni
               PCF8583=TWI_read(zegar,0x04);       
             pcf_godz_1 = PCF8583 >> 4;            //dziesiatki godzin
             dec_godz_1 = bcd_na_dec(pcf_godz_1);   //konwersja na dec          
               pcf_godz_0 = PCF8583 & 0x0F;         //jednostki godzin
             dec_godz_0 = bcd_na_dec(pcf_godz_0);   //konwersja na dec
               PCF8583=TWI_read(zegar,0x03);      
             pcf_min_1 = PCF8583 >> 4;            //dziesiatki minut
             dec_min_1 = bcd_na_dec(pcf_min_1);      //konwersja na dec      
               pcf_min_0 = PCF8583 & 0x0F;            //jednostki minut
             dec_min_0 = bcd_na_dec(pcf_min_0);      //konwersja na dec
               PCF8583=TWI_read(zegar,0x02);      
             pcf_sec_1 = PCF8583 >> 4;            //dziesiatki          
               pcf_sec_0 = PCF8583 & 0x0F;            //jednostki sekund
             //--------------------------------------------------------------odczyt nastaw timerów
             PCF8583=TWI_read(zegar,0x08);      //czas timer_1 włącz kanał 1      
             godz_timer_1 = PCF8583;
             PCF8583=TWI_read(zegar,0x09);   
             min_timer_1 = PCF8583;
             PCF8583=TWI_read(zegar,0x0a);      //czas timer_1 wyłącz kanał 1
             godz_timer_2 = PCF8583;
             PCF8583=TWI_read(zegar,0x0B);   
             min_timer_2 = PCF8583;
             PCF8583=TWI_read(zegar,0x0C);      //czas timer_2 włącz kanał 2      
             godz_timer_3 = PCF8583;
             PCF8583=TWI_read(zegar,0x0D);   
             min_timer_3 = PCF8583;
             PCF8583=TWI_read(zegar,0x0E);      //czas timer_2 wyłącz kanał 2
             godz_timer_4 = PCF8583;
             PCF8583=TWI_read(zegar,0x0F);   
             min_timer_4 = PCF8583;
               IRQ==0;
             
           }//-----------------------------------------------------------------koniec odczytu czasu oraz daty
          m=((pcf_mc_1*10)+(pcf_mc_0));
          d=((pcf_dni_1*10)+(pcf_dni_0));
          y=2010;
          pcf_dzien=(d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7;//numer dnia tygodnia
          suma_czas_godz=((dec_godz_1*10)+(dec_godz_0));         //suma dziesiątek i jednostek godzin
          suma_czas_min=((dec_min_1*10)+(dec_min_0));            //suma dziesiątek i jednostek minut
          //------------------------------------------------------------------
          if((suma_czas_godz=godz_timer_1)&&(suma_czas_min=min_timer_1))//jeżeli TAK to włącz kanal 1
          {
             PORTC |=0x10;   status_k1=1;   tryb_k1=2;
             PORTC |=0x20;   status_k2=1;   tryb_k2=2;
             PORTC |=0x40;   status_k3=1;   tryb_k3=2;      
          }
          if((suma_czas_godz=godz_timer_2)&&(suma_czas_min=min_timer_2))//jeżeli TAK to wyłącz kanal 1
          {
             PORTC &=~0x10;   status_k1=0;   tryb_k1=2;
             PORTC &=~0x20;   status_k2=0;   tryb_k2=2;
             PORTC &=~0x40;   status_k3=0;   tryb_k3=2;
          }
          if((suma_czas_godz=godz_timer_3)&&(suma_czas_min=min_timer_3))//jeżeli TAK to włącz kanal 2
          {
             PORTC |=0x80;   status_k4=1;   tryb_k4=2;
                
          }
          if((suma_czas_godz=godz_timer_4)&&(suma_czas_min=min_timer_4))//jeżeli TAK to wyłącz kanal 2
          {
             PORTC &=~0x80;   status_k4=0;   tryb_k4=2;
          }

       //----------------------------------------------------------------------
       }
       char *power[4]={"OFF","ON ","Auto","Man "};
       if(!(PIND & _BV(4)))
       {
          _delay_ms(30);
          PORTB |= _BV(0);   //włącza podświetlenie LCD   
          {
             ekran++;
             _delay_ms(600);
             LCD_GoTo(0,0);  LCD_WriteText("                                          ");
             LCD_GoTo(0,1);  LCD_WriteText("                                          ");
          }
       }
       switch(ekran)
          {
                case 0:   //EKRAN GLOWNY-----WYŚWIETLANIE-----DANYCH
             break;
             case 1://-------------------------------------------------------przełączanie trybu pracy - sterowanie ręczne   
             LCD_GoTo(0,0);   LCD_WriteText("KANAL 1");
             LCD_GoTo(8,0);   LCD_WriteText(power[tryb_k1]);
             LCD_GoTo(16,0);   LCD_WriteText(power[status_k1]);

             LCD_GoTo(0,1);   LCD_WriteText("KANAL 2");
             LCD_GoTo(8,1);   LCD_WriteText(power[tryb_k2]);
             LCD_GoTo(16,1);   LCD_WriteText(power[status_k2]);

             LCD_GoTo(20,0);   LCD_WriteText("KANAL 3");
             LCD_GoTo(28,0);   LCD_WriteText(power[tryb_k3]);
             LCD_GoTo(36,0);   LCD_WriteText(power[status_k3]);

             LCD_GoTo(20,1);   LCD_WriteText("KANAL 4");
             LCD_GoTo(28,1);   LCD_WriteText(power[tryb_k4]);
             LCD_GoTo(36,1);   LCD_WriteText(power[status_k4]);
             
             if(!(PIND & _BV(5)))
             {
                _delay_ms(100);
                zmiana_kanalu = zmiana_kanalu+1;
             }
             if(zmiana_kanalu >= 5)
             {
                  zmiana_kanalu = 0;
              }
             if(zmiana_kanalu=0)
             {
                LCD_GoTo(33,1);   LCD_WriteText("  ");
                LCD_GoTo(13,0);   LCD_WriteText("<<");
             }
             if(zmiana_kanalu=1)
             {
                LCD_GoTo(13,0);   LCD_WriteText("  ");
                LCD_GoTo(13,1);   LCD_WriteText("<<");
             }
             if(zmiana_kanalu=2)
             {
                LCD_GoTo(13,1);   LCD_WriteText("  ");
                LCD_GoTo(33,0);   LCD_WriteText("<<");
             }
             if(zmiana_kanalu=3)
             {
                LCD_GoTo(33,0);   LCD_WriteText("  ");
                LCD_GoTo(33,1);   LCD_WriteText("<<");
             }   
             break;
  • Poziom 26  
    margas4542 napisał:
    Mógłbym gdyby PCF tylko włączał coś o określonej godzinie a ja potrzebuję by włączył kanał 1 o np;18:00 i wyłączył o 03:00 i analogicznie włączył kanał 2 o np;21:00 i wyłączył o 09:00 sterując poprzez optotriaki urządzeniami pracującymi w sieci 230V.

    Liczba zadań w algorytmie który zaproponowałem wcale nie ogranicza się do jednego. Zauważ, że zaproponowałem zmianę kolejnego alarmu podczas obsługi bieżącego. Zadań może być dowolnie dużo i mogą się zmieniać dynamicznie wprowadzane poprzez menu. Można to zrobić na przykład tak:
    -definiujemy tablicę dwuwymiarową (lub tablicę struktur) której elementy zawierają: godzinę, minutę, numer portu, akcję - włącz, wyłącz. np.
    Code:
    unsigned char actionTab [][4] = {
    
    {18,0,1,1},
    {3,0,1,0},
    {21,0,2,1},
    {9,0,2,0}
    }

    -tablicę należy posortować po czasie wykonania i względem aktualnego czasu. Chodzi o to, by najbliższe zdarzenie było jako pierwsze.
    - czas pierwszego zdarzenia ładuje się do RTC jako alarm
    - przy obsłudze przerwania od zegara wykonuje się operacje na porcie i wpisuje do RTCkolejną pozycję tablicy(czas kolejnego alarmu)
  • Poziom 42  
    Panowie, panowie - algorytmy, tablice, mega rozbudowane jak w powyższych przykładach IF'y, które zjadają mnóstwo pamięci programu i nie wiadomo co jeszcze ;) .... podczas gdy zagadnienie jest proste jak drut i budowa cepa.

    1. sprowadzać czas do jednej liczby całkowitej (nie musi to być od razu coś na kształt czasu UNIX'owego znanego choćby z serwerów NTP - po co?)

    2. porównywać ze sobą takie liczby - TO WSZYSTKO

    ad.1 - w tym celu można przygotować sobie prostą funkcyjkę np:

    Code:
    uint16_t get_time( uint8_t hh, uint8_t mm) {
    
        return (hh*60) + mm;
    }


    ad.2 porównywanie czasu:

    Code:

    // funkcja pobierająca czas z RTC do zmiennych
    Pobierz_czas_z_RTC( hh_now, mm_now, s_now );

    hh_now = <---- wartość bieżąca godzin z PCF (RTC)
    mm_now = <---- wartość bieżąca minut z PCF (RTC)

    // jeśli czas bieżący hh_now, mm_now jest większy niż godzina 3:00 i triak wyłączony
    if( get_time( hh_now, mm_now ) > get_time( 18, 0) && !triac ) {
        set_triac( triac );   // włącz triaka
    }

    // jeśli czas bieżący hh_now, mm_now jest większy niż godzina 3:00 i triak włączony
    if( get_time( hh_now, mm_now ) > get_time( 3, 0) && triac ) {
        reset_triac( triac );  // wyłącz triaka
    }


    cała konwersja czasu polega na pomnożeniu godzin przez wartość 60 i dodaniu minut - i macie już proste liczby, które można ładnie porównywać zamiast bawić się w nie wiadomo jakie cuda-niewida.
  • Poziom 42  
    michalko12 napisał:


    Wyżej przedstawiłem właśnie takie rozwiązanie ;) zresztą praktycznie identyczne poza z tym, że w warunku porównywania czasu jeszcze sprawdzałbym stan włączenia/wyłączenia triaka.

    Wtedy w takim warunku można dodać jeszcze inne polecenia, które wykonają się tylko raz gdy warunek będzie spełniony, a bez tego będzie on cały czas spełniany jeśli będziemy sprawdzać jakiś konkretny zakres czasu w IF.
  • Poziom 35  
    mirekk36 napisał:
    sprowadzać czas do jednej liczby całkowitej (nie musi to być od razu coś na kształt czasu UNIX'owego znanego choćby z serwerów NTP - po co?)

    mirekk36 napisał:
    ad.1 - w tym celu można przygotować sobie prostą funkcyjkę np:
    Code:

    uint16_t get_time( uint8_t hh, uint8_t mm) {
        return (hh*60) + mm;
    }


    Rozwiazanie to jest niepraktyczne. Najlepiej przydaje sie cos na ksztalt czasu unixowego, bo w efekcie mamy jeden zegar ktory idzie (prawie) zawsze tylko do przodu. Wszystko synchronizujemy pod ten zegar, a wiec wpis (czyli logiczna pozycja z datetime, nr_wyj,akcja,... )
    bardzo latwo porownac z tym glownym zegarem. Poza tym, mozemy dobierac dowolny cykl, bo wystarczy licznik%n ( [s] ) porownywac z zapisanym cyklem ( i jakies zapobieganie bledow wynikajacych z modulo w momencie przekrecania sie globalnego licznika)

    mirekk36 napisał:
    Wtedy w takim warunku można dodać jeszcze inne polecenia, które wykonają się tylko raz gdy warunek będzie spełniony, a bez tego będzie on cały czas spełniany jeśli będziemy sprawdzać jakiś konkretny zakres czasu w IF.

    Na zywo:
    Code:

    if ((czasbierzoncy==czasustawiony)&&(!stalo_sie))
    {
    //zrub cos
    stalo_sie=1;
    }

    Trzeba pamietac aby wyzerowac wszystkie "stalo_sie" kazdego wpisu (o ile istnieja) zawsze gdy zmienia sie sekunda.
    Prosciej jest przejechac forem wszystkie wpisy raz, na jedna flage ustawiana co sekunde w przerwaniu a gaszona w ifie w petli glownej (imo lepszy i latwiejszy do napisania)
    Code:

    void przerwanie(void) //zakladamy ze tlucze co sekunde
    {
    glownylicznik++; //zwiekszaj licznik;
    _zrob=1;
    }

    main(void)
    {
    //inity
    while(1)
    {
    //petelka
    //jakis kod
    if (_zrob)
    {
    _zrob=0;
    //tutaj for i sprawdzanie czasow/cykli/innych
    };
    //jakis kod
    };
    }
  • Poziom 42  
    nsvinc --> po pierwsze to pisałem, o możliwości konwersji czasu do takiego Unix'owego (zobacz sobie wyżej) ;) , Stwierdziłem tylko, że nie zawsze jest to potrzebne i można zrobić prościej zamieniając na liczbę tylko godziny i minuty.

    Po drugie - co ty opowiadasz , że trzeba zerować "stało_sie" po każdej sekundzie ??? to nieporozumienie ;) tym bardziej, jeśi interesuje mnie tylko rozdzielczość wykonywania pewnych zadań co do minuty a nie sekundy. W tym momencie sprawdzanie co sekundę byłoby już wręcz marnotrastwem.

    Po trzecie - "stało_się" w takim przypadku i to bardzo konkretnym, który opisałem odpowiadając na konkretne pytanie autora wcale nie trzeba zerować ;) ot po prostu załączając triaka przestawiam jakiś pin wyjściowy na JEDYNKĘ co symbolicznie oznaczyłem jako funkcję set_triac( triac ); , natomiast sprawdzanie warunku czegoś takiego jak !triac to tylko i wyłącznie sprawdzanie fizycznego stanu wyjścia tego portu !(PINx & (1<<Pxn)) zatem nawet nie potrzeba marnować choćby jednej komórki pamięci na "stało_się" bo po co ?

    czy przedstawione przeze mnie rozwiązanie jest praktyczne? BARDZO PRAKTYCZNE ;) ja , ale nie tylko ja z powodzeniem często z tego korzystam.

    Powiem więcej - konwersja i dekodowanie czsu na postać Unix'ową jak mówiłem ma sens ale wg mnie w uzasadnionych przypadkach i potrzebach. A gdy np robię coś na ATtiny13 gdzie potrzebne mi sią TYLKO godziny i minuty dzięki czemu mam możliwość już zorganizowania prostego systemu dobowego (zresztą co za problem dorzucić do konwersji jeszcze sam virtualny licznik dni) - to w takich sytuacjach konwersja na czas Unix'owy jest niepraktyczna i w ogóle niepotrzebna - wręcz marnotrastwo ;)

    (oczywiście przejaskrawiam trochę specjalnie wspominając o tych marntrastwach - żeby było widać o co mi chodzi)

    Reasumując - nie ma tutaj żadnego jednego PRAKTYCZNEGO sposobu co starasz się być może udowodnić. Ja tak jak i wiele osób (a wierzę, że i ty) najczęściej dobiera odpowiednie metody do danego projektu bo nie zawsze robisz coś na takim samym mikrokontrolerze i warunki się zmieniają.

    Poza tym moglibyśmy długo się tu "kłócić" który sposób jest lepszy czy "przechwalać" jak można to lepiej zrobić - tylko moim zdaniem jest to bez sensu. A jesli w takich postach mówisz o jakichś sposobach a nie podajesz konkretnego rozwiązania, które może pomóc autorowi. (moglibyśmy wręcz roziwnąć przy tej okazji temat od razu programowania w czasie pseudo rzeczywistym i tak żeby pisać funkcje w sposób nieblokujący bo taki globalny licznik czasu w przerwaniu co sekundę już daje takie możliwości, ja dodałbym zaraz, że co sekundę warto nie tylko zwiększać ten licznik ale od razu zapisywać go do jednej struktury o nazwie np: CZAS w której poza postacią UNIX'ową od razu byłyby skonwertowane postaci zjadliwe dla ludzi czasu i daty - tylko to wszystko to troszkę nie na ten konkretny temat ;) ) Widać zresztą, że jest początkujący i potrzebuje prostego rozwiązania.

    Podaj więc jeśli już wspominasz o konwersji do czsu Unix'owego kilka prostych funkcyjek do wyciągania z niego czasu lub daty w ludzkiej postaci czy też odwrotnie do zapisywania czasu w ludzkiej postaci do jednej dużej liczby. Ja je znam i niejednokrotnie ich używam gdy jest potrzeba - ale wiem, że to zajmuje troszkę kodu i nie zawsze jak dla mnie warto tego używać. To tyle.
  • Poziom 16  
    Polemika bardzo interesująca ale nie potrafię sobie wyobrazić całości kodu..odczyt czasu to cztery zmienne hh,h,mm,m binarny więc konwersja do dziesiętnego każdej zmiennej które trzeba do siebie dodać hh*10 z h oraz mm*10 z m i mam dwie zmienne np; 12 i 04 lub nawet do postaci 1204 jednej czterocyfrowej liczby teraz odczytuje wpisany do PCF-a czas np;załączenia o 12:10 czyli dwie zmienne [tylko pytanie czy dziesiętne czy binarne] i też je do siebie dodać czyli 12 , 10 lub 1210 w rezultacie mamy cztery lub dwie cyfry które należy porównać [niby proste a się wysypało]...teraz na dodatek wizualizacja statusu portów...o ile dobrze pojmuję logikę avr-ów to port ustawiony jako wyjście nie może być sprawdzany poprzez PINx więc jak sprawdzić czy port jest ustawiony czy nie.......soory to mój pierwszy program i sam się zaczynam w nim gubić w utworzonych zmiennych,warunkach i zależnościach bez zaawansowanych funkcji które zapewne by go uprościły i uczyniły bardziej czytelnym.
    Jak ktoś chce wgląd do całego programu;
    ]Link[/url]
    ftp://margas.homelinux.com/00--00/
  • Poziom 42  
    Zostaw zapis binarny bo ci tu nie jest potrzebny ;) a tak wygląda 0b00110010
    Ty z PCF'a odczytujesz w kodzie BCD i skoro już ci coś działa to chyba nie masz problemu z tym, żeby zamienić z BCD na normalaną postać dziesiętną prawda?

    czyli jeśli masz zmienną hh to po konwersji z BCD masz w niej normalne wartości godzin: 12, 13, 14t-a i tak dalej w czym problem? w zmiennej mm masz w postaci dziesiętnej minuty: 1,2,3....14,15 itd

    czyli np czas: 12:45 będzie zapisany u ciebie w zmiennych:

    Code:
    hh = 12
    
    mm = 45

    tak czy nie?

    przejrzyj prosty kod, który ci podałem wyżej - prosty jak drut, bo nie dziwię się, że początkujący może kota dostać jak ktoś od razu rzuca go na konwersję czasu unixowego, małymi kroczkami panowie.

    masz w tym moim przykładzie funkcję o może mylącej nieco nazwie ale możesz ją sobie zmienić np na time_to_int() - jak to było w przykładach z linka kolegi michałko12

    Code:
    get_time();

    przyjmuje ona dwa argumenty, właśnie wpostaci np twoich zmiennych hh oraz mm

    Code:
    get_time(hh,mm);

    trudne ?

    i teraz jeśli chcesz sprawdzić czy czas w tych zmiennych jest już większy niż np 12:48 to robisz proste porównanie:

    Code:
    if( get_time(hh,mm) > get_time(12,48) ) {
    
       zrób_coś_tam();
    }

    te funkcje za ciebie zamienią czas na jedną liczbę typu uint16_t, którą następnie za pomocą takich wywołań można sobie dowolnie porównywać.

    A co do portu:

    Jeśli np twój triak wysterowany ma być poziomem niskim np na porcie PB4 to:

    Code:
    PORTB &= ~(1<<PB4);  // tak włączasz triaka

    a później w kodzie tak możesz sprawdzić czy jest włączony:

    Code:
    if( !(PINB & (1<<PB4) ) {
    
        zrób_coś_gdy_triak_wlaczony();
    }

    albo

    Code:
    if( (PINB & (1<<PB4) ) {
    
        zrób_coś_gdy_triak_wylaczony();
    }

    albo

    Code:
    // tu sprawdzasz zarówno stan triaka i czas
    
    if( get_time(hh,mm) > get_time(12,48) && !(PINB & (1<<PB4) ) {
        zrób_coś_gdy_triak_wlaczony_i_minela_godzina_12_48();
    }
  • Poziom 16  
    Z odczytem nie jest tak że po konwersji dostaje cyfre np;12 bo odczytuje osobno dziesiątki i jednostki czyli 2 x 4 bity BCD bo te dwa rejestry są niezależne i jeżeli czytałbym całe 8 bitów i robił konwersje do dec to wyjdą bzdury.Więc muszę dziesiątki d_h i jednostki j_h ze sobą najpierw scalić oby otrzymać liczbę dwucyfrową 12 i podobnie zrobić z minutami...próbowałem zaadoptować twój przykład mirek36 ale chyba coś sknociłem..muszę nad tym posiedzieć.Teraz to mam tak..
    Code:

          suma_czas_godz=((dec_godz_1*10)+(dec_godz_0));         //suma dziesiątek i jednostek godzin
          suma_czas_min=((dec_min_1*10)+(dec_min_0));            //suma dziesiątek i jednostek minut
          //------------------------------------------------------------------
          if(tryb_k1=0)   //określa czy obwód_1 pracuje w trybie automatycznym "0" czy ręcznym "1"
          {
             if((czas_time(suma_czas_godz,suma_czas_min) > czas_timer_1(godz_timer_1,min_timer_1))&& (PINB & (1<<PB4))) 
             {
                PORTB &= ~(1<<PB4);     //włącz obwód nr.1
             }
             if((czas_time(suma_czas_godz,suma_czas_min) > czas_timer_1(godz_timer_1,min_timer_1))&& !(PINB & (1<<PB4)))
             {
                PORTB &= ~(1<<PB4);     //wyłącz obwód nr.1
             }
             if(!(PINB & (1<<PB4)))      //sprawdz czy obwód włączony
             {
                 status_k1=1;         //zmienna wyświetlana na LCD jako ON
             }
             if(PINB & (1<<PB4))         //sprawdz czy obwód wyłączony
             {
                 status_k1=0;         //zmienna wyświetlana na LCD jako OFF
             }
          }

       //----------------------------------------------------------------------
       }
       char *power[4]={"OFF","ON ","Auto","Man "};
       if(!(PIND & _BV(4)))
       {
          _delay_ms(30);
          PORTB |= _BV(0);   //włącza podświetlenie LCD   
          {
             ekran++;
             _delay_ms(600);
             LCD_GoTo(0,0);  LCD_WriteText("                                          ");
             LCD_GoTo(0,1);  LCD_WriteText("                                          ");
          }
       }
       switch(ekran)
          {
                case 0:   //EKRAN GLOWNY-----WYŚWIETLANIE-----DANYCH
                            //ekran główny w tym przypadku nieistotne
             break;
             case 1://-------------------------------------------------------przełączanie trybu pracy - sterowanie ręczne   
             LCD_GoTo(0,0);   LCD_WriteText("KANAL 1");
             LCD_GoTo(8,0);   LCD_WriteText(power[tryb_k1]);//tryb pracy AUTO lub MANUAL
             LCD_GoTo(16,0);   LCD_WriteText(power[status_k1]);//staus obwodu WŁ lub WYŁ