[PROJEKT] Wielokanałowy termometr i termostat z wyświetlaczem OLED [1]
Obsługa magistrali SPI została zrealizowana programowo – listing 1.
List. 1. Programowa obługa SPI
//definicje linii interfejsu define CS LATBbits.LATB7 #define CS_TRIS TRISBbits.TRISB7 #define MOSI LATBbits.LATB8 #define MOSI_TRIS TRISBbits.TRISB8 #define CLK LATBbits.LATB9 #define CLK_TRIS TRISBbits.TRISB9 #define DC LATBbits.LATB6 #define DC_TRIS TRISBbits.TRISB6 void PutSpi(unsigned char data) //procedura wyslania 8 bitowej danej przez SPI { unsigned char i=0; CS=0;Nop();Nop(); CLK=0;Nop();Nop(); for(i=0;i<8;i++) { if((data&0x80)==0x80) MOSI=1; else MOSI=0; Nop();Nop(); CLK=1;Nop();Nop(); CLK=0;Nop();Nop(); data<<=1; } CLK=0;Nop();Nop(); CS=1;Nop();Nop(); }
Dwie kolejne procedury to procedura zapisu danej do pamięci obrazu wyświetlacza OledData (listing 2) i zapisu danej do rejestru sterującego SH1106 OledCmd (listing 3).
List. 2. Zapis danej do pamięci obrazu
void OledData(unsigned char data) { DC=1; CS=0; PutSpi(data); }
List. 3. Zapis danej do rejestru sterującego
void OledCmd(unsigned char cmd) { DC=0; CS=0; PutSpi(cmd); }
Sterownik wyświetlacza graficznego wymaga zainicjowania. Konieczność inicjalizacji wynika na przykład z możliwości ustalania współrzędnej początkowej (0,0) zależnie od mocowania mechanicznego panelu, różnych źródeł zasileń driverów matrycy (wewnętrzna przetwornica vs napięcie podawane zewnętrznie),poziomu kontrastu, częstotliwości odświeżania itp. Inicjalizacja polega na wysłaniu szeregu komend ustalających początkowe parametry pracy.
W tabeli 1 pokazano zestawienie ważniejszych komend sterownika SH1106.
Tab. 1. Najważniejsze komendy sterownika SH1106
Komenda | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | Funkcja |
Adres kolumny 4 młodsze bity | 0 | 0 | 0 | 0 | Młodsza część licznika kolumn | Ustawienie 4 młodszych bitów licznika kolumn | |||
Adres kolumny 4 starsze bity | 0 | 0 | 0 | 1 | Starsza część licznika kolumn | Ustawienie 4 starszych bitów licznika kolumn | |||
Napięcie wyjściowe wbudowanej przetwornicy DC/DC | 0 | 0 | 1 | 1 | 0 | 0 | napięcie | Ustawienie napięcia wyjściowego wbudowanej przetwornicy DC/DC | |
Linia początkowa wyświetlacza | 0 | 1 | Licznik linii początkowej wyświetlacza | Przypisanie pozycji w pamięci obrazu do COM0 | |||||
Ustawienie kontrastu | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | Kod komendy |
Poziom kontrastu 0…255 | Wartość kontrastu | ||||||||
Remapowanie segmentów | 1 | 0 | 1 | 0 | 0 | 0 | 0 | ADC
|
ADC=0 |
Włączenie całego wyświetlacza | 1 | 0 | 1 | 0 | 0 | 1 | 0 | D
|
D=0 wyświetlacz wyłączony
D=1 wyświetlacz włączony |
Wyświetlanie w negatywie | 1 | 0 | 1 | 0 | 0 | 1 | 1 | D
|
D=0 wyświetlanie normalne
D=1 negatyw |
Multiplex ration | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | Ilość aktywnych kolumn skanowanych w jednej ramce odświeżania |
* | * | Ilość kolumn 1…64 (domyślnie 64) | |||||||
Sterownie wewnętrzną przetwornicą DC/DC | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | D=0 DC/DC wyłączona
D=1 DC/DC wyłączona |
1 | 0 | 0 | 0 | 1 | 0 | 1 | D | ||
Włączenie/wyłączenie wyświetlacza | 1 | 0 | 1 | 0 | 1 | 1 | 1 | D | D=0 wyświetlacz wyłączony
D=1 wyświetlacz włączony |
Ustawienie licznika stron | 1 | 0 | 1 | 1 | Licznik stron | Ustawienie licznika stron | |||
Kierunek skanowania kolumn | 1 | 1 | 0 | 0 | D | * | * | * | D=0 COM0->COM63
D=1 COM63->COM0 |
Offset wyświetlania | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | Ustawia pierwszą linię przypisaną początkowi pamięci obrazu |
* | * | COMx | |||||||
Częstotliwość wewnętrznego zegara | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | B3..B0 – dzielnik czestotliwości 1…16
B7…B4 regulacja częstotliwości -25%…_50% |
Regulacja częstotliwości | Dzielnik | ||||||||
Sprzętowa konfiguracja wyprowadzeń | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | Ustawia 2 sekwencje sterowania wyświetlaczem |
0 | 0 | 0 | D | 0 | 0 | 1 | 0 | ||
Ustawienie napięcia VCOM | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | Ustawienie napięcia VCOM |
VCOM=(B[7:0]Xv ref) |
Na podstawie zestawu komend musimy tak zainicjować sterownik, żeby pracował poprawnie z panelem wyświetlacza. Ponieważ część komend wymaga oprócz samej komendy dodatkowego argumentu, to wszystkie bajty komend inicjalizacji łącznie z niezbędnymi argumentami zostały umieszczone w buforze Buffer_Init. Zawartość bufora z pierwszym bajtem kontrolnym 0x80 jest wysyłana do sterownika wyświetlacza funkcją I2C_Master_BufferWrite.
Zawartość tego bufora została pokazana na listingu 4, a procedura inicjalizacji na listingu 5.
List. 4. Bufor Buffer_Init z komendami inicjalizacji
uint8_t Buffer_Init[255]={0x80, //control byte 0xae,//Display OFF 0x00,//Low Column 0x10,//High Column 0xB0,//Page 0x40,//Start line 0xA1,//remap 0xDA,//com pins 0x12, 0xD3, //display offset 0x00,//NO offset 0xc0,//scan direction 0xc8, 0xA6,//normal display 0xA4,//display ON 0x81,//set contrast 0x50,//contrast DATA 0xa8,//multiplex ratio 0x3f,//1/64 duty 0xD5,//Display clock divide 0x80, 0xd9,//precharge period 0xF1, 0xDB,//VCOM deselect 0x40, 0x8d,//charge pump 0x14, 0xAF,//display ON };
List. 5. Inicjalizacja wyświetlacza
void InitOled(void){ unsigned char i; CS_TRIS=0;MOSI_TRIS=0;CLK_TRIS=0;DC_TRIS=0; DC=0; for(i=0;i<29;i++){ CS=0; PutSpi(Buffer_Init[i]); } }