Lekcja 14: Programowa realizacja transmisji
W poprzedniej lekcji przedstawiona była transmisja szeregowa z wykorzystaniem wbudowanego w mikrokontroler 8051 sterownika transmisji szeregowej. Po odpowiednim ustawieniu sterownika, transmisja sprowadzała się w praktyce do zapisu bądź odczytu bajtu z rejestru SBUF. Jednak nie zawsze programista zastaje tak komfortowe warunki. Czasami trzeba zorganizować dwa oddzielne łącza szeregowe, a większość mikrokontrolerów posiada tylko l sterownik transmisji szeregowej. Niektóre małe mikrokontrolery w ogóle nie posiadają, sterownika transmisji szeregowej. W takich przypadkach pozostają dwa wyjścia:
• dołączyć zewnętrzny sterownik transmisji szeregowej
• zorganizować programowe sterowanie transmisji.
Pierwsze rozwiązanie prowadzi do podniesienia kosztów systemu, poboru prądu, wielkości płytki drukowanej itp. Jeśli nie ma innych przeciwwskazań, to raczej należy wykorzystać drugie rozwiązanie. W systemie DSM-51 wbudowano dwa kanały transmisji szeregowej:
COM1 - obsługiwany przez sterownik transmisji szeregowej mikrokontrolera 8051, COM2 - obsługiwany programowo przez mikrokontroler.
W niniejszej lekcji omówiona jest programowa obsługa transmisji szeregowej prowadzonej przez kanał COM2.
Dane wyjściowe są wysyłane z mikrokontrolera poprzez linię P l.O - stan na złączu jest bezpośrednim odwzorowaniem stanu tej linii. Linia ta nie jest podłączona bezpośrednio do złącza COM2, gdyż pomiędzy mikrokontrolerem a złączem musi istnieć układ dopasowania napięć. Mikrokontroler może wystawiać napięcia OV (stan 0) i 5V (stan l), natomiast transmisja szeregowa odbywa się na poziomie napięć +12V (stan 0) i -12V (stan l). Zadanie to wykonywane jest przez układ typu MAX 232.
Wysłanie bajtu polega na ustawianiu linii P l.O zgodnie z kolejnymi bitami. Każdy bit powinien być wystawiony na linię P l.O na jednakowy czas, zgodny z przyjętą prędkością transmisji. Należy jeszcze pamiętać o-wysłaniu na początku bitu startu, a na koniec bitów stopu. Poniższy przykład przedstawia prosty sposób realizacji nadawania przez kanał szeregowy.
******************** przykład 1 ***********************************
Podstawową sprawą, przy programowej realizacji transmisji szeregowej jest dokładne odliczanie czasu. Najwygodniej jest to zrealizować wykorzystując do tego celu time-ry. Ponieważ wszystkie kolejne odcinki czasu muszą być jednakowe, wykorzystano więc Timer O pracujący w trybie 2, czyli z automatycznym przeładowywaniem. Dzięki temu, kolejne przerwania od timera taktujące transmisję szeregową, przychodzą w równych odcinkach czasu, ustawianych w rejestrze THO. Zatem właśnie od wartości wpisanej do tego rejestru zależy prędkość transmisji. Ponieważ timer liczy impulsy zegarowe mikrokontrolera podzielone przez 12, prędkość transmisji wyraża się wzorem:
V = (f„sc /12 ) / okres Timera O
Ponieważ w trybie 2 timer pracuje jako 8-bitowy, minimalna prędkość transmisji przy tych ustawieniach wynosi:
V = (11.059.200 /12 )/256 = 3600
Jeżeli potrzebna jest prędkość niższa, to należy wykorzystać 16-bitowy tryb timera, ale wtedy trzeba przy każdym przerwaniu pamiętać o ładowaniu wartości początkowych do timera.
Należy oczywiście wybierać jedną ze standardowych prędkości transmisji. W przykładzie przyjęto wartość 4800 bodów. Dla tej prędkości timer musi odliczyć:
N = (l 1.059.200 /12 ) / 4800 = 192 okresy zegara
Ponieważ timer liczy w górę, więc do rejestru THO należy wpisać wartość:
256 - 192 = 64.
Transmisja bajtu rozpoczyna się od wysłania bitu startu. W tym celu należy ustawić P l.O na O i włączyć timer, który odliczy długość tego bitu (właściwa wartość timera powinna być wpisana wcześniej).
Przy kolejnych przerwaniach od timera wysyłany bajt obracany jest o jeden bit w prawo, poprzez wskaźnik przeniesienia (rozkaz RRC A). Zgodnie z bitem we wskaźniku przeniesienia ustawiany jest stan linii Pl.O. W ten sposób kolejne bity sterują linią P l. O przez czas określony timerem.
Po wysłaniu wszystkich 8 bitów, przy kolejnym przerwaniu od timera, stan linii Pl.O ustawiany jest na l. Od tego miejsca rozpoczyna się bit stopu. Timer jest zatrzymywany, gdyż nie ma potrzeby wyróżniania końca bitu stopu. Stan linii Pl.O jest równy l zarówno w czasie trwania bitu stopu, jak i pomiędzy nadawaniem bajtów. W powyższym przykładzie założono, że przed zakończeniem nadawania jednego bajtu nie będzie zainicjowane przez program główny nadawanie kolejnego bajtu. Jeżeli nie można zagwarantować, że założenie to jest zawsze prawdziwe, to należy odliczyć czas trwania bitów stopu, a program uzupełnić o flagi sygnalizujące trwanie transmisji.
Podobnie jak nadawanie, można zorganizować odbiór transmisji szeregowej. Dane wejściowe trafiają do systemu mikroprocesorowego (również poprzez układ MAX 232) jako sygnał IRS. Sygnał ten podłączony jest do sterownika przerwań. Jednak przy standardowej konfiguracji sterownika przerwań, jest on faktycznie bezpośrednio podłączony do wejścia INTO mikrokontrolera. Dzięki temu, dane przychodzące poprzez łącze szeregowe mogą zarówno generować przerwanie, jak i być bezpośrednio czytane przez mikrokontroler. W poniższym przykładzie przedstawiono sposób odbioru z kanału szeregowego.
******************* przykład 2**************************
Odbiór z kanału szeregowego jest inicjowany przychodzącym bitem startu. Początek tego bitu powoduje wygenerowanie przerwania z wejścia INTO. Od tego momentu mikrokontroler powinien odczytywać stan tej linii w równych odstępach czasu. Nie potrzeba, aby zmiany na tym wejściu powodowały przerwanie. Tak więc przerwania z wejścia INTO są blokowane, natomiast uruchamiany jest timer:
Timer, tak jak w poprzednim przykładzie, pracuje w trybie 2. Przy kolejnych przerwaniach od timera, stan linii jest odczytywany do bitu C, a następnie poprzez obrót wpisywany jest do rejestru, w którym gromadzony jest odbierany bajt. W ten sposób po 8 kolejnych przerwaniach w rejestrze zgromadzony jest cały bajt. Następne przerwanie od timera powinno trafić już w bit stopu. Stan na linii powinien być już ustawiony na „l" i nie może się zmienić, aż do transmisji kolejnego bajtu. Można więc zatrzymać timer i odblokować przerwanie z wejścia INTO. Dzięki temu, bit startu kolejnego bajtu ponownie zainicjuje odbiór.
Prędkość transmisji nigdy nie jest idealnie ustawiona ani w nadajniku, ani w odbiorniku. Powstałe błędy mogą się kumulować przy odczycie kolejnych bitów. Dlatego też najbezpieczniej odczytywać wartość danego bitu w środku czasu jego trwania. Zatem pierwszy odliczany czas powinien odpowiadać długości nie jednego a półtora bitu (od początku bitu startu do połowy pierwszego bitu).
W przykładzie przy prędkości 4800 bodów należało odliczyć 192 x 1.5 = 288 impulsy zegarowe. Liczba ta jest większa od 256, więc należałoby zmienić tryb pracy time-ra. Aby tego uniknąć, zastosowano inne rozwiązanie. Najpierw odliczany jest czas równy połowie jednego bitu, czyli 192 x 0.5 = 96 impulsów zegarowych. Następnie, już w odstępach l bitu, odczytywanych jest kolejno 9 bitów. Pierwszy z nich jest bitem startu. Jednak przy zastosowanej metodzie składania bąjtu, bit startu zostaje wysunięty z rejestru docelowego przy odczycie ósmego bitu przesyłanego bąjtu. W ten sposób po zakończeniu odbioru w rejestrze jest złożony przesłany bajt.
Przy tej metodzie możliwa jest jednoczesna transmisja w obie strony. Trzeba tylko wykorzystać do tego celu dwa timery: jeden do nadawania, a drugi do odbioru. Projektując taką transmisję należy uwzględnić czas odbioru jednego bitu, czyli czas obsługi przerwania od timera. Prędkość transmisji nie może być zbyt duża, gdyż okaże się, że zanim zostanie odebrany jeden bit, już należy zacząć odbiór następnego. Przy dopuszczeniu jednoczesnej transmisji w obie strony, to wymaganie jest jeszcze bardziej kategoryczne. Na przykład nadawanie jednego bitu nie może spowodować zbyt dużego opóźnienia w odbiorze. Z kolei odbiór nie może powodować zbyt dużych odchyleń przy nadawaniu. Należy pamiętać, że drugie urządzenie również nie realizuje idealnej transmisji, a błędy zawsze mogą się zsumować.
W powyższym przykładzie nie uwzględniono jeszcze jednego elementu, który jest ważny dla dokładności odbioru. Założono mianowicie, że nie istnieje żadne opóźnienie między źródłem przerwania a obsługą przerwania przez mikrokontroler. W rzeczywistości opóźnienie to wynosi kilka cykli maszynowych i zależy od wykonywanej przez mikrokontroler instrukcji w momencie przyjścia przerwania. Każda instrukcja musi zostać zakończona, a więc na przykład instrukcja mnożenia może wymusić cztery cykle, zanim mikrokontroler rozpocznie obsługę przerwania. Następnie mikrokontroler musi przechować bieżący adres na stosie i wykonać skok do adresu obsługi przerwania. To też zajmie dodatkowy czas. Na początku obsługi przerwania jest zazwyczaj kilka rozkazów nie związanych bezpośrednio z transmisją, na przykład PUSH PSW. Zatem faktyczna obsługa transmisji rozpoczyna się od kilku do kilkunastu cykli maszynowych po pojawieniu się źródła przerwania.
Przy prędkości transmisji 4800, gdy jeden bit trwa 192 cykle maszynowe, można było to wszystko pominąć. Ale chcąc osiągnąć wyższe prędkości, należy te wszystkie dodatkowe czasy uwzględniać. Należy na przykład odpowiednio skorygować czas od początku bitu startu do momentu odczytu pierwszego bitu.
Aby osiągnąć bardzo wysokie prędkości transmisji, trzeba wybrać inną metodę. Odliczanie prędkości na timerze trzeba zastąpić odpowiednią liczbą wykonywanych rozkazów. Kolejny przykład ilustruje nadawanie szeregowe z prędkością 115200.
*************** przykład 3 ***************
Jak można łatwo policzyć, przy prędkości 115200 na jeden bit transmisji przypada:
N = ( 11.059.200 /12 ) /115200 = 8 cykli maszynowych.
Tak więc, co 8 cykli linia wyjściowa musi być ustawiona zgodnie z kolejnym bitem. Nie jest to dużo, ale w mikrokontrolerze 8051 można to bez kłopotu wykonać - trzeba jeszcze dokładać rozkazy NOP. Jeżeli jednak w programie wykorzystywane są przerwania, to na czas transmisji trzeba je bezwzględnie wyłączyć. Nawet najkrótsze przerwanie skutecznie zakłóci nadawanie. Analogicznie do nadawania można również odbierać z taką. samą prędkością.
**************8 przykład 4 ******************8
Odbiór całego bajtu odbywa się wewnątrz przerwania. Ponieważ w programie głównym stale wykonywany jest rozkaz SJMP, wejście w program obsługi przerwania będzie trwało od 3 do 5 cykli maszynowych. Do obliczeń w programie przyjęto wartość średnią, czyli 4. Odczytanie pierwszego bitu powinno nastąpić po 12 cyklach od wystąpienia sygnału przerwania, czyli po ośmiu cyklach wewnątrz przerwania. Odczytanie kolejnych bitów wykonywane jest co osiem cykli maszynowych.
Tak jak przy nadawaniu, odbiór bajtu nie może być niczym przerwany. Jeżeli więc w programie wykorzystywane są inne przerwania, to przerwanie z wejścia INTO musi mieć najwyższy priorytet.
Przy tym sposobie transmisji nadawanie i odbiór nie mogą odbywać się jednocześnie. Jednak przy prawidłowo zorganizowanym protokole transmisji, sposób ten może być z powodzeniem wykorzystywany. Należy zauważyć, że osiągnięta prędkość 115200 jest wyższa niż prędkość osiągana przez sterownik transmisji szeregowej mikrokon-trolera 8051, który pracuje w trybie l lub 3.
ZADANIA
Zadanie l
Zmodyfikować przykład l, tak aby nadawanie odbywało się z prędkością 3 00 bodów. Zadanie 2
Przykład z zadania l zmodyfikować tak, aby program główny nie mógł zainicjować nadawania kolejnego bajtu przed zakończeniem nadawania poprzedniego.
Zadanie 3
Przykład 2 przestaje prawidłowo odbierać przy transmisji z prędkością 3 8400 bodów. Zmodyfikować go w ten sposób, aby możliwy był odbiór przy tej prędkości.
WSKAZÓWKI
Ad.l
Przy tak niskiej prędkości transmisji dla odliczania czasu trwania jednego bitu po-' trzebnyjest timer 16-bitowy, czyli pracujący w trybie l. Obsługę przerwania od time-ra należy uzupełnić o ładowanie wartości początkowej do timera. Dlaczego wystarczy ładować tylko starszy bajt timera?
Ad. 2
Tak jak to było pokazane w lekcji poprzedniej, należy przykład uzupełnić o flagę sygnalizującą nadawanie bajtu. Flaga ta powinna zezwalać na rozpoczęcie nadawania dopiero po zakończeniu bitu (bitów) stopu.
Ad. 3
W celu zagwarantowania prawidłowego odbioru należy zadbać, aby odczytanie danego bitu nastąpiło możliwie w środku czasu jego nadawania. Decyduje o tym przede wszystkim prawidłowe odliczenie czasu od początku bitu startu do środka pierwszego bitu danych. Przy tak dużej prędkości nie ma potrzeby odliczania najpierw pół bitu, tylko można od razu odliczać półtora. Należy zatem odpowiednio skorygować wartość początkową ładowaną do timera. W tej korekcie trzeba uwzględnić:
• czas od początku bitu startu do momentu wystartowania timera
• czas od przepełnienia timera do odczytania bitu z portu.