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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-08-20T19:58:43+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=8071&amp;mode</id>
<entry>
<author><name><![CDATA[Aress]]></name></author>
<updated>2014-08-20T19:58:43+01:00</updated>
<published>2014-08-20T19:58:43+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92222#p92222</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92222#p92222"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów, problem z INTx]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92222#p92222"><![CDATA[
<div class="quotetitle">atmel napisał(a):</div><div class="quotecontent"><br />Pierwszym błędem jest wywołanie funkcji &quot;inicjalizacja&quot; w przerwaniu...<br /></div><br />Bez tej inicjalizacji program mi się nie uruchamia na uC.<br /><br /><div class="quotetitle">atmel napisał(a):</div><div class="quotecontent"><br />Kolejny to zupełnie zbędne ciągłe ustawianie &quot;pull-up'a&quot; (PORTB = (1&lt;&lt;PD2);)...<br /></div><br />Program na początku pisałem patrząc na inny i jakoś mi to umknęło.<br /><br />[syntax=c]PORTD = ~(1&lt;&lt;PD2);[/syntax]<br />Tu chodziło mi o to, żeby PWM dostał jeden sygnał po podłączeniu zasilania aby się uruchomił bez konieczności przyciskania przycisku.<br /><br />Mam jeszcze takie pytanie czy maskowanie tutaj zapewnia lepsze działanie czy po prostu tak jest poprawniej?<br /><br />A tak poza tym to program działa w 100% tak jak chciałem. Dziękuję bardzo za pomoc, omówienie i wyjaśnienie <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=5096">Aress</a> — 20 sie 2014, o 19:58</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[atmel]]></name></author>
<updated>2014-08-20T12:38:18+01:00</updated>
<published>2014-08-20T12:38:18+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92142#p92142</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92142#p92142"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów, problem z INTx]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92142#p92142"><![CDATA[
Pierwszym błędem jest wywołanie funkcji &quot;inicjalizacja&quot; w przerwaniu, która powinna zgodnie ze swoją nazwą być wywołana jednokrotnie przed pętlą główną programu.<br /><br />Kolejny to zupełnie zbędne ciągłe ustawianie &quot;pull-up'a&quot; (<strong>PORTB = (1&lt;&lt;PD2);</strong>) w funkcji &quot;przycisk&quot;. Zapewne chodziło o &quot;pull-up&quot; dla PD2, a nie PB2, dlatego tę linię można zupełnie usunąć, gdyż takowa znajduje się już w funkcji &quot;inicjalizacja&quot;. <br /><br />Następnie kolejna uwaga dotycząca ustawiania kierunku portów. Nie wiem jakie było założenie, ale w tym wypadku wszystkie piny oprócz PD2 będą wyjściami:<br /><br />[syntax=c]PORTD = ~(1&lt;&lt;PD2);[/syntax]<br />Nie powinno być w ten sposób?:<br /><br />[syntax=c]PORTD &amp;= ~(1&lt;&lt;PD2);[/syntax]<br />Podobnie sytuacja wygląda w głównej pętli &quot;while&quot; programu. Tam również warto użyć maskowania (jeżeli zmianie ma ulec stan jedynie niektórych pinów).<br /><br />&quot;<strong>SIGNAL(SIG_INTERRUPT0)</strong>&quot; jest to przestarzały zapis i lepiej używać: &quot;<strong>ISR(INT0_vect)</strong>&quot;.<br /><br />Przechodząc do sedna problemu, przy pierwszym naciśnięciu klawisza wywoływana jest funkcja &quot;tryb2&quot;, później &quot;tryb3&quot;, a następnie zmianie ulega jedynie zmienna &quot;n&quot; nie wywołując przy tym żadnych akcji. Dobrze byłoby ustawiać jej stan przed instrukcją wyboru &quot;switch&quot;. Można to zrobić w dwojaki sposób:<br />1. Używając reszty z dzielenia [syntax=c]n = n++ % 3;[/syntax]<br />2. Używając warunku [syntax=c]if (++n &gt; 3) n = 1;[/syntax]<br /><br />Cały kod przedstawia się następująco:<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#define swich bit_is_clear(PIND, 2)<br />#define PWM_A (1&lt;&lt;PB1)<br /><br />void inicjalizacja()<br />{<br />DDRD |= 1&lt;&lt;PD2;<br />PORTD |= 1&lt;&lt;PD2;<br />DDRB |= PWM_A;<br />DDRC |= 1&lt;&lt;PC2 | 1&lt;&lt;PC0;<br /><br />// INICJALIZACJA PWM<br />TCCR1A |= 1&lt;&lt;WGM10 | 1&lt;&lt;COM1A1;<br />TCCR1B |= 1&lt;&lt;CS11;<br /><br />MCUCR |= 1&lt;&lt;ISC00;<br />GICR |= 1&lt;&lt;INT0;<br />sei();<br />}<br /> <br />char przycisk(void)<br />{<br />if (swich) {<br />_delay_ms(30);<br />if (swich) <br />while (swich);<br />else return 0;<br />return 1;<br />} else return 0;<br />// Eliminacja drgań styków<br />}<br /> <br />void tryb1(void)<br />{<br />OCR1A = 235;<br />}<br /> <br />void tryb2(void)<br />{<br />OCR1A = 140;<br />}<br /> <br />void tryb3(void)<br />{<br />OCR1A = 50;<br />}<br /> <br />ISR(INT0_vect)<br />{<br />static uint8_t n = 1;<br />if (przycisk())<br />if (++n &gt; 3) n = 1;// Można również zamiast tej linijki zastąpić ją takim zapisem: &quot;n = n++ % 3;&quot;<br />switch (n) {<br />case 1:tryb1();break;<br />case 2:tryb2();break;<br />case 3:tryb3();break;<br />}<br />}<br /> <br />int main(void)<br />{<br />        inicjalizacja();<br />        PORTD &amp;= ~(1&lt;&lt;PD2);<br />        while(1) {<br />PORTC &amp;= ~(1&lt;&lt;PC2);<br />PORTC |= 1&lt;&lt;PC0;<br />_delay_ms(200);<br />PORTC &amp;= ~(1&lt;&lt;PC0);<br />PORTC |= 1&lt;&lt;PC2;<br />_delay_ms(200);<br />}<br />return 0;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1183">atmel</a> — 20 sie 2014, o 12:38</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Aress]]></name></author>
<updated>2014-08-20T06:29:07+01:00</updated>
<published>2014-08-20T06:29:07+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92117#p92117</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92117#p92117"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=92117#p92117"><![CDATA[
Witam ponownie. Jak na razie najłatwiej było mi ogarnąć INTx, ale nie do końca wszystko mi wyszło tak jak bym chciał.<br />Mam 2 problemy ze swoim programem. <br />1- Czasami jest tak, że program przełącza PWM na 3 tryby ale prawie cały czas jest tak, że przechodzi tylko przez 2.<br />2- Jak przełącza się po trybach to jak dojdzie do ostatniego (tego co jest przed &quot;default&quot;) to, żeby przejść do początku trzeba wcisnąć dwa razy przycisk.<br /><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#define swich bit_is_clear(PIND,2)<br />#define PWM_A (1&lt;&lt;PB1)<br /><br /><br /><br />void inicjalizacja(){<br /><br />DDRD |= (1&lt;&lt;PORTD2);<br />PORTD |= (1&lt;&lt;PORTD2);<br /><br />DDRB |= (PWM_A);<br /><br />DDRC |= (1&lt;&lt;PC0)|(1&lt;&lt;PC2);<br /><br /><br />// INICJALIZACJA PWM<br />TCCR1A |= (1&lt;&lt;WGM10);<br />TCCR1A |= (1&lt;&lt;COM1A1);<br />TCCR1B |= (1&lt;&lt;CS11);<br /><br /><br /><br />MCUCR |= (1&lt;&lt;ISC00);<br />GICR |=(1&lt;&lt;INT0);<br />sei();<br /><br /><br />}<br /><br />char przycisk(void)<br />{<br /><br />PORTB = (1&lt;&lt;PD2);<br />if(swich)<br />{<br />_delay_ms(30);<br />if(swich) {while (swich){};}<br />else return 0;<br />return 1;<br />}<br />else return 0;<br /><br />// Eliminacja drgań styków<br />}<br /><br />void tryb1(void){<br /><br />OCR1A =   235;  <br /><br />}<br /><br />void tryb2(void){<br /><br />OCR1A =   140;  <br /><br />}<br /><br />void tryb3(void){<br /><br />OCR1A =   50;  <br /><br />}<br /><br />SIGNAL(SIG_INTERRUPT0){<br /><br />inicjalizacja();<br />static char n=1;<br /><br /><br />if(przycisk())n++;<br />switch (n)<br />{<br />    case 1:<br />      tryb1();<br />    break;<br /><br />    case 2:<br />      tryb2();<br />    break;<br /><br />    case 3:<br />      tryb3();<br />    break;<br /><br />    default:<br />      n=1;<br />    <br />}<br /><br />}<br /><br />int main(void){<br /><br />inicjalizacja();<br /><br />PORTD = ~(1&lt;&lt;PD2);<br /><br />while(1){<br /><br />PORTC = (1&lt;&lt;PC0);<br />_delay_ms(200);<br />PORTC = (1&lt;&lt;PC2);<br />_delay_ms(200);<br />}<br />return 0;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5096">Aress</a> — 20 sie 2014, o 06:29</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Aress]]></name></author>
<updated>2014-08-10T08:02:26+01:00</updated>
<published>2014-08-10T08:02:26+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90896#p90896</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90896#p90896"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90896#p90896"><![CDATA[
Ok. Jeszcze raz dzięki za pomoc <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=5096">Aress</a> — 10 sie 2014, o 08:02</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Federerer]]></name></author>
<updated>2014-08-09T21:23:50+01:00</updated>
<published>2014-08-09T21:23:50+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90866#p90866</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90866#p90866"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90866#p90866"><![CDATA[
Tak jak pisałem wcześniej, do wywoływania zadań z określonym interwałem czasowym można użyć systemu który nazywa się Super Simple Tasker, taki trochę RTOS, z jednym stosem. Opis jest tu:<br /><a href="http://www.embedded.com/design/prototyping-and-development/4025691/Build-a-Super-Simple-Tasker"  class="postlink">http://www.embedded.com/design/prototyping-and-development/4025691/Build-a-Super-Simple-Tasker</a><br />Biblioteki autorstwa Artura Lipowskiego tu (wymaga zalogowania):<br /><a href="http://www.avrfreaks.net/index.php?module=Freaks%20Academy&amp;func=viewItem&amp;item_id=725&amp;item_type=project"  class="postlink">http://www.avrfreaks.net/index.php?module=Freaks%20Academy&amp;func=viewItem&amp;item_id=725&amp;item_type=project</a><br /><br />Tak w ramach zabawy uruchomiłem kiedyś przykład z tej paczki na attiny2313 i atmedze8. Na attiny można było tylko pomigać diodą, za mało flasha i ramu <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> Na atmedze wyświetlałem sobie wartości timerów na LCD i bawiłem się dodając w funkcjach delaye i zmieniając ich priorytety, patrząc czy się zawiesi <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" />. Np dając duże opóźnienie w funkcji wyświetlania na LCD spadała częstotliwość odświeżania, ale timer mierzył czas poprawnie, bo miał wyższy priorytet. Gdy zamieniłem priorytety, timer gubił impulsy, bo procesor mielił delayem, który miał wyższy priorytet niż obsługa timera. Nic poważniejszego nie testowałem. Kod przykładu przerobiony przeze mnie wyglądał tak:<br /><br />main.c<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;avr/sleep.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &quot;sst/sst_timer.h&quot;<br />#include &quot;LCD/lcd44780.h&quot;<br /><br />#define TIMER_TASK_PRIO        (SST_MIN_TASK_PRIO + 2)<br />#define EVENT_TASK_PRIO        (SST_MIN_TASK_PRIO + 1)<br /><br />SST_TaskID_T timer_task_id;<br />SST_TaskID_T event_task_id;<br /><br />static CPU_Base_T ticks;<br /><br />SST_TICKER_DEFINE(ticker, 1);<br /><br /><br />inline void ioinit(void) {<br /><br />#if defined (__AVR_ATmega8__)<br /><br />TCCR2 |= (1 &lt;&lt; WGM21); // tryb CTC<br />TCCR2 |= (1 &lt;&lt; CS22); // prescaler 64<br />OCR2 = (uint8_t) (F_CPU / 64 / 1000); // 1ms<br />TIMSK |= (1 &lt;&lt; OCIE2);<br /><br />#elif defined (__AVR_ATtiny2313__)<br /><br />TCCR0A |= (1 &lt;&lt; WGM01); // tryb CTC<br />TCCR0B |= (1 &lt;&lt; CS02) | (1 &lt;&lt; CS00); // prescaler 1024<br />OCR0A = (uint8_t) (F_CPU / 1024 / 100); // 100ms<br />TIMSK |= (1 &lt;&lt; OCIE0A);<br /><br />#endif<br /><br />lcd_init();<br /><br />}<br /><br /><br />void timer_task_func(SST_Event_T e)<br />{<br /><br /><br />    ticks++;<br /><br />    // do some other processing<br />    <br />    // sometime start event triggered task<br />    if (0 == (ticks % 3))<br />    {<br />        SST_PostEvent(event_task_id, 3, ticks);<br /><br />    }<br />    if (0 == (ticks % 8))<br />    {<br />        SST_PostEvent(event_task_id, 8, ticks);<br />    }<br /><br />}<br /><br /><br /><br />void event_task_func(SST_Event_T e)<br />{<br /><br />   lcd_locate(0,0);<br />   lcd_int((uint16_t)e.sig);<br /><br />   lcd_locate(1,0);<br />   lcd_int((uint16_t)e.par);<br />   lcd_str(&quot;  &quot;);<br /><br />}<br /><br /><br />void SST_Start(void)<br />{<br /><br />    // perform some IO anf HW initialization<br />    ioinit();<br /><br />    timer_task_id = SST_CreateTask(TIMER_TASK_PRIO, timer_task_func);<br />    event_task_id = SST_CreateTask(EVENT_TASK_PRIO, event_task_func);<br /><br />    // create a periodic task -  period is 100 calls of ticker<br />    (void) SST_MakeTimedTask(timer_task_id, 100, true, &amp;ticker);<br /><br />    // enable interrupts<br />    SST_INT_UNLOCK();<br /><br />}<br /><br /><br />void SST_OnIdle(void)<br />{<br /><br />sleep_enable();<br />    sleep_cpu();<br />    sleep_disable();<br /><br />}<br /><br /><br />int main(void)<br />{<br />    SST_Run();<br />}<br /><br /><br />// this is an ISR function for periodic timer interrupt<br />#if defined (__AVR_ATmega8__)<br />ISR(TIMER2_COMP_vect)<br />#elif defined (__AVR_ATtiny2313__)<br />ISR(TIMER0_COMPA_vect)<br />#endif<br />{<br /><br />    SST_DECLARE_ISR;<br /><br />    // do some timer HW housekeeping (if needed)<br /><br />    SST_ISR_ENTRY(SST_MIN_INT_PRIO+1);<br />    <br />    // timer tick<br />    SST_TimerTick(&amp;ticker);<br /><br />    SST_ISR_EXIT();<br /><br />}[/syntax]<br /><br />dodatkowo w pliku sst_base_def.h trzeba sobie ustawić kilka rzeczy. U mnie wyglądało to tak:<br />[syntax=c]#define SST_MAX_NO_OF_TASKS     2<br />#define SST_MAX_EV_QUEUE_LEN    2<br />#define SST_MAX_TASK_PRIO       100<br />#define SST_USE_EOI             0<br /><br />#define SST_USE_SIGNAL_MASK     0<br />#define SST_USE_LAZY_TIMER      0<br /><br /><br />typedef uint8_t CPU_Base_T;<br />typedef uint8_t CPU_SR_T;[/syntax]<br /><br />Wrzucę na wszelki wypadek w załączniku cały projekt bez bibliotek Mirka, bo nie jestem pewien czy czasem nie edytowałem czegoś w reszcie plików.<br /><br />Aha, kompilowałem pod toolchainem atmela. W winavr nie znajdzie pliku bool.h, trzeba go dorobić ręcznie i dołączyć.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4440">Federerer</a> — 9 sie 2014, o 21:23</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Aress]]></name></author>
<updated>2014-08-09T07:44:38+01:00</updated>
<published>2014-08-09T07:44:38+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90803#p90803</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90803#p90803"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90803#p90803"><![CDATA[
OK. Dzięki wielkie Wam za pomoc. <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />Federerer jak to nie stwarza Ci żadnego problemu to chętnie zobaczę jaki jest jeszcze na to sposób.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5096">Aress</a> — 9 sie 2014, o 07:44</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Federerer]]></name></author>
<updated>2014-08-09T00:04:45+01:00</updated>
<published>2014-08-09T00:04:45+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90797#p90797</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90797#p90797"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90797#p90797"><![CDATA[
No tu nie ma niestety priorytetów i wywłaszczania a funkcje są wykonywane w przerwaniu, więc nie należy przesadzać z objętością, bo będziemy gubić milisekundy jeżeli funkcja się nie wyrobi. W razie czego można zmniejszyć rozdzielczość timera do 10 ms, lub w przerwaniu odblokowywać przerwania, co pozwoli na ich zagnieżdżanie. Jeśli by następnie dodać do funkcji priorytety to dostaniemy właśnie Super Simple Taskera. Mam gdzieś uruchomiony przykład z wykorzystaniem bibliotek stworzonych przez Artura Lipowskiego. Przy ustawieniu najwyższego priorytetu dla obsługi timera wywoływanego co 1 ms można nawet w innej funkcji wrzucić _delay_ms albo nieskończoną pętlę a system co 1 ms sprawdzi czy nie ma czegoś ważniejszego do roboty, wykona to i wróci do mielenia delayem <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> a jeśli nie ma nic do roboty to uśpi procesor do następnego przerwania od timera. Jutro wrzucę i opiszę, bo myślę, że koncepcja jest dość ciekawa, a nie znalazłem w sieci przykładów zastosowania. Jedyne co, to trzeba pilnować użycia stosu, bo jak &quot;się zagnieździmy&quot; za bardzo to program pójdzie w maliny <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=4440">Federerer</a> — 9 sie 2014, o 00:04</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[atmel]]></name></author>
<updated>2014-08-08T23:15:47+01:00</updated>
<published>2014-08-08T23:15:47+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90796#p90796</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90796#p90796"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90796#p90796"><![CDATA[
O to jest właśnie to czego Koledze Aress potrzeba <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br /><br />SPAM:<br />Ja z kolei na potrzeby dość rozbudowanego projektu musiałem dynamicznie tworzyć zadania oraz funkcje, które będą im przyporządkowywane, dodatkowo z wywłaszczeniem. Niestety nie znalazłem żadnego gotowego rozwiązania i myślałem żeby całkiem przejść na ASM'a, ale przy tak świetnych poradnikach Mirka o wstawkach asemblerowych postanowiłem wszystko napisać w C, a jedynie krytyczne modyfikacje stosu umieścić w takich właśnie procedurkach <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" /><br /><br />Problem autora tematu nie wymaga jednak aż tak złożonego podejścia, dlatego z pewnością z przedstawionym powyższym kodem wszystko będzie działać jak należy <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=1183">atmel</a> — 8 sie 2014, o 23:15</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Federerer]]></name></author>
<updated>2014-08-08T22:57:37+01:00</updated>
<published>2014-08-08T22:57:37+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90795#p90795</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90795#p90795"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90795#p90795"><![CDATA[
Ja bym doradził jeszcze nie pisanie w ten sposób:<br />[syntax=c]DDRB = 0x02;[/syntax]<br /><br />a tak:<br />[syntax=c]DDRB = (1&lt;&lt;PB1);[/syntax]<br /><br />Wtedy łatwiej innym analizować kod <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br /><div class="quotetitle">atmel napisał(a):</div><div class="quotecontent"><br />&quot;scheduler z dispatcher'em&quot; (system operacyjny [jakiś RTOS])<br /></div><br /><br />Ja ostatnio uruchomiłem na avrach Super Simple Tasker. Tylko, że trochę to zasobożerne w porównaniu do timera, ale zadania można kolejkować i jest też coś w stylu wywłaszczania.<br /><br />Z prostszych rozwiązań z timerami programowymi, można np tak:<br /><br />main.c<br />[syntax=c]/*<br /> * main.c<br /> *<br /> *  Created on: 18-07-2014<br /> *      Author: Federerer<br /> */<br /><br /><br />#include &lt;avr/io.h&gt;<br />#include &quot;soft_timer.h&quot;<br /><br />void tsr_timer1(void);<br />void tsr_timer2(void);<br />void tsr_timer3(void);<br />void tsr_timer4(void);<br />void tsr_timer5(void);<br /><br />timer_t timer1, timer2, timer3, timer4, timer5;<br /><br />int main (void)  {<br /><br />DDRD = (1&lt;&lt;PD0) | (1&lt;&lt;PD1) | (1&lt;&lt;PD2) | (1&lt;&lt;PD3) | (1&lt;&lt;PD4);<br /><br />set_timer( &amp;timer1, 100, tsr_timer1 );<br />set_timer( &amp;timer2, 250, tsr_timer2 );<br />set_timer( &amp;timer3, 700, tsr_timer3 );<br />set_timer( &amp;timer4, 1100, tsr_timer4 );<br />set_timer( &amp;timer5, 1300, tsr_timer5 );<br /><br />enable_timers();<br /><br />while(1) {<br /><br />//pusta pętla<br /><br />}<br /><br />}<br /><br />void tsr_timer1(void) {<br /><br />PORTD ^= (1&lt;&lt;PD0);// jakieś miganie ledem<br /><br />}<br /><br />void tsr_timer2(void) {<br /><br />PORTD ^= (1&lt;&lt;PD1);<br /><br />}<br /><br />void tsr_timer3(void) {<br /><br />PORTD ^= (1&lt;&lt;PD2);<br /><br />}<br /><br />void tsr_timer4(void) {<br /><br />PORTD ^= (1&lt;&lt;PD3);<br /><br />}<br /><br />void tsr_timer5(void) {<br /><br />PORTD ^= (1&lt;&lt;PD4);<br /><br />}[/syntax]<br /><br />soft_timer.h<br />[syntax=c]/*<br /> * soft_timer.h<br /> *<br /> *  Created on: 19-07-2014<br /> *      Author: Federerer<br /> */<br /><br />#ifndef SOFT_TIMER_H_<br />#define SOFT_TIMER_H_<br /><br />#ifdef __cplusplus<br />extern &quot;C&quot; {<br />#endif<br /><br />// maksymalna ilość timerów<br />#define TIMERS_COUNT 5<br /><br />typedef struct {<br /><br />uint16_t interval;<br />uint16_t time;<br />void (*wsk)(void);<br /><br />} timer_t;<br /><br /><br />extern timer_t *wskazniki&#91;&#93;;<br />extern uint8_t timer_n;<br /><br />void enable_timers(void);<br /><br />void set_timer ( timer_t * timer, uint16_t interval, void (*wsk)(void) );<br /><br />void timer_event(void);<br /><br />#ifdef __cplusplus<br />}<br />#endif<br /><br />#endif /* SOFT_TIMER_H_ */[/syntax]<br /><br />soft_timer.c<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &quot;soft_timer.h&quot;<br /><br />timer_t *wskazniki&#91;TIMERS_COUNT&#93;;<br />uint8_t timer_n;<br /><br />void enable_timers(void)  {<br /><br />// może wymagać modyfikacji tak, by przerwanie wywoływane było co 1 ms<br />TCCR0A |= (1 &lt;&lt; WGM01); // tryb CTC<br />TCCR0B |= (1 &lt;&lt; CS01) | (1 &lt;&lt; CS00); // prescaler 64<br />OCR0A = (uint8_t) (F_CPU / 64 / 1000); // 1ms<br />TIMSK |= (1 &lt;&lt; OCIE0A);<br /><br />sei();<br /><br />}<br /><br />void set_timer ( timer_t * timer, uint16_t interval, void (*wsk)(void) ) {<br /><br />timer-&gt;interval = interval;<br />timer-&gt;time = interval;<br />timer-&gt;wsk = wsk;<br />wskazniki&#91;timer_n&#93; = timer;<br />timer_n++;<br /><br />}<br /><br />void timer_event(void) {<br /><br />for(uint8_t i=0; i &lt; timer_n; i++) {<br /><br />wskazniki&#91;i&#93;-&gt;time--;<br /><br />if(!(wskazniki&#91;i&#93;-&gt;time)) {<br /><br />wskazniki&#91;i&#93;-&gt;time = wskazniki&#91;i&#93;-&gt;interval;<br />if(wskazniki&#91;i&#93;-&gt;wsk) wskazniki&#91;i&#93;-&gt;wsk();<br /><br />}<br /><br />}<br /><br />}<br /><br /><br />ISR(TIMER0_COMPA_vect){<br /><br />timer_event();<br /><br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4440">Federerer</a> — 8 sie 2014, o 22:57</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[atmel]]></name></author>
<updated>2014-08-08T23:04:11+01:00</updated>
<published>2014-08-08T22:46:43+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90794#p90794</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90794#p90794"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90794#p90794"><![CDATA[
Sądzę że z tego powodu o którym pisałem tzn. opóźnienie 400ms powoduje bardzo rzadkie &quot;odpytywanie&quot; przycisku, co w efekcie może dać odczucie braku płynności działania. Dla testu spróbuj zakomentować linie z wywołaniem funkcji &quot;miganie&quot; i spróbować czy będzie ok. Jeśli tak to masz co najmniej dwa proste wyjścia:<br />1. Zmianę stanu portu C zrealizować w przerwaniu od któregoś timer'a.<br />2. Przycisk obsługiwać poprzez przerwanie zewnętrzne (INTx).<br /><br />Jest oczywiście jeszcze całe mnóstwo sposobów, ale podaje te, które się &quot;nie zemszczą&quot;, bo z doświadczenia wiem, że chcąc zrobić coś na szybko &quot;na około&quot; to w najmniej odpowiednim momencie da o sobie znać. Mimo tej zasady i raczej bezkompromisowego zwolennika przerwań, podam sposób, który powinien działać, ale nie polecam go na dłuższą metę.<br />Oczywiście jeśli jest to finalny program i wszystko działa jak należy oraz nie planujesz jego późniejszej rozbudowy to poniższy kod może być jak najbardziej ok <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />[syntax=c]int main(void)<br />{<br />   inicjalizacja();<br />   uint16_t Time = 0;<br />   while (1) {<br />      if (Time == 200)<br />         PORTC = 0x01;<br />      else if (Time == 400) {<br />         PORTC = 0x02;<br />         Time = 0;<br />      }<br />      jasnosc();<br />      Time++;<br />      _delay_ms(1);<br />   }<br />   return 0;<br />}[/syntax]<br /><br />Ma to oczywiście tę wadę, że przy naciśnięciu przycisku ten czas dodatkowo wydłuży się o 60ms (swoją drogą trochę zbyt dużo, spokojnie wystarczy 20-30ms), ale to już pozostawiam Tobie do dalszych rozważań nad tym, czy jest to wogóle dobra droga, bo moim zdaniem NIE i radzę zastosowanie przerwań.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1183">atmel</a> — 8 sie 2014, o 22:46</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Aress]]></name></author>
<updated>2014-08-08T22:31:42+01:00</updated>
<published>2014-08-08T22:31:42+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90793#p90793</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90793#p90793"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90793#p90793"><![CDATA[
Ogólnie działa tylko to PWM nie zawsze reaguje na przycisk. Wiesz może czemu? I dzięki wielkie za pomoc.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5096">Aress</a> — 8 sie 2014, o 22:31</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[atmel]]></name></author>
<updated>2014-08-08T22:15:18+01:00</updated>
<published>2014-08-08T22:15:18+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90787#p90787</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90787#p90787"/>
<title type="html"><![CDATA[Re: Sterowanie PWM i wł/wył portów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90787#p90787"><![CDATA[
Trudno się dziwić, skoro program &quot;wpada&quot; w nieskończoną pętle.<br />Umieść pętle &quot;while&quot; z obu funkcji jako jedną obejmującą wywołania tych funkcji. Funkcja &quot;inicjalizacja&quot; powinna być wywoływana tylko raz przed główną pętlą programu.<br /><br />[syntax=c]int main(void)<br />{<br />   inicjalizacja();<br />   while (1) {<br />      miganie();<br />      jasnosc();<br />   }<br />   return 0;<br />}[/syntax]<br /><br />Nie zamieszczam całego kodu, a tylko ten fragment, bo z funkcji &quot;miganie&quot; oraz &quot;jasnosc&quot; wystarczy usunąć pętle &quot;while&quot; oraz wywołanie funkcji &quot;inicjalizacja&quot;.<br /><br />Rozumiem, że chciałeś zrobić coś na wzór zadań (wątków), ale do takich działań niezbędny jest tzw &quot;scheduler z dispatcher'em&quot; (system operacyjny [jakiś RTOS]), albo chociaż obsługa timerów (również programowych).<br />W związku z czym zapewne nie będziesz miał zakładanych rezultatów, ponieważ program przez funkcję &quot;miganie&quot; zostanie wstrzymany na 400ms...<br /><br />Aha i tak na przyszłość umieszczaj kod na forum w znacznikach SYNTAX a nie Code.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1183">atmel</a> — 8 sie 2014, o 22:15</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Aress]]></name></author>
<updated>2014-08-20T06:43:49+01:00</updated>
<published>2014-08-08T21:59:42+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90784#p90784</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90784#p90784"/>
<title type="html"><![CDATA[Sterowanie PWM i wł/wył portów, problem z INTx]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8071&amp;p=90784#p90784"><![CDATA[
Witam. Mam problem z napisaniem programu, który by co określony czas wł i wył port i przy tym samym, żeby można było sterować PWM. Jestem dopiero początkujący w pisaniu programów w języku C. <br />Program, który napisałem wykonuje tylko tą czynność która jest pierwsza w poleceniu &quot; int main(void) &quot;. Jak jest na początku &quot; miganie &quot; to steruje portami, a gdy daje na początek &quot; jasnosc &quot; to działa tylko PWM. <br />Prosiłbym o podpowiedź jak to można połączyć aby działało wszystko razem. Pozdrawiam.<br /><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#define swich bit_is_clear(PINB,0)<br />#define PWM_A (1&lt;&lt;PB1)<br /><br /><br /><br />void inicjalizacja(void)<br />{<br /><br />// USTAWIENIE WYJŚĆ<br />DDRB |= (PWM_A);    //Wyjścia PWM<br /><br />DDRB = 0x02;<br />DDRC = 0x07;<br /><br />PORTB = 0x01;<br />PORTC = 0x00;<br /><br />// INICJALIZACJA PWM<br />TCCR1A |= (1&lt;&lt;WGM10);<br />TCCR1A |= (1&lt;&lt;COM1A1);<br />TCCR1B |= (1&lt;&lt;CS11);<br /><br />}<br /><br />char przycisk(void)<br />{<br /><br />PORTB = 0x01;<br />if(swich)<br />{<br />_delay_ms(60);<br />if(swich) {while (swich){};}<br />else return 0;<br />return 1;<br />}<br />else return 0;<br /><br />// Eliminacja drgań styków<br />}<br /><br />void czas1(void)<br />{<br />//Sterowanie prędkością<br />OCR1A =   200;      //Kanał PWM<br /><br /><br />}<br /><br />void czas2(void)<br />{<br />//Sterowanie prędkością<br />OCR1A =   50;      //Kanał PWM<br /><br /><br />}<br /><br />void miganie(void)<br />{<br />inicjalizacja();<br />while(1)<br />{<br />_delay_ms(200);<br />PORTC = 0x01;<br />_delay_ms(200);<br />PORTC = 0x02;<br />}<br />}<br /><br />void jasnosc(void)<br />{<br /><br />inicjalizacja();<br />static char n=1;<br />while(1)<br />{<br />if(przycisk())n++;<br />switch (n)<br />{<br />    case 1:<br />      czas1();<br />    break;<br /><br />    case 2:<br />      czas2();<br />    break;<br /><br />    default:<br />      n=1;<br />    break;<br />}<br />}<br />}<br /><br /><br />int main(void)<br />{<br /><br /><br />miganie();<br /><br />jasnosc();<br />return 0;<br />}[/syntax]<br /><br /><span style="color: #FF0000"><strong>Proszę poprawić post ....  kody umieszczamy w znacznikach SYNTAX    -SunRiver</strong></span><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=5096">Aress</a> — 8 sie 2014, o 21:59</p><hr />
]]></content>
</entry>
</feed>