Kurs AVR GCC Wyświetlacz LCD od Nokii 3310

background image

Artykuł pochodzi ze strony XYZ HOBBY ROBOT (

xyz.isgreat.org

)

Kurs AVR-GCC Wyświetlacz LCD od Nokii_3310

26.04.11 ABXYZ

Niniejszy tekst jest dodatkiem poszerzającym tematykę
publikowanego na tej stronie

kursu AVR-GCC

.

Jak mówią, jeden obraz wart jest tysiąca słów, dlatego warto
zainteresować się wyświetlaczami graficznymi. W tym artykule
zajmiemy się wykorzystaniem wyświetlaczy LCD od popularnych
niegdyś telefonów komórkowych Nokia 3310/3410. Pewnie
niektórzy czytelnicy zastanawiają się, czemu nie wybrałem dużego,
kolorowego wyświetlacza o rozdzielczości QVGA. Przede wszystkim
ze względu na cenę, szkoda montować w każdym urządzeniu
modułu LCD kosztujący ponad 100zł, zaś wyświetlacze od starych
komórek praktycznie nic nie kosztują i też są fajne:)

Wyświetlacz LCD od telefonu Nokia 3310 posiada
monochromatyczny ekran o rozdzielczość 84x48 (wymiary
czynnego pola ekranu 30x20mm). Wyposażony jest w sterownik
PCD8544(lub podobny) z szeregowym interfejsem SPI. Dostępny
jest wyłącznie tryb graficzny, ale można łatwo programowo
zaaranżować tryb tekstowy; przykładowo można pokazać sześć linii
tekstu, każda po 14 znaków wielkości 6x8 pikseli.

Wyświetlacz od telefonu nokia 3310 wraz z oryginalną ramką. Identycznie wygląda

wyświetlacz od noki 3410.

Wyświetlacz od telefonu nokia 3310 wydobyty z ramki.

Wyświetlacz od Nokii3410 wygląda identycznie jak wyświetlacz od
Nokii3310, ten sam układ wyprowadzeń złącza, ale ma nieco
większą rozdzielczość: 96x65 (można pokazać 8 linii tekstu, każda
po 16 znaków 6x8). Wyświetlacz od Nokii3410 wyposażony jest

1 z 11

background image

w kontroler "Philips OM6206", który programuje się prawie w ten
sam sposób jak kontroler PCD8544 z Nokii3310. Do obsługi obu
typów wyświetlaczy będziemy wykorzystywać te same funkcje
napisane w języku C.

LCD Nokia 3310 LCD Nokia 3410

Rozdzielczość

84x48

96x65

kontroler

PCD8544

OM6206

cena

<10zł

<10zł

Monochromatyczne wyświetlacze LCD od telefonów nokia 3310/3410

Podłączenie wyświetlacza do mikrokontrolera AVR

Wyświetlacz jest delikatnym elementem, dlatego lepiej jest
pozostawić go w jego oryginalnej ramce. Ramkę można
odpowiednio przyciąć i wraz z wyświetlaczem przykręcić wkrętami
do jakieś płytki, albo przykleić.

Na tylnej stronie ramki wyświetlacza dostępne jest złącze; w
telefonie miedziane styki złącza przylegają do ścieżek na płytce
drukowanej.

Złącze na tylnej stronie wyświetlacza.

Nr

styku

Sygnał kierunek

Opis

1

VDD

zasilanie

Zasilanie 2.7 .. 3.3 V

2

SCLK

wejście

Serial clock. Sygnał zegarowy taktujący

dane na linii SDIN

3

SDIN

wejście

Wejście danych synchronizowane

sygnałem SCLK

4

D/C

wejście

Wejście wyboru rodzaju danych

wprowadzanych do sterownika

(wyświetlane-1,sterujące -0)

5

SCE

wejście

Wejście aktywujące interfejs

szeregowy(aktywny stan niski)

6

GND

zasilanie

Masa zasilania

7

VOUT

zasilanie

Ouptut voltage. Kondensator

elektrolityczny 1-10 uF między VOUT i

GND.

8

/RES

input

Reset LCD (aktywny stan niski)

Opis wyprowadzeń w złączu wyświetlacza od noki 3310/3410

Najprostszym sposobem przyłączenia wyświetlacza jest przylutować
przewody bezpośrednio do miedzianych styków złącza, bez
rozbierania ramki. Ale trzeba lutować szybko i zdecydowanie,
inaczej plastykowa listwa, na której osadzone są miedziane styki
złącza może się pod wpływem ciepła roztopić i odkształcić.

