Serwis Edukacyjny
Nauczycieli
w I-LO w Tarnowie

Do strony głównej I LO w Tarnowie

Materiały dla uczniów liceum

  Wyjście       Spis treści       Poprzedni       Następny  

©2018 mgr Jerzy Wałaszek
I LO w Tarnowie

Autor artykułu: mgr Jerzy Wałaszek
Konsultacje: Wojciech Grodowski, mgr inż. Janusz Wałaszek

 

 

Elementy

Transmisja danych cyfrowych

Rozdziały artykułu:
Wstęp
Teoria
Warsztat
Elementy
    Przewody
    Złącza
    Baterie i akumulatory
    Obwody elektroniczne
    Przyciski
    Oporniki
    Kondensatory
    Diody
    Tranzystory
    Bramki cyfrowe
    Sieci logiczne
    Układy kombinacyjne
    Przerzutniki
    Rejestry
    Liczniki
    Generatory
    Wzmacniacze operacyjne
    Przekaźniki
    Przetworniki akustyczne
    Czujniki
    Przetworniki A/C i C/A
    Transmisja danych cyfrowych
    Transformatory
    Programatory
    Mikrokontrolery
Projekty
Mikrokontrolery

 

Co to jest transmisja cyfrowa?

Przez transmisję (ang. transmission) będziemy ogólnie rozumieć przesyłanie danych pomiędzy dwoma urządzeniami. Transmisja cyfrowa (ang. digital transmission) polega na przesyłaniu bitów, które stanowią informację cyfrową. Aby mogło dojść do przesłania informacji musi być spełnione kilka warunków. Spójrz na poniższy rysunek:

Przedstawia on kanał transmisyjny (ang. transmission chanel). Transmisja odbywa się w ośrodku, który umożliwia przesył sygnałów wybranych do przenoszenia informacji. Ośrodkiem może być np. przestrzeń (fale elektromagnetyczne, światło lasera, promieniowanie podczerwone, itp.), przewód (prąd elektryczny), powietrze (fala akustyczna, ultradźwięki). Sygnał jest wytwarzany przez nadajnik (ang. transmitter), a następnie przemieszcza się przez ośrodek i dociera do odbiornika (ang. receiver). Nadajnik i odbiornik tworzą dopasowaną parę, tzn. odbiornik musi być w stanie odbierać i odpowiednio zinterpretować sygnały wytwarzane przez nadajnik.

Nadajnik otrzymuje informację w postaci bitów, następnie zamienia ją w odpowiednią postać sygnału i wysyła do ośrodka. Sygnał poprzez ośrodek dociera do odbiornika, zostaje odebrany i z powrotem zamieniony w bity. W ten sposób odbywa się transmisja cyfrowa. Zasada jest prosta, diabeł tkwi w szczegółach.

Pierwszy problem polega na doborze właściwego sygnału, który łatwo (czytaj tanio) będzie można wytworzyć, a który skutecznie przeniesie pożądaną informację przez dany ośrodek.

Następny problem pojawia się przy wyborze sposobu przesyłania bitów. Możemy to robić na dwa sposoby: równocześnie przesyłając zadaną liczbę bitów – transmisja równoległa (ang. parallel transmission) lub przesyłając bity pojedynczo jeden za drugim – transmisja szeregowa (ang. serial transmission).

Transmisja równoległa jest szybsza, gdyż naraz przesyła się kilka bitów, jednak wymaga rozdzielnych kanałów transmisyjnych lub skomplikowanego kodowania danych.

Transmisja szeregowa jest wolniejsza, lecz prostsza do zrealizowania. Wymaga pojedynczego kanału transmisji.

Zanim dane będą mogły być przesłane przez ośrodek, muszą zostać odpowiednio ukształtowane w sygnał, który przeniesie je w danym ośrodku. Przy transmisji cyfrowej przesyłamy bity. Bit może występować w dwóch różnych postaciach, które tutaj oznaczamy cyframi 0 i 1. Oczywiście zamiast cyfr mogą to być dwa poziomy napięć, np. w technice TTL bit o stanie 1 reprezentowany jest napięciem 2,4...5V, a bit o stanie 0 reprezentuje napięcie 0...0,8V. Napięcia te są wykorzystywane przez bramki, przerzutniki i sieci logiczne do przetwarzania informacji binarnej. Jeśli chcemy przesyłać bity przez ośrodek, to musimy określić postać sygnału dla bitu o stanie 1 i dla bitu o stanie 0. Przykładowo załóżmy, że będziemy przesyłać informację przewodem elektrycznym za pomocą prądu. Możemy wtedy umówić się, że bit o stanie 1 będzie przesyłany, jeśli w przewodzie płynie prąd, a bit o stanie 0 jest przesyłany, jeśli prąd nie płynie lub ma bardzo małą wartość.

Kształtowanie sygnału na podstawie bitu, który sygnał ma przenosić, nazywamy modulacją (ang. modulation).

Istnieje wiele typów modulacji. Najpierw przyjrzyjmy się parametrom fali sinusoidalnej, która jest najbardziej naturalną postacią sygnału przemieszczającego się przez ośrodek.

Powyższy rysunek przedstawia wykres dwóch funkcji sinusoidalnych w czasie. Czerwoną linią zaznaczyliśmy wykres podstawowy, a zieloną wykres przesunięty w czasie. Na wykresie zaznaczono:

A amplituda, czyli największa wartość funkcji (na moduł)
T okres, czas, po upływie którego funkcja przyjmuje te same wartości
φ przesunięcie fazowe

Funkcja podstawowa ma postać:

Prędkość kątowa ω dana jest wzorem:

Jednostka prędkości kątowej to radiany na sekundę. Po wstawieniu prędkości kątowej do wzoru funkcji otrzymujemy:

Wzór dla funkcji przesuniętej fazowo przyjmuje teraz postać:

 

Te trzy parametry wykorzystuje się do modulacji sygnału:

 

Modulacja amplitudy (ang. AM – Amplitude Modulation):

Dla stanów bitów przyjmuje się różne wartości amplitudy:

   

Jeśli dane są przesyłane szeregowo bit po bicie, to każdy bit jest przesyłany przez ściśle określony czas i w tym czasie, zwanym oknem bitowym, sygnał ma stałą amplitudę. Załóżmy, że przesyłamy w ten sposób daną 8-bitową 01101001. Sygnał ma postać:

 

Nadajnik przesyłając bit o stanie 0 wysyła w oknie bitowym sygnał o małej amplitudzie (amplituda raczej nie wynosi zero, ponieważ wtedy odbiornik nie może stwierdzić, czy w ogóle odbiera sygnał, zatem nawet dla bitu 0 wybiera się małą amplitudę). Gdy nadajnik przesyła bit o stanie 1, w oknie bitowym transmituje sygnał o dużej amplitudzie. Odbiornik odczytuje amplitudę sygnału w oknie bitowym. Jeśli jest niska, odbiornik "wie", że przesyłany jest bit o wartości 0. Jeśli jest wysoka, odbiornik interpretuje ją jako bit o wartości 1.

Modulacja amplitudy jest prosta w realizacji, jednak jest ona mało odporna na zakłócenia w kanale transmisyjnym.

