<?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=22411&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2019-07-17T16:59:10+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=22411&amp;mode</id>
<entry>
<author><name><![CDATA[MarKl]]></name></author>
<updated>2019-07-17T16:59:10+01:00</updated>
<published>2019-07-17T16:59:10+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220446#p220446</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220446#p220446"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220446#p220446"><![CDATA[
Ok, dzięki.<br /><br />Tak, nie wiesza się. Specjalnie nawet zapchałem główna pętlę delayami, zapisami do RTC, całość około 2 sekundy - i co tyle się odświeża, więc flaga działa.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=20777">MarKl</a> — 17 lip 2019, o 16:59</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Adam12]]></name></author>
<updated>2019-07-16T19:05:51+01:00</updated>
<published>2019-07-16T19:05:51+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220425#p220425</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220425#p220425"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220425#p220425"><![CDATA[
Właśnie to chciałem napisać, że podciągnięcie tylko wejścia uC jest poprawne i jest wystarczające.<br /><br />To, że działa z flagą to znaczy, że już się nie wiesza?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=16417">Adam12</a> — 16 lip 2019, o 19:05</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[MarKl]]></name></author>
<updated>2019-07-16T18:10:48+01:00</updated>
<published>2019-07-16T18:10:48+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220422#p220422</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220422#p220422"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220422#p220422"><![CDATA[
Czyli tak jak myślałem - bździna. Już nadrobiłem rozdział o volatile w niebieskiej książce.<br /><br />Działa z volatile uint8_t flaga_tmp, jak i dla volatile TFLAGS flagi1. Odświeża też czas.<br /><br />Z tym komplikowaniem to zgodzę się i nie. Funkcje, definicje, deklaracje itp. stopniowo przerzucałem z main.c do innych plików, za każdym razem sprawdzając, czy program się skompiluje i czy wciąż działa tak jak wcześniej. Jak już wszystko przeniosłem, to chciałem dodać obsługę flagi. No i tu był chyba błąd, bo zamiast w main.c to od razu tworzyłem w funkcje.h i funkcje.c. Później jak obsługa flagi w głównej pętli nie działała, to pierwsze co wywaliłem to właśnie obsługa rtc i lcd, później zamiast struktury flag utworzyłem jedną zmienną tymczasową, a na końcu dodałem diodę.<br />Pozostałe rady co do kodu - dzięki za rady, przydadzą się na pewno.<br /><br />Może wyposażę się w ten analizator - na moje potrzeby lepszy od oscyloskopu cyfrowego - tańszy a bardziej przydatny.<br /><br />Chyba się nie zrozumieliśmy z podciągnięciem przerwania. Wnioskuję, że Ty piszesz o DS3231, bo tam jest na pierwszej stronie ten schemat.<br />Przerwanie INT/SQW z DS3231 mam podciągnięte przez rezystor do 5V. Moje pytanie dotyczy podciągania programowego wejścia PD2/INT0 Atmegi32A (przerwanie na zbocze narastające). Teraz przyszło mi na myśl jeszcze jedno pytanie - czy gdybym podciągnął tylko wejście uC, to wyjścia RTC nie muszę w sumie już podciągać, prawda?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=20777">MarKl</a> — 16 lip 2019, o 18:10</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Adam12]]></name></author>
<updated>2019-07-16T17:30:41+01:00</updated>
<published>2019-07-16T17:30:41+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220421#p220421</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220421#p220421"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220421#p220421"><![CDATA[
Może tak: <br />volatile uint8_t flaga_tmp;<br /><br />Masz talent do komplikowania sobie życia w momencie kiedy trzeba wszystko uprościć żeby znaleźć źródło problemu. Jeśli dalej program będzie się zawieszał, nie twórz nowych plików tylko przeciwnie to z czym jest problem wrzuć do main.c czyli główną pętlę, obsługę przerwania, podstawowe inicjalizacje i funkcję odczytu daty_czasu. Potem jeśli dalej nie działa wywal np. wszystko związane z LCD itd. Taki okrojony kod łatwiej będzie też komuś analizować na forum.<br /><br />Poza tym polecam zakup analizatora stanów logicznych. Sam szybko znalazłbyś odpowiedź na pytanie o konflikt zapis-odczyt generując jakieś zakłócające przerwanie i podglądając co się dzieje na liniach TWI.<br /><br />Co do podciągnięcia INT0 - zajrzałem do noty i na pierwszej stronie jest jak byk schemat z rezystorem podciągającym więc podciągnięcie programowe jest ok.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=16417">Adam12</a> — 16 lip 2019, o 17:30</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[MarKl]]></name></author>
<updated>2019-07-16T15:34:24+01:00</updated>
<published>2019-07-16T15:34:24+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220419#p220419</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220419#p220419"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220419#p220419"><![CDATA[
Mam problem z tą flagą.<br /><br />Wszystkie funkcje, jakie sobie tworzę, przerzuciłem do zewnętrznego pliku źródłowego funkcje_do_programu.c. (dalej będę to nazywał funkcje.c)<br />Spodziewam się, że będę potrzebował dużo flag, więc w pliku nagłówkowym funkcje_do_programu.h zdefiniowałem typ TFLAGS z 8 jednobitowymi flagami (jak będzie rzeczywiście dużo, to zmienię sobie tylko rozmiar &quot;typu&quot;). Jako że flag zamierzam używać w funkcje.c i main.c, w nagłówku zdeklarowałem od razu zmienną flagi1 typu TFLAGS.<br /><br />W funkcje.c mam obsługę przerwania do obsługi SQW, o którym pisałem w pierwszym poście - oznacz flagę, a dla debugowania przełącz diodę (dioda się przełącza).<br />W pętli głównej w main.c mam prostego if'a, który przy oznaczeniu flagi ma (narazie) wyzerować ją i przełączyć inną diodę - i tutaj już dioda się nie przełącza. Kombinowałem różnymi sposobami, fladze przypisywałem (i sprawdzałem) wartości dziesiętne i szesnastkowe. Utworzyłem tymczasową zmienną uint8_t która miała być tymczasową flagą, kombinowałem z deklaracją jej jako extern - nic nie pomogło.<br /><br />Wrzucam fragmenty kodów, jak na obecną chwilę wygląda program, flaga tymczasowa jest zakomentowana.<br /><br />Tak jak wcześniej, byłbym wdzięczny za wskazanie, pod jakim hasłem szukać jakiś materiałów na ten temat, albo jeśli rozwiązanie jest trywialne - to o podanie go (obstawiam pomieszanie widoczności zmiennych albo inną bździnę). Poza tym, pytania o ten konflikt zapis-odczyt i o podciągnięcie z poprzedniego wpisu nadal aktualne <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />Main.c:<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;util/delay.h&gt;<br />//#include &lt;avr/pgmspace.h&gt;<br />//#include &lt;avr/eeprom.h&gt;<br /><br />#include &quot;I2C_TWI/i2c_twi.h&quot;<br />#include &quot;DS3231/DS3231.h&quot;<br />#include &quot;HD44780/hd44780.h&quot;<br />#include &quot;funkcje_do_programu/funkcje_do_programu.h&quot;<br />//#include &quot;LCD/lcd.h&quot;<br /><br /><br />int main (void)<br />{<br />DDRD |= (1&lt;&lt;PD0) | (1&lt;&lt;PD1);<br />PORTD &amp;= !((1&lt;&lt;PD0) | (1&lt;&lt;PD1));<br /><br />//konfiguracja przerwania INT0<br />DS3231_uC_interruptInit();<br /><br />LCD_init();<br /><br />TWI_setBitrate_kHz(50);<br />DS3231_init();<br /><br />LCD_str(&quot;Hello world!&quot;);<br />for(uint8_t i = 0; i &lt; 4; i++)_delay_ms(250);// wstrzymanie na 2 sekundy<br /><br />sei();<br /><br /><br />while(1)<br />{<br />if(FLAG_getDateTime==0x01)<br />//if(flaga_tmp == 1)<br />{<br /><br />//DS3231_getDatetime(&amp;datetime);<br />//LCD_locate(0, 0);<br />//showDate(&amp;datetime);<br />//LCD_locate(1, 0);<br />//showTime(&amp;datetime);<br />//FLAG_getDateTime = 0x00;<br />flaga_tmp = 0;<br />PORTD ^= (1&lt;&lt;PD0);<br />}<br /><br />}<br /><br />return 0;<br />}[/syntax]<br /><br />funkcje_do_programu nagłówek:<br />[syntax=c]#ifndef FUNKCJE_DO_PROGRAMU_FUNKCJE_DO_PROGRAMU_H_<br />#define FUNKCJE_DO_PROGRAMU_FUNKCJE_DO_PROGRAMU_H_<br /><br />#define ON1<br />#define OFF0<br /><br />#define FLAG_getDateTimeflagi1.flaga1<br /><br />extern uint8_t flaga_tmp;<br /><br /><br />typedef struct<br />{<br />uint8_t flaga1:1;<br />uint8_t flaga2:1;<br />uint8_t flaga3:1;<br />uint8_t flaga4:1;<br />uint8_t flaga5:1;<br />uint8_t flaga6:1;<br />uint8_t flaga7:1;<br />uint8_t flaga8:1;<br />}TFLAGS;<br /><br />TDATETIME datetime;<br />char days&#91;7&#93;&#91;4&#93;;<br />TFLAGS flagi1;<br /><br /><br />ISR (_MERGE(INT, DS3231_INT_NUM, _vect));<br />ISR (BADISR_vect);<br /><br />void showTime(TDATETIME * dt);<br />void showDate(TDATETIME * dt);<br /><br />#endif /* FUNKCJE_DO_PROGRAMU_FUNKCJE_DO_PROGRAMU_H_ */[/syntax]<br /><br />..i plik źródłowy:<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;util/delay.h&gt;<br /><br />#include &quot;../DS3231/DS3231.h&quot;<br />#include &quot;../HD44780/hd44780.h&quot;<br />#include &quot;funkcje_do_programu.h&quot;<br /><br />char days&#91;7&#93;&#91;4&#93; = { &quot;Pon&quot;, &quot;Wt &quot;, &quot;Sr &quot;, &quot;Czw&quot;, &quot;Pt &quot;, &quot;Sob&quot;, &quot;Nie&quot; };<br /><br />uint8_t flaga_tmp;<br /><br />ISR (BADISR_vect) {}// obsluga nieuzywanych przerwan<br /><br />ISR (_MERGE(INT, DS3231_INT_NUM, _vect))<br />{<br />FLAG_getDateTime = 0x01;<br />//flaga_tmp = 1;<br />PORTD ^= (1&lt;&lt;PD1);<br />}<br /><br />//pokazuje czas w formacie hh:mm:ss<br />void showTime(TDATETIME * dt)<br />{<br />if (dt-&gt;hh &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;hh);<br />LCD_str(&quot;:&quot;);<br />if (dt-&gt;mm &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;mm);<br />LCD_str(&quot;:&quot;);<br />if (dt-&gt;ss &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;ss);<br />}<br /><br />//pokazuje datę w formacie dd.mm.rr   dow<br />void showDate(TDATETIME * dt)<br />{<br />if(dt-&gt;day &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;day);<br />LCD_str(&quot;.&quot;);<br />if(dt-&gt;month &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;month);<br />LCD_str(&quot;.&quot;);<br />if(dt-&gt;year &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;year);<br />LCD_str(&quot;   &quot;);<br />LCD_str(days&#91;dt-&gt;day_of_week - 1&#93;);<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=20777">MarKl</a> — 16 lip 2019, o 15:34</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[MarKl]]></name></author>
<updated>2019-07-15T19:23:38+01:00</updated>
<published>2019-07-15T19:23:38+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220412#p220412</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220412#p220412"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220412#p220412"><![CDATA[
<div class="quotetitle">Adam12 napisał(a):</div><div class="quotecontent"><br />Czy ja dobrze widzę, że w obsłudze przerwania masz całe wyświetlanie na LCD?? To są bardzo długotrwałe operacje. Przede wszystkim wywal to z przerwania. W przerwaniu najlepiej ustawiaj tylko jakąś flagę, a odczyt daty, czasu i wyświetlanie na LCD załatwiaj w głównej pętli.<br /></div><br /><br />O kurcze, rzeczywiście... Nie wpadłem na to <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" /> Dzięki <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br />Źródła problemu szukałem w funkcjach do komunikacji TWI albo w tych do DS3231. Na szybko zrobiłem, zostawiając tylko odczyt (potem go wrzucę do głównej pętli) i przełączanie diody - działa.<br /><br />Ale jak już poruszyłem temat, to gdybym teoretycznie miał dużą ilość danych do wysłania po TWI, a ponadto miał jakieś przerwanie, którego obsługa byłaby absolutnie priorytetowa, zajmowała chwilę (nie tak długą jak ten LCD, ale jednak znaczną) i nie mogła być wykonana przez flagę - w jakim kierunku powinna iść implementacja tego?<br /><br />Edit:<br />Poza tym, czy jeżeli przerwanie INT0 jest na zbocze narastające, to poprawnym jest podciągnięcie tego pinu? Teraz działa, ale nie jestem pewny poprawności i bezawaryjności tego<br /><br />Edit 2:<br />Nawet funkcja odczytania czasu w przerwaniu zawiesza program (implementacja flagi w drodze)<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=20777">MarKl</a> — 15 lip 2019, o 19:23</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2019-07-15T18:30:01+01:00</updated>
<published>2019-07-15T18:30:01+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220411#p220411</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220411#p220411"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220411#p220411"><![CDATA[
<div class="quotetitle">Adam12 napisał(a):</div><div class="quotecontent"><br />Przede wszystkim wywal to z przerwania.<br /></div><br />Ło Matko, kolega ma sokole oko !.... bardzo słuszna uwaga<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 15 lip 2019, o 18:30</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Adam12]]></name></author>
<updated>2019-07-15T17:32:53+01:00</updated>
<published>2019-07-15T17:32:53+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220400#p220400</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220400#p220400"/>
<title type="html"><![CDATA[Re: AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220400#p220400"><![CDATA[
Czy ja dobrze widzę, że w obsłudze przerwania masz całe wyświetlanie na LCD?? To są bardzo długotrwałe operacje. Przede wszystkim wywal to z przerwania. W przerwaniu najlepiej ustawiaj tylko jakąś flagę, a odczyt daty, czasu i wyświetlanie na LCD załatwiaj w głównej pętli.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=16417">Adam12</a> — 15 lip 2019, o 17:32</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[MarKl]]></name></author>
<updated>2019-07-15T14:52:30+01:00</updated>
<published>2019-07-15T14:52:30+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220398#p220398</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220398#p220398"/>
<title type="html"><![CDATA[AVR TWI - konfilkt zapisu-odczytu]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=22411&amp;p=220398#p220398"><![CDATA[
Witam wszystkich!<br /><br />Jest to mój pierwszy post na tym forum, gdybym coś nie po kolei zrobił - proszę o zrozumienie i poprawienie <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br /><br />Pracuję nad małym projektem sterowania oświetleniem w zależności od dnia miesiąca, godziny, oszczędnie z energią na ile się da. Sam projekt na razie nie jest tu ważny.<br /><br />Do tego projektu używam Atmegi32A (wbudowany oscylator RC 1MHz), LCD HD47780 i RTC DS3231 (ostatnie dwa kupione kilka lat temu w chińskim sklepie). To wszystko mam połączone na zestawie uruchomieniowym ZL3AVR, a jak coś trzeba to obok na płytce stykowej.<br />Biblioteki (lcd, twi) pisałem w oparciu o niebieską książkę Pana Mirka, a początek biblioteki do RTC na podstawie jego filmu, czyli:<br />- LCD jest sterowane w trybie czterech pinów, bez obsługi pinu RW<br />- DS3231 jest przez TWI (50kHz).<br /><br />Do wykrywania impulsu 1Hz używam na razie przerwania INT0 na zbocze rosnące, podciągnięte, z obsługą sprzętową, nie programową w pętli while. Sygnał z DS'a też jest podciągnięty do VCC.<br />Z rtc będę potrzebować na pewno alarm(y) do wybudzania mikrokontrolera, ale chcę też wykorzystać generowany przez niego 1Hz, gdy będzie potrzeba wyświetlenia czasu na lcd. Napisałem więc funkcję, która włącza/wyłącza ten sygnał. Chcąc ją przetestować, w pętli while ustawiam na przemian włączenie/wyłączenie tego sygnału z przerwami _delay_ms od setek milisekund do paru sekund (przy użyciu for). I tu następuje problem - program się zawiesza.<br />Co udało mi się ustalić przy &quot;debugowaniu&quot; diodami (używam eclips'a i usbasp), to:<br />- wyłączenie programowe przerwania eliminuje zawieszenie<br />- odłączenie pinu przerwania tak samo eliminuje problem<br />(dwa powyższe sprawdziłem na oscyloskopie, sprawdzając sygnał SQW z DS3231 - pojawia się i znika według ustawień w while)<br />- zacinanie się jest losowe - w programie dodałem sobie licznik zliczający ilość przerwań od początku programu, czasami jest to pierwsze przerwanie, czasami 20, zależy od &quot;przypadku&quot; i ustawionych przerw w while (&quot;okrągłe&quot; 100, 250ms i &quot;nieokrągłe&quot; 143, 149ms).<br />- program wiesza się:<br />  1. w pętli while(!(TWCR &amp; (1&lt;&lt;TWINT))) czekającej na zapis/odczyt bajtu <br />  2. i/lub zapisie kilku bajtów funkcją TWI_writeBuf<br />  które pierwsze - 1 czy 2 - to nie wiem, ponieważ oscyloskop mam analogowy, z jedną sondą<br />- dodanie w obsłudze przerwania pętli oczekującej na zapis jak wyżej nie pomaga, program wiesza się na tym<br /><br />To na razie tyle, co udało mi się ustalić. Podejrzewam, że podczas zapisu przez TWI wypada przerwanie, które chce odczytać kiedy slave jest w trybie zapisu, lub odwrotnie, lub coś około tego. Szukałem już jakichś podobnych wątków na ten temat, również w języku angielskim, ale nie znalazłem nic pożytecznego.<br />Gdybym mógł poprosić, pod jakim hasłem szukać rozwiązania, co dodać/usunąć lub jeśli rozwiązanie jest trywialne - to o podanie go.<br /><br />Za pomoc z góry dziękuję! <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />Obsługa TWI:<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &quot;i2c_twi.h&quot;<br /><br />static inline void TWI_waitForComplete(void)<br />{<br />while(!(TWCR &amp; (1&lt;&lt;TWINT)))PORTD |= (1&lt;&lt;PD0);<br />PORTD &amp;= ~(1&lt;&lt;PD0);<br />}<br /><br />static inline void TWI_waitForStop(void)<br />{<br />while(TWCR &amp; (1&lt;&lt;TWSTO));<br />}<br /><br />/*<br /> * SCL_min = F_CPU/24<br /> * i.e. F_CPU=1MHz -&gt; SCL_min=41,(6)kHz<br /> */<br />void TWI_setBitrate_kHz(uint16_t bitrateKHz)<br />{<br />bitrateKHz = (F_CPU/bitrateKHz/1000-16) / 2;// SCL = F_CPU/(16+2(TWBR)*4^TWPS)<br />uint8_t prescaler = 0;<br />while(bitrateKHz &gt; 255)<br />{<br />prescaler++;<br />bitrateKHz /= 4;<br />}<br />TWSR = (TWSR &amp; (1&lt;&lt;TWPS1 | 1&lt;&lt;TWPS0)) | prescaler;// Bits 1:0 – TWPS: TWI Prescaler Bits<br />TWBR = bitrateKHz;// TWI Bit Rate Register<br />}<br /><br />void TWI_start(void)<br />{<br />// warunek startu<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN) | (1&lt;&lt;TWSTA);<br />// czeka na koniec transmisji<br />TWI_waitForComplete();<br />}<br /><br />void TWI_stop(void)<br />{<br />// warunek stopu<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN) | (1&lt;&lt;TWSTO);<br />//czeka na zakonczenie<br />TWI_waitForStop();<br />}<br /><br />/*<br /> * writes one byte to register<br /> */<br />void TWI_write(uint8_t byte)<br />{<br />TWDR = byte;<br />TWCR = (1&lt;&lt;TWINT) | (1&lt;&lt;TWEN);<br />TWI_waitForComplete();<br />}<br /><br />/*<br /> * reads one byte from register<br /> */<br />uint8_t TWI_read(uint8_t ack)<br />{<br />TWCR = (1&lt;&lt;TWINT) | (ack&lt;&lt;TWEA) | (1&lt;&lt;TWEN);<br />TWI_waitForComplete();<br />return TWDR;<br />}<br /><br />/*<br /> * writes a table of bytes to registers<br /> * slave - address of slave<br /> * addr - address of first register<br /> */<br />void TWI_writeBuf(uint8_t slave, uint8_t addr, uint8_t length, uint8_t *buf)<br />{<br />PORTD |= (1&lt;&lt;PD3);<br />TWI_start();<br />TWI_write(slave);<br />TWI_write(addr);<br />while(length--)TWI_write(*buf++);<br />TWI_stop();<br />PORTD &amp;= ~(1&lt;&lt;PD3);<br />}<br /><br />/*<br /> * reads registers into table of bytes<br /> * slave - address of slave<br /> * addr - address of first register<br /> */<br />void TWI_readBuf(uint8_t slave, uint8_t addr, uint8_t length, uint8_t *buf)<br />{<br />PORTD |= (1&lt;&lt;PD4);<br />TWI_start();<br />TWI_write(slave);<br />TWI_write(addr);<br />TWI_start();<br />TWI_write(slave | 0x01);// wysłanie rozkazu READ<br />while(length--)*buf++ = TWI_read(length ? ACK : NACK);<br />TWI_stop();<br />PORTD &amp;= ~(1&lt;&lt;PD4);<br />}[/syntax]<br /><br />Obsługa DS3231 (w funkcji DS3231_1Hz_SQW ręcznie ustawiłem wartości do wpisania do rejestru, żeby wykluczyć niedziałającą funkcję do ustawiania/zerowania bitu w bajcie; alarmów nie sprawdzałem jeszcze):<br /><br />[syntax=c]#ifndef DS3231_DS3231_H_<br />#define DS3231_DS3231_H_<br /><br />#defineDS3231_ADDR0xD0<br /><br />// interrupt settings for atmega32 (INT0 or INT1)<br />#define DS3231_INT_PORTD// PORT of DS3231_INT<br />#define DS3231_INT_LINE2// LINE of DS3231_INT<br />#define DS3231_INT_NUM0// NUMBER of DS3231_INT<br /><br />// ustawienia kompilacji<br />#define DS3231_USE_INT1// turn on interrupt<br />#define DS3231_USE_ALARM1// use (1) alarms or not (0)<br /><br />// definitions for DS3231 interrupt initialization<br />#define DS3231_INT_ACTIVATE(GICR |= (1&lt;&lt; _MERGE(INT,DS3231_INT_NUM,)))<br />#define DS3231_INT_POS_EDGE(MCUCR |= (1&lt;&lt; _MERGE(ISC, DS3231_INT_NUM, 1)) | (1&lt;&lt; _MERGE(ISC, DS3231_INT_NUM, 0)))<br />#define DS3231_INT_DDR_IN( _MERGE(DDR, DS3231_INT_PORT,) &amp;= ~(1&lt;&lt; _MERGE(P, DS3231_INT_PORT, DS3231_INT_LINE)))<br />#define DS3231_INT_PORT_PULLUP( _MERGE(PORT, DS3231_INT_PORT,) |= (1&lt;&lt; _MERGE(P, DS3231_INT_PORT, DS3231_INT_LINE)))<br /><br />enum Registers{<br />Seconds, Minutes, Hours, Day, Date, Month=5, Century=5, Year,<br />Alarms=7, Alarm1_Seconds=7, Alarm1_Minutes, Alarm1_Hour, Alarm1_Day=10, Alarm1_Date=10,<br />Alarm2_Minutes, Alarm2_Hour, Alarm2_Day=13, Alarm2_Date=13,<br />Control, Control_Status, Aging_Offset, MSB_Temp, LSB_Temp<br />};<br /><br />enum Alarm1_registerMaskBits{<br />_oncePerSecond=0x0F, _ss=0x0E, _mm_ss=0x0C, _hh_mm_ss=0x08, _date_hh_mm_ss=0x00, _day_hh_mm_ss=0x00<br />// Alarm:once per second; when match:seconds|minutes &amp; ss |hours &amp; mm&amp;ss |date &amp; hh&amp;mm&amp;ss | day &amp; hh&amp;mm&amp;ss<br />};<br /><br />enum Alarm2_registerMaskBits{<br />_oncePerMinute=0x07, _mm=0x06, _hh_mm=0x04, _date_hh_mm=0x00, _day_hh_mm=0x00<br />// Alarm:once per minute; when match:minutes|hours &amp; mm |date &amp; hh&amp;mm |day &amp; hh&amp;mm&amp;<br />};<br /><br />// char days&#91;7&#93;&#91;4&#93; = { &quot;Pon&quot;, &quot;Wt &quot;, &quot;Sr &quot;, &quot;Czw&quot;, &quot;Pt &quot;, &quot;Sob&quot;, &quot;Nie&quot; };// copy it to main.c<br /><br />typedef union{<br />uint8_t bytes&#91;7&#93;;<br />struct{<br />uint8_t ss;<br />uint8_t mm;<br />uint8_t hh;<br />uint8_t day_of_week;<br />uint8_t day;<br />uint8_t month;<br />uint8_t year;<br />};<br />}TDATETIME;<br /><br />void DS3231_init(void);<br />void DS3231_getDatetime(TDATETIME * dt);<br />void DS3231_uC_interruptInit(void);<br />void DS3231_setTime(uint8_t hh, uint8_t mm, uint8_t ss);<br />void DS3231_setDate(uint8_t day, uint8_t month, uint8_t year);<br />uint8_t DS3231_dayOfWeek(uint8_t date, uint8_t month, uint8_t year);<br />void DS3231_setAlarm(uint8_t alarmNr, uint8_t regMask, uint8_t ss, uint8_t mm, uint8_t hh, uint8_t dd);<br />void DS3231_changeBit(uint8_t reg, uint8_t bit, uint8_t val);<br />void DS3231_1Hz_SQW(uint8_t state);<br /><br />uint8_t dec2bcd(uint8_t dec);<br />uint8_t bcd2dec(uint8_t bcd);<br /><br />// makra upraszczające sklejanie<br />#define _MERGE(x1, x2, x3)_SMERGE(x1, x2, x3)<br />#define _SMERGE(x1, x2, x3)(x1##x2##x3)<br /><br />#endif /* DS3231_DS3231_H_ */[/syntax]<br /><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;util/delay.h&gt;<br /><br />#include &quot;DS3231.h&quot;<br />#include &quot;../I2C_TWI/i2c_twi.h&quot;<br /><br />/*<br /> * **** ****<br /> */<br /><br />// TDATETIME datetime;// variable for time and date keeping<br /><br />uint8_t shiftR(uint8_t * byte);<br /><br />/*<br /> * **** ****<br /> */<br /><br />// inicjalizacja zegarka<br />void DS3231_init()<br />{<br />uint8_t ctrl = 0;// SQW blinks with 1Hz frequency<br />TWI_writeBuf(DS3231_ADDR, Control, 1, &amp;ctrl);<br />for(uint8_t i = 0; i &lt; 4; i++)_delay_ms(250);// wait 1s for oscillator startup<br />}<br /><br />// Odczyt danych z rejestrów zegara<br />void DS3231_getDatetime(TDATETIME * dt)<br />{<br />uint8_t buf&#91;7&#93;;<br />TWI_readBuf(DS3231_ADDR, Seconds, 7, buf);<br />for(uint8_t i = 0; i&lt;7; i++)<br />dt-&gt;bytes&#91;i&#93; = bcd2dec(buf&#91;i&#93;);<br />}<br /><br />// Ustawianie czasu w rejestrach zegara<br />void DS3231_setTime(uint8_t hh, uint8_t mm, uint8_t ss)<br />{<br />uint8_t buf&#91;3&#93;;<br />buf&#91;0&#93; = dec2bcd(ss);<br />buf&#91;1&#93; = dec2bcd(mm);<br />buf&#91;2&#93; = dec2bcd(hh);<br />TWI_writeBuf(DS3231_ADDR, Seconds, 3, buf);<br />}<br /><br />// Ustawianie daty w rejestrach zegara<br />void DS3231_setDate(uint8_t date, uint8_t month, uint8_t year)<br />{<br />uint8_t dayOfWeek = DS3231_dayOfWeek(date, month, year) + 1;<br />uint8_t buf&#91;4&#93;;<br />buf&#91;0&#93; = dayOfWeek;<br />buf&#91;1&#93; = dec2bcd(date);<br />buf&#91;2&#93; = dec2bcd(month);<br />buf&#91;3&#93; = dec2bcd(year);<br />TWI_writeBuf(DS3231_ADDR, Day, 4, buf);<br />}<br /><br />// przerwanie wyjścia SQW<br />#if DS3231_USE_INT == 1<br />void DS3231_uC_interruptInit(void)<br />{<br />DS3231_INT_ACTIVATE;<br />DS3231_INT_POS_EDGE;<br />DS3231_INT_DDR_IN;<br />DS3231_INT_PORT_PULLUP;<br />}<br />#endif<br /><br />// Oblicza dzień tygodnia w przedziale<br />uint8_t DS3231_dayOfWeek(uint8_t date, uint8_t month, uint8_t year)<br />{<br /><br />}<br /><br />// ustawia alarm nr 1 lub 2 w formacie 24-godzinnym<br />#if DS3231_USE_ALARM == 1<br />void DS3231_setAlarm(uint8_t alarmNr, uint8_t regMask, uint8_t dd, uint8_t hh, uint8_t mm, uint8_t ss)<br />{<br />if (alarmNr != 1 &amp;&amp; alarmNr != 2)return;// wrong number of alarm<br />alarmNr--;<br />regMask &lt;&lt;= alarmNr;<br /><br />uint8_t buf&#91;4&#93;;<br />buf&#91;0&#93; = buf&#91;1&#93; = buf&#91;2&#93; = buf&#91;3&#93; = 0;<br /><br />buf&#91;0&#93; = (shiftR(&amp;regMask) &amp; 0x80) | dec2bcd(ss);<br />buf&#91;1&#93; = (shiftR(&amp;regMask) &amp; 0x80) | dec2bcd(mm);<br />buf&#91;2&#93; = (shiftR(&amp;regMask) &amp; 0x80) | dec2bcd(hh);<br />buf&#91;3&#93; = (shiftR(&amp;regMask) &amp; 0x80) | dec2bcd(dd);<br />TWI_writeBuf(DS3231_ADDR, Alarms + alarmNr*4, 4 - alarmNr, &amp;buf&#91;alarmNr&#93;);<br />// (shiftR(*regMask) &amp; 0x80) - przesuwa bity o 1 w prawo przenosząc LSB na MSB, następnie maskuje wszystkie bity poza MSB<br /><br />// enable Alarm interrupt in Control register<br />DS3231_changeBit(Control, alarmNr, 1);<br />}<br />#endif<br /><br />// changes value of chosen bit in register<br />void DS3231_changeBit(uint8_t reg, uint8_t bit, uint8_t val)<br />{<br />uint8_t tmp;<br /><br />TWI_readBuf(DS3231_ADDR, reg, 1, &amp;tmp);<br />tmp &amp;= ~(1&lt;&lt;bit);<br />if(val &amp;&amp; 0x01)tmp |= (1 &lt;&lt; bit);<br />TWI_writeBuf(DS3231_ADDR, reg, 1, &amp;tmp);<br />}<br /><br />// Switches on (1) or off (0) the 1Hz square wave on SQW output<br />void DS3231_1Hz_SQW(uint8_t state)<br />{<br />uint8_t ctrl=0b00000100;<br />if(state)// enable SQW 1Hz<br />{<br />ctrl = 0;<br />TWI_writeBuf(DS3231_ADDR, Control, 1, &amp;ctrl);<br />//DS3231_changeBit(Control, 2, 0);<br />//DS3231_changeBit(Control, 3, 0);<br />//DS3231_changeBit(Control, 4, 0);<br /><br />}<br />elseTWI_writeBuf(DS3231_ADDR, Control, 1, &amp;ctrl);<br />//DS3231_changeBit(Control, 2, 1);<br />}<br /><br />/*<br /> * **** ****<br /> */<br />uint8_t dec2bcd(uint8_t dec)<br />{<br />return ((dec / 10) &lt;&lt; 4) | (dec % 10);<br />}<br /><br />uint8_t bcd2dec(uint8_t bcd)<br />{<br />return ((((bcd) &gt;&gt; 4) &amp; 0x0F) * 10) + ((bcd) &amp; 0x0F);<br />}<br /><br />// cyclic shift of one bit<br />uint8_t shiftR(uint8_t * byte)<br />{<br />uint8_t tmp = 0;<br />tmp = *byte &lt;&lt; 7;<br />*byte &gt;&gt;= 1;<br />*byte |= tmp;<br />return *byte;<br />}[/syntax]<br /><br />Obsługa przerwań:<br />[syntax=c]ISR (BADISR_vect) {}// obsluga nieuzywanych przerwan<br /><br />ISR (_MERGE(INT, DS3231_INT_NUM, _vect))<br />{<br />//while(!(TWCR &amp; (1&lt;&lt;TWINT)));<br />DS3231_getDatetime(&amp;datetime);<br />//PORTD |= (1&lt;&lt;PD0);<br />LCD_locate(0, 0);<br />showDate(&amp;datetime);<br />//PORTD |= (1&lt;&lt;PD1);<br />LCD_locate(1, 0);<br />showTime(&amp;datetime);<br />//PORTD |= (1&lt;&lt;PD3);<br />LCD_locate(1, 11);<br />LCD_int(licznik++);<br />}<br /><br />// pokazuje czas w formacie hh-mm-ss<br />void showTime(TDATETIME * dt)<br />{<br />if (dt-&gt;hh &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;hh);<br />LCD_str(&quot;:&quot;);<br />if (dt-&gt;mm &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;mm);<br />LCD_str(&quot;:&quot;);<br />if (dt-&gt;ss &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;ss);<br />}<br /><br />void showDate(TDATETIME * dt)<br />{<br />if(dt-&gt;day &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;day);<br />LCD_str(&quot;.&quot;);<br />if(dt-&gt;month &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;month);<br />LCD_str(&quot;.&quot;);<br />if(dt-&gt;year &lt; 10)LCD_str(&quot;0&quot;);<br />LCD_int(dt-&gt;year);<br />LCD_str(&quot;   &quot;);<br />LCD_str(days&#91;dt-&gt;day_of_week - 1&#93;);<br />}[/syntax]<br /><br />Main (zapis daty i czasu działa):<br />[syntax=c]int main (void)<br />{<br />//konfiguracja przerwania INT0<br />DS3231_uC_interruptInit();<br /><br />LCD_init();<br /><br />TWI_setBitrate_kHz(50);<br />DS3231_init();<br /><br />LCD_str(&quot;Hello world!&quot;);<br />for(uint8_t i = 0; i &lt; 8; i++)_delay_ms(250);// wstrzymanie na 2 sekundy<br /><br />sei();<br /><br />//DS3231_setDate(12, 7, 19);<br />//DS3231_setTime(22, 36, 30);<br /><br />while(1)<br />{<br /><br />DS3231_1Hz_SQW(ON);<br />//PORTD ^= (1&lt;&lt;PD0);<br />//PORTD |= (1&lt;&lt;PD4);<br />for(uint8_t i = 0; i &lt; 8; i++)<br />_delay_ms(250);// wstrzymanie na 2 sekundy<br /><br /><br />DS3231_1Hz_SQW(OFF);<br />//PORTD &amp;= ~(1&lt;&lt;PD4);<br />//PORTD ^= (1&lt;&lt;PD0);<br />for(uint8_t i = 0; i &lt; 20; i++)<br />_delay_ms(250);// wstrzymanie na 5 sekund<br /><br />}<br /><br />return 0;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=20777">MarKl</a> — 15 lip 2019, o 14:52</p><hr />
]]></content>
</entry>
</feed>