2 z 11

background image

Najprostszym sposobem przyłączenia wyświetlacza jest przylutować przewody do

miedzianych styków złącza, bez wyciągania wyświetlacza z oryginalnej ramki.

Wyświetlacz z przewodami przystosowanymi do podłączenia do płytki stykowej.

Wyświetlacz wymaga napięcia zasilania 2.7-3.3 VDC, zatem
najprościej jest zasilać całość: mikrokontroler i wyświetlacz
napięciem 3.3V. W takim przypadku wejścia sygnałowe
wyświetlacza można podłączyć bezpośrednio do wyprowadzeń
portów we/wy mikrokontrolera. Na schematach wejścia sygnałowe
wyświetlacza połączone są do wyprowadzeń mikrokontrolera
skojarzonych ze sprzętowym interfejsem SPI AVRa atmega.
W przykładowych programach, które będziemy dalej uruchamiać,
można wybrać sprzętowe lub programowe SPI; w przypadku wyboru
programowego SPI, sygnały sterujące wyświetlaczem można
przyłączyć do dowolnych porów we/wy AVRa.

Schemat 1 Sposób przyłączenia wyświetlacza od nokii3310/3410 do interfejsu SPI

mikrokontrolera atmega8(88) zasilanego napięciem 3.3V

3 z 11

background image

Nie wszystkie wersje AVR mogą być zasilane napięciem 3.3V,
schemat nr 2 pokazuje, jak można podłączyć wyświetlacz zasilany
napięciem 3.3V do mikrokontrolera zasilanego napięciem 5V.
Wyświetlacz od Nokii 3310 zużywa minimalne ilości prądu, napięcie
3.3V do jego zasilania można uzyskać stosując dzielnik napięcia:
rezystor i dioda zenera 3.3V. Na schemacie wejścia sterujące
wyświetlacza połączono z portami we/wy AVRa poprzez bufor
74ls07. Scalony układ 74LS07 zawiera sześć cyfrowych buforów
z wyjściami typu otwarty kolektor, wyjścia te zostały podciągnięte
rezystorami 330 do napięcia 3.3V.

Schemat 2 Sposób przyłączenia wyświetlacza od nokii3310/3410 zasilanego napięciem

3.3V do mikrokontrolera zasilanego napięciem 5V

Komunikacja z wyświetlaczem

Wyświetlacz od Nokii 3310 wyposażony jest kontroler PCD8544 z
szeregowym interfejsem SPI(Serial Peripheral Interface). Interfejs
posiada cztery wejścia:

SDIN - szeregowe wejście danych,
SCLK - sygnał zegarowy taktujący dane na linii, SDIN
/SCE - wejście aktywujące interfejs szeregowy,
D/C - wejście wyboru rodzaju danych (wyświetlane lub
sterujące).

Komunikacja przebiega tylko w jednym kierunku, od
mikrokontrolera do wyświetlacza. Zależnie od stanu linii D/C, bajty
danych wysyłane do wyświetlacza, mogą być interpretowane przez
kontroler jako komendy do wykonania albo dane zapisywane do
pamięci RAM obrazu; stan wysoki na linii D/C sygnalizuje daną,
stan niski komendę.

Rys.1 pokazuje przebieg transmisji jednego bajtu danych od
mikrokntrolera do wyświetlacza Komunikację rozpoczyna się od
ustawienia linii /SCE w stan niski, co aktywuje interfejs SPI. Jeśli
wysyłany bajt jest komendą, linię D/C ustawia się w stan niski,
a jeśli zwykłą daną - w stan wysoki Następnie, linią SDIN,
szeregowo(bit po bicie) przesyła się 8 bitów danej, zaczynając od
bitu najbardziej znaczącego. Transmisja szeregowa jednego bitu
przebiega w następujący sposób: Wpierw na linii danych SDIN
ustawia się stan niski lub wysoki, zależnie od wartości przesyłanego
bitu; następnie na linii SCLK podaje się impuls: 0-1-0 - kontroler
odczytuje kolejne bity danych przy rosnącym zboczu sygnału SCLK.
Zmiana na linii /SCE stanu niskiego na wysoki sygnalizuje
zakończenie transmisji.

Rys.1 Przesłanie jednego bajtu do wyświetlacza przez SPI.

A oto funkcja "lcd_write_byte" realizująca w sposób programowy
przesłanie jednego bajtu z mikrokontrolera do wyświetlacza:

void

lcd_write_byte(

(

(

(

unsigned

char

c_d,

,

,

,

unsigned

char

data )

)

)

)

