LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
Artykuły

e-paper: wyświetlacze w teorii i praktyce [1]

List. 2. Procedura zapisywania jednego wiersza wyświetlacza

void SendSOURCEData(u8 *pArray)
{

	EPD_LE_H;                       	//LE =1

	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1
	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1
	
	EPD_LE_L; 				//LE=0	

	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1
	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1
	
	EPD_OE_H;                       	//OE =1
	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1
	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1

	EPD_SPH_L;                         //SPH=0                      
	
	old_data = (uint16_t)(EPD_DB_PORT->ODR);
	old_data &= 0xFF00;
	for(column= 0; column < 200; column++)     	// zapisanie 200bajtów z tablicy wiersza
	{
		new_data = old_data | (u16)pArray[column];
		(EPD_DB_PORT->ODR) = new_data;

		EPD_CL_L; 	//CL=0  takt zegara taktującego rejestr SOURCE
		EPD_CL_H;	//CL=1
	}

	EPD_SPH_H;                       	//STH=1
 
	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1
	EPD_CL_L;				//CL=0
	EPD_CL_H;				//CL=1

 	EPD_CPV_L;                        //CPV=0 – zegar taktujacy bufor GATE
	EPD_OE_L;                        //OE =0
	EPD_CL_L;			     //CL=0
	EPD_CL_H;			     //CL=1
	EPD_CL_L;			     //CL=0
	EPD_CL_H;			    //CL=1
	
	EPD_CPV_H;                        //CPV=1
}

Sekwencja zapisu rozpoczyna się od ustawienia LE=1 i LE=0 oraz OE=1. Każda zmiana stanu tych linii sterujących wymaga jednego cyklu. Potem jest zapisywanych 200 bajtów z wcześniej przygotowanego bufora pArray. Każdy bajt jest wpisywany narastającym zboczem sygnału zegara CL. Wprowadzenie zmiennej old_data zapobiega niszczeniu stanów nie używanych linii portu przy zapisywaniu linii magistrali danych.

Po zapisaniu 200 bajtów jest aktywowany sygnał OE i zawartość rejestru LATCH pojawia się na wyjściu bufora SOURCE. Jednocześnie na linii CPV jest wymuszane zbocze opadające a potem narastające. Po każdym zapisaniu wiersza trzeba zmienić zawartość licznika wierszy – czyli rejestru GATE, tak by następny wiersz był zapisywany w następnej pozycji na wyświetlaczu. Cykl uaktywnienia zapisywania rejestru, tak by sterował pierwszym wierszem (G1) rozpoczyna się od wystawienia stanu niskiego na STV i wymuszeniu zbocza narastającego na linii zegarowej CPV (szczegóły w dokumentacji sterownika).

Każda sekwencja zapisu rejestrów wyświetlacza powinna się zaczynać od wykonania procedury EPD-StartScan() wymuszającej taką sekwencję – listing 3.

 

List. 3. Wymuszenie początku skanowania linii wyświetlacza

void EPD_Start_Scan(void)
{
	  
	EPD_STV_H;                       //STV=1

	loop = 2;                    		
	while(loop--)              
	{
		EPD_CPV_L;		CPV=0
		Delay(0xf);	
		EPD_CPV_H;		CPV=1
		Delay(0xf);
	}
 
	EPD_STV_L;                       //STV=0

	loop = 2;
	while(loop--)
	{
		EPD_CPV_L;          	  //CPV=0
		Delay(0xf);		
		EPD_CPV_H;		 //CPV=1
		Delay(0xf);
	}

	EPD_STV_H;                       //STV=1
	loop = 2;
	while(loop--)
	{
		EPD_CPV_L;
		Delay(0xf);
		EPD_CPV_H;
		Delay(0xf);
	}
}

