AVR GCC kompilator C dla mikrokontrolerów AVR, część 12


K U R S
AVR GCC: kompilator C dla
mikrokontrolerów AVR, część 12
Obsługa interfejsu USART
Jako uzupełnienie odcinków o przerwaniach przedstawiamy
przykłady ich praktycznego zastosowania. Jednym
z najpopularniejszych przykładów jest obsługa interfejsu
komunikacji szeregowej USART.
Po modyfikacjach przedstawio- na komendy z PC, nadajnik jest zajmuje się teraz handler prze-
nych w poprzedniej części artyku- włączony ale przerwania nadaj- rwania nadajnika: pobiera ko-
łu, główny plik projektu main.c nika pozostają zablokowane; lejne znaki komunikatu i ładuje
wygląda teraz następująco:  komunikacja jest zorganizowana je do rejestru UDR, natomiast
// główny moduł projektu
w trybie tekstowym, co umoż- w momencie natrafienia na znak
#define _MAIN_MOD_ 1
// pliki dołączone (include):
liwia jej wypróbowanie przy null (o wartości zerowej, który
#include  projdat.h
#include
pomocy dowolnego terminala: zawsze w standardzie C kończy
#include
#include
odbiornik reaguje na komendy łańcuch tekstowy) zatrzymuje
#include
jednoznakowe, a w odpowiedzi nadawanie wyłączając przerwa-
#define MS100_DELAY 5
mikrokontroler odsyła krótkie nie (makro TX_OFF);
// dane:
powiadomienia;  na czas nadawania dodatkowo
static char Ms100_counter;
static volatile uchar LedState = 1;
 w obsłudze przerwania odbiorni- ustawiamy flagę TX_BUSY, któ-
// funkcje:
ka wykonujemy (zgodnie z wcze- ra blokuje reakcję na dalsze
śniejszymi zaleceniami) tylko komendy (co mogłoby w trakcie
//====================
// funkcja main()
podstawowe czynności: przepi- wysyłania odpowiedzi przesta-
int main(void)
{ sanie znaku z rejestru UDR do wić wskaznik i narobić zamie-
// inicjalizacja
bufora i ustawienie flagi otrzy- szania);
OSCCAL=eeprom_read_byte((uchar*)E-
mania nowej komendy NEW_  oddzielna funkcja SendPrompt
2END);
// zapis kalibracji w ostatniej komór-
COMMAND; wysyła jednorazowy komunikat
ce eeprom
DDRB=0xff;
 flaga ta informuje program startowy po inicjalizacji.
InitT2();
główny o konieczności wykona- Pracę programu możemy obej-
InitUsart();
sei(); nia przewidzianej akcji: w na- rzeć bez fizycznego sprzętu posłu-
szym przypadku jest to wywoła- gując się opisanym już HAPSIM em
SendPrompt();
nie funkcji SendAnswer urucha- . Dodajemy okno terminala, usta-
// pętla główna
while (1)
miającej wysyłanie odpowiedzi, wiamy jego typ na usart i wyłącza-
{
// obsługa systemowego  zegarka
parametrem funkcji jest wartość my lokalne echo. Po uruchomieniu
100ms
if (MS100_FLAG)
liczbowa komendy (przeliczona AvrStudio wysyłamy z terminala
{
MS100_FLAG = false; z kodu ASCII cyfry 1...3 przy- jednoznakowe komendy otrzymując
if (++Ms100_counter == MS100_DELAY)
słanej tekstowo z terminala); z symulowanej kostki odpowiedzi
{
Ms100_counter = 0;
 funkcja akceptuje wartości 1...3, (rys. 28).
// nasza okresowa akcja (przełą-
czenie wyjścia) uruchamiana
w innych przypadkach argument Koniecznie trzeba zdawać sobie
// zegarem systemowym co 100ms *
MS100_DELAY (0,5s)
zostaje zastąpiony zerem; w taki sprawę, że zadziałanie powyższej
PORTB=LedState;
if(LedState==128) LedState=1;
sposób argument może bezpo- symulacji wcale nie jest równo-
else LedState = LedState<<1;
} średnio posłużyć jako indeks ta- znaczne z poprawną pracą rzeczy-
}
blicy AnswerTable, w której ulo- wistego zmontowanego układu. Do-
// obsługa komend przesłanych przez
kowane są wskazni-
usart
if (NEW_COMMAND)
ki na poszczególne
{
NEW_COMMAND = false;
teksty odpowiedzi;
SendAnswer(RxBuffer[0]  0x30);
}
 uruchomienie wy-
}
} syłania odpowiedzi
Jak widać obsługa naszej prostej sprowadza się do
komunikacji to w module głównym ustawienia wskaz-
tylko kilka dodatkowych linijek. nika TxPtr na po-
Działa to wszystko w następujący czątek właściwego
sposób: tekstu i włączenie
 przy starcie programu inicjali- przerwania nadajni-