{

{

{

{

unsigned

char

m;

;

;

;

LCD_CE_CLR

if

(

(

(

(c_d)

)

)

)

4 z 11

background image

LCD_DC_SET

else

LCD_DC_CLR

for

(

(

(

(m=

=

=

=

0x80

;

;

;

; m;

;

;

; m>>=

>>=

>>=

>>=

1

)

)

)

)

{

{

{

{

if

(

(

(

(data &

&

&

& m)

)

)

)

LCD_DATA_SET

else

LCD_DATA_CLR

LCD_CLK_SET
LCD_NOP
LCD_CLK_CLR
}

}

}

}

LCD_CE_SET
}

}

}

}

Listing nr 1. Funkcja przesyłająca szeregowo jeden bajt danych z mikrokontrolera do

wyświetlacza LCD poprzez interfejs SPI zrealizowany programowo.

Pierwszy argument funkcji "lcd_write_byte" wskazuje czy wysyłana
jest komenda, czy bajt zwykłych danych (1-komend, 0-zwykła
dana); drugi argument to kod komendy lub bajt danych. Użyte w
funkcji makrodefinicje: LCD_x_SET, LCD_x_CLR ustawiają na
liniach sygnałowych stan wysoki lub niski, a makro LCD_NOP to
krótkie opóźnienie w programie.

Mikrokontrolery atmega wyposażone są w sprzętowy interfejs SPI,
który możemy wykorzystać do sterowania naszym wyświetlaczem.
Poniżej znajduje się listing drugiej wersja funkcji "lcd_write_byte",
która wysyła do wyświetlacza jeden bajt z wykorzystaniem
sprzętowego interfejsu SPI.

/**/

SPCR =

=

=

=(

(

(

(

1

<<

<<

<<

<<SPE)|(

)|(

)|(

)|(

1

<<

<<

<<

<<MSTR)|(

)|(

)|(

)|(

1

<<

<<

<<

<<SPR0);

);

);

);

/**/

void

lcd_write_byte(

(

(

(

unsigned

char

c_d,

,

,

,

unsigned

char

data )

)

)

)

{

{

{

{
LCD_CE_CLR

if

(

(

(

(c_d)

)

)

)

LCD_DC_SET

else

LCD_DC_CLR

SPDR =

=

=

= data;

;

;

;

while

(!(

(!(

(!(

(!(SPSR &

&

&

& (

(

(

(

1

<<

<<

<<

<<SPIF)));

)));

)));

)));

LCD_CE_SET

}

}

}

}

Listing nr 2. Funkcja przesyłająca szeregowo jeden bajt danych z mikrokontrolera do

wyświetlacza poprzez sprzętowy interfejs SPI AVRa atmega.

Do kontroli sprzętowego interfejsu SPI AVRa atmeaga wykorzystuje
się trzy rejestry IO :

SPDR -SPI Data Register,
SPCR -SPI Control Register,
SPSR -SPI Status Register.

Sprzętowy interfejs SPI mikrokontrolera atmega ma szerokie
możliwości konfiguracji, ale do sterowanie naszym wyświetlaczem
pasują ustawienia domyślne. Pozostaje tylko wybrać szybkość
działania interfejsu SPI, tzn. częstotliwość sygnału taktującego na
linii SCLK. Służą do tego celu bity SPR0, SPR1 rejestru SPCR(SPI
Control Register) oraz bit SPI2X rejestru SPSR(SPI -Status
Register), tabela poniżej:

SPI2X SPR1 SPR0 SCK Frequency

0

0

0

fosc/4

0

0

1

fosc/16

0

1

0

fosc/64

0

1

1

fosc/128

1

0

0

fosc/2

1

0

1

fosc/8

1

1

0

fosc/32

1

1

1

fosc/64

Wybór częstotliwości sygnału taktującego na linii SCLK interfejsu SPI mikrokontrolera

atmega

W naszych przykładach transmisja przez sprzętowy interfejs SPI
będzie przebiegać z częstotliwością fosc/16, czyli przy częstotliwości
pracy mikrokontrolera 16MHz sygnał taktujący na wyjściu SCLK
będzie mieć częstotliwość 1MHz.

Ustawienie bitów SPE i MSTR w rejestrze SPCR(SPI Control
Register) włącza interfejs SPI AVRa w trybie MASTER. Wysłanie

5 z 11

background image

bajtu następuje po zapisaniu danej do rejestru SPDR(SPI Data
register), a ustawiony bit SPIF w rejestrze SPSR(SPI Status
Register) sygnalizuje zakończenie transmisji.

