poniedziałek, 25 listopada 2013

LPC1114 z wyświetlaczem LCD HD44780

Wyświetlacze oparte na poczciwym kontrolerze HD44780 bez problemu współpracują z mikrokontrolerem LPC1114 pomimo, że większość wyświetlaczy pracuję na napięci 5 V, są także specjalnie produkowane na na pięcie 3,3 V jednak są zwykle drozsze niz "standardowe" 5 V.
Ponieważ mikrokontroler LPC1114 ma porty wejścia/wyjścia tolerujące 5 V bez problemu obsługuje wyświetlacze oparte na HD44780 dla 5 V.

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. }

czwartek, 15 sierpnia 2013

Szybkie przejście z 8 bit na 32 bit

Jeżeli brakuje Ci mocy obliczeniowej w Twoim projekcje, w którym dotychczas korzystałeś z 8 bitowych mikrokontrolerów warto zainteresować się szybszym 32 bitowym mikrokontrolerem LPC 1114.
Co prawda nie znajdziesz go w obudowie DIP tylko SMD, lecz SMD nie jest tak trudne w wykorzystaniu w "domowych" projektach.
Jeżeli nie możesz, nie potrafisz skonstruować projektu z użyciem SMD, zawsze możesz zakupić gotowy moduł na pokładzie z LPC 1114, np. takie jak:
  1.  Mini M0,
  2. Port LPC1114,
  3. AVT1620 Cortexino 
Na początek nie potrzebujesz żadnego programatora, do programowania wykorzystasz interfejs RS-232 z odpowiednią transalacją poziomów logicznych do 3,3 V. Świetnie nadaje się układ MAX3232, a jeżeli nie posiadasz portu RS-232 tylko USB to układ FT232R lub podobny.

AVR'y mają trzy 8 bitowe rejestry służące do operacji na portach:

DDRx  - rejestry kierunku
PORTx - rejestry wyjściowe
PINx  - rejestry wejściowe

Podobnie jest w 32 bitowym LPC 1114:

LPC_GPIOx->DIR - rejestry kierunku
LPC_GPIOx->DATA - rejestry wyjściowe / wejściowe



Poniżej przykład w AVR ustawiający kierunek wyjścia pinu 1 portu A oraz ustawienie na nim stanu niskiego:


DDRA |= (1<<PA1); // kierunek pinu 1 portu PA na wyjściowy
PORTA &= ~(1<<PA1); // ustawienie stanu niskiego na pinie PA1

Analogicznie do w/w przykładu steruje się portami w LPC 1114:

LPC_GPIO0->DIR |= (1<<1); // kierunek pinu portu PORT0 na wyjściowy
LPC_GPIO0->DATA &|= ~(1<<1); // ustawienie stanu niskiego na pinie P0_1

Pora na przykład Witaj Świecie  na LPC 1114, czyli mruganie diodą:

 
  1. #include "LPC11xx.h"
  2.  
  3. #define PIN_LED (1<<2)
  4.  
  5. int main(void)
  6. {
  7. uint32_t i, j;
  8.  
  9.  
  10. LPC_GPIO0->DIR |= PIN_LED; // ustawienie pinu P0_2 na wyjsciowy
  11.  
  12. while (1)
  13. {
  14. LPC_GPIO0->DATA |= PIN_LED; // stan wysoki na pinie P0_2
  15. for ( i = 0; i < 1000000; i++); // realizacja opoznienia (taki niby delay :)
  16. j++;
  17.  
  18. LPC_GPIO0->DATA &= ~PIN_LED; // stan niski na pinie P0_2
  19. for ( i = 0; i < 1000000; i++); // realizacja opoznienia (taki niby delay :)
  20. j++;
  21. }
  22. }