Przez zakłócenie rozumiemy obcy sygnał (nie wysłany przez nadajnik), który może losowo się pojawić w ośrodku transmisyjnym. Skąd się biorą takie zakłócenia? To zależy od ośrodka oraz rodzaju przesyłanego sygnału. Na przykład przesyłanie za pomocą fal radiowych może być zakłócane przez warunki atmosferyczne, urządzenia elektryczne lub inne nadajniki pracujące w pobliżu. Zakłócenia sumują się z sygnałem i mogą powodować błąd w transmisji. Dla transmisji cyfrowej przez błąd transmisji rozumiemy odebranie bitu o stanie przeciwnym do nadanego. Na przykład:

Kolorem niebieskim zaznaczony jest sygnał zakłócający transmisję. W efekcie sygnał nadajnika zostaje zniekształcony i odbiornik odbiera dwa bity (zaznaczone na czerwono) o stanie przeciwnym do nadanego. Powstaje błąd transmisji.  Błędami zajmiemy się w dalszej części rozdziału.

 

Modulacja częstotliwości (ang. FM – frequency modulation):

Częstotliwość jest liczbą okresów sygnału w ciągu sekundy. Jednostką częstotliwości jest herc Hz. 1Hz jest częstotliwością sygnału, którego okres wynosi 1 sekundę. W praktyce stosowane są większe częstotliwości:
1kHz kiloherc = 1000Hz
1MHz megaherc = 1000kHz = 1000.000Hz
1GHz gigaherc = 1000MHz = 1000.000kHz = 1000.000.000Hz

W tej modulacji przydziela się różne częstotliwości sygnału dla bitu o stanie 0 i dla bitu o stanie 1, które są przesyłane w oknie bitowym. Amplituda sygnału nie jest wykorzystywana:

 

Transmisja z modulacją częstotliwości jest bardziej odporna na zakłócenia od transmisji z modulacją amplitudy. O ile zakłócenie nie zmieni częstotliwości przesyłanego sygnału, nie wpłynie na odbiór danych. Odbiornik w oknie bitowym bada częstotliwość odebranej fali (można to robić za pomocą odpowiednio dostrojonych filtrów) i na tej podstawie rozróżnia bit o stanie 0 i bit o stanie 1.

 

Modulacja fazy (ang. PM Phase Modulation):

Stany bitów kodowane są przesunięciem fazowym:

  

Szybkość transmisji sygnału wyrażamy za pomocą bodów (ang. bauds). Body określają liczbę zmian postaci fali niosącej informację w ciągu jednej sekundy. Jeżeli zmiana oznacza przesłanie jednego bitu, to liczba bodów odpowiada liczbie przesłanych bitów w ciągu jednej sekundy. Lecz czasem stosuje się kilka modulacji jednocześnie w celu zwiększenia liczby przesyłanych bitów w danej jednostce czasu. Dla przykładu załóżmy, że stosujemy jednocześnie modulację amplitudy i modulację częstotliwości. Fala nośna będzie w takim przypadku mogła przybierać 4 różne postacie, które umożliwią jednoczesne przesyłanie dwóch bitów:

Zwróć uwagę, że stosując dwie modulacje w jednym oknie bitowym przesyłane są po dwa bity jednocześnie, zatem prędkość transmisji wzrasta dwukrotnie. Dodając kolejne modulacje można zwiększyć liczbę bitów. W ten sposób zwiększa się przepustowwość kanału transmisyjnego.

Z tego typu modulacjami spotkasz się przy przesyłaniu danych za pomocą fal radiowych, np. w telewizji cyfrowej.

Do formowania i odbioru sygnałów służą urządzenia zwane modemami (ang. modulator + demodulator). Zawierają one dwa elementy: nadajnik i odbiornik sygnału, który jest dopasowany do ośrodka transmisyjnego. Modemy współpracują z mikrokontrolerami:

W praktyce amatorskiej dane będą przesyłane najczęściej przewodem za pomocą prądu elektrycznego na nieduże odległości (do kilku metrów). W takim przypadku nadajniki i odbiorniki można wykonać w prosty sposób z kilku tranzystorów lub zastosować gotowe układy transmisyjne. Większość współczesnych mikrokontrolerów posiada tego typu elementy już wbudowane w swoją strukturę.

 

Nadajniki i odbiorniki cyfrowe linii

Technika przesyłania sygnałów cyfrowych (bitów) nie jest prosta. Dlatego dobrze jest stosować typowe rozwiązania, które wielokrotnie sprawdziły się w praktyce.

Przesyłanie danych na małą odległość nie wymaga zwykle skomplikowanych układów. Można nawet wykorzystać zwykłe bramki cyfrowe:

Do transmisji potrzebny jest przewód dwużyłowy. Jedną żyłą przesyłane są dane, druga podłączona jest w obu urządzeniach do masy.  Przewód może mieć długość kilka metrów. jako nadajnik dobrze jest zastosować bramkę mocy.

Lepszym rozwiązaniem jest zastosowanie gotowego układu nadajnika linii. W handlu można spotkać wiele typów takich układów. Na przykład:


SN75450

SN75451

 

SN75452

SN75453

 

SN75454

Układy mogą pełnić rolę nadajników. W zależności od typu zawierają dwie bramki NAND (SN75450/SN75451), AND (SN75452), NOR (SN75453) lub OR (SN75454) oraz dwa tranzystory npn z otwartymi obwodami kolektorów. Takie rozwiązanie pozwala stosować różne konfiguracje nadajników (najbardziej uniwersalny jest układ SN75450):

  

  

Jeśli linia transmisyjna jest dłuższa niż kilka metrów, to problem przesyłania danych komplikuje się, ponieważ w takiej linii pojawiają się pojemności i indukcyjności pasożytnicze, które zakłócają transmitowany sygnał. Dodatkowo dłuższe przewody są czułe na zewnętrzne pola elektryczne i magnetyczne. W takich przypadkach dane przesyła się dwoma liniami w ten sposób, iż sygnały mają w nich fazy przeciwne. Zakłócenia znoszą się wzajemnie w obu przewodach. Odbiornikiem jest wzmacniacz różnicowy:

Do przesyłania i odbioru danych poprzez długą linię stosuje się zwykle gotowe układy scalone nadajników i odbiorników, np. SN75121/SN75122,  SN65LVDS1, SN65LVDS2, itp.

 

Rodzaje transmisji cyfrowych

W zależności od sposobu przesyłania bitów mamy transmisję równoległą (ang. parallel transmission) i transmisję szeregową (ang. serial transmission).

W transmisji równoległej bity są przesyłane jednocześnie grupami, np. po 8 bitów. Transmisja wymaga osobnych kanałów dla każdego bitu grupy.  W latach 90-tych ubiegłego wieku większość produkowanych wtedy komputerów posiadała złącze równoległe Centronics, które było wykorzystywane do transmisji danych do drukarki:

Gniazdo Centronics

Wtyczka Centronics

Wraz z upowszechnieniem się standardu USB złącza Centronics zniknęły z komputerów PC, jednakże ich składniki są wciąż dostępne w sprzedaży i możesz je wykorzystywać we własnych projektach. Informację bez trudu znajdziesz w sieci.