Inicjalizacja wyświetlacza

Poniżej znajduje się listing funkcji inicjującej wyświetlacz. Na
początku funkcji program resetuje wyświetlacz ustawiając linie
/RES w stan niski na ok 15ms, po resecie funkcja wysyła kilka
instrukcji inicjujących wyświetlacz.

/* Inicjuje wyświetlacz */

void

lcd_init(

(

(

(

void

)

)

)

)

{

{

{

{
LCD_RST_CLR;

;

;

;


// < 30ms

_delay_ms(

(

(

(

15

);

);

);

);


LCD_RST_SET

LCD_CE_SET

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0x21

);

);

);

);

// Function set - extended instruction set

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0x13

);

);

);

);

// Bias - 1:48

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0x06

);

);

);

);

// Temperature Control

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0xa5

);

);

);

);

// Set Vop

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0x20

);

);

);

);

// Function set - basic instruction set, horizontal addressing

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0x0C

);

);

);

);

// Display control - normal mode

}

}

}

}

Listing nr 3. Funkcja inicjująca wyświetlacz.

Pamięć RAM obrazu wyświetlacza

Każdemu pikselowi na ekranie wyświetlacza odpowiada jeden bit
w pamięci RAM obrazu. Ekran wyświetlacza od Nokii 3310 ma
rozdzielczość 84x48, zatem, aby zapamiętać cały obraz, kontroler
wyświetlacza potrzebuje mieć 4032 bity pamięci RAM obrazu. Bity
w pamięci obrazu pogrupowane są w komórki po 8 bitów(bajty),
zapisując dane do pamięci obrazu zmieniamy od razu cały
bajt(osiem pikseli na ekranie wyświetlacza). Niestety nie ma
możliwości odczytu danych z pamięci RAM obrazu :( Komórki
pamięci RAM obrazu są ponumerowane, numer komórki w pamięci
nazywany jest jej adresem. Kolejnym ośmiu bitom każdej komórki
pamięci RAM obrazu, odpowiada osiem kolejnych pikseli na ekranie
LCD, ALE w kierunku pionowym, LSB na górze, MSB na dole ,patrz
rys. 2. Przykładowo, jeśli gdzieś w pamięci RAM obrazu zapisana
zostanie bajt o wartości 0xff, to w odpowiednim miejscu na ekranie
wyświetlacza pojawi się pionowa kreska | o wysokości 8 pikseli,
patrz rys.2.

Rys.2 Tak można wyobrazić sobie pamięć obrazu wyświetlacza od nokii 3310, widzimy

tablicę: 6 wierszy i 84 kolumny - każda kratka w tabeli to jeden bajt w pamięci RAM obrazu.

Dodatkowo, obok pamięci RAM obrazu, kontroler wyświetlacza
posiada rejestr: licznik_adresu. Liczniku_adresu zawiera adres
wskazujący na komórkę w pamięci RAM obrazu, gdzie zostanie
zapisany następny bajt danych wysyłany do wyświetlacza, gdy na
linii D/C występuje stan wysoki. Każdorazowo po zapisaniu bajtu
danych w pamięci obrazu, licznik adresu zwiększa się
automatycznie o jeden i wskazuje na następną komórkę w pamięci
RAM obrazu. Wysyłając do wyświetlacza komendy:
Set_Y_address_of_RAM i Set_X_address_of_RAM można ustawić
zawartość licznika_adresu tak, aby skazywał na dowolną komórkę
w pamięci RAM obrazu.

Komendy kontrolera

Jak pisałem wcześniej, bajty danych wysyłane do wyświetlacza
mogą być interpretowane przez kontroler wyświetlacza jako

6 z 11

background image

komendy do wykonania albo jako dane kopiowane do pamięci RAM
obrazu - zależnie od stanu linii sygnału D/C. Bajty danych
i komendy będziemy wysyłać do LCD omawianą wcześniej funkcją:

void lcd_write_byte(unsigned char c_d, unsigned char byte )

Parametr "c_d" to stan linii D/C, parametr "byte" to wysyłany bajt
danych albo kod komendy.

Zbiór wszystkich komend wyświetlacza można znaleźć
w dokumentacji kontrolera PCD8544. W naszych przykładach
będziemy najczęściej wysyłać do LCD komendy
Set_Y_address_of_RAM i Set_X_address_of_RAM", żeby ustawić
zawartość licznika_adresu.

Wszystkie komendy kontrolera mają rozmiar jednego bajta(osiem
bitów). Na bitach 6..0 kodu komendy Set_X_address_of_RAM
kodowana jest współrzędna X, która może przyjmować wartości od
0 do 83, patrz rys.2.

1 X X X X X X X

Na bitach 2..0 kodu komendy Set_Y_address_of_RAM kodowana
jest współrzędna Y, która może przyjmować wartości od 0 do 5,
patrz rys.2

0 1 0 0 0 Y Y Y

W przypadku wyświetlacza od Nokii3410 z kontrolerem OM6206
można ustawić współrzędną Y na wartości 0..7, a współrzędną X na
wartości 0..96

I to jest wszystko, co potrzebujemy wiedzieć, aby wykorzystać
wyświetlacz od Nokii_3310. W dalszej części artykułu uruchomimy
kilka przykładowych programików. Wszystkie przykłady są
maksymalnie uproszczone, bo jak wiadomo, dobry przykład, to
prosty przykład:)