W teorii mamy wszystko do potrzeba by wyświetlić dowolną bitmapę. Zapisujemy 600 razy rejestr SOURCE o rozmiarze 800×2 bity jednocześnie zmieniając wpisy do rejestru GATE. Zależnie od wartości 2 bitów programujących napięcie wyjściowe dla określonego piksela (kapsułki) punkt na ekranie będzie czarny lub biały, tak jak to zostało już wyżej opisane. Jednak w praktyce nie jest to takie proste. Okazuje się, że do zmiany „świecenia” punktu na ekranie potrzeba czegoś więcej, niż prostego przebiegunowania elektrod sterujących. Po to by obraz wyświetlił się tak jak chcemy i w dodatku mógł pozostawać w tym stanie przez długi czas potrzeba kilku zdefiniowanych sekwencji zapisywania całego wyświetlacza. Na elektrodach sterujących kapsułkami trzeba wymusić coś w rodzaju przebiegu cyfrowego (waveform). Długość przebiegu i jego „kształt” może zależeć zależy od producenta matrycy, a nawet o konkretnego modelu wyświetlacza. Przebiegi sterujące będą wyglądać inaczej dla zmiany „świecenia” kapsułki , a inaczej dla sekwencji „odświeżenia” już wyświetlanej informacji.

Podanie przebiegu na każdą z elektrod sterujących sprowadza się do wykonania kilku zapisów (sekcji) całego wyświetlacza tak jak to zostało pokazane na rysunku 4. Okres skanowania wyświetlacza jest określony przez czas od wysterowania G0 do wysterowania G599, czy czas potrzebny do zapisania całego wyświetlacza.

 

Rys. 4. Skanowanie wyświetlacza

 

Rys. 5. Przykładowe ustawienie piksela w czasie 12 zapisów

 

Przykład zapisu piksela jest pokazany na rysunku 5. Każdy z pikseli jest zapisywany 12 razy (12 sekcji). Każda sekcja to jeden zapis całego wyświetlacza. W czasie sterowania wyświetlaczem każdy piksel może zmieniać swój stan w następujący sposób:

  • Z białego na biały
  • Z białego na czarny
  • Z czarnego na biały
  • Z czarnego na czarny

Dla każdej z takich sekwencji trzeba zdefiniować przebieg sterujący – tabela 2.

 

Tab. 2. Przykładowe sekwencje zmiany stanu pikseli

 

 

W naszym przypadku definicja sekwencji sterujących jest wykonywana przez funkcję make_vave_tablelisting 4.

 

List. 4. Tworzenie tablicy definicji sekwencji sterującej

void make_wave_table(void)

void make_wave_table(void)
{
	int frame, num;
	unsigned char tmp,value;
for(frame=0; frame  >6)&0x3][frame];
					
			tmp = tmp < < 2;
			tmp &= 0xfffc;
			tmp |= wave_end[(num > >4)&0x3][frame];

			tmp = tmp < < 2;
			tmp &= 0xfffc;
			tmp |= wave_end[(num > >2)&0x3][frame];

			tmp = tmp < < 2;
			tmp &= 0xfffc;
			tmp |= wave_end[(num)&0x3][frame];

			value = 0;
			value = (tmp  < <6) & 0xc0;
			value += (tmp < <2) & 0x30;
			value += (tmp > >2) & 0x0c;
			value += (tmp > >6) & 0x03;
			wave_end_table[num][frame] = value;
		}
	}
}

W wyniku działania tej funkcji jest zapisywana dwuwymiarowa tablica vave_end_table o wymiarach 256×12. Procedura wyświetlania całego obrazu jest pokazana na listingu 5. Rozpoczyna się od włączenia zasilania matrycy (procedura EPD_PowerOn()).

 

List. 5. Procedura wyświetlania całego obrazu

void EPD_Display_PIC(void)
{
 	int line, frame;
	bool led_flag = TRUE;
	unsigned char *ptr;

	EPD_PowerOn(); //włączenie zasilania 
	ptr = (unsigned char *)(ac);	
	for(frame=0; frame 

Ilość sekcji zapisu jest określona przez wartość FRAME_END_LEN. W każdej sekcji zapisu najpierw jest wywoływana funkcja EPD_Start_Scan() ustawiająca skanowanie linii na początek, czyli od aktywnego sygnału na linii G0. Potem program wywołuje 600 razy w pętli funkcję line_end_piclisting 6.

 

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.