wtorek, 24 września 2013

Interfejs SPI w LPC 1114

Mikrokontroler LPC 1114 posiada dwa sprzętowe kontrolery SPI nazwane następująco SSP0 i SSP1. Nazwa SSP to skrót od Synchronous Serial Port, czyli Szeregowy Synchroniczny Port. Posiada 8 bitowy bufor FIFO dla wysyłanych i odbieranych danych, rozmiar ramki danych można definiować od 4 do 16 bitów. Maksymalna częstotliwość taktowania zegara 25 MHz przy założeniu taktowania rdzenia 50 MHz. Należy pamiętać, że po resecie zegar taktujący kontroler jest włączony tylko dla SSP0, chcąc korzystać z SSP1 należy ustawić bit 18 w rejestrze SYSAHBCLKCTRL !

Procedura inicjalizacyjna i konfiguracyjna kontrolera SSP wygląda następująco:
1. Pierwszym etapem jest konfiguracja wyprowadzeń odpowiedzialnych za komunikację SPI, ponieważ standardowo te piny są zwykłymi portami wejścia / wyjścia. Należy ustawić odpowiednie wartości w rejestrze IOCON_LOC pamiętając, aby włączyć zegar dla tego bloku konfiguracyjnego:
    LPC_SYSCON->SYSAHBCLKCTRL |=  (0x1<<16) ; // włącza zegar taktujący dla IOCON_LOC
dla interfejsu SSP0 piny SPI:
  • P0.8 - MISIO
  • P0.9 - MOSI
  • P0.2 - SSEL sprzętowy wybór urządzenia (CS), oczywiście można nie konfigurować tego pinu, wtedy wybieranie musi być obsługiwane programowo dowolnym pinem
  • natomiast SCK, czyli zegar zależy od ustawień w rejestrze IOCON_SCK_LOC, domyślnie jest na P0.10, może być również na P0.6 i P2.11
dla interfejsu SSP1 piny SPI:
  • P2.2 - MISIO
  • P2.3 - MOSI
  • P2.0 - SSEL sprzętowy wybór urządzenia (CS), analogicznie jak SSP0 można obsługiwać programowo
  • P2.1 - SCK

2. Jak wcześniej wspomniałem należy włączyć zegar taktujący kontrolery SSP:
    LPC_SYSCON->SYSAHBCLKCTRL |=  (0x1<<11) ; // włącza zegar taktujący SSP0
    LPC_SYSCON->SYSAHBCLKCTRL |=  (0x1<<18) ; // włącza zegar taktujący SSP1
3. Następnie należy ustawić podzielnik zegara odpowiednio dla kontrolera SSP0 lub SSP1. Spójrz na rysunek



Jak widać na obrazku Fig.8 sygnał taktujący main clock dociera m.in. do dzielnika zegara SPIO PERIPHERAL CLOCK DIVIDER oraz SPI1 PERIPHERAL CLOCK DIVIDER. Odpowiednią wartość wpisuje się do rejestru SSP0CLKDIV oraz SSP1CLKDIV. Wartościami poprawnymi są wartości od 0 do 255, przy czym wpisanie 0 (po resecie przyjmuję wartość 0) spowoduje wyłączenie taktowania kontrolera SPI.

LPC_SYSCON->SSP0CLKDIV = 0x1;   // bez podzielnika zegara main clock

LPC_SYSCON->SSP0CLKDIV = 0xFF;   // 255 podzielenie main clock

LPC_SYSCON->SSP0CLKDIV = 0;   // zegar taktujący przestaje docierać do  kontrolera SSP0

4. Przed rozpoczęciem konfiguracji parametrów pracy kontrolerów SSP0/SSP1 należy wyłączyć "reset" przez odpowiednio ustawienie bitu 0 dla SPP0, ustawienie bitu 1 dla SSP1 w rejestrze PRESETCTRL:

LPC_SYSCON->PRESETCTRL |= (0x1<<0); // wylaczenie resetu SPP0

LPC_SYSCON->PRESETCTRL |= (0x1<<1); // wylaczenie resetu SPP1


5. Konfiuguracja kontrolera SSP
Rejestry odpowiedzialne za konfigurację parametrów pracy oraz przerwań związanych z kontrolerami SSP przedstawia poniższa tabelka:



Głównych ustawień dokonuje się w rejestrze SSP0CR0 lub SSP1CR0 w zależności, który kontroler SSP ustawiamy


Przedstawione w tabelce bity rejestru  SSP0CR0 / SPP1CR0 odpowiadają kolejno
  • DDS - bity 3:0 konfigurują rozmiar ramki (4-16 bit)
  • FRF - bity 5:4 format ramki - domyślnie po resecie są wyzerowane więc format transmisja SPI
  • CPOL -  bit 6 odpowiada za polaryzację zegara
  • CPHA -  bit 7 wyjście fazy zegara
  • SCR -  bity 15:8 biorą udział przy taktowaniu zegara transmisji SPI