Przykład pierwszy. Jak wyświetlić obrazek

W programie

MicroLCD

narysowałem przykładowy obrazek w dwóch

kolorach, który zostanie pokazany na ekranie naszego
wyświetlacza. Obrazek ma wymiary 84x48 - zajmie cały ekran
wyświetlacza.

Przykładowy obrazek do pokazania na wyświetlaczu narysowany w programie

MicroLCD

.

Dane obrazka wyeksportowałem do pliku tekstowego "hello_img.c",
wybierając w menu programu

MicroLCD

opcję:

File->Export (.C hex file)

Plik z danymi obrazka zostaje dołączony do programu instrukcją
preprocesora #include "hello_img.c", dane obrazka trafią do tablicy
typu char.

unsigned

char

hello_img[]

[]

[]

[] PROGMEM =

=

=

= {

{

{

{

#include "hello_img.c"

};

};

};

};

Słówko PROGMEM w deklaracji tablicy decyduje, że tablica zostanie
utworzona w pamięci programu (we FLASHu AVRa).

7 z 11

background image

Teraz, aby pokazać obrazek na ekranie, wystarczy przekopiować
dane z tablicy we FLASHu AVRa do pamięci RAM obrazu
wyświetlacza, robi to funkcja "lcd_image".

/* */

void

lcd_image(

(

(

(

unsigned

char

img[],

[],

[],

[],

char

x0,

,

,

,

char

y0,

,

,

,

char

w,

,

,

,

char

h)

)

)

)

{

{

{

{

unsigned

int

i,

,

,

,j,

,

,

,k;

;

;

;


for

(

(

(

(i=

=

=

=

0

,

,

,

,j=

=

=

=

0

,

,

,

,k=

=

=

=

0

;

;

;

; i<

<

<

<h;

;

;

; i++)

++)

++)

++)

{

{

{

{

/* Komenda LCD "Set Y address of RAM" */

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0x40

|(

|(

|(

|(i+

+

+

+y0));

));

));

));

/* Komenda "Set X address of RAM"*/

lcd_write_byte(

(

(

(LCD_CMD,

,

,

,

0x80

|(

|(

|(

|(x0));

));

));

));

/* Kopiowanie z FLASH do pamięci obrazu LCD */

for

(

(

(

(j=

=

=

=

0

;

;

;

; j<

<

<

<w ;

;

;

; j++,

++,

++,

++,k++)

++)

++)

++)

lcd_write_byte(

(

(

(LCD_DATA,

,

,

, pgm_read_byte(&

(&

(&

(&img[

[

[

[k]));

]));

]));

]));

}

}

}

}

}

}

}

}

Listing nr 4. Funkcja wyświetlająca obrazek na ekranie LCD.

Pierwszy argument funkcji "lcd_image" to tablica we FLASHu
z danymi obrazka; kolejne dwa argumenty (x0,y0), to położenie
górnego lewego rogu obrazka na ekranie LCD; argument czwarty
i piąty to szerokość i wysokość obrazka. Parametry: y0 i wysokość
obrazka trzeba podać w bajtach (osiem pikseli pionowo, patrz
rys.2); na przykład, jeśli obrazek ma wysokość 48 pikseli, to należy
wstawić 6.

A oto główny pliku pierwszego przykładu. Najpierw funkcja
"lcd_init" inicjuje wyświetlacz, następnie funkcja "lcd_image"
kopiuje dane obrazka z tablicy we FLASHu do pamięci RAM obrazu
wyświetlacza.

/*
Plik "main.c"
*/

#include <avr/io.h>
#include <avr/pgmspace.h>

#include "lcd.h"

/* Dołącza dane z obrazkiem, obrazek zostanie
umieszczony w pamięci programu, we FLASHu */

