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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2017-10-07T20:36:13+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=23&amp;t=11552&amp;mode</id>
<entry>
<author><name><![CDATA[jnk0le]]></name></author>
<updated>2015-05-10T10:57:37+01:00</updated>
<published>2015-05-10T10:57:37+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128737#p128737</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128737#p128737"/>
<title type="html"><![CDATA[Re: USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128737#p128737"><![CDATA[
Tak, ale tylko do użytku wewnątrz tegoż pliku.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=8491">jnk0le</a> — 10 maja 2015, o 10:57</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[ryba84]]></name></author>
<updated>2015-05-09T19:02:00+01:00</updated>
<published>2015-05-09T19:02:00+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128676#p128676</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128676#p128676"/>
<title type="html"><![CDATA[Re: USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128676#p128676"><![CDATA[
Dzięki za podpowiedzi. Myślałem o rozwiązaniu z makrami, i może dorobię takie do wykorzystania w bibliotece. Na razie naniosłem kolejne poprawki w kodzie usuwając poważny błąd przy wykrywaniu przepełnienia bufora odbioru (funkcja, która powinna być wywoływana przy przepełnieniu była wywoływana przy każdym odebraniu danych).<br />A tak z innej beczki czy dopuszczalne jest definiowanie makr w pliku*.c?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3170">ryba84</a> — 9 maja 2015, o 19:02</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[jnk0le]]></name></author>
<updated>2017-10-07T20:36:13+01:00</updated>
<published>2015-05-03T19:20:00+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128145#p128145</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128145#p128145"/>
<title type="html"><![CDATA[Re: USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=128145#p128145"><![CDATA[
Dosyć ciekawe podejście z callbackami.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=8491">jnk0le</a> — 3 maja 2015, o 19:20</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[ryba84]]></name></author>
<updated>2015-04-30T21:49:34+01:00</updated>
<published>2015-04-30T21:49:34+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127909#p127909</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127909#p127909"/>
<title type="html"><![CDATA[Re: USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127909#p127909"><![CDATA[
Mam to ustawione i to się odnosi tylko do nieużywanych funkcji. Tutaj problemem jest część kodu znajdująca się w funkcji. Pomijając sprawdzanie czy funkcje zostały zarejestrowane zyskujemy 12 bajtów w tym konkretnym przykładzie (program ma 898bajtów bez sprawdzania i 910 bajtów z, co dla Atmegi2560 akurat ma kolosalne znaczenie <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> ). Brak rejestracji funkcji może wprowadzać w błąd (ciągłe resetowanie się procka) i w konsekwencji szukanie błędu nie tam gdzie trzeba. W pierwszym poście poprawiłem to dla innych. Ja albo sobie dorobię makra do wyłączania zbędnych sekcji, albo może znajdą się flagi wywalające zbędny kod. Tylko to nie takie proste, bo kompilator nie kompiluje od razu całego projektu tylko pliki po kolei, więc kompilując usart.c nie wie jeszcze czy użyszkodnik będzie rejestrował callbacki w głównym programie. Trafiłem kiedyś na flagi możliwe do użycia tylko jak wszystko kompilowało się z jednej linii polecenia, ale nie działają z najnowszym toolchain Atmela (albo ja nie umiem ich użyć).<br /><br />EDYTA:<br />Są dwie opcje kompilacji: <ul><li>-fwhole-program - tego nie umiem w ogóle zmusić do działania - trzeba przekazywać wszystkie pliki źródłowe na raz do kompilatora</li><li>-flto - pod Eclipse tworzy większy kod (1416 bajtów), ale z linii komend daje 894 bajty (system linux):<div class="codetitle"><b>Code:</b></div><div class="codecontent">avr-gcc -Wall -I&quot;/home/ryba/Programowanie/avr/usart_lib&quot; -Os -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -ffreestanding -fno-tree-scev-cprop -mcall-prologues -flto -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega2560 -DF_CPU=16000000UL -MD -MP -MT -MF&quot;usart_lib.d&quot; &quot;../usart.c&quot; &quot;../main.c&quot; -mmcu=atmega2560 -Wl,--relax -Wl,--gc-sections -Wl,-Map=usart_lib.map -o usart_lib.elf</div>żeby nie było tak różowo to i w Eclipse i z linii komend wali warningiem:<div class="codetitle"><b>Code:</b></div><div class="codecontent">In function '__vector_25':<br />../main.c:74:1: warning: '_vector_25' appears to be a misspelled signal handler &#91;enabled by default&#93;<br /> ISR(USART0_RX_vect) {<br /> ^<br />In function '__vector_27':<br />../main.c:78:1: warning: '_vector_27' appears to be a misspelled signal handler &#91;enabled by default&#93;<br /> ISR(USART0_TX_vect) {</div>co nie zmienia faktu, że program działa.</li></ul>Pierwsza opcja może być wydajniejsza gdyż wszystkie funkcje w plikach traktuje jako statyczne pozwalając na bardziej agresywną optymalizację, ale ja nie umiem jej zmusić do działania.<br /><br />EDYTA2:<br />Działa też -fwhole-program nawet w Eclipse. Tylko żeby działało musiałem dać na górze main.c[syntax=c]#include &quot;usart.c&quot;[/syntax]co nie jest zbyt ładną praktyką. Daje to kod wielkości 816 bajtów (ok. 10% mniejszy)!!! Według dokumentacji GCC nie wolno łączyć obu optymalizacji.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3170">ryba84</a> — 30 kwi 2015, o 21:49</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[lemurek]]></name></author>
<updated>2015-04-30T21:20:09+01:00</updated>
<published>2015-04-30T21:20:09+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127908#p127908</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127908#p127908"/>
<title type="html"><![CDATA[Re: USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127908#p127908"><![CDATA[
jeśli chodzi o flagi to <br />W konfiguracji projektu C/C++ Build -&gt; Settings -&gt; AVR Compiler -&gt; Optimization zaznaczone opcje -ffunction-sections oraz -fdata-sections<br />ewentualnie w starszej wersji avr plugin dopisać w Other Optimization Flags <br /><div class="codetitle"><b>Code:</b></div><div class="codecontent">-ffunction-sections -fdata-sections</div><br />następnie w  AVR C Linker -&gt; General -&gt; Other Arguments dopisać <br /><div class="codetitle"><b>Code:</b></div><div class="codecontent">-Wl,--gc-sections</div><br /><br />i jeśli dobrze pamiętam to Eclipse Gadget ma tez opcję z dodaniem tych parametrów do projektu<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=776">lemurek</a> — 30 kwi 2015, o 21:20</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[ryba84]]></name></author>
<updated>2015-04-30T21:12:34+01:00</updated>
<published>2015-04-30T21:12:34+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127906#p127906</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127906#p127906"/>
<title type="html"><![CDATA[Re: USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127906#p127906"><![CDATA[
To by było ciekawe czy działa pod PIC. Jak jest możliwość pomijania zbędnego kodu w GCC to z chęcią z niej skorzystam. Albo może jakiś warning/błąd podczas kompilacji, że nie zarejestrowałem funkcji. Ja dopiero raczkuję w C i tylko w wolnym czasie, więc jak są jakieś sugestie to z chęcią ich posłucham(przeczytam <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=3170">ryba84</a> — 30 kwi 2015, o 21:12</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[ryba84]]></name></author>
<updated>2015-04-30T21:14:05+01:00</updated>
<published>2015-04-30T20:51:49+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127903#p127903</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127903#p127903"/>
<title type="html"><![CDATA[Re: USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127903#p127903"><![CDATA[
Nie tak ostro bo w piórka obrosnę <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />. Masz rację powinienem sprawdzać czy mam podpięty callback bo program pójdzie w maliny, ale chciałem kilkadziesiąt bajtów zaoszczędzić (chyba, że masz pomysł jakich flag optymalizacji użyć aby GCC samo usuwało zbędny kod). Z drugiej strony jeśli użytkownik nie zarejestruje funkcji to i tak mu nie będzie działać to co chce. Sprawdzam tylko czy ktoś chce obsługiwać przepełnienie bufora. Reszta ma być bo inaczej nie działa <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />. Tak trzeba się wysilić aby użyć tej biblioteki (inicjalizacja), ale dzięki takiemu podejściu jak się przesiądę na jakiś inny procek (ARM?PIC?) to nadal można korzystać z tego kodu (chyba <img src="https://forum.atnel.pl/images/smilies/icon_question.gif" alt=":?:" title="Znak zapytania" /> ). Za to dorobienie do tego obsługi RS485 w trybie half duplex jest banalnie proste, bo wystarczy wachlować dodatkowym pinem podczas uruchamiania i wyłączania trybu nadawania. Kombinowałem z napisaniem jakiejś prostej funkcji inicjalizacji pod AVR z callbackiem pod rejestry użyszkodnika, ale to moim zdaniem strata czasu. Równie dobrze może być tak jak jest, a po niewielkich przeróbkach (które za jakiś czas wrzucę) możemy korzystać z kilku USART-ów na raz z oddzielnymi buforami dla każdego z nich.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3170">ryba84</a> — 30 kwi 2015, o 20:51</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[ryba84]]></name></author>
<updated>2015-05-09T18:47:30+01:00</updated>
<published>2015-04-30T20:25:26+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127900#p127900</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127900#p127900"/>
<title type="html"><![CDATA[USART po raz n-ty.]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=11552&amp;p=127900#p127900"><![CDATA[
Witam.<br /><br />Chciałbym się podzielić z Wami biblioteką mojego autorstwa służącą do obsługi USART w AVR. Celem było napisanie jak najbardziej uniwersalnej oraz nieblokującej obsługi USART.<br />Funkcjonalność biblioteki:<br /><ul><li>Pełna niezależność od rejestrów procesora(naoglądałem się Mirka poradników o callbackach <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" />) - ta przyjemność pozostaje po stronie użytkownika.</li><li>Obsługa buforów cyklicznych z obsługą przepełnienia - po jednym dla nadawania i odbierania danych.</li><li>Nieblokujące funkcje wysyłania i odbierania - transmisja z i do bufora odbywa się w przerwaniach.</li></ul>Poniżej kod biblioteki:<br />usart.h<br />[syntax=c]/*<br /> * usart.h<br /> *<br /> *  Created on: 27 kwi 2015<br /> *      Author: Piotr Rudzki ryba.lodz@gmail.com<br /> *Version: 1.0<br /> *Changelog:<br /> *1.0 - added macro definitions to use when more compact code is needed.<br /> *- removed bug in usartRxIsrRoutine - bad detecting buffer overflow.<br /> *0.9 - added missing tests when calling callback functions.<br /> *- added _rxDataReady callback.<br /> *- moved buffers definitions.<br /> *- added txStarted flag.<br /> *0.8 - initial release.<br /> */<br /><br />#ifndef USART_H_<br />#define USART_H_<br /><br />#include &lt;stdint.h&gt;<br />#include &lt;avr/io.h&gt;<br /><br />// Pojemność buforów danych. W celu szybszej obsługi wielkość buforów powinna być potęgą 2.<br />// Maksymalna pojemność bufora 256.<br />#define BUFFER_LENGHT 16<br />#define USART_TX_ENABLE // Włączenie kodu nadawania. Dodaje do kodu tylko flagę nadawania do zmiennych globalnych.<br /><br />// Dodatkowe definicje jeśli nie chcemy korzystać z mechanizmów callback,<br />// np. w celu optymalizacji kodu (oszczędność ~150bajtów).<br />// Definicja funkcji rozpoczynającej odbiór danych.<br />/*#define USART_RX_START(UCSR0B |= (1 &lt;&lt; RXEN0))<br />// Definicja wywoływana podczas przepełnienia bufora odbioru.<br />#define USART_RX_BUFFER_FULLextern void rxBufferFull(void);\<br />rxBufferFull()<br />// Definicja funkcji wywoływanej po odebraniu pierwszych danych.<br />#define USART_RX_DATA_READYextern void rxDataReady(void);\<br />rxDataReady()<br />// Definicja funkcji rozpoczęcia nadawania.<br />#define USART_TX_START(UCSR0B |= (1 &lt;&lt; TXEN0))<br />// Definicja funkcji końca nadawania.<br />#define USART_TX_STOP(UCSR0B &amp;= ~(1 &lt;&lt; TXEN0))<br />*/<br /><br />// Struktura opisująca kolejkę FIFO.<br />typedef struct {<br />uint8_t tail; // wskaźnik na początek bufora<br />uint8_t head; // wskaźnik na koniec bufora<br />uint8_t buff&#91;BUFFER_LENGHT&#93;; // bufor z danymi<br />} fifo_t;<br /><br />// Definicje funkcji biblioteki. Część można zastąpić makrami definiowanymi powyżej.<br />// Odbieranie danych.<br />void regRxStart(void (*callback)(void)); // Rejestracja funkcji wywoływanej podczas startu odbierania.<br />void regRxBufferFull(void (*callback)(void)); // Rejestracja funkcji wywoływanej podczas przepełnienia bufora odbioru.<br />void regRxDataReady(void (*callback)(void)); // Rejestracja funkcji wywoływanej po odebraniu bajtu danych.<br />void usartRxStart(); // Start odbioru danych.<br />int16_t usartReadRxBuffer(volatile fifo_t *rxBuffer); // Odczyt danych z bufora odbioru.<br />void usartRxIsrRoutine(volatile uint8_t *usartDataReg, volatile fifo_t *rxBuffer); // Funkcja wywoływana w przerwaniu.<br /><br />// Nadawanie danych.<br />void regTxStart(void (*callback)(void)); // Rejestracja funkcji wywoływanej podczas startu wysyłania.<br />void regTxStop(void (*callback)(void)); // Rejestracja funkcji wywoływanej podczas końca wysyłania.<br />void usartTxStart(volatile uint8_t *usartDataReg, volatile fifo_t *txBuffer); // Start nadawania danych.<br />int8_t usartWriteTxBuffer(uint8_t data, volatile fifo_t *txBuffer); // Zapis znaku do bufora nadawania.<br />void usartTxIsrRoutine(volatile uint8_t *usartDataReg, volatile fifo_t *txBuffer); // Funkcja wywoływana w przerwaniu.<br />#endif /* USART_H_ */[/syntax]<br />usart.c<br />[syntax=c]/*<br /> * usart.c<br /> *<br /> *  Created on: 27 kwi 2015<br /> *      Author: Piotr Rudzki ryba.lodz@gmail.com<br /> *Version: 1.0<br /> *Changelog:<br /> *1.0 - added macro definitions to use for more compact code.<br /> *- removed bug in usartRxIsrRoutine - bad detecting buffer overflow.<br /> *- small code optimizations.<br /> *0.9 - added missing tests when calling callback functions.<br /> *- added _rxDataReady callback<br /> *- moved buffers definitions<br /> *- added txStarted flag<br /> *0.8 - initial release<br /> */<br /><br />#include &quot;usart.h&quot;<br /><br />#ifdef USART_TX_ENABLE<br />volatile uint8_t txStarted; // Flaga nadawania. Jeśli nadawanie trwa przyjmuje wartość 1.<br />#endif<br /><br />/*<br /> * Funkcje wewnętrzne biblioteki.<br /> */<br />// Odczyt bajtu z bufora danych. Zwraca bajt z bufora lub -1 w przypadku pustego bufora.<br />static int16_t usartReadCharBuff(volatile fifo_t *buffer) {<br />if (buffer-&gt;tail != buffer-&gt;head) { // Jeśli bufor nie jest pusty.<br />uint8_t tmp = buffer-&gt;buff&#91;buffer-&gt;tail&#93;; // Odczyt kolejnego bajtu z bufora.<br />buffer-&gt;tail = (buffer-&gt;tail + 1) % BUFFER_LENGHT; // Przesuń początek bufora na następną pozycję.<br />return tmp;<br />}<br />return -1;<br />}<br />// Zapis bajtu do bufora danych. Zwraca -1 w przypadku przepełnionego bufora.<br />static int8_t usartWriteCharBuff(volatile fifo_t *buffer, uint8_t data) {<br />uint8_t next = (buffer-&gt;head + 1) % BUFFER_LENGHT; // Ustalamy numer kolejnego bajtu w buforze.<br />// Sprawdzamy czy jest miejsce w buforze.<br />if (next != buffer-&gt;tail) {<br />buffer-&gt;buff&#91;buffer-&gt;head&#93; = data; // Zapisz kolejny bajt w buforze.<br />buffer-&gt;head = next;<br />return 0;<br />}<br />return -1;<br />}<br /><br />/*<br /> * Odbiór danych.<br /> */<br />#ifndef USART_RX_START<br />// Callback wywoływany podczas uruchamiania nasłuchu.<br />void (*_usartRxStart)(void);<br />// Rejestracja powyższej funkcji.<br />void regRxStart(void (*callback)(void)) {<br />_usartRxStart = callback;<br />}<br />#endif<br />#ifndef USART_RX_BUFFER_FULL<br />// Callback wywoływany w przypadku zapełnienia bufora odbierania.<br />void (*_rxBufferFull)(void);<br />// Rejestracja powyższej funkcji.<br />void regRxBufferFull(void (*callback)(void)) {<br />_rxBufferFull = callback;<br />}<br />#endif<br />#ifndef USART_RX_DATA_READY<br />// Callback wywoływany w przypadku odebrania danych.<br />void (*_rxDataReady)(void);<br />// Rejestracja powyższej funkcji.<br />void regRxDataReady(void (*callback)(void)) {<br />_rxDataReady = callback;<br />}<br />#endif<br />#ifndef USART_RX_START<br />// Start odbioru danych.<br />void usartRxStart() {<br />if (_usartRxStart) {<br />(*_usartRxStart)();<br />}<br />}<br />#endif<br />// Odczyt danych z bufora odbioru. Zwraca -1 w przypadku pustego bufora.<br />int16_t usartReadRxBuffer(volatile fifo_t *rxBuffer) {<br />return usartReadCharBuff(rxBuffer);<br />}<br />// Wypełnianie bufora w przerwaniu. Jako argument przyjmuje rejestr bufora danych USART.<br />void usartRxIsrRoutine(volatile uint8_t *usartDataReg,<br />volatile fifo_t *rxBuffer) {<br />uint8_t tmp = *usartDataReg;<br />if (usartWriteCharBuff(rxBuffer, tmp) &gt; -1) { // Sprawdzamy czy bufor nie został przepełniony.<br />#ifndef USART_RX_DATA_READY<br />if (_rxDataReady) {<br />(*_rxDataReady)(); // Odebrano dane.<br />}<br />#else<br />USART_RX_DATA_READY;<br />#endif<br />} else {<br />#ifndef USART_RX_BUFFER_FULL<br />if (_rxBufferFull) {<br />(*_rxBufferFull)(); // Przepełnienie bufora odbioru.<br />}<br />#else<br />USART_RX_BUFFER_FULL;<br />#endif<br />}<br />}<br /><br />/*<br /> * Wysyłanie danych<br /> */<br />#ifndef USART_TX_START<br />// Callback wywoływany podczas uruchamiania nadawania.<br />void (*_usartTxStart)(void);<br />// Rejestracja powyższej funkcji.<br />void regTxStart(void (*callback)(void)) {<br />_usartTxStart = callback;<br />}<br />#endif<br />#ifndef USART_TX_STOP<br />// Callback wywoływany podczas wyłączania nadawania.<br />void (*_usartTxStop)(void);<br />// Rejestracja powyższej funkcji.<br />void regTxStop(void (*callback)(void)) {<br />_usartTxStop = callback;<br />}<br />#endif<br />// Start nadawania. Jeśli wywołamy przy pustym buforze to nie uruchomi nadawania.<br />void usartTxStart(volatile uint8_t *usartDataReg, volatile fifo_t *txBuffer) {<br />if (txStarted == 0) {<br />int16_t tmp = usartReadCharBuff(txBuffer);<br />if (tmp &gt; -1) { // Sprawdzamy czy było coś w buforze.<br />txStarted = 1;<br />#ifndef USART_TX_START<br />if (_usartTxStart) {<br />(*_usartTxStart)(); // Uruchamiamy nadawanie.<br />}<br />#else<br />USART_TX_START;<br />#endif<br />*usartDataReg = tmp; // Wysyłamy pierwszy znak - reszta z bufora pójdzie w przerwaniu.<br />}<br />}<br />}<br />// Zapis znaku do bufora. Zwraca -1 w przypadku przepełnienia bufora.<br />int8_t usartWriteTxBuffer(uint8_t data, volatile fifo_t *txBuffer) {<br />return usartWriteCharBuff(txBuffer, data);<br />}<br />// Wysyłanie danych w przerwaniu. Jako argument przyjmuje rejestr bufora danych USART.<br />void usartTxIsrRoutine(volatile uint8_t *usartDataReg,<br />volatile fifo_t *txBuffer) {<br />int8_t tmp = usartReadCharBuff(txBuffer);<br />if (tmp &gt; -1) { // Sprawdzamy czy jest coś w buforze nadawania.<br />*usartDataReg = tmp; // Wysyłamy kolejny bajt z bufora.<br />} else {<br />txStarted = 0;<br />#ifndef USART_TX_STOP<br />if (_usartTxStop) {<br />(*_usartTxStop)(); // Wyłączamy nadawanie danych.<br />}<br />#else<br />USART_TX_STOP;<br />#endif<br />}<br />}[/syntax]<br />I oczywiście przykładowe wykorzystanie biblioteki. Tutaj proste echo odebranych danych wersja dla Atmegi2560:<br />main.h<br />[syntax=c]/*<br /> * main.h<br /> *<br /> *  Created on: 27 kwi 2015<br /> *      Author: Piotr Rudzki ryba.lodz@gmail.com<br /> */<br /><br />#ifndef MAIN_H_<br />#define MAIN_H_<br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;util/setbaud.h&gt;<br /><br />#include &quot;usart.h&quot;<br /><br />#endif /* MAIN_H_ */[/syntax]<br />main.c<br />[syntax=c]/*<br /> * main.c<br /> *<br /> *  Created on: 27 kwi 2015<br /> *      Author: Piotr Rudzki ryba.lodz@gmail.com<br /> */<br /><br />// Poniżej definiujemy prędkość USART.<br />#define BAUD 38400<br /><br />#include &quot;main.h&quot;<br /><br />volatile fifo_t rxBuffer;// Bufor odbioru danych.<br />volatile fifo_t txBuffer;// Bufor nadawania danych.<br /><br />// Inicjalizacja USART0 w Mega2560.<br />static inline void usartInit() {<br />// Prędkość transmisji (definiowana w BAUD powyżej).<br />UBRR0H = UBRRH_VALUE;<br />UBRR0L = UBRRL_VALUE;<br />UCSR0A = (USE_2X &lt;&lt; U2X0);<br />// Przerwania po odebraniu i wysłaniu danych.<br />UCSR0B = (1 &lt;&lt; RXCIE0) | (1 &lt;&lt; TXCIE0);<br />// Format 8N1 (8 bitów, bez parzystości, jeden bit stopu).<br />UCSR0C = (1 &lt;&lt; UCSZ00) | (1 &lt;&lt; UCSZ01);<br />// Start przerwań.<br />sei();<br />}<br />// Start odbierania danych - wywoływany jako callback przez bibliotekę.<br />void rxStart() {<br />UCSR0B |= (1 &lt;&lt; RXEN0); // Włączenie odbiornika.<br />}<br />// Start nadawania danych - wywoływany jako callback przez bibliotekę.<br />void txStart() {<br />UCSR0B |= (1 &lt;&lt; TXEN0); // Włączenie nadajnika.<br />}<br />// Koniec nadawania danych - wywoływany jako callback przez bibliotekę.<br />void txStop() {<br />UCSR0B &amp;= ~(1 &lt;&lt; TXEN0); // Wyłączenie nadajnika.<br />}<br />// Przepełnienie bufora odbioru - wywoływany jako callback przez bibliotekę.<br />void bufferFull() {<br />// Tutaj funkcja opróżniająca bufor odbioru w razie przepełnienia.<br />}<br />void rxDataReady() {<br />// Tutaj funkcja wywoływana po pojawieniu się danych w buforze odbioru.<br />}<br /><br />int main(void) {<br />int16_t tmp; // Zmienna przechowująca odczytany bajt z bufora odbioru.<br />int8_t txBufferFlag; // Flaga zajętości bufora nadawania.<br /><br />regRxStart(rxStart); // Rejestracja funkcji uruchomiającej odbiór danych.<br />regTxStart(txStart); // Rejestracja funkcji uruchamiającej nadawanie danych.<br />regTxStop(txStop); // Rejestracja funkcji wyłączającej nadawanie danych.<br />regRxBufferFull(bufferFull); // Rejestracja funkcji wywoływanej przy przepełnieniu bufora odbioru.<br />usartInit(); // Inicjalizacja USART.<br /><br />usartRxStart(); // Start odbioru danych.<br />// Pętla programu<br />while (1) {<br />// Poniżej prosta funkcja odsyłająca odebrane dane.<br />tmp = usartReadRxBuffer(&amp;rxBuffer);<br />if (tmp &gt; -1) { // Jeśli odczytano znak z bufora.<br />txBufferFlag = usartWriteTxBuffer(tmp, &amp;txBuffer);<br />if (txBufferFlag == 0) { // Sprawdzamy czy wpisywany znak znalazł miejsce w buforze.<br />usartTxStart(&amp;UDR0, &amp;txBuffer); // Start nadawania danych.<br />}<br />}<br />// Tutaj możemy robić coś więcej bez czekania na USART.<br />}<br />}<br />// Przerwanie końca odbioru.<br />ISR(USART0_RX_vect) {<br />usartRxIsrRoutine(&amp;UDR0, &amp;rxBuffer);<br />}<br />// Przerwanie końca nadawania.<br />ISR(USART0_TX_vect) {<br />usartTxIsrRoutine(&amp;UDR0, &amp;txBuffer);<br />}[/syntax]<br />Proszę o niekopiowanie kodu w innych miejscach bez mojej zgody. Kod udostępniam do użytku niekomercyjnego.<br />Myślę, że komentarze w plikach wystarczą za wyjaśnienie sposobu użytkowania tej biblioteki. Wszelka konstruktywna krytyka mile widziana.<br />EDYTA1:<br />Zmiany w bibliotece:<ul><li>Bufory definiowane przez użytkownika, wskaźniki na nie należy przekazywać do funkcji biblioteki. Dzięki temu można zunifikować bufor jeśli transmitujemy w trybie half duplex.</li><li>Dodano callback do funkcji odbierania wywoływany po pierwszym pojawieniu się danych w buforze.</li><li>Dodano flagę wysyłania tak by nie było możliwe kilkukrotne uruchamianie wysyłania.</li></ul>EDYTA2:<br />Kolejne zmiany i poprawki.<ul><li>Dodano możliwość skorzystania z makr zamiast systemu callback-ów co zmniejsza kod wynikowy.</li><li>Usunąłem błąd w procedurze odbierania danych polegający na błędnym wykrywaniu przepełnienia bufora. Chyba nikt nie przejrzał kodu bo aż raziło <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /></li></ul><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3170">ryba84</a> — 30 kwi 2015, o 20:25</p><hr />
]]></content>
</entry>
</feed>