|
Tutorial zum Ansteuern eines Grafikdisplays EW12A03GLY mit einem Atmel ATMega16
Beschreibung
Grundlagen GLCD
Das Board
Die Software des Atmel
Die Software des PC
Download
Beschreibung
Es handelt sich hier um ein Tutorial zur Ansteuerung eines Grafik-LCD mit Hilfe eines Mikrocontrollers ATMega16.
Es wird ein Bild aus dem EEProm in einen Puffer geladen und dann auf das Display ausgegeben.
Die dafür entwickelte Platine enthält das Display, den Atmel, eine Spannungsversorgung, ein ISP-Interface, ein I2C-Interface und einige Taster.
Die Software wird in Assembler geschrieben und kann per ISP jederzeit geändert werden. Geplant ist, in einem erweiterten Tutorial, die Ansteuerung per I2C-Bus und die Implementierung der Taster zum Zeichnen eigener Bilder direkt auf dem Display sowie einer Textausgabe.
Grundlagen GLCD
Das Grafikdisplay EW12A03GLY von "Emerging Display" hat eine Auflösung von 122*32 Pixel. Diese werden von 2 Controller SED1520 angesteuert, welche sich die linke und die rechte Displayhälfte teilen. Jeder Controller bedient damit ein Feld von 61*32 Pixel. Die Daten werden dem Controller in 8-Bit breite Blöcke übergeben. Dieses Byte wird senkrecht auf dem Display ausgegeben, wobei das LSB oben liegt. Bei einer Display-Höhe von 32 Pixel ergeben sich vier "Zeilen", die so genannten Pages. Wenn man also den obersten linken Pixel setzen möchte, muss man ein Byte 0b00000001 an Page 0 und Spalte 0 des linken Controllers senden. Dabei werden immer auch die sieben darunter liegenden Pixel definiert. In unserem Beispiel zurückgesetzt. Wenn man also eine horizontale Linie zeichnen möchte, ohne dabei den Rest des Bildes zu verändern, muss man wissen was in den betroffenen Page-Spalten dargestellt wird, um diese Daten unverändert wieder zu senden. Da man bei diesem Display keine Daten auslesen kann, muss ein Bildpuffer im ATMega16 umgesetzt werden, in dem das dargestellte Bild 1:1 gespeichert ist.
Das Board
Allgemein
Auf dem Board sind alle für den Betrieb nötigen Komponenten enthalten. Das gesamte Board ist möglichst flexibel gehalten. So ist es möglich diverse Leuchtdioden, Widerstände und Kondensatoren in SMD- oder in Print-Technik auszuführen. Die Spannungsversorgung wird mit einem L200 realisiert. Dies ist ein einstellbarer Festspannungsregler, welcher uns die gewünschten 5V Betriebsspannung liefern wird. Man könnte auch einen anderen fest eingestellten Festspannungsregler verwenden, nur hatte ich den L200 gerade vorrätig und ich befand es für eine gute Gelegenheit ihn mal vorzustellen. Die Taster sowie die I2C-Schnittstelle werden in diesem Tutorial nicht verwendet und können weg gelassen werden. Auch der Reset-Taster ist nicht zwingend notwendig.
Stückliste
SMD |
Print |
Wert |
Beschreibung |
Einheit |
|
X3 |
7-12V |
Spannungsversorgung |
|
|
LCD1 |
|
Grafik-LCD |
|
|
R4 |
20k |
Kontrasteinstellung |
|
|
R2 |
680Ω |
|
Festspannung |
|
R3 |
820Ω |
|
Festspannung |
|
IC4 |
L200 |
|
Festspannung |
|
C1 |
470μF/50V |
|
Gleichrichtung |
|
C2 |
100nF/50V |
|
|
|
B1 |
|
Brückengleichrichtung |
Gleichrichtung |
LED2 |
LED1 |
|
Betriebsspannung |
|
R5 |
R11 |
|
Vorwiderstand LED |
|
|
IC1 |
ATMega16 |
|
|
C5/C6 |
C3/C4 |
100nF |
|
|
|
S6 |
|
Reset |
|
R9/R10 |
R7/R8 |
|
Pullup |
I2C |
|
X1/X2 |
|
|
I2C |
R1 |
R6 |
12Ω |
Vorwiderstand Bel. |
|
|
S1..S5 |
|
Taster |
|
|
K1 |
|
ISP |
|
Die Anschlüsse
X3
X3 ist der Anschluss für die Spannungsversorgung. Die Eingangsspannung darf zwischen 7 über 12 Volt liegen. Ob Wechsel- oder Gleichspannung und die Polarität ist bei voller Beschaltung egal. Wer nur mit Gleichspannung arbeiten möchte kann den Brückengleichrichter B1 und den Glättungskondensator C1 weg lassen und entsprechend überbrücken. Dann ist aber besonders auf die Polarität zu achten, denn eine verpolter L200 ist ein toter L200
K1
Die ISP-Schnittstelle wird benötigt um den ATMega16 zu programmieren. Die Pinbelegung ist identisch mit der Pinbelegung des "ISP10PIN" auf dem Entwicklungsboard STK500 von Atmel.
Das STK500 und das GLCD-Board können also mit einem einfachen 10-adriges Flachkabel verbunden werden.
Da der Festspannungsregler vom STK500 nicht rückgespeist werden darf, ist der Jumper "VTARGET" (des STK500) zu öffnen.
X1 / X2
Das I²C-Interface wird in diesem Tutorial nicht behandelt und kann zusammen mit R7 - R10 entfallen.
Schaltplan
Der Schaltplan wurde mit EAGLE von CadSoft entworfen und steht als *.sch zum download bereit.
Layout
Auch das Layout wurde mit EAGLE von Cadsoft entworfen. Es steht als *.jpg und als *.brd zum download bereit.
EAGLE - Bibliotheken
Einige Bauteile wurden von mir selbst entworfen, darunter auch das Display und die ISP-Schnitstelle. Die entsprechenden Bibliotheken liegen wie immer zum download bereit. Sollten noch weitere Bauteile fehlen schreibt mir einfach eine Mail an Info@HarryGr.de!
Hinweise
- Das Display hat 4 Halblöcher zur Befestigung. Ursprünglich wollte ich mit M2-Abstandshaltern arbeiten, doch da diese sehr schwer in Kleinstmengen zu bekommen sind, schwebt mein Display noch immer einfach frei herum.
- Der Festspannungsregler sollte gekühlt werden. Bei 12V stellen sich rechnerisch 95°C ein, was noch im Rahmen wäre aber doch schon sehr weh tun kann.
Die Software des Atmel
Das Display soll einen wieder verwendbaren Code bekommen und wird deshalb in einer separaten Datei gekapselt. Alle Befehle und Variablen bekommen den Suffix LCD_. Um sicher zu stellen das keine anderen Programmteile beeinträchtig werden, wird von allen verwendeten Variablen der Speicher auf den Stack gelegt, um sie, nach Beenden der Funktion, wieder herstellen zu können.
Um Befehle an das Display zu senden, legt man HIGH an Pin A0, danach gibt man das Byte des Befehls am Datenport aus und zieht E1 und E2 kurz auf Masse. Das Datenbyte wird in unserem Fall im Register Temp erwartet.
LCDctrlout:
cbi LCD_cntr,A0
out LCD_data,Temp
cbi LCD_cntr,E1
cbi LCD_cntr,E2
sbi LCD_cntr,E1
sbi LCD_cntr,E2
ret
Daten werden auf ähnliche Weise gesendet. Der Unterschied ist nur, dass man vorher A0 setzten muss und dann nur eine Displayhälfte abspricht.
LCDdata1out:
sbi LCD_cntr,A0
out LCD_data,Temp
cbi LCD_cntr,E1
sbi LCD_cntr,E1
ret
LCDdata2out:
sbi LCD_cntr,A0
out LCD_data,Temp
cbi LCD_cntr,E2
sbi LCD_cntr,E2
ret
Das Display muss, bevor es verwendet werden kann, initialisiert werden. Dies geschieht durch den LCD_RESET-Befehl. Obwohl danach eine ganze Menge Einstellungen auf Standartwerte gesetzt sein sollten, wird immer wieder empfohlen alle Parameter zu initialisieren.
LCD_Startup:
push Temp
rcall LCD_Portinit
ldi temp,LCD_RESET
rcall LCDctrlout
ldi temp,LCD_SET_ADR
rcall LCDctrlout
ldi temp,LCD_ADC+LCD_ADC_CW
rcall LCDctrlout
ldi temp,LCD_DUTY +1
rcall LCDctrlout
ldi temp,LCD_END
rcall LCDctrlout
ldi temp,LCD_ON
rcall LCDctrlout
rcall LCD_Clear
pop temp
ret
Da man bei diesem Display keine Daten auslesen kann, muss ein Bildpuffer im ATMega16 umgesetzt werden, in dem das dargestellte Bild 1:1 gespeichert ist. Da das Display 122x32 Pixel hat, brauchen wir 488 Bytes Speicher. Dieser Speicher muss nicht remanent sein und könnte unter Umständen sehr oft beschrieben und gelesen werden. Deshalb wählen wir den SRAM des Controllers. Aus Kompatibilitätsgründen beginnen wir unseren Bildpuffer bei 0x0100. Er endet demnach bei 0x02E7. Der Speicher wird in vier Zeilen geteilt, ähnlich wie die Pages des Displays.
Mit LCD_Clear werden der Buffer und das Display sicher gelöscht, da sich anderenfalls noch Datenmüll im RAM des Displays und des Controllers befinden könnte.
LCD_Clear:
push Temp
push Temp2
clr Temp2 ;Leer für den Speicher
ldi ZH,HIGH(LCD_Zeile1)
ldi ZL,LOW(LCD_Zeile1)
ldi Temp,122 ;Counter
st Z+,Temp2
dec Temp
brne PC-2
ldi ZH,HIGH(LCD_Zeile2)
ldi ZL,LOW(LCD_Zeile2)
ldi Temp,122 ;Counter
st Z+,Temp2
dec Temp
brne PC-2
ldi ZH,HIGH(LCD_Zeile3)
ldi ZL,LOW(LCD_Zeile3)
ldi Temp,122 ;Counter
st Z+,Temp2
dec Temp
brne PC-2
ldi ZH,HIGH(LCD_Zeile4)
ldi ZL,LOW(LCD_Zeile4)
ldi Temp,122 ;Counter
st Z+,Temp2
dec Temp
brne PC-2
pop Temp2
pop Temp
rcall LCD_Ausgeben ;Leeren RAM auf das Display ausgeben
ret
Mit LCD_Ausgeben wird der gesamte Bildpuffer auf das Display ausgegeben.
LCD_Ausgeben:
push Temp
push Temp2
ldi temp,LCD_PAGE + 0 ;Zeile 1 des LCD
rcall LCDctrlout
ldi temp,LCD_SET_ADR ;erstes Zeichen
rcall LCDctrlout
ldi XH,HIGH(LCD_Zeile2) ;Zeile 1 im SRAM
ldi XL,LOW(LCD_Zeile2) ;(es wird Rückwärts gezählt!)
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 1 Rechts ausgeben
rcall LCDdata2out
dec Temp2
brne PC-3
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 1 Links ausgeben
rcall LCDdata1out
dec Temp2
brne PC-3
ldi temp,LCD_PAGE + 1
rcall LCDctrlout
ldi temp,LCD_SET_ADR
rcall LCDctrlout
ldi XH,HIGH(LCD_Zeile3)
ldi XL,LOW(LCD_Zeile3)
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 2 Rechts
rcall LCDdata2out
dec Temp2
brne PC-3
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 2 Links
rcall LCDdata1out
dec Temp2
brne PC-3
ldi temp,LCD_PAGE + 2
rcall LCDctrlout
ldi temp,LCD_SET_ADR
rcall LCDctrlout
ldi XH,HIGH(LCD_Zeile4)
ldi XL,LOW(LCD_Zeile4)
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 3 Rechts
rcall LCDdata2out
dec Temp2
brne PC-3
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 3 Links
rcall LCDdata1out
dec Temp2
brne PC-3
ldi temp,LCD_PAGE + 3
rcall LCDctrlout
ldi temp,LCD_SET_ADR
rcall LCDctrlout
ldi XH,HIGH(LCD_NachBuffer)
ldi XL,LOW(LCD_NachBuffer)
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 4 Rechts
rcall LCDdata2out
dec Temp2
brne PC-3
ldi Temp2,61 ;Counter
ld Temp,-X ;Zeile 4 Links
rcall LCDdata1out
dec Temp2
brne PC-3
pop Temp2
pop Temp
ret
Zu guter Letzt eine Funktion die den SRAM füllt, und zwar mit Daten aus dem EEProm. Man hätte die Daten auch direkt aus dem EEProm auf das Display ausgeben können, doch um späteren Funktionen eine brauchbare Basis zu liefern, puffern wir das Bild. Im EEProm sind die Daten genau so arrangiert wie im SRAM, können also 1:1 übernommen werden. Das Bild beginnt bei 0x00.
LCD_vom_EEPROM:
push Temp
push Temp2
push r19
push r20
push r21
clr r20
clr r19
ldi ZH,HIGH(LCD_Zeile1)
ldi ZL,LOW(LCD_Zeile1)
ldi Temp2,122 ;Counter
rcall EEPROM_read
st Z+,Temp
ldi r21,1
clr Temp
add r19,r21
adc r20,Temp
dec Temp2
brne PC-7
ldi ZH,HIGH(LCD_Zeile2)
ldi ZL,LOW(LCD_Zeile2)
ldi Temp2,122 ;Counter
rcall EEPROM_read
st Z+,Temp
ldi r21,1
clr Temp
add r19,r21
adc r20,Temp
dec Temp2
brne PC-7
ldi ZH,HIGH(LCD_Zeile3)
ldi ZL,LOW(LCD_Zeile3)
ldi Temp2,122 ;Counter
rcall EEPROM_read
st Z+,Temp
ldi r21,1
clr Temp
add r19,r21
adc r20,Temp
dec Temp2
brne PC-7
ldi ZH,HIGH(LCD_Zeile4)
ldi ZL,LOW(LCD_Zeile4)
ldi Temp2,122 ;Counter
rcall EEPROM_read
st Z+,Temp
ldi r21,1
clr Temp
add r19,r21
adc r20,Temp
dec Temp2
brne PC-7
pop r21
pop r20
pop r19
pop Temp2
pop Temp
rcall LCD_Ausgeben
ret
Die Software des PC
Es werden mehrere Programme auf dem PC benötigt:
- Grafikprogramm
um ein Bild zu erstellen, welches auf dem Display ausgegeben wird
- Programmer und Flasher
um den Quellcode zu bearbeiten und auf den Atmel zu übertragen
- Konverter
um das Bild in ein Format zu wandeln, welches sich in den EEProm laden lässt
- Optional das CAD-Programm EAGLE von CadSoft
Grafikprogramm
Es können so ziemlich alle erhältlichen Grafikprogramme verwendet werden, sogar das hypergeile "MS Paint". Wichtig ist nur, dass man eine Bitmap (BMP) mit einer Auflösung von 122*32 Pixel und 1 Bit Farbtiefe speichern kann.
Konverter
Der Konverter wird benötigt um das Bild so zu übersetzten dass es der EEProm aufnehmen kann. Bei dem Entwicklungsboard STK500 von Atmel wird die Programmiersoftware "AVR-Studio" mitgeliefert welche die Flash-Software "STK500" beinhaltet. Mit ihr können textbasierte *.Hex-Files in den EEProm übertragen werden, welche eine spezielle Anordnung der Daten zwischen Adressen und Prüfsummen erwartet. Um solch ein Hex-File zu erzeugen wurde ein spezieller Konverter programmiert, welcher im Zuge dieses Tutorials zur Verfügung gestellt wird.
Programmer
Ich verwende das AVR-Studio von Atmel. Da ich keine Erfahrung mit anderen Programmern habe, kann ich auch nicht sagen ob andere verwendet werden können. Auf jeden Fall wird hier in Assembler programmiert.
Flasher
Auch hier benutze ich das original STK500 von Atmel. Und auch hier möchte bitte jeder selber prüfen ob sein Flasher meine Daten übertragen kann. Insbesondere das File welches das Bild enthält sollte auf Kompatibilität geprüft werden.
Das Board wird per "In-System Programming" geflasht. Das heißt, dass der Atmel im Board (also im System) sitzen bleiben kann, während er geflasht wird. Der Atmel soll mit 8MHz internem RC-Takt laufen. Dies wird per Fuse-Bits eingestellt und kann nur außerhalb des Systems geschehen, denn vom LCD-Board erhält er keinen Takt und wenn er auf einen externen Takt eingestellt ist macht er schlichtweg gar nichts.
Download
Das auf www.HarryGr.de zur Verfügung gestellte ZIP-File enthält folgende Teile:
- ASM
Assembler-Code und Hexfile, welche das Programm enthalten
- EAGLE
Der Schaltplan, das Layout, ein Bild vom Layout und ein paar Bibliotheken
- Konverter
Ein kleines, sehr einfaches Programm zum umwandeln eines Bildes in ein Hex-File, ein Bild sowie das bereits gewandelte Bild
|
|