unsigned

char

hello_img[]

[]

[]

[] PROGMEM =

=

=

= {

{

{

{

#include "hello_img.c"

};

};

};

};

int

main(

(

(

(

void

)

)

)

)

{

{

{

{

/* Inicjuje wyświetlacz */

lcd_init();

();

();

();

/* Wyswietla obrazek */

lcd_image(

(

(

(hello_img,

,

,

,

0

,

,

,

,

0

,

,

,

,

84

,

,

,

,

6

);

);

);

);

/* Zatrzymanie programu */

while

(

(

(

(

1

);

);

);

);

return

0

;

;

;

;

}

}

}

}

Listing nr 5. Główny plik przykładu pierwszego.

Przykładowy obrazek pokazany na ekranie LCD od Nokii_3310

Katalog z plikami przykładu pierwszego można pobrać klikają w link
poniżej, są dwie wersje:

wersja a

- z programowym SPI,

wersja

b

- wykorzystująca sprzętowy interfejs SPI AVRa atmega. Katalogi z

plikami źródłowymi przykładów zawierają także plik Makefile, który
należy dostosować: wybrać typ AVRa, częstotliwość pracy
mikrokontrolera, typ programatora -przykłady były testowane na
atmega8 16MHz.

Przykład drugi. Tekst na ekranie LCD

Nasz wyświetlacz nie udostępnia trybu tekstowego, zatem aby
napisać na ekranie tekst, trzeba samemu rysować litery. W
programie

MicroLCD

przygotowałem obrazek ze wzorami liter, cyfr

i innych znaków z tablicy kodów ASCII, każdy znak narysowany jest

8 z 11

background image

na polu o wymiarach 6x8 punktów. Dane obrazka ze wzorami
znaków wyeksportowałem do pliku tekstowego i dołączyłem do
programu komendą preprocesora #include "font6x8p.c". Wzory
znaków trafią do tablicy o nazwie "font" umieszczonej w pamięci
programu (we FLASHu)

Obrazek ze wzorami znaków dla wyświetlacza.

Aby tekst pojawił się na ekranie wyświetlacza, program będzie
kopiował wzory znaków z tablicy "font" do odpowiedniego miejsca
w pamięci RAM obrazu wyświetlacza. Ekran wyświetlacza
podzielony jest na linie tekstowe o wysokości ośmiu punktów, taka
jest organizacja pamięci RAM obrazu naszego wyświetlacza, patrz
rys.2. śeby narysować jeden znak o wymiarach 6x8, trzeba
skopiować sześć kolejnych bajtów; każdy bajt to osiem ułożonych
pionowo punków na ekranie wyświetlacza. Wyświetlacz Noki_3310
ma rozdzielczość 84x48, zatem można na nim pokazać 6 linii teksu,
po 14 znaków 6x8. A to jest funkcja pisząca na ekranie
wyświetlacza tekst:

/*
Wyświetla tekst - znaki 6x8
s - ciąg znaków zakończony zerem
x - pierwsza kolumna 0..84(96)
y - wiersz 0..5(7)
*/

void

lcd_text(

(

(

(

char

s[],

[],

[],

[],

unsigned

char

x,

,

,

,

unsigned

char

y)

)

)

)

{

{

{

{

unsigned

int

c,

,

,

,j;

;

;

;

unsigned

char

i,

,

,

,k;

;

;

;

/* Kody polskich literek z ogonkami */

char

pl[]

[]

[]

[] =

=

=

= {

{

{

{

'ą'

,

,

,

,

'ć'

,

,

,

,

'ę'

,

,

,

,

'ł'

,

,

,

,

'ń'

,

,

,

,

'ó'

,

,

,

,

'ś'

,

,

,

,

'ź'

,

,

,

,

'ż'

,

,

,

,

'Ą'

,

,

,

,

'Ć'

,

,

,

,

'Ę'

,

,

,

,

'Ł'

,

,

,

,

'Ń'

,

,

,

,

'Ó'

,

,

,

,

'Ś'

,

,

,

,

'Ź'

,

,

,

,

'ś'

};

};

};

};


/* Ustawia położenia pierwszej litery tekstu na ekranie LCD */

lcd_write_byte(

(

(

(LCD_CMD,

,

,

, LCD_SETY|(

|(

|(

|(y));

));

));

));

lcd_write_byte(

(

(

(LCD_CMD,

,

,

, LCD_SETX|(

|(

|(

|(x));

));

));

));

/* Rysuje znak po znaku */

for

(

(

(

(k=

=

=

=

0

;

;

;

; (

(

(

(c =

=

=

= s[

[

[

[k]);

]);

]);

]); k++)

++)

++)

++)

{

{

{

{

/* Dopasowuje kody znaków z ogonkami */

for

(

(

(

(i=

=

=

=

0

;

;

;

; (

(

(

(i<

<

<

<

18

)

)

)

) &&

&&

&&

&& (

(

(

(pl[

[

[

[i]!=

]!=

]!=

]!=c);

);

);

); i++)

++)

++)

++) ;

;

;

;

if

(

(

(

(i<

<

<

<

18

)

)

)

) c=

=

=

=

0x80

+

+

+

+i;

;

;

;

/* Kopiuje jeden znak(6x8) z FLASH do pamięci obrazu LCD */

for

(

(

(

(i=

=

=

=

0

,

,

,

, j=(

=(

=(

=(c-

-

-

-

32

)*

)*

)*

)*

6

;

;

;

; i<

<

<

<

6

;

;

;

; i++,

++,

++,

++,j++)

++)

++)

++)

lcd_write_byte(

(

(

(LCD_DATA,

,

,

, pgm_read_byte(&

(&

(&

(&font[

[

[

[j]));

]));

]));

]));

}

}

}

}

}

}

}

}

