LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
Artykuły

Biblioteki graficzne Microchipa: obsługa touch-panela i LCD ze sterownikiem SSD1289

Teraz można było ocenić jakość matrycy wyświetlacza. Pomimo niskiej ceny wyświetlany obraz jest kontrastowy i wyraźny. Nie zauważyłem wyraźniej różnicy pomiędzy tym wyświetlaczem, a wyświetlaczem z fabrycznego modułu MEB. Ekran wyświetla się bez dużych opóźnień. To zapewne zasługa szybkiego mikrokontrolera, ale też 16-bitowej równoległej magistrali (mimo zastosowania programowej emulacji).

W tym momencie możemy uznać, że integracja wyświetlacza z biblioteką zakończyła się częściowym sukcesem. Częściowym, bo przed nami jeszcze ważny element: obsługa interfejsu dotykowego, pozwalająca na interakcję graficznego interfejsu z użytkownikiem.

 

Panel dotykowy – obsługa sterownika XPT2046

Jak już wspomniałem wyświetlacz jest wyposażony w 4-przewodowy rezystancyjny panel dotykowy. Taki panel może być obsłużony przez mikrokontroler z wbudowanym przetwornikiem analogowo cyfrowym, lub za pomocą dedykowanego kontrolera – naszym przypadku jest to kontroler XPT2046. Biblioteka Microchipa wspiera obsługę przy pomocy przetwornika (plik TouchScreenResistive.c ), oraz za pomocą specjalizowanego kontrolera Microchipa AR1020 (plik AR1020.c ). Jak widać nie ma wsparcia dla XPT2046 i w zasadzie prawie identycznego układu ADS7843. Dlatego trzeba napisać obsługę od podstaw.

Zasada działania pomiaru zmiany rezystancji rezystancyjnego panelu dotykowego jest opisana w wielu źródłach. Można tez o tym poczytać w dokumentacji układu.

XPT2046 komunikuje się z mikrokontrolerem z pomocą szeregowego interfejsu SPI. Podobnie jak w przypadku komunikacji ze sterownikiem wyświetlacza obsługa magistrali została wykonana programowo, bo w trakcie uruchamiania w programowych emulacjach łatwiej jest znaleźć błędy. Po uruchomieniu , kiedy wszystko działa można zamienić programową obsługę na transmisje wykonywana przez sprzętowe moduły komunikacyjne.

Magistrala SPI składa się z linii (z punktu widzenia XPT2046): danych wyjściowych DOUT, danych wejściowych DIN, zegara taktującego DCLK, oraz linii aktywacji interfejsu CS. Interfejs komunikacyjny jest uzupełniony o linię sygnalizacyjną PENIRQ. Na listingu 12 pokazano definicję linii portów, a w tabeli 2 połączenie z wyświetlaczem.

 

List. 12. Definicja linii interfejsu SPI XPT2046

#define TP_DCLK        PORTCbits.RC3
#define TP_DCLK_TRIS     TRISCbits.TRISC3
#define TP_DIN        PORTGbits.RG1
#define TP_DIN_TRIS     TRISGbits.TRISG1
#define TP_DOUT        PORTGbits.RG0
#define TP_DOUT_TRIS     TRISGbits.TRISG0
#define TP_CS        PORTCbits.RC4
#define TP_CS_TRIS     TRISCbits.TRISC4
#define TP_PENIRQ      PORTAbits.RA6
#define TP_PENIRQ_TRIS   TRISAbits.TRISA6

Tab. 2. Połączenie interfejsu SPI z wyświetlaczem

Linia interfejsu

Wyprowadzenie modułu wyświetlacza

Linia portu GPIO

TP_DIN Dane wejściowe DIN

T_DIN

RG1

TP_DOUT Dane wyjściowe DOUT

T_DOUT

RG0

TP_CLK Zegar

T_CLK

RC3

TP_CS Wybór interfejsu

T_CS

RC4

TP-PENIRQ sygnalizacja naciśnięcia

T_IRQ

RA6

 

Po zdefiniowaniu linii trzeba je z zainicjować przez zdefiniowanie kierunku (wejście/wyjście) , oraz stanu początkowego linii – listing 13.

 

List. 13. Inicjalizacja interfejsu SPI dla XPT2046

void InitTpSpi(void)
{
  
  TP_CS_TRIS=0;
  TP_DCLK_TRIS=0;
  TP_DIN_TRIS=0;
  TP_DOUT_TRIS=1;
  TP_PENIRQ_TRIS=1;
  TP_CS=1;
  TP_DCLK=1;
  TP_DIN=1;
  TP_CS=1;
  
}

Do komunikacji z układem potrzebne będą dwie procedury: zapisu 8-bitowej danej (listing 14) i odczytu 12-bitowej danej (listing 15). Do sterownika będziemy zapisywać komendy sterujące jego pracą, a potem odczytywać 12-bitową wartość rezystancji zmierzoną przez przetwornik analogowo cyfrowy.

 

List. 14. Zapis danej 8-bitowej do XPT2046