Transmisja równoległa jest kłopotliwa przy wyższych prędkościach przesyłu, ponieważ poszczególne kanały oddziałują na siebie wzajemnie i należy je ekranować. Jeśli jednak linia przesyłu danych (zwana tutaj zwykle magistralą) nie jest zbyt długa, a szybkość transmisji nie jest zbyt duża, to do przesyłania sygnałów można wykorzystać zwykłą taśmę wieloprzewodową:

Aby uniknąć zakłóceń, żyły sygnałowe przedziela się żyłami masy.

W ten sposób możesz przesyłać dane pomiędzy różnymi elementami swojego urządzenia: wyświetlaczami, klawiaturami, pamięciami, mikrokontrolerami, itp.

 

W transmisji szeregowej bity są przesyłane kolejno jeden za drugim. Zaletą jest tutaj to, iż naraz przesyłany jest jeden sygnał, zatem prostsza staje się jego ochrona przed zakłóceniami. Drugą zaletą jest mała liczba linii sygnałowych niezbędnych do realizacji transmisji, co jest istotne szczególnie w przypadku mikrokontrolerów, gdzie liczba dostępnych portów wejścia/wyjścia jest ograniczona. Typowym przykładem transmisji szeregowej jest powszechnie stosowany obecnie standard USB (ang. Universal Serial Bus – uniwersalna magistrala szeregowa), który doczekał się już wersji nr 3. W użyciu są również inne standardy, które krótko opiszemy dalej. Współczesne mikrokontrolery posiadają zwykle elementy do transmisji szeregowej, co jest olbrzymim ułatwieniem dla konstruktorów.

 

Transmisję równoległą i szeregową dzielimy dalej na transmisję z potwierdzeniem odbioru i na transmisję bez potwierdzenia odbioru.

W przypadku transmisji z potwierdzeniem (ang. handshake transmission) odbiornik posiada dodatkowy kanał zwrotny, którym przesyła sygnał potwierdzający odebranie danych ACK (ang. acknowledgment, potwierdzenie). Nadajnik w odpowiedzi na ten sygnał może przesłać kolejną porcję danych. W tego rodzaju transmisji można łatwo zrealizować transmisję z powtórzeniem w przypadku błędu. Odbiornik po stwierdzeniu błędu w odebranych danych wysyła do nadajnika specjalny sygnał negatywnego potwierdzenia NACK (ang. negative acknoledgment). W odpowiedzi nadajnik powtarza jeszcze raz transmisję danych.

W transmisji bez potwierdzenia nadajnik wysyła dane, lecz nie sprawdza, czy zostały odebrane. Tak jest np. w przypadku telewizji cyfrowej. Dane są zwykle odpowiednio kodowane tak, aby umożliwić odbiornikowi naprawę błędów transmisji.

 

Kolejny podział daje nam transmisję synchroniczną i asynchroniczną.

W transmisji synchronicznej (ang. synchronous transmission) oprócz sygnału danych przesyłany jest sygnał synchronizujący, który ułatwia odbiornikowi odczyt informacji. Sygnał synchronizacji przesyłany jest zwykle osobnym kanałem transmisyjnym, zatem dla transmisji szeregowej wymagane są dwie linie przesyłowe:

Narastające zbocza impulsów zegarowych wyznaczają moment odczytu danych przez odbiornik. Ten rodzaj transmisji pozwala przesyłać dane z różnymi prędkościami.

W transmisji asynchronicznej (ang. asynchronous transmission) przesyłany jest tylko sygnał danych, lecz ustala się stałą prędkość transmisji. Dane poprzedzane są zwykle tzw. bitem startu, który nie należy do danych, lecz pozwala odbiornikowi wykryć początek transmisji. Po przesłaniu odpowiedniej liczby bitów przesyłany jest bit stopu o wartości przeciwnej do bitu startu. Gdy prędkość transmisji jest ustalona i stała, odbiornik po wykryciu bitu startu odczytuje z odpowiednią prędkością bity danych, a po odebraniu bitu stopu czeka na kolejną porcję bitów:

Transmisja asynchroniczna jest chętnie stosowana, ponieważ przy szeregowym przesyle danych wymaga tylko jednej linii transmisyjnej.

 

Ostatni podział daje nam transmisję duplex i simplex (pół duplex).

Transmisja duplex polega na możliwości przesyłania informacji w obu kierunkach jednocześnie. Oba urządzenia komunikujące się posiadają nadajniki i odbiorniki, które łączą się dwoma kanałami transmisyjnymi:

W transmisji simplex mamy jeden kanał transmisyjny, który jest wykorzystywany naprzemiennie przez oba urządzenia do transmisji dwukierunkowej, jednak w danej chwili transmisja jest możliwa tylko w jednym kierunku:

 

Błędy w transmisji

Omawiając transmisję cyfrową nie można nie wspomnieć o błędach. Błędy pojawiają się z różnych powodów. Najczęściej spowodowane są uszkodzeniem sygnału w trakcie przesyłania go przez kanał transmisyjny. Do takiego uszkodzenia dochodzi, gdy w kanale pojawia się obcy sygnał, który nie należy do transmisji. Sygnał ten sumuje się z sygnałem nadawanym i zniekształca go. W rezultacie odbiornik może źle zinterpretować odebrany sygnał i dochodzi do błędu.

Transmisja cyfrowa polega na przesyłaniu bitów. Bity mogą przyjmować tylko dwa różne stany, które umownie oznaczamy tu cyframi 0 (stan niski) i 1 (stan wysoki). Błąd wystąpi wtedy, gdy odbiornik odbierze bit o stanie przeciwnym do nadanego: tzn. nadajnik wysyła bit o stanie 1, a odbiornik odbiera go jako bit o stanie 0 lub na odwrót.

Jeśli nie stosuje się żadnych zabezpieczeń przed błędami, to odbiornik nie jest w stanie stwierdzić, czy odebrana informacja jest lub nie jest poprawna. Transmisja bez zabezpieczeń stosowana jest zwykle wtedy, gdy prawdopodobieństwo wystąpienia błędów jest bardzo małe, np. wewnętrzne przesłania danych pomiędzy elementami urządzenia. Gdy błędy mogą się pojawić, a informacja jest istotna, należy zabezpieczać transmisję.

Zabezpieczenie informacji polega na jej odpowiednim kodowaniu. Wymyślono dwa rodzaje kodów zabezpieczających:

  • kody detekcyjne EDC (ang. error detection codes), które potrafią wykryć, że odebrana informacja nie jest poprawna. Stosuje się je w transmisji z potwierdzeniem. Gdy odbiornik wykryje błąd, kanałem zwrotnym przesyła negatywne potwierdzenie NACK, a odbiornik powtarza transmisję danych. W ten sposób informacja zostanie odebrana poprawnie nawet w przypadku błędów, jedynie czas transmisji zostanie wydłużony.
  • kody korekcyjne ECC (ang. error correction codes), które potrafią naprawiać błędy transmisyjne (do pewnego stopnia). Stosuje się je tam, gdzie nie ma kanału zwrotnego lub powtórzenie transmisji danych nie usuwa błędów (np. odczyt z porysowanej płyty DVD).

Kody detekcyjne EDC