Listing nr 6. Funkcja wyświetlająca ekranie LCD tekst

Pierwszym argumentem funkcji lcd_text jest ciąg znaków
zakończony zerem, tekst może zawierać polskie znaki z ogonkami.
Drugi i trzeci argument to położenie tekstu na ekranie LCD; x może
przyjmować wartości 0..84, y-wartości 0..5.

A to jest główny plik drugiego przykładu:

/*
Plik "main.c"

LCD od nokia3310 przykład 2
KURS AVR-GCC www.abxyz.bplaced.net

testowane na atmega8 (16MHz)
*/

#include <avr/io.h>

9 z 11

background image

#include <avr/pgmspace.h>
#include "lcd.h"

/* */

int

main(

(

(

(

void

)

)

)

)

{

{

{

{

/* Inicjuje wyświetlacz */

lcd_init();

();

();

();

/* Czyści ekran */

lcd_clear();

();

();

();

/* Wyświetla tekst */

lcd_text(

(

(

(

"Kurs AVR-GCC"

,

,

,

,

1

*

*

*

*

6

,

,

,

,

0

);

);

);

);

lcd_text(

(

(

(

"ABXYZ :)"

,

,

,

,

4

*

*

*

*

6

,

,

,

,

1

);

);

);

);

lcd_text(

(

(

(

"Wyświetlacz"

,

,

,

,

1

*

*

*

*

6

,

,

,

,

3

);

);

);

);

lcd_text(

(

(

(

"LCD"

,

,

,

,

5

*

*

*

*

6

,

,

,

,

4

);

);

);

);

lcd_text(

(

(

(

"od Nokii 3310"

,

,

,

,

0

*

*

*

*

6

,

,

,

,

5

);

);

);

);

/* Zatrzymanie programu */

while

(

(

(

(

1

);

);

);

);

return

0

;

;

;

;

}

}

}

}

Listing nr 7. Główny plik przykładu drugiego.

Przykładowy tekst na ekranie wyświetlacza od Nokii 3310.

Katalog z plikami przykładu drugiego można pobrać klikają w link
poniżej: są dwie wersje:

wersja a

- z programowym SPI,

wersja

b

- wykorzystująca sprzętowy interfejs SPI AVRa atmega.

Przykład trzeci. Płynący tekst.

Przykład trzeci. Obrazek na górze ekranu, płynący tekst na dole.

/*
Plik "main.c"

LCD od Nokii_3310 przykład 3
KURS AVR-GCC www.abxyz.bplaced.net

testowane na atmega8 16(MHz)
*/

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdio.h>
#include "lcd.h"

// Dane obrazka "avr_gcc"

unsigned

char

screen[]

[]

[]

[] PROGMEM =

=

=

= {

{

{

{

#include "avr_gcc.c"

};

};

};

};

// Wzory znaków 6x8 dla funkcji "scroll"

extern

unsigned

char

font[]

[]

[]

[] PROGMEM;

;

;

;

// Tekst płynącego napisu

unsigned

char

tekst[]

[]

[]

[] PROGMEM =

=

=

=

" Internetowy kurs programowania mikrokontrolerów AVR w języku C

// Funkcja tworzy na ekranie LCD płynący napis

void

scroll(

(

(

(

unsigned

char

txt[],

[],

[],

[],

unsigned

char

line)

)

)

)

