<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=4&amp;t=12892&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2016-03-03T18:37:14+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=12892&amp;mode</id>
<entry>
<author><name><![CDATA[zbynio_k]]></name></author>
<updated>2016-03-03T18:37:14+01:00</updated>
<published>2016-03-03T18:37:14+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=155363#p155363</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=155363#p155363"/>
<title type="html"><![CDATA[Re: Zegarek i termometr czyli klasyka]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=155363#p155363"><![CDATA[
witam,<br />pomijając niedociągnięcia w temacie rozdzielania plików i techniki programowania<br />BARDZO dobry przykład dla początkujących w temacie wskaźników do funkcji<br />brak struktur menu itp.<br />dzięki za podpowiedź do mojego projektu  <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> <br />pozdrawiam<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=11423">zbynio_k</a> — 3 mar 2016, o 18:37</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Jarcio]]></name></author>
<updated>2015-09-22T20:21:06+01:00</updated>
<published>2015-09-22T20:21:06+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=140424#p140424</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=140424#p140424"/>
<title type="html"><![CDATA[Re: Zegarek i termometr czyli klasyka]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=140424#p140424"><![CDATA[
Dzięki za linki. Przetrawiłem je. <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />  <br />Bardzo wartościowe linki jeżeli chodzi o jakość kodu.<br />Szczególnie ten <a href="http://www.ipa.go.jp/files/000040508.pdf"  class="postlink">http://www.ipa.go.jp/files/000040508.pdf</a> dokument jest bardzo fajny.<br />Bardzo wyraźnie jest pokazane jakich konstrukcji nie stosować i dlaczego.<br />Polecam wszystkim.<br /><br />Jeżeli chodzi o poprawę kodu/ podział na moduły to prace trwają... Z braku czasu bardzo powoli...<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=10579">Jarcio</a> — 22 wrz 2015, o 20:21</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Jarcio]]></name></author>
<updated>2015-09-12T20:54:16+01:00</updated>
<published>2015-09-12T20:54:16+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139687#p139687</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139687#p139687"/>
<title type="html"><![CDATA[Re: Zegarek i termometr czyli klasyka]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139687#p139687"><![CDATA[
Dziękuje za uwagi.<br />Z większością uwag kolegi mokrowski muszę się zgodzić. Przejrzałem kod i wychodzi na to że prościej go napisać od nowa <img src="https://forum.atnel.pl/images/smilies/icon_lol.gif" alt=":lol:" title="Śmieje się" /> <br />Człowiek uczy się na błędach. Zaciekawiła mnie uwaga z pkt 11 na temat sprawdzania kodu. Mam prośbę o lekkie rozwinięcie tematu sprawdzania jakości kodu. Czy są jakieś darmowe narzędzia do tego, czy trzeba tworzyć jakieś szablony kodu wg których następuje sprawdzanie itp..<br /><br />Zacząłem na nowo pisać kod od razu dzieląc go na moduły. Funkcje do odczytania i wyświetlenia czasy wyrzuciłem do modułu czas, definicje klawiszy i wszystkiego co się wiąże z podłączeniem do avr wpisałem definicje.h. Teraz rzeczywiście wygląda to lepiej  <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />  Na razie jest wyświetlany sam zegarek, reszta dojdzie w przyszłości...<br />Tak wygląda obecnie main.c<br />[syntax=c]#include &lt;stdbool.h&gt;<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />/*<br /> * poniższe biblioteki z książki<br /> * Mikrokontrolery AVR Język C - podstawy programowania<br /> */<br />#include &quot;LCD/lcd44780.h&quot;<br />#include &quot;I2C_TWI/i2c_twi.h&quot;<br /><br />#include &quot;Czas/czas.h&quot;<br />#include &quot;definicje.h&quot;<br /><br />volatile uint8_t int0_flag=1;   // flaga zmieniana w przerwaniu i sprawdzana w pętli głównej<br /><br />void inicjuj (void);<br /><br /><br />/*<br /> * main - START<br /> */<br />int main (void)<br />{<br />    CZAS_t akt_czas;<br /><br />    inicjuj ();<br /><br />    sei();<br /><br />    while (1)<br />    {<br />        // działania podejmowane co 1s<br />        if (int0_flag)<br />        {<br />            akt_czas = czas_odczytaj ();        // odczytujemy czas z RTC<br />            czas_wyswietl (0, 4, akt_czas, true);   // i wyświetlamy na LCD<br />        }<br />    }<br /><br />    return 0;<br />}<br />/*<br /> * main - KONIEC<br /> */<br /><br /><br />// procedura obsługi przerwania INT 0<br />ISR( INT0_vect ) {<br />    int0_flag = 1;<br />}<br /><br /><br />/*<br /> * inicjujemy co można<br /> */<br />void inicjuj (void)<br />{<br />    // Przerwanie INT0<br />    MCUCR |= (1&lt;&lt;ISC01);    // wyzwalanie zboczem opadającym<br />    GICR |= (1&lt;&lt;INT0);      // odblokowanie przerwania<br />    PORTD |= (1&lt;&lt;PD2);      // podciągnięcie pinu INT0 do VCC<br /><br />    // podpinamy klawisze<br />    DDRC &amp;= ~(KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN);<br />    PORTC |= KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN;<br /><br />    lcd_init();             // inicjujemy LCD<br /><br />    // włączamy podświetlenie LCD<br />    DDRA |= LCD_LED_PIN;<br />    LCD_LED_ON;<br /><br />    i2cSetBitrate (100);    // USTAWIAMY prędkość 100 kHz na magistrali I2C<br />}[/syntax]<br />Czas.h<br />[syntax=c]#ifndef CZAS_CZAS_H_<br />#define CZAS_CZAS_H_<br /><br /><br />#define PCF8583_ADDR 0xA2<br /><br /><br />//struktura do określania czasu<br />typedef struct  {<br />                    uint8_t godz;   // godzina<br />                    uint8_t min;    // minuta<br />                    uint8_t sek;    // sekunda<br />                } CZAS_t;<br /><br /><br />/*<br /> * konwersja liczby dziesiętnej na BCD<br /> */<br />uint8_t dec2bcd(uint8_t dec);<br /><br /><br />/*<br /> * konwersja liczby BCD na dziesiętną<br /> */<br />uint8_t bcd2dec(uint8_t bcd);<br /><br /><br />/*<br /> * odczytanie czasu z RTC<br /> */<br />CZAS_t czas_odczytaj (void);<br /><br /><br />/*<br /> * wyświetlenie czasu na LCD<br /> * parametry:<br /> *      uint8_t y   - pozycja y na lcd<br /> *      uint8_t x   - pozycja x na lcd<br /> *      CZAS_t czas - czas do wyświetlenia<br /> *      bool czy_sek - czy wyświetlać sekundy (true/false)<br /> */<br />void czas_wyswietl (uint8_t y, uint8_t x, CZAS_t czas, bool czy_sek);<br /><br /><br />#endif /* CZAS_CZAS_H_ */[/syntax]<br />czas.c<br />[syntax=c]#include &lt;stdbool.h&gt;<br />#include &lt;avr/io.h&gt;<br /><br />/*<br /> * poniższe biblioteki z książki<br /> * Mikrokontrolery AVR Język C - podstawy programowania<br /> */<br />#include &quot;../LCD/lcd44780.h&quot;<br />#include &quot;../I2C_TWI/i2c_twi.h&quot;<br /><br />#include &quot;czas.h&quot;<br /><br /><br />// konwersja liczby dziesiętnej na BCD<br />uint8_t dec2bcd(uint8_t dec) {<br />    return ((dec / 10)&lt;&lt;4) | (dec % 10);<br />}<br /><br /><br />// konwersja liczby BCD na dziesiętną<br />uint8_t bcd2dec(uint8_t bcd) {<br />    return ((((bcd) &gt;&gt; 4) &amp; 0x0F) * 10) + ((bcd) &amp; 0x0F);<br />}<br /><br /><br />CZAS_t czas_odczytaj (void)<br />{<br />    uint8_t bufor_rtc&#91;4&#93;;       // rezerwacja bufora 4 bajty na odczyt TRC<br />    CZAS_t czas;                // zmienna na aktualny czas<br />    //odczyt 4 bajtów do bufora od adresu 0x01 z pamięci RAM naszego RTC<br />    TWI_read_buf( PCF8583_ADDR, 0x01, 4, bufor_rtc );<br /><br />    czas.sek  = bcd2dec( bufor_rtc&#91;1&#93; );<br />    czas.min  = bcd2dec( bufor_rtc&#91;2&#93; );<br />    czas.godz = bcd2dec( bufor_rtc&#91;3&#93; );<br /><br />    return czas;<br />}<br /><br /><br />void czas_wyswietl (uint8_t y, uint8_t x, CZAS_t czas, bool czy_sek)<br />{<br />    lcd_locate(y,x);<br />    if( czas.godz &lt; 10 )<br />    {<br />        lcd_str(&quot;0&quot;);<br />    }<br />    lcd_int(czas.godz);<br />    lcd_str(&quot;:&quot;);<br />    if (czas.min &lt; 10)<br />    {<br />        lcd_str(&quot;0&quot;);<br />    }<br />    lcd_int(czas.min);<br />    if (czy_sek)<br />    {<br />        lcd_str(&quot;:&quot;);<br />        if( czas.sek &lt; 10 )<br />        {<br />            lcd_str(&quot;0&quot;);<br />        }<br />        lcd_int(czas.sek);<br />    }<br />}[/syntax]<br />No i co wiąże z podłączenie pinów do procka przeniosłem do definicje.h<br />[syntax=c]#ifndef DEFINICJE_H_<br />#define DEFINICJE_H_<br /><br />// definicja klawiszy<br />#define KEY1_PIN (1&lt;&lt;PC6)     // key 1 - poprzednia pozycja (previous)<br />#define KEY2_PIN (1&lt;&lt;PC5)      // key 2 - nastepna pozycja (next)<br />#define KEY3_PIN (1&lt;&lt;PC2)    // key 3 - zatwierdzenie (enter, wywolanie menu)<br />#define KEY4_PIN (1&lt;&lt;PC3)   // key 4 - włącznie podświetlenia jeżeli jest ustawiony wyłączony LCD przez wygaszacz<br />//         lub jeżeli jest ustawiony wygaszacz to również ręczne wyłączenie podswietlenia<br />//         ostatnia funkcja to wyłączenie budzika :-)<br />// i innych rzeczy :-)<br />#define LCD_LED_PIN (1&lt;&lt;PA7)// podswietlenie LCD<br />#define LCD_LED_ON PORTA |= LCD_LED_PIN<br />#define LCD_LED_OFF PORTA &amp;= ~LCD_LED_PIN<br />#define LCD_LED_TOG PORTA ^= LCD_LED_PIN<br /><br />#define BEEP_PIN (1&lt;&lt;PB2)// beeper<br />#define BEEP_ON PORTB |= BEEP_PIN<br />#define BEEP_OFF PORTB &amp;= ~BEEP_PIN<br />#define BEEP_TOG PORTB ^= BEEP_PIN<br /><br />#endif /* DEFINICJE_H_ */[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=10579">Jarcio</a> — 12 wrz 2015, o 20:54</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2015-09-10T21:48:01+01:00</updated>
<published>2015-09-10T21:48:01+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139510#p139510</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139510#p139510"/>
<title type="html"><![CDATA[Re: Zegarek i termometr czyli klasyka]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139510#p139510"><![CDATA[
Ja też po 20 latach programowania w Pascalu długo się trzymałem takich przyzwyczajeń jak zaczynałem uczyć się C <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> .... a teraz ...<br /><br />jak mam napisać i=i+1 to mnie obrzydzenie bierze <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> wolę i++<br /><br />co ciekawe jak na PC zaczynam coś pisać w moim Delphi bo wciąż na PC używam Delphi to aż mi brakuje takich fajnych fiuczerów z C <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 10 wrz 2015, o 21:48</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Jarcio]]></name></author>
<updated>2015-09-10T21:44:12+01:00</updated>
<published>2015-09-10T21:44:12+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139508#p139508</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139508#p139508"/>
<title type="html"><![CDATA[Re: Zegarek i termometr czyli klasyka]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139508#p139508"><![CDATA[
OK<br />I o to mi chodziło. Wiem na co bardziej zwrócić uwagę.<br /><br />Kiedyś prawie wszędzie uczyli wszędzie Pascala - do którego osobiście nic nie mam. Cuda też można tam robić.<br />Pozostały również stare przyzwyczajenia z ... FoxPro dla DOS . Ciekawe czy ktoś to pamięta <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> <br />Stąd też również dziwne przyzwyczajenia do formatowania kodu, co optycznie go znacznie wydłuża...<br />Nie napiszę kodu pętli w ten sposób:<br />[syntax=c]for (i=0; i&lt;10; i++){<br />   polecenie1();<br />   polecenie2();<br />}[/syntax]U mnie musi być<br />[syntax=c]for (i=0; i&lt;10; i++)<br />{<br />   polecenie1();<br />   polecenie2();<br />}[/syntax]<br />Pierwszy przypadek jest dla mnie na razie całkowicie nieczytelny.<br />Również z tego powodu nie zmieniam wartości zmiennych przez np i++. U mnie musi być i=i+1 itp...<br />I tak wychodzą przyzwyczajenia po begin..end.<br />Koniec marudzenia. C coraz bardziej mi się to podoba.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=10579">Jarcio</a> — 10 wrz 2015, o 21:44</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2015-09-10T07:29:04+01:00</updated>
<published>2015-09-10T07:29:04+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139433#p139433</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139433#p139433"/>
<title type="html"><![CDATA[Re: Zegarek i termometr czyli klasyka]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139433#p139433"><![CDATA[
<div class="quotetitle">Jarcio napisał(a):</div><div class="quotecontent"><br />Mam tylko nadzieję że krytyka będzie delikatna...<br /></div><br />Krytyką to mogą się zajmować ludzie zajmujący się sztuką, kulturą, dziełami sztuki itp .... <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />Ja nie mam z nimi nic wspólnego więc kilka mała uwaga.<br /><br />Przede wszystkim, brak podziału projektu na pliki - postaraj się tego jak najszybciej nauczyć, bo teraz przypomina ten kod - najczystszą postać z bascoma (jeden wielki plik (worek) do którego wrzucono wszystko co się da)<br /><br />O ile masz w bibliotekach obsługę RTC, 1wire czy LCD to pomyśl u ciebie pięknie można wydzielić kolejne bloki logiczne jak <br /><br />- obsługa menu (oddzielny plik)<br />- obsługa zegarka (oddzielny plik i funkcje)<br />- obsługa alarmów/budzika (oddzielny plik i funkcje, szczególnie ta menu_func_ustaw_budzik () wprost nadaje się do wydzielenia)<br />- oddzielne funkcje do wyświetlania poszczególnych danych<br /><br />bo w tej chwili twoja funkcja main() jest spuchnięta do nieskończoności.<br /><br />Mówię tylko, że przydałoby się to zrobić bo wtedy kod byłby 100x bardziej czytelny a tym bardziej, że bardzo ładnie go sobie komentowałeś (duży PLUS) <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> <br /><br />Podsumowując gdy nauczysz się lepszego podziału na pliki sam z tego skorzystasz - mówię ci i gorąco polecam ci takie podejście. Zaś prezentowany tu kod będzie wtedy miał wszystko czego potrzeba.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 10 wrz 2015, o 07:29</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Jarcio]]></name></author>
<updated>2015-09-09T22:57:47+01:00</updated>
<published>2015-09-09T22:57:47+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139430#p139430</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139430#p139430"/>
<title type="html"><![CDATA[Zegarek i termometr czyli klasyka]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=12892&amp;p=139430#p139430"><![CDATA[
Witam wszystkich<br />Jest to mój pierwszy post na tym forum więc proszę o wyrozumiałość <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> <br />Od roku jestem posiadaczem ATB i niebieskiej książki. W sumie chciałem się pochwalić swoim pierwszym większym kodem. <br />Ponieważ prawie każdy zaczyna od zegarka, termometru, migania diodami (może nie w tej kolejności  <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ) więc mój kod również tego dotyczy. Dodatkowo ponieważ na forum często pojawiają się pytania o menu to również chciałem przedstawić swoje podejście (jako osoby początkującej) do tego problemu.<br />Moje menu nie jest oparte na strukturach, listach, dużej ilości wskaźników itp. Podszedłem do problemu dość prosto. <br />W kodzie mam dwie tablice. Jedna zawiera opisy jakie się pojawiają na LCD. Druga tablica zawiera wskaźniki do funkcji jakie będą wywołane dla poszczególnych opisów. Poruszając się po opisach ustawiamy sobie indeks który jest użyty do wywołania właściwej funkcji z drugiej tablicy.<br />Dodatkowo dla uproszczenia całości w pierwszym wierszu LCD są wyświetlane tylko opisy menu. Ustawianie parametrów natomiast odbywa się w  drugim wierszu.<br />Program może nie jest napisany w najlepszym stylu jak powinno się pisać na avr. Do tematu programowania podszedłem bowiem bardzo liniowo. Kodowi również przydałaby się jeszcze optymalizacja. W paru miejscach funkcje prawie są jednakowe, np. te od ustawiania temperatury w menu. Jeżeli chodzi o obsługę przycisków to również jest najprostsza z możliwych. Zatem ich obsługa jest czasami irytująca. Miejmy nadzieję że następna wersja będzie lepsza...<br />Opis połączeń na ATB i funkcjonalności programu jest w kodzie. W razie pytań o kod postaram się na nie odpowiedzieć.<br />Mam tylko nadzieję że krytyka będzie delikatna...  <img src="https://forum.atnel.pl/images/smilies/icon_redface.gif" alt=":oops:" title="Zawstydzony" /> <br />Przy okazji pytanko - jak w eclipse wpisać literę &quot;ć&quot;. U mnie pojawia się okienko z prośbą o podanie ścieżki do ChangeLog.<br /><br />[syntax=c]/*****************************************************************<br /> * Podłączenie pinów na zestawie uruchomieniowym ATB<br /> *****************************************************************<br /> *<br /> * WYSWIETLACZ<br /> *   PA0 - PA7 --&gt; RS, RW, E, D4, D5, D6, D7, 8 (backlight)<br /> * KLAWISZE<br /> *   K1 --&gt; PC6<br /> *   K2 --&gt; PC5<br /> *   K3 --&gt; PC2<br /> *   K4 --&gt; PC3<br /> * RTC<br /> *   RTC INT (1) --&gt; PD2<br /> * 1WIRE<br /> *   1Wire --&gt; PB1<br /> * BUZZER<br /> *   J5 --&gt; PB2<br /> *<br /> *  Wykorzystano dwa czujniki DS1820<br /> *  Jeden wbudowany zestaw, drugi podpięty do pinów ATB<br /> *****************************************************************/<br /><br />/*****************************************************************<br /> * Opis dzialania<br /> *****************************************************************<br /> *<br /> * Po podłączeniu płytki ATB zgodnie z powyższym opisem<br /> * na wyświetlaczu powinna pojawic sie jakaś godzina z RTC<br /> * i powinien byc odliczany czas<br /> *<br /> * Do momentu ustawienia w menu odpowiednich czujników do<br /> * temperatury &quot;zewnętrznej&quot; i &quot;wewnętrznej&quot; na LCD będą<br /> * widoczne &quot;-----&quot; kreski.<br /> *<br /> * Po ustawieniu budzika powinien się pojawic dodatkowo na LCD<br /> * napis BUDZIK.<br /> *<br /> * Funkcjonalnośc menu jest opisana w pobliżu tablicy menu_opt,<br /> * która zawiera napisy jakie pojawią się w menu.<br /> *<br /> * Trochę o budziku.<br /> * Sygnał dźwiękowy jest najprostrzy jak się da. Co jedną sekundę<br /> * włącza się beper na płycie ATB na jedną sekunę i potem sekunda przerwy. :-)<br /> * Dodatkowo w tym samym czasie mryga podświetlenie LCD.<br /> * Do ustawienia budzika służą aż 3 opcje z menu<br /> * 1. USTAW BUDZIK - ustawiamy czas włączenia budzika<br /> * 2. BUDZIK AKTYWNY - czy o danym czasie budzik ma dzwonic<br /> * 3. SYGNAL DZWIEKOWY - czy budzik ma wydawac dźwięki<br /> * Jeżeli jest ustawione NIE to budzik tylko mryga wyświetlaczem<br /> * np żebyśmy poszli szybciej do łóżka a nie siedzieli po nocach przed ATB :-)<br /> * I nie stawia całej rodziny na nogi ...<br /> * Czas trwania budzenia został z lenistwa zaszyty w kodzie w<br /> *    #define BUDZIK_CZAS  1 - czas podajemy w minutach<br /> *<br /> * Wciskajac klawis K3 mozemy wywolac menu<br /> * Za pomocą klawisza K1 wybieramy poprzednia pozycje menu<br /> * Za pomoca klawisza K2 wybieramy nastepna pozycje menu<br /> * Po wybraniu pozycji można ją zatwierdzic klawiszem K3<br /> * Klawisz K4 służy do włączenia lub wyłączenia podświetlenia LCD<br /> * oraz do wyłączenia budzika :-)<br /> *<br /> * W celu uproszczenia obslugi menu troche inaczej podszedlem do<br /> * problemu jego wyswietlania i wyboru pozycji. Menu jest tylko w<br /> * pierwszym wierszu lcd i tam są opisy<br /> *<br /> * Drugi wiersz służy do zmiany parametrów.<br /> * Może nie jest to najbardziej eleganckie rozwiązanie<br /> * ale za to proste w implementacji.<br /> *<br /> *****************************************************************/<br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;avr/eeprom.h&gt;<br />#include &lt;util/delay.h&gt;<br /><br />// poniższe biblioteki są z książki Pana Mirosława Kardasia<br />// Mikrokontrolery AVR Język C - podstawy programowania<br />// wydanej przez wydawnictwo Atnel<br />// i nie są załączone do kodu<br />#include &quot;LCD/lcd44780.h&quot;<br />#include &quot;I2C_TWI/i2c_twi.h&quot;<br />#include &quot;1Wire/ds18x20.h&quot;<br /><br /><br />//struktura do określania czasu<br />typedef struct  {<br />                    uint8_t godz;   // godzina<br />                    uint8_t min;    // minuta<br />                    uint8_t sek;    // sekunda<br />                } CZAS;<br /><br /><br />// struktura do ustawień<br />typedef struct  {<br />                    uint8_t beep;               // beeper 0-NIE / 1 - TAK<br />                    uint8_t czas_wygaszacza;    // czas do wyłączenie podświetlenia<br />                    uint8_t tz_sensor &#91;8&#93;;      // sensor temperatury zewnetrznej<br />                    uint8_t tw_sensor &#91;8&#93;;      // sensor temperatury wewnętrznej<br />                    uint8_t jest_budzik;        // czy budzik ma działac 0-NIE/1-TAK<br />                    CZAS    budzik_godz;        // godzina włączenia budzika<br />                } USTAWIENIA;<br /><br /><br />#define EEMEM __attribute__((section(&quot;.eeprom&quot;)))<br /><br />USTAWIENIA EEMEM ee_ustawienia;         // ustawienia przechowywane w eeprom<br />USTAWIENIA ustawienia;                  // ustawienia przechowywane w ram<br /><br />#define BUDZIK_CZAS     1               // czas trwania budzika w minutach<br /><br /><br />#define MAX_OPTIONS     8               //definiujemy max ilosc opcji w menu<br /><br />// opisy menu też przechowujemy w eeprom<br />char EEMEM menu_opt&#91;MAX_OPTIONS&#93;&#91;17&#93; = {&quot;SYGNAL DZWIEKOWY&quot;, // Czy jest beep po wciśnięciu klawisza lub sygnał dzwiękowy budzika<br />                                        &quot;USTAW CZAS&quot;,       // Ustawianie zegarka i zapis danych do RTC<br />                                        &quot;WYGASZACZ&quot;,        // Określenie po jakim czasie w &#91;s&#93; ma się wyłączyc podświetlenie LCD<br />                                        &quot;TEMP ZEWN&quot;,        // Podpięcie właściwego czujnika DS18B20 do termometru zewnętrznego<br />                                        &quot;TEMP WEWN&quot;,        // Podpięcie właściwego czujnika DS18B20 do termometru wewnętrznego<br />                                        &quot;BUDZIK AKTYWNY&quot;,   // Budzik aktywny TAK/NIE<br />                                        &quot;USTAW BUDZIK&quot;,     // Ustaw godzinę włączenia budzika<br />                                        &quot;KONIEC&quot;            // Wyjście z menu<br />                                       };<br /><br />// funkcje do obsługi poczczególnych pozycji menu<br />void menu_func_01();<br />void menu_func_02();<br />void menu_func_03();<br />void menu_func_04();<br />void menu_func_tz();<br />void menu_func_tw();<br />void menu_func_budzik_akt();<br />void menu_func_ustaw_budzik();<br /><br />// i tablica wskaznikow do funkcji do obslugi menu<br />void (*menu_func&#91;MAX_OPTIONS&#93;)() = {    menu_func_01,<br />                                        menu_func_02,<br />                                        menu_func_03,<br />                                        menu_func_tz,<br />                                        menu_func_tw,<br />                                        menu_func_budzik_akt,<br />                                        menu_func_ustaw_budzik,<br />                                        menu_func_04<br />                                    };<br /><br /><br />int8_t item = 0;                // biezaca pozycja menu<br />int8_t jestem_w_menu = 0;       // jestesmy w menu<br />int8_t pierwszy = 0;            // wyrysowanie startowe menu - po wejsciu do menu<br /><br />uint8_t wygaszacz = 0;          // wygaszacz ekranu NIE=0/TAK=1<br />uint8_t czas_wygaszenia = 0;    // czas do wygaszenia ekranu<br /><br />uint8_t subzero, cel, cel_fract_bits; // do obsługi termometru<br />uint8_t czujniki_cnt;                 // ilość czujników na magistrali<br /><br /><br />// definicja klawiszy<br />#define KEY1_PIN (1&lt;&lt;PC6)           // key 1 - poprzednia pozycja (previous)<br />#define KEY2_PIN (1&lt;&lt;PC5)           // key 2 - nastepna pozycja (next)<br />#define KEY3_PIN (1&lt;&lt;PC2)           // key 3 - zatwierdzenie (enter, wywolanie menu)<br />#define KEY4_PIN (1&lt;&lt;PC3)           // key 4 - włącznie podświetlenia jeżeli jest ustawiony wyłączony LCD przez wygaszacz<br />                                    //         lub jeżeli jest ustawiony wygaszacz to również ręczne wyłączenie podswietlenia<br />                                    //         ostatnia funkcja to wyłączenie budzika :-)<br /><br />// i innych rzeczy :-)<br />#define LCD_LED_PIN (1&lt;&lt;PA7)                // podswietlenie LCD<br />#define LCD_LED_ON PORTA |= LCD_LED_PIN<br />#define LCD_LED_OFF PORTA &amp;= ~LCD_LED_PIN<br />#define LCD_LED_TOG PORTA ^= LCD_LED_PIN<br /><br /><br />#define BEEP_PIN (1&lt;&lt;PB2)                   // beeper<br />#define BEEP_ON PORTB |= BEEP_PIN<br />#define BEEP_OFF PORTB &amp;= ~BEEP_PIN<br />#define BEEP_TOG PORTB ^= BEEP_PIN<br /><br />#define PCF8583_ADDR 0xA2                   // adres RTC<br /><br />uint8_t klawisz_wcisniety(uint8_t klawisz); // funkcja obsługi wcisnietego klawisza - najprostsza z możliwych<br />                                            // funkcja wzięta żywcem z BB, z małymi modyfikacjami<br /><br />void disp_opt(int8_t item);                 // wyświetlenie określonej pozycji menu na LCD<br /><br />// funkcje odpowiedzialne za wizualizacje menu na LCD<br />void menu_disp_tak_nie (uint8_t stan);<br />void menu_disp_czas (uint8_t pozycja, CZAS akt_czas, uint8_t wyswietlaj_sekundy);<br />void menu_disp_03 (uint8_t czas);<br />void menu_disp_sensor (uint8_t poz&#91;&#93;);<br /><br />// wyświetlanie temperatury na lcd<br />void display_temp(uint8_t y, uint8_t x);<br /><br /><br />volatile uint8_t int0_flag=1;   // flaga zmieniana w przerwaniu i sprawdzana w pętli głównej<br /><br />// konwersja liczby dziesiętnej na BCD<br />uint8_t dec2bcd(uint8_t dec);<br />// konwersja liczby BCD na dziesiętną<br />uint8_t bcd2dec(uint8_t bcd);<br /><br /><br />//*******************************************************************************************<br />// main (void)<br />//*******************************************************************************************<br />int main(void) {<br /><br />    uint8_t bufor_rtc&#91;4&#93;;   // rezerwacja bufora 4 bajty<br />    CZAS akt_czas;          // zmienna na aktualny czas<br /><br />    int czas_aktualny;      // zmienne do wyliczanki czasów<br />    int czas_wl_budzika;<br /><br />    DDRA |= LCD_LED_PIN;    // włączamy podświetlenie LCD<br />    LCD_LED_ON;<br /><br />    // Przerwanie INT0<br />    MCUCR |= (1&lt;&lt;ISC01);    // wyzwalanie zboczem opadającym<br />    GICR |= (1&lt;&lt;INT0);      // odblokowanie przerwania<br />    PORTD |= (1&lt;&lt;PD2);      // podciągnięcie pinu INT0 do VCC<br /><br />    DDRC &amp;= ~(KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN);<br />    PORTC |= KEY1_PIN | KEY2_PIN | KEY3_PIN | KEY4_PIN;<br /><br />    //odczyt ustawien programu<br />    eeprom_read_block (&amp;ustawienia, &amp;ee_ustawienia, sizeof (ustawienia));<br /><br />    // sprawdzamy ile czujników DS18xxx widocznych jest na magistrali<br />    czujniki_cnt = search_sensors();<br />    // wysyłamy rozkaz wykonania pomiaru temperatury do wszystkich czujników na magistrali 1Wire<br />    DS18X20_start_meas( DS18X20_POWER_EXTERN, NULL );<br />    _delay_ms(750);<br /><br />    lcd_init();<br /><br />    i2cSetBitrate( 100 ); // USTAWIAMY prędkość 100 kHz na magistrali I2C<br /><br />    sei();<br /><br />    // i pętla główna programu<br />    while(1) {<br /><br />        if (ustawienia.czas_wygaszacza)                     // jeżeli ustawiony czas wygaszacza<br />        {<br />            if (wygaszacz &amp;&amp; klawisz_wcisniety (KEY4_PIN))  // i włączony LCD wygaszony<br />            {<br />                wygaszacz = 0;<br />                LCD_LED_ON;                                 // to zapal podświetlenie<br />            }<br /><br />            if (!wygaszacz &amp;&amp; klawisz_wcisniety (KEY4_PIN)) // jeżeli ustawiony czas wygaszacza<br />            {                                               // to możesz ręcznie<br />                wygaszacz = 1;                              // wyłączyc podświetlenie<br />                LCD_LED_OFF;<br />            }<br />        }<br /><br />        if (ustawienia.jest_budzik)                         // jeżeli jest budzik<br />        {<br />            if (klawisz_wcisniety (KEY4_PIN))               // i wcisniemy K4<br />            {<br />                ustawienia.jest_budzik = 0;                 // to wyłącz budzik - ustawienia są zmieniane tylko w ram<br />                                                            // jeżeli nie będziemy nic zmieniac w menu to po resecie się przywrócą<br />                                                            // jeżeli coś zmienimy z wyjątkiem zegarka to się zapiszą....<br />                if (!jestem_w_menu)                         // aby nie pisac po menu<br />                {                                           // to jeżeli w nim nie jesteś<br />                    lcd_locate(1,1);<br />                    lcd_str (&quot;      &quot;);                     // to zakryj napis BUDZIK<br />                }<br />                LCD_LED_ON;                                 // i włącz wyświetlacz<br /><br />                if (ustawienia.beep)                        // tu możesz lub nie musisz<br />                {<br />                    BEEP_OFF;                               // popikac beeperem<br />                }<br />            }<br />        }<br /><br />        // wciskamy klawisz menu<br />        if (klawisz_wcisniety (KEY3_PIN) &amp;&amp; (!jestem_w_menu) &amp;&amp; (!wygaszacz))<br />        {<br />            jestem_w_menu = 1;<br />            pierwszy = 1;<br />        }<br /><br />        // jestesmy w menu<br />        if (jestem_w_menu)<br />        {<br />            // jezeli dopiero weszlismy do menu to wyswietlamy<br />            // jednorazowo (po wejsciu do menu) menu od pierwszej pozycji<br />            if (pierwszy)<br />            {<br />                disp_opt (0);<br />                pierwszy = 0;   //wyswietlilismy menu to do nastepnego wywolania menu<br />            }<br /><br />            // a tu poruszamy sie po menu glownym<br />            if (klawisz_wcisniety (KEY1_PIN))       // jezeli wcisniety KEY 1<br />            {<br />                item = item - 1;                    // zmniejsz pozycje menu<br />                if (item &lt; 0)                       // jezeli poczatek menu<br />                {<br />                    item = 0;                       // to nie zmniejszaj<br />                }                                   // mozna ewentualnie przeskoczyc na koniec menu<br />                disp_opt(item);                     // ponownie narysuj menu<br />            }<br /><br />            if (klawisz_wcisniety (KEY2_PIN))       // jezeli wcisniety KEY 2<br />            {<br />                item = item + 1;                    // zwieksz pozycje menu<br />                if (item &gt;= MAX_OPTIONS-1)          // pamietajmy ze tablice liczymy od 0 a nie od 1<br />                {                                   // stąd zapis MAX_OPTIONS-1<br />                    item = MAX_OPTIONS-1;           // to nie zwiekszaj<br />                }                                   // zamiast stac na koncu mozna przewinac menu na poczatek<br />                                                    // osobiscie tego nie preferuje<br />                disp_opt(item);                     // ponownie narysuj menu<br />            }<br /><br />            if (klawisz_wcisniety (KEY3_PIN))       // jezeli wcisniety klawisz KEY 3<br />            {<br />                menu_func&#91;item&#93;();                  // wywolaj funkcje obslugi wybranego menu<br />                if (jestem_w_menu)                  // zabezpieczenie przed wyrysowaniem menu na LCD<br />                {                                   // po wyjsciu z menu<br />                    disp_opt(item);                 // jezeli wyjdziesz z powyzszej funkcji obslugi menu<br />                                                    // to ponownie wyswietl menu na aktualnej pozycji<br />                }<br />            }<br />        }<br /><br />        // wyświetlanie zegarka co 1s jeżeli nie jestem w menu<br />        // dzięki przerwaniu INT0 na porcie PD1 który jest podpięty do RTC<br />        if ( int0_flag )<br />        {<br /><br />            //odczyt 4 bajtów do bufora od adresu 0x01 z pamięci RAM naszego RTC<br />            TWI_read_buf( PCF8583_ADDR, 0x01, 4, bufor_rtc );<br /><br />            akt_czas.sek = bcd2dec( bufor_rtc&#91;1&#93; );<br />            akt_czas.min = bcd2dec( bufor_rtc&#91;2&#93; );<br />            akt_czas.godz = bcd2dec( bufor_rtc&#91;3&#93; );<br /><br /><br />            if (ustawienia.czas_wygaszacza)                             // jeżeli ustawiony czas do wygaszenia LCD<br />            {<br />                if (!wygaszacz)                                         // i wygaszacz nie włączony jeszcze<br />                {<br />                    if (czas_wygaszenia &gt;= ustawienia.czas_wygaszacza)  // i nadszedł czas wyłączenia<br />                    {<br />                        LCD_LED_OFF;                                    // to wyłącz podświetlenie LCD<br />                        wygaszacz = 1;<br />                    }<br />                    else                                                // jeżeli nie nadszedł czas wyłączenia<br />                    {<br />                        czas_wygaszenia = czas_wygaszenia + 1;          // to dalej licz ile ci brakuje do wyłączenia<br />                    }<br />                }<br />            }<br /><br /><br />            // ponieważ nie jesteśmy w menu<br />            // to możemy sobie spokojnie wyświetlac na LCD to co chcemy<br />            // czyli zegarek i temperatury<br />            if (!jestem_w_menu)<br />            {<br />                // wyświetlenie czasu na LCD<br />                lcd_locate(0,0);<br />                if( akt_czas.godz &lt; 10 ) lcd_str(&quot;0&quot;);<br />                lcd_int(akt_czas.godz);<br />                lcd_str(&quot;:&quot;);<br />                if( akt_czas.min &lt; 10 ) lcd_str(&quot;0&quot;);<br />                lcd_int(akt_czas.min);<br />                lcd_str(&quot;:&quot;);<br />                if( akt_czas.sek &lt; 10 ) lcd_str(&quot;0&quot;);<br />                lcd_int(akt_czas.sek);<br /><br />                // co trzy sekundy wysyłaj rozkaz pomiaru do czujnika<br />                if( 1 == (akt_czas.sek%3) ) DS18X20_start_meas( DS18X20_POWER_EXTERN, NULL );<br /><br />                //  jedną sekundę po rozkazie konwersji<br />                //  dokonuj odczytu i wyświetlania temperatury<br />                if( 2 == (akt_czas.sek%3) )<br />                {<br />                    // wyświetlamy temperaturę &quot;zewnętrzną&quot; lub '-----'<br />                    if( DS18X20_OK == DS18X20_read_meas(ustawienia.tz_sensor, &amp;subzero, &amp;cel, &amp;cel_fract_bits) )<br />                    {<br />                        display_temp(0, 10);<br />                    }<br />                    else<br />                    {<br />                        lcd_locate(0,10);<br />                        lcd_str(&quot;-----&quot;);<br />                    }<br />                    // wyświetlamy temperaturę &quot;wewnętrzną&quot; lub '-----'<br />                    if( DS18X20_OK == DS18X20_read_meas(ustawienia.tw_sensor, &amp;subzero, &amp;cel, &amp;cel_fract_bits) )<br />                    {<br />                        display_temp(1, 10);<br />                    }<br />                    else<br />                    {<br />                        lcd_locate(1,10);<br />                        lcd_str(&quot;-----&quot;);<br />                    }<br />                }<br />            }<br /><br />            // budzik jest aktywny<br />            if (ustawienia.jest_budzik)<br />            {<br />                if (!jestem_w_menu)<br />                {<br />                    lcd_locate(1,1);<br />                    lcd_str (&quot;BUDZIK&quot;);<br />                }<br /><br />                //wyliczamy aktualny czas do liczby<br />                czas_aktualny = (akt_czas.godz * 60) + akt_czas.min;<br />                // wyliczamy czas włączenia budzika do liczby<br />                czas_wl_budzika = (ustawienia.budzik_godz.godz * 60) + ustawienia.budzik_godz.min;<br /><br />                // i porónujemy liczby<br />                // jeżeli nam pasują czasy to włączmy budzik<br />                if ((czas_aktualny &gt;= czas_wl_budzika) &amp;&amp; (czas_aktualny &lt; (czas_wl_budzika + BUDZIK_CZAS)))<br />                {<br />                    LCD_LED_TOG;            // pomrygajmy sobie co 1s wyświetlaczem<br />                    if (ustawienia.beep)<br />                    {<br />                        BEEP_TOG;           // i możemy dodatkowo poudawac że jesteśmy muzykalni...<br />                    }<br />                }<br />            }<br /><br />            int0_flag=0;<br />        }<br />    }<br />}<br /><br />//*******************************************************************************************<br />// main (void) - KONIEC<br />//*******************************************************************************************<br /><br /><br />// procedura obsługi przerwania INT 0<br />ISR( INT0_vect ) {<br />    int0_flag = 1;<br />}<br /><br /><br />// konwersja liczby dziesiętnej na BCD<br />uint8_t dec2bcd(uint8_t dec) {<br />    return ((dec / 10)&lt;&lt;4) | (dec % 10);<br />}<br /><br />// konwersja liczby BCD na dziesiętną<br />uint8_t bcd2dec(uint8_t bcd) {<br />    return ((((bcd) &gt;&gt; 4) &amp; 0x0F) * 10) + ((bcd) &amp; 0x0F);<br />}<br /><br /><br />//--------------------------------------------------------<br />// Sprawdza czy klawisz jest wcisniety<br />//--------------------------------------------------------<br />uint8_t klawisz_wcisniety(uint8_t klawisz)<br />{<br />    if (!(PINC &amp; klawisz))                  // czy klawisz został wciśnięty ?<br />    {<br />        _delay_ms(120);                     // odczekajmy trochę<br />        if(!(PINC &amp; klawisz))               // i ponownie zobaczmy czy nadal jest wcisniety<br />        {<br />//          if (ustawienia.beep)            // tu pikała dodatkowo klawiatura<br />//          {                               // po naciśnięciu przycisku<br />//              BEEP_ON;                    // ale powodowało to problemy z obsługą<br />//              _delay_ms(30);<br />//              BEEP_OFF;<br />//          }<br /><br />            if (ustawienia.czas_wygaszacza) // jeżeli jest ustawiony czas wygaszenia wyświetlacza<br />            {                               // to po wciśnięciu przyciku<br />                czas_wygaszenia = 0;        // po prostu go zerujemy aby biegł od początku<br />            }<br />            return 1;                       // jednak jest wcisniety, to konczymy i zwracamy 1<br />        }<br />    }<br />    return 0;                               // skoro nie jest wcisniety to zwracamy 0<br />}<br /><br /><br />//--------------------------------------------------------<br />// Wyswietla pozycje menu glownego<br />//--------------------------------------------------------<br />void disp_opt(int8_t item)<br />{<br />    lcd_cls();                      // czyscimy lcd<br />    lcd_locate(0,0);                // ustawiamy kursor<br /><br />    lcd_str_E(&amp;menu_opt&#91;item&#93;&#91;0&#93;);  // to wypisz podaną pozycję menu<br />}<br /><br /><br />//--------------------------------------------------------<br />//  funkcja odpowiedzialna za<br />//  wyświetlanie menu TAK/NIE<br />//  parametr stan - okresla logicznie stan funkcji (TAK - 1 / NIE - 0)<br />//--------------------------------------------------------<br />void menu_disp_tak_nie (uint8_t stan)<br />{<br />    if (stan)               // jezeli stan==1 to jest zaznaczone TAK<br />    {<br />        lcd_locate(1,2);    // i ladnie rysujemy napis '&gt;TAK&lt;  NIE'<br />        lcd_char ('&gt;');<br />        lcd_str (&quot;TAK&quot;);<br />        lcd_char ('&lt;');<br />        lcd_locate(1,9);<br />        lcd_char (' ');<br />        lcd_str (&quot;NIE&quot;);<br />        lcd_char (' ');<br />    }<br />    else                    // jezeli stan==0 to jest zaznaczone NIE<br />    {<br />        lcd_locate(1,2);    // i ladnie rysujemy napis 'TAK  &gt;NIE&lt;'<br />        lcd_char (' ');<br />        lcd_str (&quot;TAK&quot;);<br />        lcd_char (' ');<br />        lcd_locate(1,9);<br />        lcd_char ('&gt;');<br />        lcd_str (&quot;NIE&quot;);<br />        lcd_char ('&lt;');<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// funkcja odpowiedzialna za obsluge 1 pozycji menu<br />// SYGNAL DZWIEKOWY przy wciskaniu klawiszy<br />// wybieramy TAK - jest beep<br />//           NIE - brak beep<br />//--------------------------------------------------------<br />void menu_func_01 ()<br />{<br />    uint8_t in_function = 1;        // ustawiamy flagę in_function<br />                                    // okresla nam czy znajdujemy sie w funkcji do obslugi<br />                                    // wybranej wczesniej pozycji menu<br /><br />    menu_disp_tak_nie (ustawienia.beep);    // w drugiej linii wypisujemy opcje menu (TAK/NIE)<br /><br />    while (in_function)                     // petla dziala dopóki nie zatwierdzimy wybory w opcji menu<br />    {<br />        if (klawisz_wcisniety (KEY1_PIN))   //  KEY1 zmienia stan opcji menu na przeciwny<br />        {<br />            if (!ustawienia.beep)<br />            {<br />                ustawienia.beep = 1;<br />            }<br />            else<br />            {<br />                ustawienia.beep = 0;<br />            }<br />            menu_disp_tak_nie (ustawienia.beep);    // ponownie rysujemy menu ze zmieniona opcją<br />        }<br /><br />        if (klawisz_wcisniety (KEY2_PIN))           // tym  razem dla klawisza KEY2 zmieniamy<br />        {                                           // stan opcji menu na przeciwny<br />            if (!ustawienia.beep)<br />            {<br />                ustawienia.beep = 1;<br />            }<br />            else<br />            {<br />                ustawienia.beep = 0;<br />            }<br />            menu_disp_tak_nie (ustawienia.beep);    // ponownie rysujemy menu ze zmieniona opcją<br />        }<br /><br />        if (klawisz_wcisniety (KEY3_PIN))           // klawiszem KEY3 - zatwierdzamy wybrana opcje<br />        {<br />            in_function = 0;                        // i wychodzimy do menu glownego<br />                                                    // jednak zanim wyjdziemy to nalezy pamietac o zapisaniu opcji<br />            eeprom_write_block (&amp;ustawienia, &amp;ee_ustawienia, sizeof(ustawienia));<br />        }<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// funkcja odpowiedzialna za narysowanie zegarka ze<br />// znacznikami w drugim wierszu LCD<br />// pozycja - okresla co zmieniamy 0 - godziny, 1 - minuty, 2 - sekundy<br />// akt_czas - podajemy czas jaki ma byc na wyswietlaczu<br />// wyswietlaj_sekundy - czy wyświetlac sekundy na LCD<br />//<br />// na wyświetlaczu otrzymamy coś takiego &gt;gg&lt;: mm : ss<br />// znaczniki &gt; &lt; wędrują sobie po lcd w zalezności od parametru pozycja<br />//----------------------------------------------------------<br />void menu_disp_czas (uint8_t pozycja, CZAS akt_czas, uint8_t wyswietlaj_sekundy)<br />{<br />    if (pozycja == 0)               // ustawiamy godzine<br />    {                               // i ladnie rysujemy &gt;hh&lt;: mm : ss<br />        lcd_locate(1,0);<br />        lcd_char ('&gt;');<br />        if (akt_czas.godz &lt; 10)<br />        {<br />            lcd_char ('0');<br />        }<br />        lcd_int (akt_czas.godz);<br /><br />        lcd_str (&quot;&lt;: &quot;);<br />        if (akt_czas.min &lt; 10)<br />        {<br />            lcd_char ('0');<br />        }<br />        lcd_int (akt_czas.min);<br /><br />        if (wyswietlaj_sekundy)<br />        {<br />            lcd_str (&quot; : &quot;);<br />            if (akt_czas.sek &lt; 10)<br />            {<br />                lcd_char ('0');<br />            }<br />            lcd_int (akt_czas.sek);<br />            lcd_char (' ');<br />        }<br />    }<br /><br />    if (pozycja == 1)               // ustawiamy minuty<br />    {                               // i ladnie rysujemy hh :&gt;mm&lt;: ss<br />        lcd_locate(1,0);<br />        lcd_char (' ');<br />        if (akt_czas.godz &lt; 10)<br />        {<br />            lcd_char ('0');<br />        }<br />        lcd_int (akt_czas.godz);<br />        lcd_str (&quot; :&gt;&quot;);<br />        if (akt_czas.min &lt; 10)<br />        {<br />            lcd_char ('0');<br />        }<br />        lcd_int (akt_czas.min);<br />        lcd_str (&quot;&lt;&quot;);<br /><br />        if (wyswietlaj_sekundy)<br />        {<br />            lcd_str (&quot;: &quot;);<br />            if (akt_czas.sek &lt; 10)<br />            {<br />                lcd_char ('0');<br />            }<br />            lcd_int (akt_czas.sek);<br />            lcd_char (' ');<br />        }<br />    }<br /><br />    if ((pozycja == 2) &amp;&amp; wyswietlaj_sekundy)   // ustawiamy sekundy<br />    {                                           // i ladnie rysujemy hh : mm :&gt;ss&lt;<br />        lcd_locate(1,0);<br />        lcd_char (' ');<br />        if (akt_czas.godz &lt; 10)<br />        {<br />            lcd_char ('0');<br />        }<br />        lcd_int (akt_czas.godz);<br />        lcd_str (&quot; : &quot;);<br />        if (akt_czas.min &lt; 10)<br />        {<br />            lcd_char ('0');<br />        }<br />        lcd_int (akt_czas.min);<br />        lcd_str (&quot; :&gt;&quot;);<br />        if (akt_czas.sek &lt; 10)<br />        {<br />            lcd_char ('0');<br />        }<br />        lcd_int (akt_czas.sek);<br />        lcd_char ('&lt;');<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// funkcja odpowiedzialna za obsluge 2 pozycji menu<br />// USTAW CZAS - tu chodzi o zegarek<br />//----------------------------------------------------------<br />void menu_func_02 ()<br />{<br />    uint8_t in_function = 1;<br />    uint8_t pozycja = 0;        // określamy czy ustawiamy godzine = 0, minuty = 1, sekundy = 2<br />    uint8_t bufor&#91;4&#93;;           // zmienna pozmocnicza przy odczycie czasu z PCFa<br /><br />    CZAS czas_ustawiany;        // czas jaki mamy ustawic :-)<br /><br />    TWI_read_buf( PCF8583_ADDR, 0x01, 4, bufor );  // odczytujemy czas<br /><br />    czas_ustawiany.sek = bcd2dec( bufor&#91;1&#93; );<br />    czas_ustawiany.min = bcd2dec( bufor&#91;2&#93; );<br />    czas_ustawiany.godz = bcd2dec( bufor&#91;3&#93; );<br /><br />    menu_disp_czas (pozycja, czas_ustawiany, 1);    // druga linia z ustawieniami czasu<br /><br />    while (in_function)                             // jestesmy w funkcji tak dlugo dopóki nie ustawimy czasu<br />    {<br />        if (klawisz_wcisniety (KEY1_PIN))           // wcisniety klawisz KEY 1 - zmniejszamy wartosci<br />        {<br />            if (pozycja == 0)                       // zmniejszamy godziny<br />            {<br />                if (czas_ustawiany.godz == 0)<br />                {<br />                    czas_ustawiany.godz = 23;<br />                }<br />                else<br />                {<br />                    czas_ustawiany.godz = czas_ustawiany.godz - 1;<br />                }<br />            }<br /><br />            if (pozycja == 1)                       // zmniejszamy minuty<br />            {<br />                if (czas_ustawiany.min == 0)<br />                {<br />                    czas_ustawiany.min = 59;<br />                }<br />                else<br />                {<br />                    czas_ustawiany.min = czas_ustawiany.min - 1;<br />                }<br />            }<br /><br />            if (pozycja == 2)                       // zmniejszamy sekundy<br />            {<br />                if (czas_ustawiany.sek == 0)<br />                {<br />                    czas_ustawiany.sek = 59;<br />                }<br />                else<br />                {<br />                    czas_ustawiany.sek = czas_ustawiany.sek - 1;<br />                }<br />            }<br /><br />            menu_disp_czas (pozycja, czas_ustawiany, 1);    // i na koniec wyswietlamy czas<br />        }<br /><br /><br />        if (klawisz_wcisniety (KEY2_PIN))           // wcisniety klawisz KEY2 - zwiekszamy wartosci<br />        {<br />            if (pozycja == 0)                       // zwiekszamy godziny<br />            {<br />                if (czas_ustawiany.godz == 23)<br />                {<br />                    czas_ustawiany.godz = 0;<br />                }<br />                else<br />                {<br />                    czas_ustawiany.godz = czas_ustawiany.godz + 1;<br />                }<br />            }<br /><br />            if (pozycja == 1)                       // zwiekszamy minuty<br />            {<br />                if (czas_ustawiany.min == 59)<br />                {<br />                    czas_ustawiany.min = 0;<br />                }<br />                else<br />                {<br />                    czas_ustawiany.min = czas_ustawiany.min + 1;<br />                }<br />            }<br /><br />            if (pozycja == 2)                       // zwiekszamy sekundy<br />            {<br />                if (czas_ustawiany.sek == 59)<br />                {<br />                    czas_ustawiany.sek = 0;<br />                }<br />                else<br />                {<br />                    czas_ustawiany.sek = czas_ustawiany.sek + 1;<br />                }<br />            }<br />            menu_disp_czas (pozycja, czas_ustawiany, 1);        // i wyswietlamy ustawiony czas<br />        }<br /><br />        if (klawisz_wcisniety (KEY3_PIN))               // wcisniety klawysz KEY 3 - (enter)<br />        {<br />            pozycja = pozycja + 1;                      // zwiekszamy pozycje<br />                                                        // czyli pozycja = 0 - ustawiamy godzine<br />                                                        //       pozycja = 1 - ustawiamy minuty<br />                                                        //       pozycja = 3 - ustawiamy sekundy<br />            menu_disp_czas (pozycja, czas_ustawiany, 1);        // wyswietlamy ustawienia czasu<br /><br />            if (pozycja &gt; 2)                                // jezeli ustawimy w zmiennej pozycja 0, 1, 2<br />            {                                               // to po nastepnym nacisnieciu klawisza mozemy zapisac dane do EPROM<br />                bufor&#91;0&#93; = 0;                               // setne części sekundy<br />                bufor&#91;1&#93; = dec2bcd(czas_ustawiany.sek);     // sekundy<br />                bufor&#91;2&#93; = dec2bcd(czas_ustawiany.min);     // minuty<br />                bufor&#91;3&#93; = dec2bcd(czas_ustawiany.godz);    // godziny<br />                // zapis 4 bajtów z bufora pod adres 0x01 w pamięci RAM naszego RTC<br />                TWI_write_buf( PCF8583_ADDR, 0x01, 4, bufor );<br /><br />                in_function = 0; // i mozemy zakonczyc prace funkcji<br />            }<br />        }<br />    }<br />}<br /><br />//---------------------------------------------------------<br />// funkcja odpowiedzialna na narysowanie drugiej linii<br />// na wyświetlaczu w menu wygaszacza<br />//---------------------------------------------------------<br />void menu_disp_03 (uint8_t czas)<br />{<br />    lcd_locate(1,0);<br />    lcd_str (&quot;CZAS &#91;s&#93;: &quot;);<br />    lcd_char ('&gt;');<br />    if (czas &lt; 100)<br />    {<br />        lcd_char ('0');<br />    }<br />    if (czas &lt; 10)<br />    {<br />        lcd_char ('0');<br />    }<br />    lcd_int (czas);<br />    lcd_str (&quot;&lt; &quot;);<br />}<br /><br /><br />//----------------------------------------------------------<br />// funkcja odpowiedzialna za obsluge 3 pozycji menu<br />// ustawienie czasu wygaszacza<br />// czas do ustawienia<br />// od 0 - wyłączony wygaszacz<br />// do 180 sekund z krokiem co 10s<br />//----------------------------------------------------------<br />void menu_func_03 ()<br />{<br />    uint8_t in_function = 1;<br /><br />    menu_disp_03 (ustawienia.czas_wygaszacza);  // wyswietlamy 2 linie na lcd<br />    while (in_function)<br />    {<br />        if (klawisz_wcisniety (KEY1_PIN))       // zmniejszamy czas o 10 s<br />        {<br />            if (ustawienia.czas_wygaszacza &lt; 10)<br />            {<br />                ustawienia.czas_wygaszacza = 0;<br />            }<br />            else<br />            {<br />                ustawienia.czas_wygaszacza = ustawienia.czas_wygaszacza - 10;<br />            }<br />            menu_disp_03 (ustawienia.czas_wygaszacza);<br />        }<br /><br />        if (klawisz_wcisniety (KEY2_PIN))       // zwiekszamy czas o 10 s<br />        {<br />            if (ustawienia.czas_wygaszacza &gt;= 180)<br />            {<br />                ustawienia.czas_wygaszacza = 180;<br />            }<br />            else<br />            {<br />                ustawienia.czas_wygaszacza = ustawienia.czas_wygaszacza + 10;<br />            }<br />            menu_disp_03 (ustawienia.czas_wygaszacza);<br />        }<br /><br />        if (klawisz_wcisniety (KEY3_PIN))       // kończymy pracę w tym menu<br />        {                                       // i zapisujemy ustawienia w eeprom<br />            in_function = 0;<br />            eeprom_write_block (&amp;ustawienia, &amp;ee_ustawienia, sizeof(ustawienia));<br />        }<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// funkcja odpowiedzialna za obsluge 4 pozycji menu<br />// KONIEC<br />//----------------------------------------------------------<br />void menu_func_04 ()<br />{<br />    item = 0;           // zerujemy pozycje w menu aby przy nastepnym wywolaniu<br />                        // menu uruchomilo sie od poczatku<br />    jestem_w_menu = 0;  // opuszczamu menu<br />    lcd_cls ();         // czyscimy po sobie ekran<br />}<br /><br /><br />//----------------------------------------------------------<br />// obsluga menu do wyboru czujnika temperatury zewnętrznej<br />//----------------------------------------------------------<br />void menu_func_tz ()<br />{<br />    uint8_t in_function = 1;<br />    uint8_t nr_sensora = 0;<br />    uint8_t ii;<br /><br />    if (czujniki_cnt)<br />    {<br />        menu_disp_sensor (gSensorIDs&#91;nr_sensora&#93;);<br />    }<br />    else<br />    {<br />        lcd_locate (1,0);<br />        lcd_str (&quot;BRAK CZUJNIKOW&quot;);<br />    }<br /><br />    while (in_function)<br />    {<br />        if (klawisz_wcisniety (KEY1_PIN))<br />        {<br />            if (nr_sensora &lt;= 0)<br />            {<br />                nr_sensora = 0;<br />            }<br />            else<br />            {<br />                nr_sensora = nr_sensora - 1;<br />            }<br />            menu_disp_sensor (gSensorIDs&#91;nr_sensora&#93;);<br />        }<br /><br />        if (klawisz_wcisniety (KEY2_PIN))<br />        {<br />            if (nr_sensora &lt; (czujniki_cnt-1))<br />            {<br />                nr_sensora = nr_sensora + 1;<br />            }<br />            else<br />            {<br />                nr_sensora = czujniki_cnt-1;<br />            }<br />            menu_disp_sensor (gSensorIDs&#91;nr_sensora&#93;);<br />        }<br /><br />        if (klawisz_wcisniety (KEY3_PIN))       // kończymy pracę w tym menu<br />        {                                       // i zapisujemy ustawienia w eeprom<br />            in_function = 0;<br /><br />            if (czujniki_cnt)<br />            {<br />                for (ii=0; ii&lt;8; ii++)<br />                    ustawienia.tz_sensor&#91;ii&#93; = gSensorIDs&#91;nr_sensora&#93;&#91;ii&#93;;<br /><br />                eeprom_write_block (&amp;ustawienia, &amp;ee_ustawienia, sizeof(ustawienia));<br />            }<br />        }<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// obsluga menu do wyboru czujnika temperatury wewnętrznej<br />//----------------------------------------------------------<br />void menu_func_tw ()<br />{<br />    uint8_t in_function = 1;<br />    uint8_t nr_sensora = 0;<br />    uint8_t ii;<br /><br />    if (czujniki_cnt)<br />    {<br />        menu_disp_sensor (gSensorIDs&#91;nr_sensora&#93;);<br />    }<br />    else<br />    {<br />        lcd_locate (1,0);<br />        lcd_str (&quot;BRAK CZUJNIKOW&quot;);<br />    }<br /><br />    while (in_function)<br />    {<br />        if (klawisz_wcisniety (KEY1_PIN))<br />        {<br />            if (nr_sensora &lt;= 0)<br />            {<br />                nr_sensora = 0;<br />            }<br />            else<br />            {<br />                nr_sensora = nr_sensora - 1;<br />            }<br />            menu_disp_sensor (gSensorIDs&#91;nr_sensora&#93;);<br />        }<br /><br />        if (klawisz_wcisniety (KEY2_PIN))<br />        {<br />            if (nr_sensora &lt; (czujniki_cnt-1))<br />            {<br />                nr_sensora = nr_sensora + 1;<br />            }<br />            else<br />            {<br />                nr_sensora = czujniki_cnt-1;<br />            }<br />            menu_disp_sensor (gSensorIDs&#91;nr_sensora&#93;);<br />        }<br /><br />        if (klawisz_wcisniety (KEY3_PIN))       // kończymy pracę w tym menu<br />        {                                       // i zapisujemy ustawienia w eeprom<br />            in_function = 0;<br /><br />            if (czujniki_cnt)<br />            {<br />                for (ii=0; ii&lt;8; ii++)<br />                    ustawienia.tw_sensor&#91;ii&#93; = gSensorIDs&#91;nr_sensora&#93;&#91;ii&#93;;<br /><br />                eeprom_write_block (&amp;ustawienia, &amp;ee_ustawienia, sizeof(ustawienia));<br />            }<br />        }<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// UAKTYWNIENIE BUDZIKA w menu<br />// wybieramy TAK - budzik działa<br />//           NIE - budzik nie działa<br />//--------------------------------------------------------<br />void menu_func_budzik_akt ()<br />{<br />    uint8_t in_function = 1;        // ustawiamy flagę in_function<br />                                    // okresla nam czy znajdujemy sie w funkcji do obslugi<br />                                    // wybranej wczesniej pozycji menu<br /><br />    menu_disp_tak_nie (ustawienia.jest_budzik); // w drugiej linii wypisujemy opcje menu (TAK/NIE)<br /><br />    while (in_function)             // petla dziala dopóki nie zatwierdzimy wybory w opcji menu<br />    {<br />        if (klawisz_wcisniety (KEY1_PIN))   //  KEY1 zmienia stan opcji menu na przeciwny<br />        {<br />            if (!ustawienia.jest_budzik)<br />            {<br />                ustawienia.jest_budzik = 1;<br />            }<br />            else<br />            {<br />                ustawienia.jest_budzik = 0;<br />            }<br />            menu_disp_tak_nie (ustawienia.jest_budzik); // ponownie rysujemy menu ze zmieniona opcją<br />        }<br /><br />        if (klawisz_wcisniety (KEY2_PIN))               // tym  razem dla klawisza KEY2 zmieniamy<br />        {                                               // stan opcji menu na przeciwny<br />            if (!ustawienia.jest_budzik)<br />            {<br />                ustawienia.jest_budzik = 1;<br />            }<br />            else<br />            {<br />                ustawienia.jest_budzik = 0;<br />            }<br />            menu_disp_tak_nie (ustawienia.jest_budzik); // ponownie rysujemy menu ze zmieniona opcją<br />        }<br /><br />        if (klawisz_wcisniety (KEY3_PIN))               // klawiszem KEY3 - zatwierdzamy wybrana opcje<br />        {<br />            in_function = 0;                            // i wychodzimy do menu glownego<br />                                                        // jednak zanim wyjdziemy to nalezy pamietac o zapisaniu opcji<br />            eeprom_write_block (&amp;ustawienia, &amp;ee_ustawienia, sizeof(ustawienia));<br />        }<br />    }<br />}<br /><br /><br /><br />//----------------------------------------------------------<br />// funkcja odpowiedzialna za obsluge 2 pozycji menu<br />// USTAW CZAS<br />//----------------------------------------------------------<br />void menu_func_ustaw_budzik ()<br />{<br />    uint8_t in_function = 1;<br />    uint8_t pozycja = 0;        // określamy czy ustawiamy godzine = 0, minuty = 1, sekundy = 2<br /><br /><br />    menu_disp_czas (pozycja, ustawienia.budzik_godz, 0);            // i druga linie z ustawieniami czasu<br /><br />    while (in_function)                                             // jestesmy w funkcji tak dlugo dopóki nie ustawimy czasu<br />    {<br />        if (klawisz_wcisniety (KEY1_PIN))                           // wcisniety klawisz KEY 1 - zmniejszamy wartosci<br />        {<br />            if (pozycja == 0)                                       // zmniejszamy godziny<br />            {<br />                if (ustawienia.budzik_godz.godz == 0)<br />                {<br />                    ustawienia.budzik_godz.godz = 23;<br />                }<br />                else<br />                {<br />                    ustawienia.budzik_godz.godz = ustawienia.budzik_godz.godz - 1;<br />                }<br />            }<br /><br />            if (pozycja == 1)                                       // zmniejszamy minuty<br />            {<br />                if (ustawienia.budzik_godz.min == 0)<br />                {<br />                    ustawienia.budzik_godz.min = 59;<br />                }<br />                else<br />                {<br />                    ustawienia.budzik_godz.min = ustawienia.budzik_godz.min - 1;<br />                }<br />            }<br /><br />            menu_disp_czas (pozycja, ustawienia.budzik_godz, 0);    // i na koniec wyswietlamy czas<br />        }<br /><br /><br />        if (klawisz_wcisniety (KEY2_PIN))                           // wcisniety klawisz KEY2 - zwiekszamy wartosci<br />        {<br />            if (pozycja == 0)                                       // zwiekszamy godziny<br />            {<br />                if (ustawienia.budzik_godz.godz == 23)<br />                {<br />                    ustawienia.budzik_godz.godz = 0;<br />                }<br />                else<br />                {<br />                    ustawienia.budzik_godz.godz = ustawienia.budzik_godz.godz + 1;<br />                }<br />            }<br /><br />            if (pozycja == 1)                                       // zwiekszamy minuty<br />            {<br />                if (ustawienia.budzik_godz.min == 59)<br />                {<br />                    ustawienia.budzik_godz.min = 0;<br />                }<br />                else<br />                {<br />                    ustawienia.budzik_godz.min = ustawienia.budzik_godz.min + 1;<br />                }<br />            }<br /><br />            menu_disp_czas (pozycja, ustawienia.budzik_godz, 0);    // i wyswietlamy ustawiony czas<br />        }<br /><br />        if (klawisz_wcisniety (KEY3_PIN))                           // wcisniety klawysz KEY 3 - (enter)<br />        {<br />            pozycja = pozycja + 1;                                  // zwiekszamy pozycje<br />                                                                    // czyli pozycja = 0 - ustawiamy godzine<br />                                                                    //       pozycja = 1 - ustawiamy minuty<br /><br />            ustawienia.budzik_godz.sek = 0;                         // sekundy budzika ustawiamy na 0<br />            menu_disp_czas (pozycja, ustawienia.budzik_godz, 0);    // wyswietlamy ustawienia czasu<br /><br />            if (pozycja &gt; 1)                                        // jezeli ustawimy w zmiennej pozycja 0, 1, 2<br />            {                                                       // to po nastepnym nacisnieciu klawisza mozemy zapisac dane do EPROM<br />                eeprom_write_block (&amp;ustawienia, &amp;ee_ustawienia, sizeof(ustawienia));<br />                in_function = 0;                                    // i mozemy zakonczyc prace funkcji<br />            }<br />        }<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// wyświetlanie ID czujnika temperatury w hex<br />// bez zer wiodących jeżeli liczba &lt; 16<br />//----------------------------------------------------------<br />void menu_disp_sensor (uint8_t poz&#91;&#93;)<br />{<br />    uint8_t i;<br />    char string&#91;3&#93;;<br /><br />    lcd_locate (1, 0);<br />    lcd_str (&quot;                &quot;);<br />    lcd_locate (1, 0);<br />    for (i=0; i&lt;8; i++)<br />    {<br />        itoa(poz&#91;i&#93;, string, 16);<br />        lcd_str (string);<br />    }<br />}<br /><br /><br />//----------------------------------------------------------<br />// wyświetlanie temperatury na pozycji Y,X na LCD<br />//----------------------------------------------------------<br />void display_temp(uint8_t y, uint8_t x)<br />{<br />    lcd_locate(y,x);<br />    if(subzero) lcd_str(&quot;-&quot;);   // jeśli (temp. ujemna) to wyświetl '-'<br />    else lcd_str(&quot;+&quot;);          // jeśli (temp. dodatnia) to wyświetl '+'<br />    lcd_int(cel);               // wyświetl dziesiętne części temperatury<br />    lcd_str(&quot;.&quot;);               // wyświetl kropkę<br />    lcd_int(cel_fract_bits);    // wyświetl dziesiętne części stopnia<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=10579">Jarcio</a> — 9 wrz 2015, o 22:57</p><hr />
]]></content>
</entry>
</feed>