Jeden z najprostszych kodów detekcyjnych to tzw. bit parzystości (ang. parity bit). Polega to na tym, iż do przesyłanych danych dołączamy jeden dodatkowy bit. Stan bitu ustalamy tak, aby liczba jedynek w całym słowie była parzysta:

Dane BP Wynik
0000 0 00000
0110 0 01100
0100 1 01001
1110 1 11101

Tak przygotowane słowo kodowe przesyłamy przez kanał transmisyjny. Jeśli nastąpi przekłamanie jednego bitu (ogólnie nieparzystej liczby bitów), to zmieni się parzystość słowa:

Jeśli bit o stanie 1 zostanie odebrany jako bit o stanie 0, to zmaleje liczba jedynek i słowo będzie posiadało ich nieparzystą liczbę:

Jeśli bit o stanie 0 zostanie odebrany jako bit o stanie 1, to wzrośnie liczba jedynej i słowo będzie zawierało ich nieparzystą liczbę:

W obu przypadkach odebrane słowo traci parzystość. Na tej podstawie odbiornik wie, że dane zawierają błąd. Kanałem zwrotnym odbiornik może zażądać powtórzenia transmisji (NACK).

Bit parzystości łatwo wygenerować za pomocą bramek EX-OR:

A B Y
0 0 0
0 1 1
1 0 1
1 1 0

SN7486

Po stronie nadajnika stosowany jest podobny układ a dodatkową bramką EX-OR:

Na wyjściu ERROR pojawia się stan 1, jeśli liczba jedynek w odebranym słowie jest nieparzysta, a zatem gdy jeden z bitów zostanie odebrany błędnie. Jeśli wyjście ERROR ma stan logiczny 0, to bity A...H zostały odebrane poprawnie lub wystąpiły błędy parzyste.

W praktyce stosowane są gotowe układy zawierające generator bitu parzystości, np. SN74180. Mikrokontrolery zwykle posiadają wbudowane elementy transmisyjne zawierające tę funkcję.

Bit parzystości pozwala wykrywać tylko błędne odebranie nieparzystej liczby bitów. Jeśli błąd wystąpi na parzystej liczbie bitów (2,4,6...), to nie zostanie wykryty, ponieważ zmiana parzystej liczby bitów na przeciwne nie zmienia parzystości słowa. Spróbuj to uzasadnić.

Suma kontrolna

Bity parzystości zabezpieczają dane o niewielkiej liczbie bitów (8, 16). Spowodowane jest to tym, iż w długim ciągu bitów rośnie prawdopodobieństwo błędu podwójnego, który przez ten system nie jest rozpoznawany. Do zabezpieczania większej liczby bitów stosuje się tzw. sumy kontrolne (ang. checksums). Zasada jest następująca:

Przesyłaną informację dzieli się na słowa o stałej liczbie bitów (najczęściej 8, czyli na bajty). Słowa te przesyłane są przez kanał transmisyjny bez zabezpieczenia lub z bitem parzystości. Po przesłaniu słowa traktowane jako liczby dwójkowe dodaje się je do sumy kontrolnej, która na początku transmisji jest zerowana. Gdy cała informacja zostanie przesłana, nadajnik wysyła do odbiornika sumę kontrolną.

Po stronie odbiorczej odbiornik na początku transmisji zeruje swoją sumę kontrolną, po czym odbiera poszczególne słowa bitowe, dodając je do swojej sumy. Na końcu transmisji odbiera sumę kontrolną i porównuje ją ze swoją sumą. Jeśli obie sumy są równe, to zakłada, że dane odebrano poprawnie. Jeśli nie, występuje błąd sumy kontrolnej (ang. checksum error), co sygnalizuje błąd w odebranych danych. Na tej podstawie odbiornik może zażądać  powtórzenia transmisji.

Zaletą sum kontrolnych jest to, iż są krótkie bitowo w porównaniu z liczbą bitów danych. Np. 16 bitów sumy kontrolnej na 1024 bitów danych.

Sumy kontrolne mogą być tworzone w sposób sprzętowy lub programowy. Poniżej przedstawiony jest przykładowy program w języku C (Code Blocks) symulujący transmisję z 4-bitową sumą kontrolną 16 danych 4-bitowych.

/*
  SYMULATOR TRANSMISJI
  Z SUMĄ KONTROLNĄ
  (C)2018 mgr Jerzy Wałaszek
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/*
  Funkcja wyświetla 4 najmłodsze bity
*/
void print4b(int x)
{
  int mask = 8; // maska bitowa:
  while(mask)
  {
      if(x & mask) printf("1");
      else         printf("0");
      mask >>= 1;
  }
}

int main()
{
  // Zmienne
  int tchksum,rchksum,i,td,rd,e;

  // Inicjujemy generator pseudolosowy
  srand((unsigned int)time(NULL));

  // Przygotowujemy sumy kontrolne nadajnika i odbiornika
  tchksum = rchksum = 0;

  printf("NADAJNIK      ODBIORNIK\n");
  printf("dane suma     dane suma\n");
  printf("--------->>>>>---------\n");
  printf("     0000          0000\n");

  // Transmisja --- Zakłócenie --- Odbiór

  for(i = 0; i < 16; i++)
  {
      td = rand() % 16;  // dane nadawane
      tchksum += td;     // uaktualniamy sumę nadajnika
      tchksum &= 0xf;    // obcinamy sumę do 4 bitów
      print4b(td);
      printf(" ");
      print4b(tchksum);
      rd = td;           // dane odbierane
      e = 0;
      while(!(rand() % 16)) // błędy transmisji
      {
        e = 1;
        rd ^= 1 << (rand() % 4);
      }
      if(e) printf(" (X) ");
      else  printf(" (-) ");
      rchksum += rd;     // uaktualniamy sumę odbiornika
      rchksum &= 0xf;    // obcinamy sumę do 4 bitów
      print4b(rd); printf(" "); print4b(rchksum);
      printf("\n");
  }

// Transmisja sumy kontrolnej

   printf("     ");
   print4b(tchksum);
   e = 0;
   while(!(rand() % 16)) // błędy transmisji
   {
      e = 1;
      tchksum ^= 1 << (rand() % 4);
   }
   if(e) printf(" (X) ");
   else  printf(" (-) ");
   print4b(tchksum);
   printf(" ");
   print4b(rchksum);
   printf("\n");
   printf("-----------------------\n");
   if(tchksum == rchksum) printf("     DANE POPRAWNE\n\n");
   else                   printf("    DANE USZKODZONE\n\n");
  return 0;
}

Program wyświetla dane nadawane oraz odbierane. Dodatkowo po przesłaniu każdej danej wyświetlane są sumy kontrolne nadajnika i odbiornika. Jeśli w trakcie transmisji pojawi się błąd, to zostanie wyświetlony napis (X). Jeśli nie było błędu, pojawi się napis (-):

NADAJNIK      ODBIORNIK
dane suma     dane suma
--------->>>>>---------
     0000          0000