{

{

{

{

unsigned

int

j,

,

,

,l,

,

,

,k,

,

,

,n;

;

;

;

unsigned

char

c,

,

,

,i,

,

,

,m;

;

;

;

// Kody polskich literek z ogonkami

unsigned

char

pl[]

[]

[]

[] =

=

=

= {

{

{

{

'ą'

,

,

,

,

'ć'

,

,

,

,

'ę'

,

,

,

,

'ł'

,

,

,

,

'ń'

,

,

,

,

'ó'

,

,

,

,

'ś'

,

,

,

,

'ź'

,

,

,

,

'ż'

,

,

,

,

'Ą'

,

,

,

,

'Ć'

,

,

,

,

'Ę'

,

,

,

,

'Ł'

,

,

,

,

'Ń'

,

,

,

,

'Ó'

,

,

,

,

'Ś'

,

,

,

,

'Ź'

,

,

,

,

'ś'

};

};

};

};

10 z 11

background image

// liczenie znaków w tekście

for

(

(

(

(n=

=

=

=

0

;

;

;

;pgm_read_byte(&

(&

(&

(&txt[

[

[

[n]);

]);

]);

]);n++);

++);

++);

++);

for

(

(

(

(j=

=

=

=

0

;

;

;

; j<(

<(

<(

<(n-(

-(

-(

-(LCD_X/

/

/

/

6

))*

))*

))*

))*

6

;

;

;

;j++)

++)

++)

++)

{

{

{

{

LCD_GOTO(

(

(

(

0

,

,

,

, line)

)

)

)


for

(

(

(

(i=

=

=

=

0

,

,

,

,l=

=

=

=j;

;

;

; i<

<

<

<LCD_X ;

;

;

;i++,

++,

++,

++,l++)

++)

++)

++)

{

{

{

{

c =

=

=

= pgm_read_byte(&

(&

(&

(&txt[

[

[

[ (

(

(

(l/

/

/

/

6

)

)

)

) ]);

]);

]);

]);

// Dopasowuje kody polskich znaków z ogonkami

for

(

(

(

(m=

=

=

=

0

;

;

;

; (

(

(

(m<

<

<

<

18

)

)

)

) &&

&&

&&

&& (

(

(

(pl[

[

[

[m]!=

]!=

]!=

]!=c);

);

);

); m++)

++)

++)

++) ;

;

;

;

if

(

(

(

(m<

<

<

<

18

)

)

)

) c=

=

=

=

0x80

+

+

+

+m;

;

;

;

k =

=

=

= (

(

(

(c-

-

-

-

32

)*

)*

)*

)*

6

+(

+(

+(

+(l%

%

%

%

6

);

);

);

);


lcd_write_byte(

(

(

(LCD_DATA,

,

,

, pgm_read_byte(&

(&

(&

(&font[

[

[

[k]));

]));

]));

]));

}

}

}

}

_delay_ms(

(

(

(

70

);

);

);

);

}

}

}

}

}

}

}

}

/* MAIN */

int

main(

(

(

(

void

)

)

)

)

{

{

{

{

// Inicjuje LCD

lcd_init();

();

();

();


// Obrazek w górnej części ekranu

lcd_image(

(

(

(screen,

,

,

,

0

,

,

,

,

0

,

,

,

,

84

,

,

,

,

5

);

);

);

);


// Płynący napis w linii nr 5

while

(

(

(

(

1

)

)

)

)

scroll(

(

(

(tekst,

,

,

,

5

);

);

);

);

return

0

;

;

;

;

}

}

}

}

Listing nr 8. Główny plik przykładu drugiego.

Katalog z plikami przykładu trzeciego można pobrać klikają w link
poniżej: są dwie wersje:

wersja a

- z programowym SPI,

wersja

b

- wykorzystująca sprzętowy interfejs SPI AVRa atmega.

26.04.11 ABXYZ

Copyright © 2009-2011 ABXYZ - Wszelkie prawa zastrzeżone

11 z 11


Wyszukiwarka

Podobne podstrony:
Kurs AVR GCC cz 1
Kurs AVR GCC, cz 2
Kurs AVR GCC cz 4 2
Kurs AVR GCC cz 2
Kurs AVR GCC Dekoder RC5
Kurs AVR GCC, cz 5
Kurs AVR GCC, cz 1
Kurs AVR GCC cz 3
Kurs AVR GCC, cz 4
Kurs AVR GCC, cz 3
Kurs AVR GCC cz 5
Kurs AVR GCC cz 1

więcej podobnych podstron