void WriteTpSpi(unsigned char data)
{
unsigned char i=0;
  TP_DCLK=0;
  for(i=0;i<8;i++)
   {
    if((data&0x80)==0)
    TP_DIN=0;
    else
    TP_DIN=1;
    Delay();
  TP_DCLK=0; Delay();
  TP_DCLK=1; Delay();
  data<<=1;
    }
  Delay();
}

List. 15. Odczyt danej 12-bitowej z XPT2046

short ReadTpSpi(void)
{
 unsigned char i=0;
 unsigned short data=0;
    TP_DOUT=0;
    for(i=0;i<12;i++)
    {
        TP_DCLK=1; ;Delay();
        TP_DCLK=0; ;Delay();
        if(TP_DOUT)
        {
           data|=1;
        }
        data<<=1;
        Delay();
    }
  return(data);
}

W trakcie uruchamiania transmisji napotkałem na nieoczekiwane problemy. Procedury zostały sprawdzone ze sprzętowym emulatorem modułu PIC32 Starter Kit i zgodnie z dokumentacją powinny działać prawidłowo. Jednak po normalnym uruchomieniu komunikacja nie działała. Obserwacja przebiegu transmisji na oscyloskopie cyfrowym pokazała, że przyczyną problemów były zbyt małe opóźnienia po zmianach stanów na liniach interfejsu SPI. Dodanie dodatkowego opóźnienia Delay() wyeliminowało ten problem.

Pomiar położenia naciskanego punktu powinien się rozpocząć po wykryciu momentu naciśnięcia folii panelu dotykowego. Wykrycie naciśnięcia można wykonać programowo testując wartości odczytane z modułu. XPT2046 ma wyprowadzenie PENIRQ, które w czasie naciśnięcia folii przechodzi w stan niski. Wystarczy testować stan PENIRQ by wiedzieć czy panel został przyciśnięty, czy nie . Ja oczywiście skorzystałem z tego mechanizmu bo jest dużo prostszy w realizacji i pewny w działaniu.

Po wykryciu naciśnięcia można przystąpić do odczytania położenia naciśniętego miejsca. Takie miejsce jest identyfikowane przez współrzędne x oraz y. Jeżeli wyświetlacz ma rozdzielczość 240x320pikseli, to:

  • x zmienia się w zakresie 0<x<319, a
  • y w zakresie 0<y<239

dla poziomej orientacji ekranu.

Programowa identyfikacja położenia będzie polegała na odczytaniu współrzędnej x , a potem współrzędnej y . O tym która współrzędna będzie czytana i z jaka rozdzielczością decyduje 8-bitowy kod komendy:

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

S

A2

A1

A0

MODE

SER/DFR

PD1

PD0

S- bit startu pomiaru (konwersji ADC) – aktywna jedynka

A2…A0 – wybór kanału pomiarowego przetwornika ADC

MODE – rozdzielczość pomiaru: „1” - 12-bitowy, „0” - 8-bitowy

SER/DFR topologia układu wejściowego: jedynka wejście Single Ended, zero wejście różnicowe

PD1…PD0 - tryb poboru mocy w stanie pomiędzy pomiarami

 

Żeby wyzwolić pomiar trzeba ustawić bit startu S, wybrać kanał pomiarowy i skonfigurować przetwornik ADC. Dla panelu o rozmiarach 320x240 pikseli wybieramy pomiar o rozdzielczości 12-bitowej, z wejściem różnicowym.

Bity PD01..PD0 będą zerowane, tak by pomiędzy pomiaramiXPT2046 przechodził w stan oszczędzania energii Power Down . Odczytanie współrzędnej x będzie wymagało wysłania komendy 0x90, a odczytanie współrzędnej y komendy 0xD0. Po wysłaniu komendy za pomocą WriteTpSpi(cmd) można odczytać wynik konwersji przez wywołanie procedury ReadTpSpi() . Ponieważ SPI jest emulowane programowo, to procedura wysyła tylko 12 taktów zegara i odczytuje 12 bitów wyniku. W przypadku modułów sprzętowych potrzeba będzie wysłać 16 taktów zegara i z wyniku odczytu wziąć 12 młodszych bitów.

 

Rys. 6. Przebiegi czasowe sekwencji odczytu współrzędnej

 

Przebiegi czasowe sekwencji odczytu współrzędnej zostały pokazane na rysunku 6. Trzeba pamiętać, że po wysłaniu komendy układ potrzebuje czasu na wykonanie pomiaru i zmierzona wartość można odczytać po pewnym czasie o wysłania komendy. Do sygnalizowania tego stanu jest przeznaczone wyprowadzenie BUSY. My z niego nie skorzystamy, a potrzebne opóźnienie zostanie odliczone programowo. Do odczytania współrzędnych są wykorzystywane 2 funkcje:

  • TouchGetXRAW() – listing 16,
  • TouchGetYRAW – listing 17.

 

Absolwent Wydziału Elektroniki Politechniki Wrocławskiej, współpracownik miesięcznika Elektronika Praktyczna, autor książek o mikrokontrolerach Microchip i wyświetlaczach graficznych, wydanych nakładem Wydawnictwa BTC. Zawodowo zajmuje się projektowaniem zaawansowanych systemów mikroprocesorowych.