0000 0000 (-) 0000 0000
1110 1110 (-) 1110 1110
0010 0000 (-) 0010 0000
0111 0111 (-) 0111 0111
1101 0100 (-) 1101 0100
0100 1000 (-) 0100 1000
1101 0101 (-) 1101 0101
1010 1111 (-) 1010 1111
0010 0001 (-) 0010 0001
1110 1111 (-) 1110 1111
0101 0100 (-) 0101 0100
1000 1100 (-) 1000 1100
1110 1010 (-) 1110 1010
0110 0000 (-) 0110 0000
0101 0101 (-) 0101 0101
0100 1001 (-) 0100 1001
     1001 (-) 1001 1001
-----------------------
     DANE POPRAWNE
   
NADAJNIK      ODBIORNIK
dane suma     dane suma
--------->>>>>---------
     0000          0000
1000 1000 (-) 1000 1000
0011 1011 (-) 0011 1011
1000 0011 (-) 1000 0011
1001 1100 (-) 1001 1100
1000 0100 (-) 1000 0100
0110 1010 (-) 0110 1010
1111 1001 (X) 1110 1000
1110 0111 (-) 1110 0110
0011 1010 (-) 0011 1001
0110 0000 (-) 0110 1111
0101 0101 (X) 0111 0110
1010 1111 (-) 1010 0000
0101 0100 (-) 0101 0101
0110 1010 (-) 0110 1011
1111 1001 (-) 1111 1010
0010 1011 (-) 0010 1100
     1011 (-) 1011 1100
-----------------------
    DANE USZKODZONE

Algorytm tworzenia sum kontrolnych jest zwykle bardziej skomplikowany. Informacje na ten temat znajdziesz w sieci.

Cykliczna kontrola nadmiarowa

Jedną z bardziej popularnych metod zabezpieczania danych przed błędami jest metoda cyklicznej kontroli nadmiarowej CRC (ang. cyclic redundancy check). Polega ona na dołączaniu do danych reszty z dzielenia tych danych przez odpowiednio dobrany dzielnik. Dzielniki dobiera się matematycznie wg kryterium największej skuteczności w wykrywaniu błędów.

Zasadę działania tej metody najlepiej jest zrozumieć na podstawie przykładu:

Załóżmy, że chcemy przesłać dane 8-mio bitowe: 00110111. Wybieramy dzielnik 4-bitowy 1011.

Zapisujemy dane, a pod nimi dzielnik:

00110111
1011

Do danych dopisujemy 3 bity o stanie 0 (reszta z dzielenia przez 4-bitowy dzielnik jest maksymalnie 3-bitowa):

00110111000
1011

Dzielnik przesuwamy w prawo, aż nad jego najstarszym bitem o wartości 1 znajdzie się bit 1 danych:

00110111000
  1011

Wykonujemy operację EX-OR na poszczególnych bitach danych i dzielnika. Wynik zapisujemy pod spodem:

00110111000
  1011
00011011000

Dzielnik zapisujemy pod wynikiem i znów przesuwamy go w prawo aż nad jego najstarszym bitem 1 pojawi się bit 1 danych:

00110111000
  1011
00011011000
   1011

Wykonujemy operację EX-OR i wynik zapisujemy pod spodem:

00110111000
  1011
00011011000
   1011
00001101000

Powtarzamy:

00110111000
  1011
00011011000
   1011
00001101000
    1011
00000110000

Powtarzamy:

00110111000
  1011
00011011000
   1011
00001101000
    1011
00000110000
     1011
00000011100

Powtarzamy:

00110111000
  1011
00011011000
   1011
00001101000
    1011
00000110000
     1011
00000011100
      1011
00000001010

Powtarzamy:

00110111000
  1011
00011011000
   1011
00001101000
    1011
00000110000
     1011
00000011100
      1011
00000001010
       1011
00000000001

Koniec, ponieważ wszystkie bity danych są wyzerowane. Reszta z dzielenia jest w dodanych trzech bitach CRC i wynosi 001. Dołączamy ją do danych i przesyłamy do odbiornika jako: 00110111001.

Jeśli w czasie transmisji nie było błędów, to odbiornik odbierze bity: 00110111001. Wykonuje na nich te same operacje, które wykonywał wcześniej nadajnik:

00110111001
  1011
00011011001
   1011
00001101001
    1011
00000110001
     1011
00000011101
      1011
00000001011
       1011
00000000000

Zwróć uwagę, że teraz dodatkowe bity CRC wyzerowały się. Jest to znak, że dane zostały odebrane poprawnie.

Załóżmy, że w trakcie transmisji doszło do dwóch błędów i odbiornik odebrał dwa bity o stanie przeciwnym do nadanego, np.: 00111101001

00111101001
  1011
00010011001
   1011
00000101001
     1011
00000000101

Obliczenia skończyły się wcześniej, ponieważ wszystkie bity danych zostały wyzerowane. Bity CRC nie wyzerowały się, zatem dane odebrano z błędami.

Poniżej prezentujemy prostą symulację przesłania danych z CRC napisaną w języku C (Code Blocks):
/*
  SYMULATOR TRANSMISJI Z CRC
  (C)2018 mgr Jerzy Wałaszek
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/*
  Funkcja wyświetla n bitów liczby x
*/
void printnb(int x, int n)
{
  int mask = 1 << (n - 1); // maska bitowa:
  while(mask)
  {
      if(x & mask) printf("1");
      else         printf("0");
      mask >>= 1;
  }
}

/*
  Funkcja wyświetla zadaną liczbę spacji
*/
void printns(int n)
{
    while(n--) printf(" ");
}

int main()
{
  // Zmienne
  int td,rd,d,p,i,e;

  // Inicjujemy generator pseudolosowy
  srand((unsigned int)time(NULL));

  printf("SYMULATOR TRANSMISJI DANYCH Z CRC\n");
  printf("=================================\n");

  // Losujemy dane do wysłania

  td = rand() & 0x1f;

  printf("NADAJNIK:");
  printf("\nDANE  = ");
  printnb(td,5);
  printf("\nCRC   = ");
  d = td << 3; // Dołączamy 3 bity 0
  printnb(d,8);
  // Wyliczamy CRC dzieląć przez wielomian 1011
  while(d & 0xf8)
  {
     // Wyznaczamy pozycję pierwszego bitu 1 w danych
     p = 7;
     while(!(d & (1 << p))) p--;
     // Pozycjonujemy wielomian na wydruku
     printf("\n");
     printns(15 - p);
     // Tworzymy dzielnik
     p = 11 << (p - 3);
     // Wyświetlamy dzielnik
     printnb(11,4);
     // Modyfikujemy wynik
     d ^= p;
     // Wyświetlamy wynik
     printf("\n");
     printns(8);
     printnb(d,8);
  }
  printf("\nWYNIK = ");
  td = (td << 3) | d;
  printnb(td,8);

  // Transmisja z ewentualnymi błędami
  printf("\n\nNADAJNIK --------> ODBIORNIK\n");
  printf("============================\n");

  printnb(td,8);
  rd = td;
  e = 0; // Błędy
  for(i = 0; i < 11; i++)
    if(!(rand() % 8))
    {
        e = 1;
        rd ^= (1 << i); // negujemy i-ty bit
    }
  if(e) printf(" ---(X)---> ");
  else  printf(" ---------> ");
  printnb(rd,8);
  // Sprawdzenie sumy kontrolnej
  d = rd;
  while(d & 0xf8)
  {
     // Wyznaczamy pozycję pierwszego bitu 1 w danych
     p = 11;
     while(!(d & (1 << p))) p--;
     // Pozycjonujemy wielomian na wydruku
     printf("\n");
     printns(27 - p);
     // Tworzymy dzielnik
     p = 11 << (p - 3);
     // Wyświetlamy dzielnik
     printnb(11,4);
     // Modyfikujemy wynik
     d ^= p;
     // Wyświetlamy wynik
     printf("\n");
     printns(20);
     printnb(d,8);
  }
  rd >>= 3;
  printf("\nDANE  = ");
  printnb(rd,5);
  printf(" CRC = ");
  printnb(d,3);
  if(!d) printf(" ACK\n\n");
  else   printf(" NACK!!!\n");
  return 0;
}