Wzór na częstotliwość transmisji ma postać PCLK / (CPSDVSR * [SCR+1]).

Należy pamiętać, że wartość zapisywana na bitach CPSDVSR w rejestrach SSP0CPSR lub SSP1CPRS musi być liczbą parzystą i zawierać się w przedziale 2 - 254.
Czyli maksymalna częstotliwość transmisji interfejsu SSP jaką można osiągnąć w LPC1114 wyraża się PCLK / 2 dla najmniejszych wartości jakie można zapisać w CPSDVSR=2 i SCR=0, ich zwiększanie odpowiednio będzie powodować zmniejszenie częstotliwości transmisji.

6. Ostatnim etapem jest włączenie kontrolera SSP wraz z ustawieniem trybu MASTER / SLAVE zgodnie z poniższa tabelką

  • LBM - bit 0 po resecie zerowany (zwykle powinien być wyzerowany), jego ustawienie  włącza tryb Loop Back. Służy on do testowania oprogramowania, włączenie spowoduje że dane wysłane na MOSI pojawią się MISO
  • SSE - bit 1także po resecie zerowany, ustawiając go załącza się kontroler SSP0/1 a tym samy można rozpocząć transmisje
  • MS - bit 2, który po resecie ma wartość 0 co oznacza że interfejs pracuje w trybie MASTER, natomiast ustawienie bitu powoduje przejście w tryb SLAVE
Poniżej przykładowy kod inicjalizujący kontroler SSP1 wraz z odpowiednim ustawieniem pinów komunikacyjnych SPI i wysyłający tekst Test SPI
 
  1. #include "LPC11xx.h"
  2.  
  3. // rozmiar bufora FIFO
  4. #define FIFOSIZE 8
  5.  
  6. // definicje na potrzeby badnia statusu SSP
  7. #define SSPSR_TFE (0x1<<0)
  8. #define SSPSR_TNF (0x1<<1)
  9. #define SSPSR_RNE (0x1<<2)
  10. #define SSPSR_RFF (0x1<<3)
  11. #define SSPSR_BSY (0x1<<4)
  12.  
  13. // funkcja wysylajaca
  14. void Send_SSP(uint8_t data) {
  15. // czeka dopoki kontroler jest zajety i kolejko FIFO TX nie jest pelna
  16. while ( (LPC_SSP1->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF );
  17. LPC_SSP1->DR = data; // wysyla dane przez SSP1
  18. }
  19.  
  20. // funkcja odbierajaca
  21. void Recive_SSP(uint8_t *data) {
  22. while ( LPC_SSP0->SR & (1<<2) ) { // dopoki bufor odbiorczy nie jest pusty
  23. *data = LPC_SSP0->DR; // pobranie bajtu
  24. data++;
  25. }
  26. }
  27.  
  28. int main(void) {
  29.  
  30. uint8_t i, tmp;
  31. uint8_t bufor[]="Test SPI" ;
  32.  
  33. // konfiguracja pinow odpowiedzialnych za komunikacjie SPI
  34. LPC_SYSCON->SYSAHBCLKCTRL |= 1<<16; //wlaczenie zegara dla bloku IOCON_LOC //
  35. LPC_IOCON->PIO2_0 |= 0x2; // P2.0 SEL1 - sprzetowy CS dla SSP1
  36. LPC_IOCON->PIO2_1 |= 0x2; // P2.1 SCK - zegar
  37. LPC_IOCON->PIO2_2 |= 0x2; // P2.2 MISO dla SSP1
  38. LPC_IOCON->PIO2_3 |= 0x2; // P2.3 MOSI dla SSP1
  39.  
  40. LPC_SYSCON->SYSAHBCLKCTRL |= 1<<18; // wlacza zegar taktujacy SSP1
  41. LPC_SYSCON->SSP1CLKDIV = 0x1; // bez podzielnika zegara, do SSP1 dociera main clock
  42. LPC_SYSCON->PRESETCTRL |= 1<<2; // wylaczenie resetu SSP1
  43. LPC_SSP1->CR0 = 0x0507; // dana 8 bitowa, ramka SPI, CPOL=0, CPHA=0, SCR=5
  44. LPC_SSP1->CPSR = 2; // CPSDVSR=2, zatem taktowanie SSP0 jest rowne 4 MHz bo PCLK / (CPSDVSR*(SCR+1). 48 / (2*(5+1) = 4
  45.  
  46. for ( i = 0; i < FIFOSIZE; i++ )
  47. tmp = LPC_SSP0->DR; // czytanie FIFO, a tym samym wyczyszczenie bufora FIFO ze smieci
  48.  
  49. LPC_SSP1->CR1 = (1<<1) ; // wlaczenie kontolera SSP/SPI w trybie MASTER
  50.  
  51.  
  52. while(1)
  53. {
  54. i = 0;
  55.  
  56. while( tmp = bufor[i++] )
  57. Send_SSP( tmp ); // wysyla kolejny znak
  58. }
  59.  
  60. return 0 ;
  61. }