zujemy USART: przerwania od- ka (makro TX_ON);
biornika są włączone i oczekują  całością wysyłania Rys. 28. Terminal znakowy symulatora HAPSIM
Elektronika Praktyczna 2/2006
107
K U R S
chodzi tutaj cały wachlarz dodat- bom. Całkiem często
kowych możliwych problemów: wystarcza coś zupeł-
 poprawność połączenia kablowe- nie zwyczajnego. Na
go ze wspólpracującym portem przykład przewiduje-
szeregowym; my okresowe podłą-
 właściwe wlutowanie i praca czenie naszego urzą-
kostki konwertera TTL< >RS dzenia do aplikacji PC
232 (np. typowy MAX232); w celu wprowadzenia
 zgodność ustawionych para- nastaw konfiguracyj-
metrów transmisji w obu urzą- nych, przeprowadzenia
dzeniach komunikacyjnych (za- kalibracji itp. Od stro-
uważmy, że HAPSIM w ogóle ny programowej spra- Rys. 29. Rozmieszczenie tekstów komunikatów w pa-
o to nie dba); wę rozwiązuje nam mięci RAM
 utrzymanie szybkości transmisji schemat komunikacji
crc:Word;
na odpowiednim poziomie (czy- master< >slave (aplikacja przesy- i,bit:Integer;
begin
li stabilna i pewna praca oscy- ła do urządzenia ramkę danych crc:=$ffff;
for i:= 1 to Length(Abuffer)  2 do
latora); o określonej długości i zawartości,
begin
crc:=crc xor Ord(Abuffer[i]);
 sprawdzona i działająca konfi- a potem czeka na analogicznie
for bit:=0 to 7 do
if odd(crc) then
guracja współpracującego portu sformatowaną odpowiedz). Wykry-
crc:=(crc shr 1) xor $a001
else
(w PC wiele zależy od zasto- cie kompletności bloku danych od-
crc:=crc shr 1;
end;
sowanego oprogramowania, np. bywa się tutaj na podstawie liczby
Result:=crc;
czasem można się spotkać z ko- odebranych lub wysłanych bajtów, end;
niecznością odpowiedniego skro- nie ma także problemów czaso- function TRejTempForm.GetRxCrc: Boole-
an;
sowania linii RTS, CTS, DSR, wych z obróbką bloku (mamy pew-
var
cr16:Word;
DTR we wtyku). ność, że w jej trakcie nie nadejdzie
begin
Move(RxBuffer[RX_SIZE  1],cr16,2);
Często pojawia się pytanie, czy następny blok, co pozwala nam
Result:= (cr16=Crc16(RxBuffer));
end;
wbudowany w AVR oscylator (ca- uniknąć dodatkowego buforowania
librated internal RC oscillator) jest np. przy użyciu typowego bufo- procedure TRejTempForm.SetTxCrc;
var
wystarczająco  pewny dla używa- ra kołowego). Jeśli zależy nam na
cr16:Word;
begin
nia w celach transmisyjnych. Na zwiększonej odporności na błędy
cr16:=Crc16(TxBuffer);
Move(cr16,TxBuffer[TX_SIZE  1],2);
ogół możemy przyjąć, że w zasto- umieszczamy na końcu ramek da-
end;
sowaniach domowych (stała poko- nych sumę kontrolną ramki. Może
jowa temperatura, przebieg trans- to być zwykła suma modulo 8 lub Zwróćmy uwagę na jeszcze je-
misji pod bezpośrednią kontrolą 16 ale avr libc dostarcza nam go- den szczegół prezentowanego przy-
 np. w przyborach warsztatowych, tową funkcję wyliczania CRC, więc kładowego projektu. Otóż łańcuchy
przystawkach do PC itp.) nie na- użycie tego silnego i niezawodnego znakowe (stringi) poszczególnych
potkamy na problemy (chociaż cza- sposobu jest całkiem niekłopotliwe. odpowiedzi ulokowane są w pa-
sem wymagane jest niewielkie do- Np. przykład współpraca aplikacji mięci RAM mikrokontrolera. Doty-
strojenie fabrycznej wartości bajtu avr gcc z programem Object Pascal czy to również tablicy zawierającej
kalibracyjnego). Natomiast w urzą- (Delphi) wygląda następująco: wskazniki na te łańcuchy (może-
void SetTxCrc(void)
dzeniu pracującym autonomicznie my to obejrzeć w oknach podglądu
{
uint CrcCalcValue;
w zmiennych warunkach termicz- zmiennych oraz pamięci w AvrStu-
int j;
nych znacznie bezpieczniej będzie dio  rys. 29). W praktyce takie
CrcCalcValue = 0xffff;
for (j=0;j<(TX_SIZE 2);j++)
przewidzieć klasyczny układ oscy- przeznaczone tylko do odczytu za-
CrcCalcValue = _crc16_update(CrcCal-
cValue,TxBuffer[j]);
latora kwarcowego. soby przechowujemy raczej w pa-
memcpy((uchar*)&TxBuffer[TX_SIZE
Powyższy przykład komunikacji  2],(uchar*)&CrcCalcValue,2); mięci programu Flash  aby nie
}
tekstowej  chociaż prosty w uru- marnować cennej (dużo mniejszej)
bool CheckRxCrc(void)
chomieniu i obsłudze  zazwyczaj przestrzeni RAM. Jednak avr gcc
{
uint CrcCalcValue;
nie wystarcza w wielu typowych ma dość specyficznie (w porówna-
uint CrcRcvValue;
int j;
zastosowaniach mikrokontrolerów, niu z komercyjnymi kompilatorami)
gdy przesyłamy bloki danych bi- CrcRcvValue = (uint)(RxBuffer[RX_SI- rozwiązaną obsługę dostępu do ob-
ZE 1] <<8) + RxBuffer[RX_SIZE 2];
narnych, wśród których mogą rzecz CrcCalcValue = 0xffff; szarów Flash oraz EEPROM. Dlate-
for (j=0;j<(RX_SIZE 2);j++)
jasna pojawić się zera. Uniemoż- CrcCalcValue = _crc16_update(CrcCal- go wrócimy do tej sprawy w od-
cValue,RxBuffer[j]);
liwia to wykorzystywanie zapre- dzielnym odcinku poświęconym
return(CrcRcvValue == CrcCalcValue);
}
zentowanego sposobu wykrywania specjalnie pamięciom AVR.
końca ramki danych. Spotkamy się Funkcje avr gcc operują bezpo- Jerzy Szczesiul, EP
z wielką liczbą rozmaitych rozwią- średnio na buforach TxBuffer oraz jerzy.szczesiul@ep.com.pl
zań protokołów komunikacyjnych RxBuffer o stałych rozmiarach ram-
stosowanych w takich przypadkach ki TX_SIZE oraz RX_SIZE. A tak to
 od całkiem prostych do wyrafi- samo realizuje Delphi po stronie UWAGA!
Środowisko IDE dla AVR GCC opracowane
nowanych i skomplikowanych. Za- PC:
function TRejTempForm.Crc16(Abuffer:
przez autora artykułu można pobrać ze
wsze więc da się wybrać sposób
String): Word;
strony http://avrside.ep.com.pl.
var
odpowiadający konkretnym potrze-
Elektronika Praktyczna 2/2006
108


Wyszukiwarka

Podobne podstrony:
AVR GCC kompilator C dla mikrokontrolerów AVR, część 11
AVR GCC kompilator C dla mikrokontrolerów AVR, część 4
AVR GCC kompilator C dla mikrokontrolerów AVR, część 3
Płytka testowa dla mikrokontrolerów AT89S oraz AVR

więcej podobnych podstron