Symulacja jest dwuetapowa. Najpierw generowane są dane 5-bitowe. Następnie nadajnik wylicza dla nich CRC. Dane są łączone z obliczonym CRC i przesyłane. W trakcie transmisji mogą pojawić się błędy przekłamujące odebrane bity. W takim przypadku wyświetlany jest symbol (X). Drgi etap polega na wyznaczeniu CRC odebranych danych. Jeśli CRC zeruje się, to dane zostały odebrane poprawnie i odbiornik wysyła potwierdzenie ACK. Jeśli dla odebranych danych CRC nie zeruje się, to odebrane zawierają błąd i nadajnik wysyła potwierdzenie negatywne NACK.

SYMULATOR TRANSMISJI DANYCH Z CRC
=================================
NADAJNIK:
DANE  = 10101
CRC   = 10101000
        1011
        00011000
           1011
        00001110
            1011
        00000101
WYNIK = 10101101

NADAJNIK --------> ODBIORNIK
============================
10101101 ---------> 10101101
                    1011
                    00011101
                       1011
                    00001011
                        1011
                    00000000
DANE  = 10101 CRC = 000 ACK
   
SYMULATOR TRANSMISJI DANYCH Z CRC
=================================
NADAJNIK:
DANE  = 00110
CRC   = 00110000
          1011
        00011100
           1011
        00001010
            1011
        00000001
WYNIK = 00110001

NADAJNIK --------> ODBIORNIK
============================
00110001 ---(X)---> 00100001
                      1011
                    00001101
                        1011
                    00000110
DANE  = 00100 CRC = 110 NACK!!!
 

Kodowanie CRC jest bardzo popularne ze względu na prostotę implementacji. Spotkasz się z nim w sieciach komputerowych oraz przy zapisie/odczycie na dyski twarde. Przy większej ilości bitów danych kod CRC ma długość 16, 32 lub 64 bity. Dzielniki CRC znormalizowano i znajdziesz je w sieci.

Kody korekcyjne ECC

