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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2018-10-10T19:11:26+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=21404&amp;mode</id>
<entry>
<author><name><![CDATA[SylwekK]]></name></author>
<updated>2018-10-10T19:11:26+01:00</updated>
<published>2018-10-10T19:11:26+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212492#p212492</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212492#p212492"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212492#p212492"><![CDATA[
Jeśli to stały czas i nie ma możliwości zmienić taktowania przerwań to ja w takich przypadkach wykorzystuje dodatkową flagę, która daje sygnał dla warunku w przerwaniach i to tam jest odświeżana wartość dla timera. Działa zawsze prawidłowo <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> Natomiast w sytuacji gdy odliczany czas jest modyfikowany stosuje inna zmienną w przerwaniach, która np.  wstępnie podzieli mi przez dwa i zamiast 300 wpisuje wtedy 150. Jest 8bit? No jeeest <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=1922">SylwekK</a> — 10 paź 2018, o 19:11</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[andrews]]></name></author>
<updated>2018-10-10T17:53:59+01:00</updated>
<published>2018-10-10T17:53:59+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212488#p212488</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212488#p212488"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212488#p212488"><![CDATA[
To nie ma znaczenia, czy użyjesz jednej zmiennej 16-bitowej, czy dwóch zmiennych 8-bitowych. Kiedy użyjesz zmiennej 16-bitowej, kompilator i tak musi rozbić to na dwie operacje 8-bitowe, bo to mikrokontroler 8-bitowy. I pomiędzy tymi operacjami nie może wystąpić przerwanie, które zmodyfikuje tę zmienną.<br /><br />Podam Ci taki przykład:<br /><ul><li>wartość zmiennej <em>Timer1</em> wynosi 255, czyli 0x00FF,</li><li>program dochodzi do momentu, kiedy wartość zmiennej <em>Timer1</em> trzeba porównać z wartością 0 (mówię tu o instrukcji warunkowej <strong><em>if( !(Timer1) )</em></strong>,</li><li>nie można porównać dwóch bajtów jednocześnie, bo mikrkontroler ma rejestry 8-bitowe, więc najpierw porównywany jest starszy bajt, który wynosi 0x00, czyli warunek jest spełniony,</li><li>teraz występuje przerwanie od timera, i zmienna zostaje powiększona o 1, czyli przyjmuje wartość 0x0100,</li><li>mikrokontroler wraca do wykonywania programu głównego, i porównuje teraz młodszy bajt (bo starszy przecież już porównał); teraz młodszy bajt (z liczby 0x0100) wynosi również 0x00, więc warunek znowu jest spełniony,</li><li>w związku z tym, że wynikiem porównaniu starszego bajtu z zerem była prawda i wynikeim porównania młodszego bajtu z zerem była prawda, mikrokontroler uznaje, że cała liczba jest równa zero, a przecież nie jest, bo wynosi 0x0100.</li></ul><br />Wszystko byłoby dobrze, gdyby pomiędzy dwoma operacjami porównania nie wystąpiło przerwanie i nie zmodyfikowało zmiennej, bo wtedy drugie porównanie zwróciłoby fałsz i wszystko byłoby OK. Dlatego w momencie modyfikowania, czy też porównywania zmiennej wielobajtowej należy przerwania wyłączyć. Przykłady masz podane powyżej.<br /><br />Można też zrobić tak, jak zrobiłeś, pod warunkiem, że wykonanie bloku instrukcji pomiędzy <strong><em>cli()</em></strong> a <strong><em>sei()</em></strong> nie będzie trwało zbyt długo. Należy zadbać o to, żeby wyłączenie przerwań trwało jak najkrócej. Dlatego podałem przykład z tworzeniem kopii zmiennej, bo to wyłącza przerwania tylko na kilka taktów. Twój sposób wyłączy zapewne na dłużej, choć w tym przypadku jeszcze nie będzie tragedii. Piszę o tym raczej, żebyś zapamiętał na przyszłość, bo gdyby w bloku instrukcji było jakieś wyświetlenie na LCD lub transmisja UART, wtedy Twój sposób nie jest dobry.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=14165">andrews</a> — 10 paź 2018, o 17:53</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[sildurian]]></name></author>
<updated>2018-10-10T17:45:52+01:00</updated>
<published>2018-10-10T17:45:52+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212487#p212487</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212487#p212487"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212487#p212487"><![CDATA[
dobra, doszedłem do właściwego dla mojego przypadku rozwiązania<br />[syntax=c]cli();<br />        if(!Timer1)<br />        {<br />            LED1_TOG;<br />            Timer1 = 300;<br />        }<br />        sei();[/syntax]<br />inaczej zazwyczaj podczas sprawdzania warunku if wchodził w przerwanie,<br />Dziękuję za pomoc i pozdrawiam <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=12675">sildurian</a> — 10 paź 2018, o 17:45</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2018-10-10T17:14:30+01:00</updated>
<published>2018-10-10T17:14:30+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212484#p212484</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212484#p212484"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212484#p212484"><![CDATA[
<div class="quotetitle">sildurian napisał(a):</div><div class="quotecontent"><br />i w momencie jak jest wykonywana operacja if może dojść do przerwania?<br /></div><br />No toż przecież po to mówimy ci o atomowym podejściu ... tak oczywiście że chodzi o przerwania - a o cóż innego miałoby chodzić. Zarówno sprawdzanie jak i zapis trzeba robić atomowo i masz przykłady wyżej na to<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 10 paź 2018, o 17:14</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[sildurian]]></name></author>
<updated>2018-10-10T16:58:50+01:00</updated>
<published>2018-10-10T16:58:50+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212483#p212483</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212483#p212483"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212483#p212483"><![CDATA[
Dziękuję,<br />W międzyczasie doszedłem do czegoś takiego i efekt jest taki jak miałem wcześniej<br />[syntax=c]while(1)<br />{<br />if((!TimL)&amp;&amp;(!TimH))<br />{<br />LED1_TOG;<br />timer_conv = 300; // zmienna globalna uint16_t<br />TimL = (uint8_t)timer_conv; // zmienna globalna volatile uint8_t<br />TimH = timer_conv &gt;&gt; 8; // zmienna globalna volatile uint8_t<br />}<br />}<br />}<br /><br />ISR(TIMER2_COMP_vect) //100kHz -&gt; 10us<br />{<br />uint8_t valTimL;<br />uint8_t valTimH;<br /><br />valTimL = TimL;<br />valTimH = TimH;<br />if(valTimL) TimL = --valTimL;<br />else if(valTimH) {TimH = --valTimH; TimL = 255;}<br />}[/syntax]<br />teraz w warunku if operuję na zmiennych 8bitowych, a i tak problem jest taki sam, czyli rozumiem, że operacja zajmuje więcej taktów zegara i w momencie jak jest wykonywana operacja if może dojść do przerwania?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=12675">sildurian</a> — 10 paź 2018, o 16:58</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2018-10-10T16:22:21+01:00</updated>
<published>2018-10-10T16:22:21+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212482#p212482</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212482#p212482"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212482#p212482"><![CDATA[
sorki - jeszcze sprawdzanie wartości timera trzeba atomowo - ale to już andrews mnie ubiegł <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 paź 2018, o 16:22</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[andrews]]></name></author>
<updated>2018-10-10T16:23:21+01:00</updated>
<published>2018-10-10T16:20:57+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212481#p212481</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212481#p212481"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212481#p212481"><![CDATA[
Nie zapewniasz atomowego dostępu atomowego dostępu do zmiennej wielobajtowej, używanej zarówno w przerwaniu, jak i w głównej pętli programu. Operacje na takiej zmiennej w mikrokontrolerach 8-bitowych, jak słusznie już sam zauważyłeś, potrzebują co najmniej dwóch taktów zegara. Jeśli pomiędzy tymi taktami wystąpi przerwanie, operacja na takiej zmiennej będzie niepoprawna. U Ciebie taka sytuacja jest to wysoce prawdopodobna, bo operacje na zmiennej <strong><em>Timer1</em></strong> to większość kodu w pętli głównej.<br /><br />Aby temu zapobiec, w programie głównym w momencie dostępu do takiej zmiennej należy wyłączać przerwania. Spróbuj zrobić na przykład coś w tym stylu:[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#define LED1 (1&lt;&lt;PB2)<br />#define LED1_OFF PORTB |= LED1;<br />#define LED1_ON PORTB &amp;=~LED1;<br />#define LED1_TOG PORTB ^= LED1;<br /><br />volatile uint16_t Timer1;<br /><br />int main (void)<br />{<br />    uint16_t kopia;<br />    <br />    /* ##### PORT_B  ################################################## */<br />    DDRB |= LED1; // jako wyjscia<br />    DDRD |= (1&lt;&lt;PD7);<br />    <br />    // ustawienie TIMER2<br />    TCCR2 |= (1&lt;&lt;WGM21);                            // tryb CTC<br />    TCCR2 |= (1&lt;&lt;CS20);                             // preskaler brak podziału<br />    TCCR2 |= (1&lt;&lt;COM20);                            // OC2 pin PD7 toggle on CompareMatch<br />    OCR2 = 109;                                             // dodatkowy podział<br />    TIMSK |= (1&lt;&lt;OCIE2);                            // zezwolenie na przerwanie CompareMatch<br />    <br />    sei();<br />    <br />    while(1)<br />    {<br />        cli();<br />        kopia = Timer1;<br />        sei();<br />        <br />        if(!kopia)<br />        {<br />            LED1_TOG;<br />            kopia = 300;<br />        }<br />        <br />        cli();<br />        Timer1 = kopia;<br />        sei();<br />    }<br />}<br /><br />ISR(TIMER2_COMP_vect) //100kHz -&gt; 10us<br />{<br />    uint16_t n;<br />    <br />    n = Timer1;<br />    if (n) Timer1 = --n;<br />}[/syntax]<br /><br />EDIT:<br />Widzę, że kolega Mirek mnie uprzedził, ale post może zostawię, bo chyba zapomniał o operacji porównania zmiennej Timer w warunku if.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=14165">andrews</a> — 10 paź 2018, o 16:20</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2018-10-10T16:19:38+01:00</updated>
<published>2018-10-10T16:19:38+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212480#p212480</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212480#p212480"/>
<title type="html"><![CDATA[Re: Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212480#p212480"><![CDATA[
Jeśli to jest aż tak istotne to trzeba wprowadzić atomowość po prostu, czyli zamień linię:<br /><br />[syntax=c]Timer1 = 300;[/syntax]<br /><br />na taką postać:<br /><br />[syntax=c]uint8_t sreg = SREG;<br />cli();<br />Timer1 = 300;<br />SREG = sreg;[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 10 paź 2018, o 16:19</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[sildurian]]></name></author>
<updated>2018-10-10T15:28:08+01:00</updated>
<published>2018-10-10T15:28:08+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212479#p212479</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212479#p212479"/>
<title type="html"><![CDATA[Problem z timerem programowym]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=21404&amp;p=212479#p212479"><![CDATA[
Cześć,<br />Robiłem projekt i musiałem wykorzystać timer programowy, niestety występowało nieregularne miganie diody, która powinna migać ze stały okresem. Chcąc sprawdzić o co chodzi napisałem uproszczony program do migania diodą i sprawdzić czy licznik sprzętowy działa poprawnie zmieniając stan wyjścia OC2. Timer sprzętowy okazuje się być ok. Problem jest wydaje mi się ze zmienną uint16_t. Atmega32 to 8 bitowy procesor i pewnie używa flagę przeniesienia. ustawiając wartość timera programowego na więcej niż 255 czyli tyle ile mieści jeden bajt zauważyłem, że wejście w warunek if występuje co 300 plus jeszcze 300-255. Co widać na zdjęciach z oscyloskopu.<br />Poniżej kod<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#define LED1 (1&lt;&lt;PB2)<br />#define LED1_OFF PORTB |= LED1;<br />#define LED1_ON PORTB &amp;=~LED1;<br />#define LED1_TOG PORTB ^= LED1;<br /><br />volatile uint16_t Timer1;<br /><br />int main (void)<br />{<br />/* ##### PORT_B  ################################################## */<br />DDRB |= LED1; // jako wyjscia<br />DDRD |= (1&lt;&lt;PD7);<br /><br />// ustawienie TIMER2<br />TCCR2 |= (1&lt;&lt;WGM21);// tryb CTC<br />TCCR2 |= (1&lt;&lt;CS20);// preskaler brak podziału<br />TCCR2 |= (1&lt;&lt;COM20);// OC2 pin PD7 toggle on CompareMatch<br />OCR2 = 109;// dodatkowy podział<br />TIMSK |= (1&lt;&lt;OCIE2);// zezwolenie na przerwanie CompareMatch<br /><br />sei();<br /><br />while(1)<br />{<br /><br />if(!Timer1)<br />{<br />LED1_TOG;<br />Timer1 = 300;<br />}<br />}<br />}<br /><br />ISR(TIMER2_COMP_vect) //100kHz -&gt; 10us<br />{<br />uint16_t n;<br /><br />n = Timer1;<br />if (n) Timer1 = --n;<br />}[/syntax]<br />testowane na zestawie atb 1.04b<br /><a href="https://obrazkiforum.atnel.pl/12675/f00963c34168ec42bd2bc156bc9f2cd0.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/12675/f00963c34168ec42bd2bc156bc9f2cd0.png" alt="Obrazek" /></a><br />zdjęcie 1. przerwanie co 100kHz, wartość Timer1 = 300, czyli co 3ms zmiana stanu pinu.<br /><a href="https://obrazkiforum.atnel.pl/12675/534386106f376c060876e5eb6cd75a56.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/12675/534386106f376c060876e5eb6cd75a56.png" alt="Obrazek" /></a><br />zdjęcie 2. przerwanie co 100kHz, wartość Timer1 = 300, czyli co 3ms zmiana stanu pinu, dodatkowo mamy zmianę stanu co około 46us<br /><a href="https://obrazkiforum.atnel.pl/12675/2e4e0771ac593224ecd069322cf95b0d.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/12675/2e4e0771ac593224ecd069322cf95b0d.png" alt="Obrazek" /></a><br />zdjęcie 3. przerwanie co 100Hz, wartość Timer1 = 300, czyli co 3s zmiana stanu pinu.<br /><a href="https://obrazkiforum.atnel.pl/12675/a9556997eff892a381202079ba524978.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/12675/a9556997eff892a381202079ba524978.png" alt="Obrazek" /></a><br />zdjęcie 4. przerwanie co 100Hz, wartość Timer1 = 300, czyli co 3s zmiana stanu pinu, dodatkowo mamy zmianę stanu co około 460ms, jednak nie zawsze, &quot;czasem&quot; działa, widać to po 3 prawidłowych zmianach stanu pinu.<br /><br />Dla wartości Timer1 &lt; 256 działa poprawnie, tak jak pisałem jest pewnie problem z caryflag. Dzieliłem już zmienną 16bit na dwie ale to nie pomogło.<br />[syntax=c]uint8_t TL;<br />uint8_t TH;<br />while(1)<br />{<br />TL = (uint8_t) Timer1;<br />TH = Timer1 &gt;&gt;8;<br /><br />if((TL == 0x00) &amp;&amp; (TH == 0x00))<br />{<br />LED1_TOG;<br />Timer1 = 300;<br />}<br />}[/syntax]<br />Dostałem coś takiego:<br /><a href="https://obrazkiforum.atnel.pl/12675/04db9aacb7b30b047ca6cf87a5360832.png"  class="postlink"><img src="https://obrazkiforum.atnel.pl/thumb/12675/04db9aacb7b30b047ca6cf87a5360832.png" alt="Obrazek" /></a><br />Jak sobie z tym radzić, co robię źle?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=12675">sildurian</a> — 10 paź 2018, o 15:28</p><hr />
]]></content>
</entry>
</feed>