Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
https://www.microchip.com/about-us/legal-information/copyright-usage-guidelines
Interfejs szeregowy (ang. Serial Peripheral Interface, SPI) pozwala na szybki synchroniczny przesył danych pomiędzy mikrokontrolerem ATtiny20 a urządzeniami peryferyjnymi lub pomiędzy kilkoma mikrokontrolerami AVR. Moduł SPI jest przedstawiony na poniższym rysunku:
Aby włączyć moduł SPI, należy wyzerować bit PRSPI w rejestrze PRR (ang. Power Reduction Register, rejestr zmniejszania poboru energii). Połączenie pomiędzy mikrokontrolerem Master a mikrokontrolerem Slave za pomocą SPI pokazuje poniższy rysunek:
System składa się z dwóch rejestrów przesuwających oraz generatora zegara Master. Mikrokontroler Master rozpoczyna cykl przesłania danych przez ustawienie w stan niski pożądanej końcówki SS wybierającej układ Slave (ang. Slave Select). Układy Master i Slave przygotowują dane do przesłania w swoich rejestrach przesuwających, a układ Master generuje impulsy zegarowe na linii SCK do wymiany danych. Dane z układu Master do Slave są zawsze przesuwane linią MOSI (ang. Master Out – Slave In), a dane z układu Slave do Master przesuwane są po linii MISO (ang. Master In – Slave Out). Po każdym pakiecie danych układ Master synchronizuje układ Slave przez ustawienie w stan wysoki linii SS (ang. Slave Select, wybór układu Slave). Po skonfigurowaniu jako Master interfejs SPI nie posiada żadnej automatycznej kontroli nad linią SS. Musi to być wykonywane przez program użytkownika, zanim będzie mogła rozpocząć się transmisja. Gdy zostanie to zrobione, zapis bajtu do rejestru danych SPI włącza generator zegara SPI i osiem bitów zostaje przesunięte sprzętowo do układu Slave. Po przesuwie jednego bajtu generator zegara SPI zatrzymuje się, ustawiając znacznik końca transmisji (SPIF). Jeśli bit włączający przerwania SPI (ang. SPI Interrupt Enable bit, SPIE) w rejestrze SPCR jest ustawiony na 1, to nastąpi żądanie przerwania. Układ Master może kontynuować przesuwanie następnego bajtu przez zapis do rejestru SPDR lub zasygnalizować koniec transmisji przez ustawienie w stan wysoki linii wyboru układu Slave SS. Ostatni odebrany bajt będzie przechowywany w rejestrze buforowym do późniejszego wykorzystania.
Gdy układ zostanie skonfigurowany jako Slave, interfejs SPI pozostaje w uśpieniu z linią MISO w stanie wysokiej impedancji tak długo, jak końcówka SS jest ustawiona w stan wysoki. W tym stanie oprogramowanie może uaktualniać rejestr danych SPI (ang. SPI Data Register, SPDR), lecz dane nie zostaną przesunięte na zewnątrz przez nadchodzące impulsy na końcówce SCK, aż końcówka SS nie zostanie ustawiona w stan niski. Gdy jeden bajt został całkowicie przesunięty, ustawiany jest znacznik końca transmisji (ang. End of Transmission Flag, SPIF). Jeśli bit włączający przerwania SPI (ang. SPI Interrupt Enable bit, SPIE) w rejestrze SPCR jest ustawiony na 1, to nastąpi żądanie przerwania. Układ Slave może kontynuować umieszczanie nowych danych do przesłania w rejestrze SPDR przed odczytem nadchodzących danych. Ostatni odebrany bajt będzie przechowywany w rejestrze buforowym do późniejszego wykorzystania.
System buforuje pojedynczo w kierunku nadawczym i podwójnie w kierunku odbiorczym. Oznacza to, iż bajty do przesłania nie mogą być zapisywane do rejestru danych SPI przed zakończeniem całego cyklu przesuwania. Jednakże przy odbiorze danych odebrany znak musi zostać odczytany z rejestru danych SPI, zanim następny znak nie zostanie w całości wsunięty. W przeciwnym razie ten pierwszy bajt zostanie utracony.
W trybie Slave SPI układ sterowania próbkuje nadchodzący sygnał na końcówce SCK. Aby zapewnić poprawne próbkowanie sygnału zegarowego, minimalne okresy stanów niskich i wysokich powinny spełniać poniższe wymagania:
Stany
niskie: dłuższe niż 2 okresy zegara mikroprocesora
Stany wysokie: dłuższe niż 2 okresy zegara mikroprocesora
Gdy interfejs SPI zostanie uaktywniony, kierunek danych na końcówkach MOSI, MISO, SCK, i SS jest wymuszany zgodnie z poniższą tabelą:
Końcówka | Kierunek w trybie MASTER | Kierunek w trybie SLAVE |
MOSI | Określany przez użytkownika | Wejście |
MISO | Wejście | Określany przez użytkownika |
SCK | Określany przez użytkownika | Wejście |
SS | Określany przez użytkownika | Wejście |
Poniższe przykłady kodów pokazują, w jaki sposób należy zainicjować interfejs SPI w trybie Master i jak wykonać prostą transmisję. DDR_SPI w tych przykładach musi zostać zastąpione przez właściwy rejestr kierunku danych, który steruje końcówkami SPI. DD_MOSI, DD_MISO i DD_SCK muszą być zastąpione przez rzeczywiste bity kierunku danych dla tych końcówek. Na przykład, jeśli MOSI znajduje się na końcówce PB5, zamień DD_MOSI przez DDB5 a DDR_SPI przez DDRB.
Przykład w kodzie maszynowym |
SPI_MasterInit: ; Ustaw MOSI i SCK jako wyjścia, pozostałe jako wejścia ldi r17,(1<<DD_MOSI)|(1<<DD_SCK) out DDR_SPI,r17 ; Włącz SPI Master, ustaw częstotliwość zegara na fck/16 ldi r17,(1<<SPE)|(1<<MSTR)|(1<<SPR0) out SPCR,r17 ret SPI_MasterTransmit: ; Rozpocznij transmisję danych (r16) out SPDR,r16 Wait_Transmit: ; Czekaj na zakończenie transmisji in r16, SPSR sbrs r16, SPIF rjmp Wait_Transmit ret |
Przykład w języku C |
void SPI_MasterInit(void) { /* Ustaw MOSI i SCK jako wyjścia, pozostałe jako wejścia */ DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK); /* Włącz SPI Master, ustaw częstotliwość zegara na fck/16 */ SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0); } void SPI_MasterTransmit(char cData) { /* Rozpocznij transmisję danych */ SPDR = cData; /* Czekaj na zakończenie transmisji */ while(!(SPSR & (1<<SPIF))) ; } |
Poniższe przykłady kodów pokazują, jak zainicjować interfejs SPI w trybie Slave i wykonać prosty odbiór danych.
Przykład w kodzie maszynowym |
SPI_SlaveInit: ; Ustaw MISO jako wyjście, wszystkie pozostałe jako wejścia ldi r17,(1<<DD_MISO) out DDR_SPI,r17 ; Włącz SPI ldi r17,(1<<SPE) out SPCR,r17 ret SPI_SlaveReceive: ; Czekaj na koniec odbierania in r16, SPSR sbrs r16, SPIF rjmp SPI_SlaveReceive ; Odczytaj odebrane dane i powróć in r16,SPDR ret |
Przykład w języku C |
void SPI_SlaveInit(void) { /* Ustaw MISO jako wyjście, wszystkie pozostałe jako wejścia */ DDR_SPI = (1<<DD_MISO); /* Włącz SPI */ SPCR = (1<<SPE); } char SPI_SlaveReceive(void) { /* Czekaj na koniec odbierania */ while(!(SPSR & (1<<SPIF))) ; /* Zwróć rejestr danych */ return SPDR; } |
Gdy SPI zostało skonfigurowane do pracy w trybie Slave, to końcówka SS (ang. Slave Select) pracuje zawsze jako wejście. Gdy na końcówce tej zostanie wymuszony stan niski, aktywuje się interfejs SPI, a MISO staje się wyjściem, jeśli tak ją skonfigurował program użytkownika. Wszystkie pozostałe końcówki interfejsu są wejściami. Gdy SS zostanie ustawione w stan wysoki, wszystkie końcówki stają się wejściami, a SPI przechodzi w stan pasywny, co oznacza, że nie będzie odbierać nadchodzących danych. Zwróć uwagę, iż logika sterowania interfejsem SPI zostaje zresetowana po wymuszeniu stanu wysokiego na końcówce SS.
Końcówka SS jest przydatna do synchronizacji pakietu/bajtu, aby utrzymywać licznik bitów układu Slave w synchronizacji z generatorem zegara układu Master. Gdy końcówka SS zostanie ustawiona w stan wysoki, układ SPI Slave natychmiast zresetuje logikę nadawania i odbioru oraz odrzuci wszelkie dane częściowo odebrane w rejestrze przesuwającym.
Gdy interfejs SPI jest skonfigurowany do pracy w trybie Master (ustawiony bit MSTR w rejestrze SPCR), użytkownik może określić kierunek końcówki SS.
Jeśli SS skonfigurowane jest jako wyjście, to końcówka ta staje się ogólną końcówką wyjścia, która nie wpływa na system SPI. Zwykle końcówka SS będzie sterowała końcówką SS układu SPI Slave.
Jeśli SS jest skonfigurowane jako wejście, to musi być utrzymywana w stanie wysokim, aby zapewnić pracę SPI Master. Jeśli układ zewnętrzny ustawi końcówkę SS w stan niski, gdy interfejs SPI pracuje w trybie Master z SS jako wejście, to system SPI zinterpretuje to jako wybranie tego SPI przez inny układ SPI Master, który rozpoczyna przesyłanie danych do tego SPI tak, jakby pracowało w trybie Slave. Aby uniknąć sporu na magistrali, system SPI podejmuje następujące działania:
Stąd, gdy stosowana jest transmisja SPI sterowana przerwaniami w trybie Master i istnieje możliwość, że SS znajdzie się w stanie niskim, to przerwanie powinno zawsze sprawdzać, czy bit MSTR jest wciąż ustawiony. Jeśli bit MSTR został wyzerowany przez końcówkę SS, to musi on zostać ustawiony przez użytkownika, aby ponownie uaktywnić tryb SPI Master.
Format przesyłu SPI z CPHA = 0
Format
przesyłu SPI z CPHA = 1
Bity danych są wysuwane i zatrzaskiwane na przeciwległych zboczach sygnału SCK, dając dostateczny czas na ustabilizowanie się sygnałów danych. Jest to pokazane w poniższej tabeli:
Tryb SPI | Warunki | Zbocze początkowe | Zbocze końcowe |
0 | CPOL=0, CPHA=0 | Próbkowanie (narastające) | Przygotowanie (opadające) |
1 | CPOL=0, CPHA=1 | Przygotowanie (narastające) | Próbkowanie (opadające) |
2 | CPOL=1, CPHA=0 | Próbkowanie (opadające) | Przygotowanie (narastające) |
3 | CPOL=1, CPHA=1 | Przygotowanie (opadające) | Próbkowanie (narastające) |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x30 | SPIE | SPE | DORD | MSTR | CPOL | CPHA | SPR1 | SPR0 | SPCR |
Zapis/Odczyt | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Ten bit powoduje wykonanie przerwania SPI, jeśli są ustawione bity SPIF w rejestrze SPSR oraz I w rejestrze stanu SREG.
Gdy bit SPE zostanie ustawiony na 1, włącza się interfejs SPI. Bit ten należy ustawić, aby uaktywnić jakiekolwiek operacje SPI.
Gdy do DORD zostanie wpisana jedynka logiczna, to najpierw
będzie przesyłany najmłodszy bit (LSB)
danych.
Gdy do DORD zostanie wpisane zero logiczne, to najpierw będzie
przesyłany najstarszy bit (MSB) danych.
Ten bit wybiera tryb Master SPI, jeśli zostanie do niego wpisana jedynka logiczna, lub tryb Slave SPI, jeśli zostanie do niego wpisane zero. Jeśli końcówka SS jest skonfigurowana jako wejście i zostanie zewnętrznie wysterowana stanem niskim przy ustawionym bicie MSTR, to bit MSTR będzie wyzerowany, a znacznik przerwania SPIF w rejestrze SPSR ustawia się na 1. Użytkownik będzie musiał w tym przypadku ustawić bit MSTR, aby ponownie uaktywnić tryb SPI Master.
Gdy do tego bitu zostanie wpisana logiczna jedynka, to w stanie nieaktywnym sygnał SCK ma wartość wysoką. Gdy do CPOL zostanie wpisane zero, sygnał SCK jest nieaktywny w stanie niskim. Poniższa tabela podsumowuje funkcjonalność CPOL:
CPOL | Zbocze początkowe | Zbocze końcowe |
0 | Rosnące | Opadające |
1 | Opadające | Rosnące |
Ustawienie bitu fazy zegara określa, czy dane będą próbkowane na zboczu początkowym, czy na zboczu końcowym sygnału zegarowego SCK. Poniższa tabela podsumowuje funkcjonalność bitu CPHA:
CPHA | Zbocze początkowe | Zbocze końcowe |
0 | Próbkowanie | Przygotowanie |
1 | Przygotowanie | Próbkowanie |
Te dwa bity kontrolują częstotliwość sygnału SCK urządzenia skonfigurowanego jako Master. W trybie Slave bity SPR1 i SPR0 nie dają żadnych efektów. Związek pomiędzy SCK a częstotliwością zegara we/wy fclk_I/O pokazuje tabela poniżej:
SPI2X | SPR1 | SPR0 | Częstotliwość SCK |
0 | 0 | 0 | fclk_I/O/4 |
0 | 0 | 1 | fclk_I/O/16 |
0 | 1 | 0 | fclk_I/O/64 |
0 | 1 | 1 | fclk_I/O/128 |
1 | 0 | 0 | fclk_I/O/2 |
1 | 0 | 1 | fclk_I/O/8 |
1 | 1 | 0 | fclk_I/O/32 |
1 | 1 | 1 | fclk_I/O/64 |
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x2F | SPIF | WCOL | - | - | - | - | - | SPI2X | SPSR |
Zapis/Odczyt | Z/O | Z/O | O | O | O | O | O | Z/O | |
Wartość początkowa | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Gdy zostanie zakończona transmisja szeregowa, ustawiany jest znacznik SPIF. Przerwanie jest generowana, jeśli są ustawione na 1 bit SPIE w rejestrze SPCR oraz bit globalnego uaktywniania przerwań I w rejestrze stanu SREG. Jeśli końcówka SS jest wejściem i zostanie wysterowana stanem niskim, gdy interfejs SPI pracuje w trybie Master, to to również ustawi znacznik SPIF.
Znacznik SPIF jest zerowany sprzętowo, gdy zostanie wywołany odpowiedni wektor obsługi przerwania. Alternatywnie bit SPIF jest zerowany przez odczytanie najpierw rejestru stanu SPI przy ustawionym SPIF, a następnie wykonanie dostępu do rejestru danych SPI (SPDR).
Bit WCOL jest ustawiany, jeśli rejestr danych SPI (SPDR). Bit WCOL (i bit SPIF) jest zerowany przez odczytanie najpierw rejestru stanu SPI z ustawionym bitem WCOL, a następnie wykonanie dostępu do rejestru danych SPI.
Te bity są zarezerwowane i przy odczycie zawsze zwracają stan zero.
Gdy bit ten zostanie ustawiony na 1, to prędkość SPI (częstotliwość SCK) będzie podwojona przy pracy w trybie Master. Oznacza to, iż minimalny okres SCK będzie równy dwóm okresom zegara we/wy. Przy pracy w trybie Slave interfejs SPI daje gwarancję pracy tylko przy częstotliwości fclk_I/O / 4 lub niższej.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
0x2E | MSB | LSB | SPDR | ||||||
Zapis/Odczyt | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | Z/O | |
Wartość początkowa | X | X | X | X | X | X | X | X |
Rejestr danych SPI jest rejestrem do odczytu i do zapisu używanym przy przesyłaniu danych pomiędzy rejestrami mikroprocesora a rejestrem przesuwającym SPI. Zapis do tego rejestru inicjuje transmisję danych. Odczyt z tego rejestru powoduje odczyt rejestru buforowego odebranych danych w rejestrze przesuwającym.
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 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:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.