i
Listing 162 Definicja komend
// H = X
fdefine LCDC_FS 0x20
fdefine LCDC_FS_BASIC O fdefine lcdc_fs_E>tended 0x01 fdefine lcdc_fs_horador 0
fdefine LCDC_FS_VERTADDR 0x02 fdefi ne LCDC_FS_PD 0x04 // H ■ 0 (BASIC) fdefine lcuc_dc 0x08
fdefine lcoc_cc_blank 0 fdefine lux._l-c_nokpal 0x04 fdefine LCDC_DC_AlLON 0x01 fdefine LCDC_DC_INVER1 0x05 fdefine LCDC_XADR 0x80 fdefine lcdc_yacr 0x40
// H = 1 (EXTENDED) fdefine LCDC_TEMP 0x04 fdefine LCDC_BIAS 0x10 fdefine LCOC_VOP 0x40
Proponuję teraz napisanie szybko programu, który umożliwi przekonanie się. że ..to żyje”. Projekt jednak będziemy od początku pisać tak. aby móc go stopniowo rozwijać, aż do pchlej aplikacji.
Utwórz nowy projekt. W moim przypadku nazwałem go lcd33 lOtest. Od razu skopiuj z poprzedniej części plik makra.k. Utwórz plik definicji sprzętu: harddef.h. części głównej programu main.c oraz pliki zawierające funkcje obsługi wyświetlacza: lcd33J0.c oraz lcd3310.h. Pamiętaj o dodaniu obu plików źródłowych w pliku makefile.
Od razu wypełnij plik harddef.h zgodnie z listingiem 160.
Do pliku Icd33i0c dodajemy potrzebne pliki nagłówkowe, zgodnie z listingiem 161. Dla własnej wygody, w pliku nagłówkowym dodajemy definicje nazw komend, zgodnie z listingiem 162. Listing 163 pokazuje propozycję procedur niskiego poziomu. Założenie jest takie, że linia D/C jest w spoczynku utrzymywana w stanie wysokim. Jeśli w dowolnym momencie wywołamy funkcję lcd Send, zostanie to potraktowane jako wysianie danych. Jeśli wyślemy komendę, zaraz po zakończeniu wysyłania linia D/C powraca w stan wysoki. To założenie upraszcza trochę pisanie programu, jednocześnie oszczędzając wykonywania dodatkowej instrukcji przy wysyłaniu danych. Trzeba wziąć pod uwagę, że statystycznie do
Listing 160 Plik hunlUeJ.h | |
#i fndef |
HARDDEF_H_1NCLUDED |
fdefine |
H4RDDE F_H_INCLUDED |
// wCD fdefine |
LCD_PDRT B |
fdefine |
LCO.RES 2 |
fdefine |
LCD_SCK 7 |
fdefine |
LCO.SO 5 |
fdefine |
LCD_DC 3 |
fdefine |
LCDlSCE 4 |
fendi f //hardoef_h_incljded |
wyświetlacza będziemy wysyłać znacznie więcej danych niż komend.
Wróć teraz do pliku nagłówkowego. Zadeklarujemy tutaj obie funkcje; lcd Send oraz IcdjCommand. Ta dniga pojawia się w pliku nagłówka po to, aby możliwe było umieszczenie niżej statycznej funkcji widocznej na listingu 164. Zawartość listingu powinna pojawić się w pliku Icd33l0.h. Statyczność tej funkcji Icd GoTo ma spore znaczenie dla optymalizacji. Najczęściej będzie ona wywoływana ze stałymi wartościami x i y. W takim przypadku wszystkie obliczenia wykona kompilator, a funkcja zostanie rozwinięta tylko do dwóch wywołań funkcji IcdjCommand.
Teraz jesteśmy gotowi, aby w prosty i czytelny sposób przeprowadzić inicjację wyświetlacza zgodnie z listingiem 165. Pamiętaj o umieszczeniu deklaracji funkcji inicjującej wyświetlacz w pliku nagłówkowym.
Przerwijmy na chwilę pisanie biblioteki LCD i przejdźmy do pliku głównego. Prosty kod z listingu 166 umożliwi włączenie wyświetlacza. Jeśli nie zerujemy pamięci wyświetlacza, po włączeniu jej zawartość jest przypadkowa. Oznacza to w praktyce, że po wykonaniu aktualnego programu na wyświet-
Listing 161 Pliki nagłówkowe w lcd3310.c
finclude <avr/1o.h> finclude <inttypes.h>
finclude 'harddef.h" finclude makra.h’ finclude lcdmo.h'
Listing 163 Procedury niskiego poziomu vo1d leci 9end(ulnjL8_L Ud La)
c
uintO_t nj
// SCK w stan niski
pORT(LdD rDRr) A- ~(1-«lcd_sck) ;
// Aktywacja interfejsu PORT(LCD_P3Rr) A- ~(1«LCD_SCE) J for(n*8 ; nl-0 ; -n)
l
// Wyprowadzenie bitu >- 128)
PORT (LCD PORT) |« 1«LCD SDJ
else
3ORT (i.od_poft) &= ~(1«lcd_sd); // Sygnał zegarowy i przesuniecie* ?ort(lcd_port) I- l«TCD_.qr'K; dara «■ 1;
PORT(LCD_P0Rr) A- -(1«LCD SCK) J
)
// Wyłączenie interfejsu ?ort(lcd_port) !• i«lcd_sce:
// wysłanie komendy do wyświetlacza void led Conmand(uint8 t corrmand)
{
port(lcd popr) A- -(1«lcd dc); lcd_Send(conunand);
// natychmiast do trybu danych PORT (lcd_ port) !■ i«lcd_dc;
Listing 164 Funkcja IcdjGoTo w led3310.1, statlc 1nl1ne vo1d
led GoTo(uint8 t x, uir.t8 t y)
{
lcd_command(LCDC_XADR| x); led command(LCUC YADRJ y);
}
Listing 165 Inicjacja wyświetlacza
void icd init(void)
{
// Zerowanie.
port(lcd_port) a- -(i«lcd. res): asm volatile(„nop\n\t nop\h\t"::); port(lcd_port) I- 1«lcd_res;
// wysyłanie sekwencji startowej led Convnand(LCX FS|LCD2_FS_EXTENDE:>); led Commarid(LCDC VOP|72); lcd_Convnand(LCDC TEMP 12 ); led Command(LCDC_BIASj 3); lcd_Com.'nand(LCDC_FS | LCDCFSB.ASICl
“l:d:_fs hdraddr);
led ConrnandĆLCDC DC|L3D2_DC N0RMAL); lcd~GoTo(U,t));
I
Listing 166 Pierwsze uruchomienie
finclude <avr/io.h> finclude <inttypes.h>
finclude „harddef.h" finclude „makra.h" finclude „lcd3310.h"
1nt main(vo1d)
{
// inicjacja portów
DDRCLCD PORT) ■ 1«LCD_R£S | U<LCD_SCK | 1«LC0 SD | 1«LCD DC | 1«LCD SCEJ PORT(LC0_PORT) - 1«LCD SZK | 1«LCD_SD | 1«XD_DC I i«lcd_śce;
lcd_Ini:O!
return 0;
Oszczędne sterowanie wyświetlaczem z telefonu NOKIA3310
Bardzo prawdopodobne, że spotkałeś się już z wyświetlaczem. który dziś przedstawiam Ze względu na prostotę sterowfcniu oraz cenę jest to element dość chętnie stoso-wuny przez elektroników. Większość propozycji sterowania, jakie udało mi się Jo tę: pory znaleźć, zakładało założenie w pomięci RAM bufora danych wyświetlacza oraz ich przesyłanie dopiero po wcześniejszym przygotowaniu obrazu. Jest to rozwiązanie bardzo wygodne, dające ponadto możliwości rysowania dość złożonych figur.
Problemem w rysowaniu na r.aszym wyświetlaczu jest to, że nie możemy odczytać wartości wcześniej wpisanej do komórki pamięci Chcąc narysować jakiś obiekt, zmieniamy zawsze cole 8 piksel,.
Jeśli jednak będziemy chcieli pisać zawsze bezpośrednio na wyświetlacz, uzyskamy program zużywający mało zasobów Ponadto program ten często okaże s:ę szybszy od programu korzystającego z bufora. Chcę pokazać dziś. że obsługa naszego wyświetlacza ma szanse zmieścić się nawet do procesora ATtiny2313.
Bez bufora - bez czyszczenia
Gdy wszystkie dane są wysyłane na ekran bez wcześniej
szego buforowania, trzeba zdać sobie sprawę z pewnego nieoczywistego ograniczenia Jeśli będziemy wypisywać dane na wyświetlaczu w trybie ciągłym (na przyklac wartości pomiarów), nic powinniśmy przed każdym wypisaniem czyścić wyświetlacza. Takie działanie sprawi, że wypisywany tekst stanie się nieczytelny (efekt na wyświetlaczu LCD jest gorszy niż migotanie obraz staje się zupełnie nieczytelny). Jeśli piszemy bezpośrednio na ekran, należy unikać jego czyszczenia.
Zauważ, ze gdybyśmy midi bufor obrazu w pamięci RAM. także nic czyścilibyśmy wyświetlacza. Czyszczony byłby najwyżej bufor, a następnie przesyłany na zapełniony wyświetlacz.
Elektronika dla Wszystkich Listopad 2006 43