TECHNIKA MIKROPROCESOROWA II

Komentarze

Transkrypt

TECHNIKA MIKROPROCESOROWA II
Akademia Górniczo – Hutnicza
im. Stanisława Staszica w Krakowie
Wydział IEiT
Katedra Elektroniki
TECHNIKA MIKROPROCESOROWA II
LAB 2
Human-Machine Interface, czyli obsługa wyświetlacza sLCD
© Sebastian Koryciak
http://www.fpga.agh.edu.pl/tm2
08.10.2015
1 WSTĘP
1.1 CEL
Niniejsze ćwiczenie ma na celu zapoznanie użytkowników ze sposobem obsługi wyświetlacza
multipleksowanego. Za przykład posłuży wyświetlacz zamontowany na płytce ewaluacyjnej FRDMKL46Z.
1.2 WYMAGANIA
Sprzętowe:


komputer klasy PC spełniający wymagania sprzętowe aplikacji KEIL v5,
zestaw FRDM-KL46Z
Programowe:


system operacyjny Windows XP lub wyższy,
środowisko Keil / uVision 5
Doświadczenie:





podstawowa umiejętność obsługi komputera klasy PC,
podstawowa znajomość systemów operacyjnych rodziny Windows,
podstawowa znajomość zagadnień z Techniki Mikroprocesorowej 1,
podstawowa znajomość zagadnień z Techniki Cyfrowej,
wykonane ćwiczenie LAB 1
2 SEGMENT LCD CONTROLLER
Mikrokontrolery z rodziny KL46 zostały wyposażone w wbudowany kontroler wyświetlaczy
multipleksowanych numerycznych, alfanumerycznych ale także i niestandardowych. Obraz mogą
tworzyć zarówno kropki (piksele), jak i symbole (specjalne obrazki lub część wyświetlacza 7
segmentowego).
2.1 ZADANIE
Na podstawie dokumentu KL46 Reference Manual proszę dowiedzieć się jakie są podstawowe
parametry kontrolera sLCD, a na ich podstawie określić jaki największy wyświetlacz może być przez ten
mikrokontroler obsługiwany.
Na płytce FRDM-KL46Z mamy do dyspozycji wyświetlacz Lumex LCD-S401M16KR. Na podstawie jego
dokumentacji możemy dowiedzieć się, że do jego sterowania wykorzystywane się następujące piny:
Natomiast poszczególne elementy wyświetlacza to:
Wyświetlacze tego typu podzielone są na dwie płaszczyzny (planes): przednią (frontplane) i tylną
(backplane). W tym przypadku mamy do czynienia z 4 pinami służącymi za sygnały wspólne, oraz 8
sterującymi poszczególne segmenty (7 + kropka). Sterowanie będzie polegało na multipleksowaniu ze
sobą poszczególnych płaszczyzn z odpowiednią częstotliwością.
Przykładowo sygnał COM0 kontroluje zaznaczone powyżej segmenty. Oznacza to, że jeżeli COM0
będzie ustawione, możemy aktywować 8 segmentów w zależności od wartości stanów na 8 pinach
sterujących tymi segmentami. Ponieważ mamy 4 fazy (4 piny COM), a każdy steruje 8 segmentami,
mamy w sumie 32 segmenty, których wartości możemy ustawić. Należy również zwrócić uwagę na
fakt, iż tego rodzaju wyświetlacz nie posiada zasilania. W związku z tym należy 4 fazy COM rozdzielić
równomiernie, tak aby wszystkie segmenty były tak samo „jasne”.
Natomiast patrząc na wyświetlacz z perspektywy poszczególnych segmentów mamy sytuację
przedstawioną na następnej grafice.
a
f
a
b
f
g
e
BP3
b
BP2
g
c
e
d
FP1
FP0
c
d
BP1
BP0
Podpięcie poszczególnych tylnych ścian (BP) do rejestrów przebiegów (zgodnie z pinami z FRDMKL46Z) powinno wyglądać następująco:
WF40
WF52
WF19
WF18
0
0
0
1
0
0
1
0
0
1
0
0
1
0
0
0
0
0
0
1
0
0
1
0
0
1
0
0
1
0
0
0
Biorą pod uwagę powyższe warunki, poszczególne segmenty będą aktywne w następujących
przebiegach:
WF8B[0]
WF8B[1]
d
dp
e
c
g
b
f
a
d
dp
e
c
g
b
f
a
Ściany BP są sterowane automatycznie, co ustawiamy w trakcie inicjalizacji. Pozostaje nam jedynie
odpowiednie wysterowanie rejestrów WF8B. Przykładowo aby wyświetlić cyfrę 4 należy ustawić:
WF8B[0]
WF8B[1]
-
c
g
b
f
-
-
c
g
b
f
-
2.2 ZADANIE
Proszę otworzyć dokument FRDM-KL46Z_Schematics i na jego podstawie stworzyć tabelę podłączenia
portów mikrokontrolera KL46 do wyświetlacza. Tabelka powinna mieć następującą formę:
LCD-S401 Pin
1
Pin connection
COM 0
KL46 LCD Pin
LCD_P40
Pin Name
PTD0
2.3 ZADANIE
Obsługę wyświetlacza należy rozpocząć od jego inicjalizacji. Proszę stworzyć nowy projekt zgodnie z
opisem zamieszczonym w instrukcji LAB 1, a następnie w pliku main.c (pamiętając o pliku
nagłówkowym i głównej funkcji main) stworzyć funkcję inicjalizującą wyświetlacz (np. sLCD_Init). Do
zawartości funkcji proszę wkleić zamieszczony poniżej kod, postępując zgodnie z następującymi
zasadami:
1. W przypadku pojawienia się znaków ?????? proszę zgodnie z komentarzem zastąpić je
odpowiednimi wartościami / rejestrami
2. W przypadku komentarza o treści !!!!!! proszę odnaleźć w dokumentacji mikrokontrolera
przeznaczenie danego rejestru (czy też maski w pliku nagłówkowym) i zastąpić znaki
odpowiednim komentarzem
1.
2.
3.
4.
5.
6.
// konfiguracja zegara dla portów wykorzystywanych przy obsłudze wyświetlacza
// i modułu sLCD
SIM->SCGC5 |= ??????
// wstępne wyłączenie i reset kontrolera
LCD->GCR |= LCD_GCR_PADSAFE_MASK; // !!!!!!
LCD->GCR &= ~LCD_GCR_LCDEN_MASK; // Clear LCDEN w trakcie konfiguracji
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
// konfiguracja multiplekserów do operacji portów jako kontroler LCD
PORT??????->PCR[??????] = PORT_PCR_MUX(0u);
// konfiguracja rejestrów LCD
LCD->GCR = // !!!!!!
LCD_GCR_RVTRIM(0x00) |
LCD_GCR_CPSEL_MASK |
LCD_GCR_LADJ(0x03) |
LCD_GCR_VSUPPLY_MASK |
LCD_GCR_ALTDIV(0x00) |
LCD_GCR_SOURCE_MASK |
LCD_GCR_LCLK(0x01) |
LCD_GCR_DUTY(0x03);
// konfiguracja migania wyświetlacza
LCD->AR = LCD_AR_BRATE(0x03); // !!!!!!
// konfiguracja rejestru FDCR
LCD->FDCR = 0x00000000; // !!!!!!
// aktywowanie 12 pinów do kontroli wyświetlaczem (dwa rejestry po 32 bity)
LCD->PEN[0] =
LCD_PEN_PEN(1u<<7 ) | // LCD_P7
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????);
LCD->PEN[1] =
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????) |
LCD_PEN_PEN(??????);
// skonfigurowanie 4 pinów płaszczyzny tylnej (dwa rejestry po 32 bity)
LCD->BPEN[0] =
LCD_BPEN_BPEN(??????) |
LCD_BPEN_BPEN(??????);
LCD->BPEN[1] =
LCD_BPEN_BPEN(??????) |
LCD_BPEN_BPEN(??????);
// konfiguracja rejestrów przebiegów (Waveform register) – 4 aktywne, reszta nie
// konfiguracja polega na równomiernym rozłożeniu faz, w tym przypadku 4, na 8 bitach
// (44.3.7 w KL46 Reference Manual)
LCD->WF[0] =
LCD_WF_WF0(0x00) |
LCD_WF_WF1(0x00) |
LCD_WF_WF2(0x00) |
LCD_WF_WF3(0x00);
LCD->WF[1] =
LCD_WF_WF4(0x00) |
LCD_WF_WF5(0x00) |
LCD_WF_WF6(0x00) |
LCD_WF_WF7(0x00);
LCD->WF[2] =
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
LCD_WF_WF8(0x00) |
LCD_WF_WF9(0x00) |
LCD_WF_WF10(0x00) |
LCD_WF_WF11(0x00);
LCD->WF[3] =
LCD_WF_WF12(0x00) |
LCD_WF_WF13(0x00) |
LCD_WF_WF14(0x00) |
LCD_WF_WF15(0x00);
LCD->WF[4] =
LCD_WF_WF16(0x00) |
LCD_WF_WF17(0x00) |
LCD_WF_WF18(??????) | // COM3 (10001000)
LCD_WF_WF19(??????); // COM2 (01000100)
LCD->WF[5] =
LCD_WF_WF20(0x00) |
LCD_WF_WF21(0x00) |
LCD_WF_WF22(0x00) |
LCD_WF_WF23(0x00);
LCD->WF[6] =
LCD_WF_WF24(0x00) |
LCD_WF_WF25(0x00) |
LCD_WF_WF26(0x00) |
LCD_WF_WF27(0x00);
LCD->WF[7] =
LCD_WF_WF28(0x00) |
LCD_WF_WF29(0x00) |
LCD_WF_WF30(0x00) |
LCD_WF_WF31(0x00);
LCD->WF[8] =
LCD_WF_WF32(0x00) |
LCD_WF_WF33(0x00) |
LCD_WF_WF34(0x00) |
LCD_WF_WF35(0x00);
LCD->WF[9] =
LCD_WF_WF36(0x00) |
LCD_WF_WF37(0x00) |
LCD_WF_WF38(0x00) |
LCD_WF_WF39(0x00);
LCD->WF[10] =
LCD_WF_WF40(??????) | // COM0 (00010001)
LCD_WF_WF41(0x00) |
LCD_WF_WF42(0x00) |
LCD_WF_WF43(0x00);
LCD->WF[11] =
LCD_WF_WF44(0x00) |
LCD_WF_WF45(0x00) |
LCD_WF_WF46(0x00) |
LCD_WF_WF47(0x00);
LCD->WF[12] =
LCD_WF_WF48(0x00) |
LCD_WF_WF49(0x00) |
111. LCD_WF_WF50(0x00) |
112. LCD_WF_WF51(0x00);
113. LCD->WF[13] =
114. LCD_WF_WF52(??????) | // COM1 (00100010)
115. LCD_WF_WF53(0x00) |
116. LCD_WF_WF54(0x00) |
117. LCD_WF_WF55(0x00);
118. LCD->WF[14] =
119. LCD_WF_WF56(0x00) |
120. LCD_WF_WF57(0x00) |
121. LCD_WF_WF58(0x00) |
122. LCD_WF_WF59(0x00);
123. LCD->WF[15] =
124. LCD_WF_WF60(0x00) |
125. LCD_WF_WF61(0x00) |
126. LCD_WF_WF62(0x00) |
LCD_WF_WF63(0x00);
// koniec konfiguracji, więc clear PADSAFE i włączenie wyświetlacza
LCD->GCR &= ~LCD_GCR_PADSAFE_MASK; // !!!!!!
LCD->GCR |= LCD_GCR_LCDEN_MASK; // włączenie wyświetlacza
2.4 ZADANIE
Następnym krokiem jest stworzenie odpowiednich makr, które ułatwią nam dalsze pisanie funkcji.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
// zdefiniowanie ilości pinów na poszczególnych płaszczyznach
#define LCD_N_FRONT 8
#define LCD_N_BACK 4
// Makra dla segmentów, każdy znak sterowany jest przez dwa piny
// Pin 1 -> (Digit*2 - 1), Pin 2 -> Digit*2
//
Pin 1 Pin 2
// COM0
D
Dec
// COM1
E
C
// COM2
G
B
// COM3
F
A
#define LCD_S_D 0x11
// segment D
#define LCD_S_E 0x22
// segment E
#define LCD_S_G 0x44 // segment G
#define LCD_S_F 0x88 // segment F
#define LCD_S_DEC 0x11
#define LCD_S_C 0x22
#define LCD_S_B 0x44
#define LCD_S_A 0x88
#define LCD_C 0x00
// clear
// Makra dla każdego pinu
#define LCD_FRONT0 37u
#define LCD_FRONT1 ??????
#define LCD_FRONT2 ??????
#define LCD_FRONT3 ??????
#define LCD_FRONT4 ??????
#define LCD_FRONT5 ??????
27.
28.
29.
30.
31.
32.
33.
34.
35.
#define LCD_FRONT6 ??????
#define LCD_FRONT7 ??????
#define LCD_BACK0 40u
#define LCD_BACK1 ??????
#define LCD_BACK2 ??????
#define LCD_BACK3 ??????
// Zmienne tworzące dwie tablice
const static uint8_t LCD_Front_Pin[??????] = {??????};
const static uint8_t LCD_Back_Pin[??????] = {??????};
2.5 ZADANIE
Wreszcie możemy napisać funkcję wykorzystującą wszystkie powyżej zainicjalizowane ustawienia oraz
zdefiniowane makra. Proszę skopiować i uzupełnić poniższą funkcję.
1. void sLCD_set(uint8_t value,uint8_t digit){
2. // value – wyświetlana wartość,
3. // digit – pozycja na której ma być wyświetlona wartość
4.
if(value==0x00){
// aby wyświetlić ‘0’ zapalamy segmenty
5.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = // D, E, F oraz A, B, C
6.
(LCD_S_D | LCD_S_E |LCD_S_F);
// (patrz tabelki w zadaniu 2.1)
7.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] =
8.
(LCD_S_A | LCD_S_B | LCD_S_C);
9.
}
10. else if(value==0x01){
11.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] =
12.
(LCD_C);
13.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] =
14.
(LCD_S_B | LCD_S_C);
15. }
16. else if(value==0x02){
17.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
18.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
19. }
20. else if(value==0x03){
21.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
22.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
23. }
24. else if(value==0x04){
25.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
26.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
27. }
28. else if(value==0x05){
29.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
30.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
31. }
32. else if(value==0x06){
33.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
34.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
35. }
36. else if(value==0x07){
37.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
38.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
39. }
40. else if(value==0x08){
41.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
42.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
43. }
44. else if(value==0x09){
45.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
46.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
47. }
48. else if(value==0x0A){
49.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
50.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
51. }
52. else if(value==0x0B){
53.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
54.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
55. }
56. else if(value==0x0C){
57.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
58.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
59. }
60. else if(value==0x0D){
61.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
62.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
63. }
64. else if(value==0x0E){
65.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
66.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
67. }
68. else if(value==0x0F){
69.
LCD->WF8B[LCD_Front_Pin[((2*digit)-2)]] = (??????);
70.
LCD->WF8B[LCD_Front_Pin[((2*digit)-1)]] = (??????);
71. }
72. }
2.6 ZADANIE
Proszę w głównej pętli wykorzystać stworzone funkcje i wyświetlić godzinę rozpoczęcia zajęć
laboratoryjnych.
2.7 ZADANIE DOMOWE
Proszę wykonać następujące czynności:
1. Proszę zrobić porządek w programie tworząc osobny plik z funkcjami dotyczącymi obsługi
wyświetlacza, oraz odpowiedni plik nagłówkowy, którego załączenie do pliku main pozwoli na
wykorzystanie tych funkcji i makr.
2. Proszę do funkcji sLCD_set() dorobić obsługę błędów, czyli wpisanie większej wartości do
wyświetlenia niż jest to możliwe, bądź też żądanie wyświetlenia wartości na innej pozycji niż
jest to możliwe.
3. Proszę napisać funkcję do obsługi kropek na wyświetlaczu.
4. Proszę napisać funkcję pozwalającą na wyświetlenie zadanej wartości w wybranym przez nas
formacie (dec, bin, hex, oct)

Podobne dokumenty