Kody korekcyjne mają za zadanie usunąć przekłamania bitów, gdy dojdzie do błędów transmisji. Stosuje się je tam, gdzie nie ma możliwości powtórzenia transmisji danych (np. telewizja cyfrowa) lub powtórzenie nie usuwa  błędu (np. porysowany dysk DVD). Kody korekcyjne są zwykle skomplikowane i dokładne omówienie ich wykracza poza ramy tego artykułu. Niemniej możemy podać przykład prostego kodu korekcyjnego, który usuwa przekłamanie 1 bitu w trakcie transmisji. Jest to tzw. kod korekcyjny Hamminga (ang. Hamming's correction code). Kod ten wykorzystuje w specyficzny sposób bity parzystości.

Pokażemy jak skonstruować słowo kodowe. Załóżmy, że chcemy przesłać 4-bitowe słowo danych 1011. Dla 4 bitów danych słowo kodowe będzie zbudowane z 7 bitów. Dodatkowe 3 bity służą do korekcji. Ponumerujmy bity od najmłodszego do najstarszego:

b7 b6 b5 b4 b3 b2 b1
             

Bity o numerach będących potęgami liczby 2 są bitami kontrolnymi, pozostałe bity są bitami danych:

b7 b6 b5 b4 b3 b2 b1
      x   x x

Wpisujemy w bity danych przesyłane bity kolejno od największego do najmniejszego:

b7 b6 b5 b4 b3 b2 b1
1 0 1 x 1 x x

Wypiszmy dwójkowo numery bitów, które mają stan 1:

7 1 1 1
5 1 0 1
3 0 1 1

Teraz w pionowych kolumnach dodajmy bit parzystości (liczba bitów 1 w kolumnie ma być parzysta):

7 1 1 1
5 1 0 1
3 0 1 1
  0 0 1

Otrzymaliśmy kolejne bity kontrolne, które wpisujemy w słowo kodowe:

b7 b6 b5 b4 b3 b2 b1
1 0 1 0 1 0 1

Dla danych 1011 słowo kodu Hamminga ma postać: 1010101. Słowo to przesyłamy do odbiornika. Załóżmy, że w trakcie transmisji przekłamaniu uległ bit b6 i odbiornik odebrał słowo kodowe:

b7 b6 b5 b4 b3 b2 b1
1 1 1 0 1 0 1

Wypisujemy dwójkowo wszystkie pozycje bitów o stanie 1, uwzględniając również bity kontrolne:

7 1 1 1
6 1 1 0
5 1 0 1
3 0 1 1
1 0 0 1

Wyznaczamy bity parzystości w kolumnach:

7 1 1 1
6 1 1 0
5 1 0 1
3 0 1 1
1 0 0 1
  1 1 0

Jeśli otrzymamy wszystkie bity 0, to znaczy, że informacja została odebrana bez błędów. W przeciwnym razie otrzymane bity traktujemy jako liczbę dwójkową 1102 = 6, która wskazuje pozycję bitu odebranego błędnie. Ponieważ błąd cyfrowy polega na odebraniu bitu o stanie przeciwnym do nadanego, zmieniamy stan bitu b6 w odebranym słowie:

b7 b6 b5 b4 b3 b2 b1
1 0 1 0 1 0 1

Usuwamy bity kontrolne i otrzymujemy przesłaną informację 1011.

Kod Hamminga potrafi  naprawić jeden bit w odebranych danych. Gdy liczba błędów może być większa, stosowane są bardziej zaawansowane kody korekcyjne, np. kod Salomona-Reeda (płyty CD/DVD). Są to zagadnienia skomplikowane i zainteresowanych odsyłam do informacji w sieci.

 

UART

UART (ang. universal asynchronous receiver-transmitter) jest układem, który służy do szeregowego nadawania i odbioru danych cyfrowych w sposób asynchroniczny. W tego typu układy są wyposażane współczesne mikrokontrolery. UART można zakupić jako samodzielny układ scalony.

W latach 90-tych wszystkie komputery PC posiadały złącze RS-232 (ang. recommended standard 232), które umożliwiało szeregowe przesyłanie danych. Obecnie standard USB zastąpił je całkowicie i w nowych komputerach nie spotkamy tego złącza. Niestety, komunikacja złączem USB jest dosyć skomplikowana, jednakże za niewielkie pieniądze możesz zakupić konwerter USB–RS-232:

Jeśli będziesz stosował moduły Arduino, to mają one już wbudowany taki konwerter.

UART przesyła/odbiera bajty danych bit po bicie w sposób szeregowy.

 

Układ posiada dwie asynchroniczne linie transmisyjne:

  • Tx – wyjście danych szeregowych . W stanie nieaktywnym na wyjściu panuje stan wysoki.
  • Rx – wejście danych szeregowych.

Transmisja rozpoczyna się od wysłania bitu startowego o stanie 0, po czym wysyłane jest 5...9 bitów danych, ewentualny bit parzystości, a na końcu przesyłany jest bit stopu, który może zostać przedłużony na dowolną liczbę bitów stopu:

Parametry transmisji (liczba bitów danych, bity parzystości, szybkość transmisji) nadajnika i odbiornika muszą być takie same, a ustawia się je w sposób określony przez producenta w dokumentacji układu UART. Gdy odbiornik skompletuje bajt danych, ustawia odpowiedni znacznik informujący, że dane są gotowe do odczytu lub generuje tzw. przerwanie, a w odpowiedzi mikrokontroler odczytuje dane i przetwarza je.

Transmisja może być prowadzona w jednym kierunku (simplex), w obu kierunkach jednocześnie (duplex) lub na zmianę raz w jednym a raz w drugim kierunku (duosimplex).

Nadajnik po otrzymaniu bajta danych  z magistrali wpisuje go do swojego rejestru przesuwającego, po czym przez odpowiedni czas generuje na wyjściu bit startu o stanie niskim, następnie przesuwa dane w rejestrze z odpowiednią szybkością. Wyjście szeregowe rejestru jest połączone z linią Tx. W ten sposób na linii Tx pojawiają się kolejne bity danych od najmłodszego do najstarszego. Gdy cała zawartość rejestru zostanie przesłana, nadajnik generuje bit stopu o stanie wysokim, po czym oczekuje na kolejny bajt danych do przesłania.

Odbiornik z odpowiednio dużą częstotliwością (przynajmniej 8 razy większą od częstotliwości przesyłania bitów) testuje stan linii Rx. Gdy wykryje stan niski, po okresie bitu startu rozpoczyna cykliczny wpis stanu tej linii do rejestru przesuwającego. Po każdym wpisie dane w rejestrze są przesuwane, w ten sposób tworzony jest bajt. Gdy do rejestru trafią wszystkie bity, odbiornik czeka na bit stopu, po czym sygnalizuje gotowość danych do odczytu. Po odczycie przez mikrokontroler danych odbiornik wraca do trybu oczekiwania na transmisję danych.

Połączenie dwóch układów UART wygląda następująco:

Jeśli transmisja ma być wykonana na większą odległość, to linie Tx i Rx należy dołączyć do odpowiednich nadajników/odbiorników linii, aby uniknąć zakłóceń.

Oprócz układów do transmisji asynchronicznej produkowane są ich odpowiedniki dla transmisji synchronicznej:

  • USRT (ang. universal synchronous receiver/transmitter) – uniwersalny, synchroniczny nadajnik/odbiornik
  • USART (ang. universal synchronous/asynchronous receiver/transmitter) – uniwersalny, synchroniczny/asynchroniczny nadajnik/odbiornik

Układami UART zajmiemy się dokładniej w sekcji poświęconej programowaniu mikrokontrolerów.

 

I2C

W roku 1982 firma Philips Semiconductor opracowała magistralę, która służy do synchronicznej transmisji danych w obu kierunkach. Transmisja I2C (również I2C lub IIC – ang. inter-integrated circuit) jest bardzo popularna w systemach mikroprocesorowych, spotkasz mnóstwo układów pamięci, wyświetlaczy oraz peryferiów, które wykorzystują magistralę I2C do wymiany informacji. Dlatego powinieneś coś wiedzieć na jej temat. Wiele mikrokontrolerów posiada zaimplementowaną komunikację magistralą I2C, a te, które takich możliwości nie mają, mogą implementować standard I2C programowo.

Oryginalna prędkość transmisji I2C jest równa 100kb na sekundę. opracowano również standardy 400kb (fast mode), 1Mb (fast mode plus) i 3,4Mb (high speed mode) na sekundę. Sam protokół I2C jest dosyć skomplikowany, na szczęście dostępne jest dużo bibliotek dla różnych mikrokontrolerów, które go implementują.

Transmisja I2C prowadzona jest dwoma liniami:

  • SCL(ang. serial clock) impulsy zegarowe, które synchronizują przesyłanie bitów danych drugą linią,
  • SDA(ang. serial data) dane szeregowe.

Stanem aktywnym jest stan niski, który uzyskuje się przez zwarcie danej linii do masy za pomocą tranzystora z otwartym kolektorem (wersja bipolarna) lub otwartym drenem (wersja polowa). Dzięki takiemu rozwiązaniu dane mogą być przesyłane pomiędzy układami o różnych poziomach zasilania. Do linii można podłączać wiele układów, dlatego nazywane są one magistralą I2C (ang. I2C bus).

Typowe połączenie magistralą I2C wygląda następująco:

Oporniki R służą do podciągania napięcia na liniach SCL i SDA, gdy nie są one zwierane do masy przez jeden z układów. Tymi samymi liniami magistrali mogą przesyłać dane więcej niż dwa układy:

W czasie transmisji danych pomiędzy dwoma układami jeden z nich pełni rolę nadrzędną (ang. master), a drugi jest podporządkowany (ang. slave). Sygnał zegarowy na linii SCL zawsze wytwarza bieżący układ nadrzędny. Układ podporządkowany może zwierać ten sygnał do masy, jeśli nie jest gotowy na przesłanie lub przyjęcie danych. Oporniki podciągające R przywracają wysoki stan na liniach I2C, gdy żaden układ nie zwiera ich do masy.

Przesłanie danych odbywa się ściśle wg protokołu I2C. Jest on bardziej skomplikowany od protokołu UART, ponieważ do magistrali I2C może być przyłączone wiele układów, zatem przed rozpoczęciem przesłania danych należy określić nadawcę i odbiorcę. Na szczęście większość układów współpracujących z magistralą I2C zawiera już odpowiednią implementację protokołu. Dane na magistrali będziemy nazywać wiadomościami (ang. messages). Wiadomość składa się z dwóch rodzajów ramek (ang. frames):

  • ramka adresowa (ang. address frame) – układ Master przesyła w tej ramce adres układu Slave, dla którego przeznaczona jest wiadomość.
  • ramka danych (ang. data frame) – takich ramek może być kilka i są one przesyłane pomiędzy układem Master a układem Slave.

Ramka adresowa

Pojawia się ona w wiadomości zawsze jako pierwsza. Celem tej ramki jest zaadresowanie właściwego układu Slave oraz poinformowanie go o trybie transmisji, tzn. czy ma odbierać, czy przesłać dane w następnych ramkach.

Transmisję rozpoczyna układ Master przez pozostawienie linii SCL (zegar) w stanie wysokim i ustawienie linii SDA (dane) w stan niski:

Jest to sygnał dla wszystkich układów Slave, że za chwilę rozpocznie się transmisja. Jeśli na magistrali I2C obecnych jest kilka układów Master, to może się zdarzyć, iż dwa lub więcej z nich rozpoczną transmisję. W takim przypadku kontrolę nad magistralą przejmuje ten, który jako pierwszy ustawił linię SDA w stan niski. Protokół I2C obejmuje powtórzenia startu transmisji.

Po starcie na linia SCL jest ustawiana w stan niski, a na linii SDA są umieszczane kolejne bity danych adresowych, które są odczytywane przez układy Slave przy narastających zboczach impulsów zegarowych na linii SCL. Najpierw przesyłane są bity adresu (zwykle 7 bitów w kolejności od najstarszego do najmłodszego), po nich idzie bit zapisu/odczytu R/W, który informuje zaadresowane urządzenie Slave, czy transmisja danych będzie do niego (zapis, Write), czy też od niego (odczyt, Read). Na końcu przesyłany jest bit potwierdzenia o stanie wysokim. Po przesłaniu 8 pierwszych bitów (7 bitów adresu + bit R/W) układ Master oddaje sterowanie linią SDA układowi Slave, który w bicie potwierdzenia powinien wymusić na tej linii stan niski, co oznacza gotowość na wykonanie operacji:

Ramka danych

Po pozytywnym przesłaniu ramki adresowej układ Master kontynuuje generowanie impulsów zegarowych i są przesyłane ramki danych (ich ilość jest dowolna i zależna od typu komunikujących się układów). Dane na linii SDA są umieszczane przez układ Master przy zapisie lub przez układ Slave przy odczycie (określa to bit R/W w ramce adresowej). Ramki danych przesyłają 8 bitów (od najstarszego do najmłodszego) oraz 9-ty bit potwierdzenia (potwierdza odbiorca):

Gdy transmisja ramek danych zostanie ukończona układ Master ustawia linię SCL w stan wysoki, po czym również ustawia linię SDA w stan wysoki i tak pozostaje do następnej transmisji:

Więcej na temat protokołu I2C znajdziesz w sieci (adresowanie 10-bitowe, wznawianie transmisji, rozciąganie impulsów zegarowych, itp.). Zagadnienie jest zbyt obszerne, aby opisać je w małym podrozdziale. Podane tutaj informacje potraktuj tylko jako wstęp.

 

SPI

SPI (ang. serial peripheral interface bus – szeregowa magistrala dla urządzeń zewnętrznych) jest standardem synchronicznego przesyłania danych opracowanym w latach 80-tych przez firmę Motorola. Transmisja jest w pełni dwukierunkowa i opiera się na modelu Master-Slave. W transmisji może uczestniczyć tylko jedno urządzenie nadrzędne (master). Urządzeń podporządkowanych (slave) może być kilka. Transmisja prowadzona jest za pomocą trzech przewodów. Czwarty przewód służy do uaktywniania urządzeń podporządkowanych:

Znaczenie sygnałów jest następujące:

SCLK (ang. Serial CLocK) impulsy zegarowe synchronizujące transmisję.
MOSI (ang. Master Output, Slave Input) wyjście danych z urządzenia Master, wejście danych dla urządzenia Slave.
MISO (ang. Master Input, Slave Output) wejście danych dla urządzenia Master, wyjście danych dla urządzenia Slave.
SS (ang. Slave Select) uaktywnienie urządzenia Slave.

Jeśli kilka urządzeń podporządkowanych ma być podłączone pod wspólną magistralę SPI, to do każdego z nich należy doprowadzić osobny sygnał SS:

Istnieje również możliwość łączenia niektórych urządzeń Slave w pierścień z urządzeniem Master.

Takie rozwiązanie pozwala stosować tylko 4 linie do transmisji SPI. Dane są przesyłane szeregowo od urządzenia Master do pierwszego urządzenia Slave, które następnie retransmituje je do następnego urządzenia Slave, itd. Urządzenie Master musi w tym przypadku zapewnić odpowiednią ilość impulsów zegarowych.

Zasada prowadzenia transmisji jest następująca:

Urządzenie Master (najczęściej twój mikrokontroler) uaktywnia wybrane urządzenie Slave przez ustawienie jego linii SS w stan niski. Następnie generuje odpowiednią ilość impulsów zegarowych na linii SCLK. Dane zapisywane do urządzenia Slave są przesyłane linią MOSI, a urządzenie Slave przesyła dane do urządzenia Master linią MISO. Przesyłane dane są odczytywane przy dodatnim lub ujemnym zboczu sygnału zegarowego w zależności od wybranego trybu pracy.

Dane przesyłane są na zasadzie rejestrów przesuwających:

Pod wpływem impulsów zegarowych dane w rejestrze Master są przesuwane i wysyłane linią MOSI. Z kolei dane z linii MISO są wpisywane z drugiej strony rejestru. W urządzeniu Slave dane z linii MOSI są wpisywane do rejestru. A dane w rejestrze Slave są przesuwane i wysyłane linią MISO. W ten sposób po 8 impulsach zegarowych (jeśli rejestry są 8-bitowe) dane z obu rejestrów zostaną wymienione między sobą.

Tutaj występuje kilka ustaleń technicznych, które zależą od konkretnego urządzenia SPI. Niestety, nie ma jednolitego standardu i musisz dostosować się do parametrów udostępnianych przez producenta:

  • Maksymalna częstotliwość sygnału zegarowego – zwykle kilkanaście MHz. Transmisja SPI została zaprojektowania do wymiany danych na niewielkie odległości (do kilkudziesięciu cm). Jeśli dane musisz przesyłać na większą odległość, to powinieneś zmniejszyć częstotliwość zegara. Czasem będzie konieczne zastosowanie odpowiednich układów nadajnika i odbiornika.
  • Polaryzacja sygnału zegarowego (ang. clock polarity) określa, czy impuls zegarowy jest dodatni lub ujemny. Przy polaryzacji dodatniej nieaktywnym stanem linii SCLK jest stan 0. Przy ujemnej jest to stan 1:

  • Faza sygnału zegarowego (ang. clock phase) określa krawędź sygnału zegarowego, przy której dane są odczytywane z linii MOSI/MISO oraz krawędź przy której na liniach tych pojawia się kolejny bit danych z rejestrów przesuwających:

  • Kolejność bitów (ang. bit order) określa sposób, w jaki są przesyłane kolejne bity danych. Możliwości są dwie: od najstarszego bitu do najmłodszego (ang. MSB first) lub od najmłodszego do najstarszego (ang. LSB first).
  • Liczba bitów danych zwykle wynosi 8, ale może to być również 16 i więcej.

Sposób komunikacji z konkretnym urządzeniem powinien być zgodny z danymi technicznymi publikowanymi przez jego producenta. Zwykle wygląda to tak, iż urządzenie Master najpierw przesyła linią MOSI 8-bitowy rozkaz, a następnie przesyła tą samą linią dane lub odczytuje dane linią MISO. Niektóre urządzenia SPI tylko przesyłają dane, zatem urządzenie Master inicjuje transmisję, po czym odczytuje linią MISO serię bitów z wybranego urządzenia Slave.

W Arduino jest odpowiednia biblioteka do komunikacji SPI. Zajmiemy się tym zagadnieniem na kursie programowania konkretnych mikrokontrolerów.

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2018 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.