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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2012-09-19T19:38:10+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=1564&amp;mode</id>
<entry>
<author><name><![CDATA[shoc]]></name></author>
<updated>2012-09-19T19:38:10+01:00</updated>
<published>2012-09-19T19:38:10+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=1564&amp;p=15496#p15496</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=1564&amp;p=15496#p15496"/>
<title type="html"><![CDATA[Tasks on AVR - zadania na AVR - pomysł]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=1564&amp;p=15496#p15496"><![CDATA[
Witam,<br /><br />wczoraj wpadłem na pomysł stworzenia na AVR zalążka zbioru funkcji obsługujących zadania pracujące &quot;w tle&quot;. <br />Całość opiera się o timer i flagę inkrementowaną w przerwaniu.<br /><br />Głównym celem stworzenia funkcjonalności była obsługa termometrów DS18B20, przy obsłudze których jesteśmy zmuszeni w pierwszej kolejności rozpocząć przetwarzanie danych a następnie po pewnym czasie odczytać pomiary. <br />Pewnie tą funkcję później wykorzystam do obsługi odświeżania menu w konsoli i na wyświetlaczu LCD. <br />Dzięki temu pętla główna będzie bardziej przejrzysta, na jej początku będzie można włączyć wszystkie wymagane zadania a w założeniu, w kolejnym etapie, poprzez np. terminal możliwe będzie sprawdzenie które zadania aktualnie są wykonywane - prosty task manager.<br /><br />Kod jest jedynie pomysłem, pewnie będę dalej go modyfikował, zmieniał i poprawiał, ale to uzależnione jest od wolnego czasu. <br /><br />task.h<br />[syntax=c]<br />#define NumberOfTasks 5<br /><br />typedef struct {<br />               uint8_t (*taskFunction)(void);<br />               } Task;<br /><br />Task          task[NumberOfTasks];<br /><br />uint8_t addTask(uint8_t (*function)(void));<br />uint8_t endTask(uint8_t (*function)(void));<br />uint8_t runTask(uint8_t _no);<br /><br />uint8_t testfunction(void);<br />[/syntax]<br /><br />task.c<br />[syntax=c]<br />/*<br />* Funkcja dodająca zadanie do listy zadań. <br />* Argumentem funkcji jest wskaźnik do funkcji.<br />* Wynikiem funkcji jest numer zadania.<br />*/<br /><br />uint8_t addTask(uint8_t (*function)(void))<br />{<br />   for(uint8_t i = 0; i &lt; NumberOfTasks; i++)<br />   {<br />      if(task[i].taskFunction == 0)<br />      {<br />         task[i].taskFunction = function;<br /><br />         return i;<br />      }<br />   }<br />   return 255;<br />}<br /><br />/*<br />* Funkcja kończąca zadanie<br />* Argumentem funkcji jest wskaźnik do funkcji.<br />* Wynikiem funkcji jest informacja o zakończeniu funkcji<br />*/<br />uint8_t endTask(uint8_t (*function)(void))<br />{<br />   for(uint8_t i = 0; i &lt; NumberOfTasks; i++)<br />   {<br />      if(task[i].taskFunction == function)<br />      {<br />         task[i].taskFunction = 0;<br />         return 1;<br />      }<br />   }<br />   return 0;<br />}<br /><br />/*<br />* Funkcja wykonująca określone zadanie<br />* Argumentem funkcji jest numer zadania<br />* Wynikiem funkcji jest informacja czy określone zadanie istnieje<br />*/<br />uint8_t runTask(uint8_t _no)<br />{<br />   if(task[_no].taskFunction != 0)<br />   {<br />      if(task[_no].taskFunction())<br />         endTask(task[_no].taskFunction);<br /><br />      return 1;<br />   }<br />   else<br />      return 0;<br />}<br /><br />/*<br />* Przykładowa funkcja<br />* Funkcja sprawdza warunki i w zależności od nich wykonuje odpowiednie czynności<br />* Jeżeli funkcja zwróci 0 -&gt; oznacza, że zadanie trwa i się jeszcze nie zakończyło<br />* Jeżeli zwróci wartość !0 -&gt; oznacza zakończenie funkcji i jednocześnie wywołuje zakończenie zadania (w funkcji runTask())<br />*/<br />uint8_t testfunction(void)<br />{<br />   <br />     if(!flag.tempMesure)<br />     {<br />          if ( DS18X20_start_meas( DS18X20_POWER_EXTERN, NULL ) == DS18X20_OK )<br />         {<br />           flag.tempMesure = 1;<br />         }<br />     }<br /><br />     if(flag.tempMesure &gt; 750)<br />     {<br />        //W tym miejscu następuje przetworzenie danych<br />        flag.tempMesure = 0;<br /><br />        return 1;<br />     }<br />     return 0;<br />}<br /><br />[/syntax]<br /><br />W pętli main należy dodać pętlę wykonującą poszczególne zadania.<br /><br />[syntax=c]<br />      for(uint8_t no = 0; no &lt; NumberOfTasks; no++)<br />      {<br />         runTask(no);<br />      }<br />[/syntax]<br /><br />Zadania dodajemy w prosty sposób:<br />[syntax=c]<br />addTask(&amp;testfunction);<br />[/syntax]<br /><br />Natomiast w przerwaniu od timera inkrementujemy naszą flagę, dobrze by było nie korzystać ze zmiennych globalnych i stworzyć funkcję do inkrementacji zmiennej lokalnej i na jej podstawie sterować funkcjami. (np. zmienna lokalna ms1000). <br /><br />Strukturę zawierającą informację o zadaniu można dowolnie zmodyfikować, przechowywać w niej warunki, nazwę funkcji w stringu, wyniki zadania itp.<br /><br />Prosił bym o opinie dotyczące pomysłu. Wszelkie uwagi i porady mile widziane <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> <br /><br />Pozdrawiam<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=269">shoc</a> — 19 wrz 2012, o 19:38</p><hr />
]]></content>
</entry>
</feed>