- Co to jest protokół komunikacyjny SPI?
- Jak działa protokół SPI?
- Różnica między komunikacją I2C i SPI
- SPI z PIC16F877A przy użyciu kompilatora XC8:
- Objaśnienie pliku nagłówkowego SPI:
- Główny program Wyjaśnienie:
- Symulacja PIC z debugerem SPI:
Mikrokontrolery PIC to potężna platforma dostarczana przez mikroczip dla projektów osadzonych; jego wszechstronny charakter umożliwił mu znalezienie sposobów na wiele zastosowań i jeszcze się bardzo nie rozwinął. Jeśli śledziłeś nasze samouczki PIC, zauważyłeś, że omówiliśmy już szeroką gamę samouczków na temat mikrokontrolera PIC, zaczynając od podstaw. W tym samym czasie przystępujemy do nauki protokołów komunikacyjnych dostępnych w PIC i jak ich używać. Omówiliśmy już I2C z mikrokontrolerem PIC.
W rozległym systemie aplikacji wbudowanych żaden mikrokontroler nie jest w stanie samodzielnie wykonać wszystkich czynności. Na pewnym etapie musi komunikować się z innymi urządzeniami, aby udostępniać informacje, istnieje wiele różnych typów protokołów komunikacyjnych do udostępniania tych informacji, ale najczęściej używane są USART, IIC, SPI i CAN. Każdy protokół komunikacyjny ma swoje zalety i wady. Na razie skupmy się na protokole SPI, ponieważ tego nauczymy się w tym samouczku.
Co to jest protokół komunikacyjny SPI?
Termin SPI oznacza „ Serial Peripheral Interface ”. Jest to powszechny protokół komunikacyjny, który służy do przesyłania danych między dwoma mikrokontrolerami lub do odczytu / zapisu danych z czujnika do mikrokontrolera. Służy również do komunikacji z kartami SD, rejestrami zmiany biegów, kontrolerami wyświetlacza i wieloma innymi.
Jak działa protokół SPI?
Komunikacja SPI jest komunikacją synchroniczną, co oznacza, że działa za pomocą sygnału zegarowego, który jest współdzielony między dwoma urządzeniami wymieniającymi dane. Jest to również komunikacja w trybie pełnego dupleksu, ponieważ może wysyłać i odbierać dane za pomocą oddzielnej magistrali. Komunikacja SPI wymaga do działania 5 przewodów. Poniżej przedstawiono prosty obwód komunikacyjny SPI między urządzeniem nadrzędnym i podrzędnym
Pięć przewodów wymaganych do komunikacji to SCK (Serial Clock), MOSI (Master Out Slave In), MISO (Master In Slave Out) i SS (Slave Select). Komunikacja SPI zawsze odbywa się tylko między master a slave. Master może mieć podłączonych wielu slaveów. Master jest odpowiedzialny za generowanie impulsu zegara i to samo jest współdzielone ze wszystkimi slave'ami. Również cała komunikacja może być inicjowana tylko przez mastera.
Pin SCK (znany również jako zegar szeregowy SCL) współdzieli sygnał zegara generowany przez urządzenie nadrzędne z urządzeniami podrzędnymi. Pin MOSI (aka SDA - seryjne wyjście danych) jest używany do wysyłania danych z mastera do salve. Pin MISO (aka SDI - Serial Data In) służy do przesyłania danych z salve do mastera. Możesz również podążać za strzałką na powyższym rysunku, aby zrozumieć ruch danych / sygnału. Wreszcie pin SS (znany również jako CS - wybór statku) jest używany, gdy do mastera jest podłączony więcej niż jeden moduł slave. Można go użyć do wybrania wymaganego urządzenia podrzędnego. Przykładowy obwód, w którym więcej niż jeden slave jest połączony z urządzeniem nadrzędnym w celu komunikacji SPI, pokazano na poniższym obwodzie.
Różnica między komunikacją I2C i SPI
Nauczyliśmy się już komunikacji I2C z PIC, więc musimy być zaznajomieni z tym, jak działa I2C i gdzie możemy ich używać, tak jak I2C może być używany do interfejsu modułu RTC. Ale teraz, dlaczego potrzebujemy protokołu SPI, skoro mamy już I2C. Powodem jest to, że zarówno komunikacja I2C, jak i SPI są zaletami na swój sposób, a zatem są specyficzne dla aplikacji.
Do pewnego stopnia można uznać, że komunikacja I2C ma pewne zalety w porównaniu z komunikacją SPI, ponieważ I2C wykorzystuje mniejszą liczbę pinów i staje się bardzo przydatna, gdy do magistrali jest podłączonych duża liczba slaveów. Ale wadą I2C jest to, że ma tę samą magistralę do wysyłania i odbierania danych, a zatem jest stosunkowo wolny. Więc to jest oparte wyłącznie na aplikacji, aby wybrać pomiędzy protokołem SPI i I2C dla twojego projektu.
SPI z PIC16F877A przy użyciu kompilatora XC8:
Dość podstaw, teraz nauczmy się, jak możemy wykorzystać komunikację SPI na mikrokontrolerze PIC16F877A przy użyciu MPLABX IDE i kompilatora XC8. Zanim zaczniemy, wyjaśnij, że ten samouczek mówi tylko o SPI w PIC16F877a przy użyciu kompilatora XC8, proces będzie taki sam dla innych mikrokontrolerów, ale mogą być wymagane niewielkie zmiany. Pamiętaj również, że w przypadku zaawansowanych mikrokontrolerów, takich jak seria PIC18F, sam kompilator może mieć wbudowaną bibliotekę do korzystania z funkcji SPI, ale w przypadku PIC16F877A nic takiego nie istnieje, więc zbudujmy ją samodzielnie. Wyjaśniona tutaj biblioteka zostanie podana jako plik nagłówkowy do pobrania na dole, który może być użyty dla PIC16F877A do komunikacji z innymi urządzeniami SPI.
W tym samouczku napiszemy mały program, który wykorzystuje komunikację SPI do zapisywania i odczytywania danych z magistrali SPI. Następnie zweryfikujemy to samo za pomocą symulacji Proteus. Cały kod związany z rejestrami SPI zostanie umieszczony w pliku nagłówkowym o nazwie PIC16f877a_SPI.h. W ten sposób możemy używać tego pliku nagłówkowego we wszystkich naszych nadchodzących projektach, w których wymagana jest komunikacja SPI. W głównym programie będziemy po prostu używać funkcji z pliku nagłówkowego. Cały kod wraz z plikiem nagłówkowym można pobrać stąd.
Objaśnienie pliku nagłówkowego SPI:
W pliku nagłówkowym musimy zainicjować komunikację SPI dla PIC16F877a. Jak zawsze najlepszym miejscem do rozpoczęcia jest arkusz danych PIC16F877A. Rejestry sterujące komunikacją SPI dla PIC16F8777a to SSPSTAT i rejestr SSPCON. Możesz o nich dowiedzieć się na stronach 74 i 75 arkusza danych.
Istnieje wiele opcji parametrów, które należy wybrać podczas inicjowania komunikacji SPI. Najczęściej używaną opcją jest to, że częstotliwość zegara zostanie ustawiona na Fosc / 4 i zostanie wykonana w środku, a zegar zostanie ustawiony jako niski w stanie idealnym. Więc używamy tej samej konfiguracji dla naszego pliku nagłówkowego, możesz je łatwo zmienić, zmieniając odpowiednie bity.
SPI_Initialize_Master ()
Funkcja inicjalizacji SPI Master jest używana do rozpoczęcia komunikacji SPI jako master. Wewnątrz tej funkcji ustawiamy odpowiednie piny RC5 i RC3 jako piny wyjściowe. Następnie konfigurujemy rejestr SSPTAT i SSPCON, aby włączyć komunikację SPI
void SPI_Initialize_Master () { TRISC5 = 0; // SSPSTAT = 0b00000000; // pg 74/234 SSPCON = 0b00100000; // pg 75/234 TRISC3 = 0; // Ustaw jako wyjście na tryb slave }
SPI_Initialize_Slave ()
Funkcja ta służy do ustawienia mikrokontrolera do pracy w trybie slave do komunikacji SPI. W trybie slave pin RC5 powinien być ustawiony jako wyjście, a pin RC3 powinien być ustawiony jako wejście. SSPSTAT i SSPCON są ustawiane w ten sam sposób zarówno dla slave jak i master.
void SPI_Initialize_Slave () { TRISC5 = 0; // Pin SDO powinien być zadeklarowany jako wyjście SSPSTAT = 0b00000000; // pg 74/234 SSPCON = 0b00100000; // pg 75/234 TRISC3 = 1; // Ustaw jako wyjście dla trybu głównego }
SPI_Write (nadchodzący znak)
Funkcja SPI Write służy do zapisywania danych na magistrali SPI. Pobiera informacje od użytkownika za pośrednictwem zmiennej przychodzącej, a następnie używa ich do przekazania do rejestru bufora. SSPBUF zostanie wyczyszczony w kolejnym impulsie zegara, a dane będą przesyłane do magistrali bit po bicie.
void SPI_Write (przychodzące znaki) { SSPBUF = przychodzące; // Zapisz dane podane przez użytkownika w buforze }
SPI_Ready2Read ()
Funkcja SPI ready to Read służy do sprawdzenia, czy dane w magistrali SPI zostały odebrane w całości i czy można je odczytać. Rejestr SSPSTAT ma bit o nazwie BF, który ustawia się po całkowitym odebraniu danych, więc sprawdzamy, czy ten bit jest ustawiony, jeśli nie jest ustawiony, musimy poczekać, aż zostanie ustawiony na odczyt czegokolwiek z magistrali SPI.
unsigned SPI_Ready2Read () { if (SSPSTAT & 0b00000001) return 1; else return 0; }
SPI_Read ()
Odczyt SPI służy do odczytu danych z magistrali SPI do mikrokontrolera. Dane obecne w magistrali SPI zostaną zapisane w SSPBUF, musimy poczekać, aż wszystkie dane zostaną zapisane w buforze i wtedy możemy je wczytać do zmiennej. Sprawdzamy bit BF rejestru SSPSTAT przed odczytaniem bufora, aby upewnić się, że odbiór danych jest zakończony.
char SPI_Read () // Odczytaj otrzymane dane { while (! SSPSTATbits.BF); // Przytrzymaj do momentu ustawienia bitu BF, aby upewnić się, że pełne dane zostaną odczytane i zwrócone (SSPBUF); // zwraca odczytane dane }
Główny program Wyjaśnienie:
Funkcje wyjaśnione w powyższej sekcji będą znajdować się w pliku nagłówkowym i można je wywołać w głównym pliku c. Napiszmy więc mały program, który sprawdzi, czy komunikacja SPI działa. Po prostu zapiszemy kilka danych do magistrali SPI i użyjemy symulacji proteus, aby sprawdzić, czy te same dane są odbierane w debugerze SPI.
Jak zwykle rozpocznij program od ustawienia bitów konfiguracyjnych, a następnie bardzo ważne jest dodanie do programu pliku nagłówkowego, który właśnie wyjaśniliśmy, jak pokazano poniżej
#zawierać
Jeśli otworzyłeś program z pobranego powyżej pliku zip, to domyślnie plik nagłówkowy będzie obecny w katalogu plików nagłówkowych pliku projektu. W przeciwnym razie musisz ręcznie dodać plik nagłówkowy do projektu, po dodaniu pliki projektu będą wyglądać następująco
W głównym pliku musimy zainicjować PIC jako Master do komunikacji SPI, a następnie wewnątrz nieskończonej pętli while będziemy zapisywać losowe trzy wartości szesnastkowe do magistrali SPI, aby sprawdzić, czy otrzymamy to samo podczas symulacji.
void main () { SPI_Initialize_Master (); podczas gdy (1) { SPI_Write (0X0A); __delay_ms (100); SPI_Write (0X0F); __delay_ms (100); SPI_Write (0X15); __delay_ms (100); } }
Zwróć uwagę, że losowe wartości użyte w programie to 0A, 0F i 15 i są to wartości szesnastkowe, więc powinniśmy zobaczyć to samo podczas symulacji. Czyli kod jest gotowy, to tylko przykład, ale możemy użyć tej samej metodologii do komunikacji z innym MCU lub z innym modułem czujników pracującym na protokole SPI.
Symulacja PIC z debugerem SPI:
Teraz, gdy nasz program jest gotowy, możemy go skompilować, a następnie przystąpić do symulacji. Proteus posiada przydatną funkcję zwaną debuggerem SPI , która może być używana do monitorowania danych przez magistralę SPI. Więc używamy tego samego i budujemy obwód, jak pokazano poniżej.
Ponieważ w symulacji jest tylko jedno urządzenie SPI , nie używamy pinu SS, a gdy nie jest używany, powinien być uziemiony, jak pokazano powyżej. Wystarczy załadować plik hex do mikrokontrolera PIC16F877A i kliknąć przycisk odtwarzania, aby zasymulować nasz program. Po rozpoczęciu symulacji pojawi się wyskakujące okienko, które wyświetla dane w magistrali SPI, jak pokazano poniżej
Przyjrzyjmy się bliżej napływającym danym i sprawdźmy, czy są takie same jak te, które zapisaliśmy w naszym programie.
Dane są odbierane w tej samej kolejności, w jakiej zapisaliśmy w naszym programie i to samo jest dla Ciebie podświetlone. Możesz także spróbować zasymulować program do komunikacji z dwoma mikrokontrolerami PIC za pomocą protokołu SPI. Musisz zaprogramować jeden PIC jako master, a drugi jako slave. Wszystkie potrzebne do tego pliki nagłówkowe są już podane w pliku nagłówkowym.
To tylko rzut oka na to, co może zrobić SPI, może również odczytywać i zapisywać dane na wielu urządzeniach. Więcej informacji na temat SPI omówimy w nadchodzących samouczkach, łącząc różne moduły współpracujące z protokołem SPI.
Mam nadzieję, że zrozumiałeś projekt i nauczyłeś się z niego czegoś pożytecznego. Jeśli masz jakiekolwiek wątpliwości, umieść je w sekcji komentarzy poniżej lub skorzystaj z forum, aby uzyskać pomoc techniczną.
Pełny kod główny podano poniżej; możesz pobrać pliki nagłówkowe z całym kodem stąd