Proog

Sparschaltung - Ansteuerung eines 128x64 Pixel LCD mit KS0108 Controller mit PWM Ladungspumpe für negative Kontrastspannung

 lcd

 

Pollin bietet derzeit für knapp 8 Euro ein 128*64 Pixel grafisches Display mit KS0108 Controller an. Die Textfarbe erscheint schwarz auf hellgrauem Hintergrund. Zudem gibt es eine stromsparende weiße LED Hintergrundbeleuchtung.

Das Display benötigt zum Betrieb eine negative Spannung im Bereich 0..-5V zur Einstellung des Kontrasts.

 

foto lcd

 

Die vorliegende Sparschaltung treibt mit einem PWM-Ausgang des AVR eine Ladungspumpe zur Erzeugung der negativen Spannung an. Hierfür genügen zwei Dioden (BAT43 oder vergleichbare Schottky-Dioden) und zwei 100nF Kondensatoren als externe Bauteile. Die Kontrastspannung lässt sich mit Veränderung der PWM-Frequenz einstellen.

 

Die Einstellung der Kontrastspannung erfolgt mit der Funktion:

void glcdContrast (int contrast);

Kleine Zahlenwerte stehen für eine hohe Frequenz und starken Kontrast. Da die Kondensatoren mit 100nF sehr klein gewählt sind, benötigt die Schaltung eine hohe PWM-Frequenz.

 

Der Treiber erzeugt ein Rechtecksignal wahlweise auf OC1A (16 Bit Counter) oder OC2A (8 Bit Counter).

Will man OC2A verwenden, so ist zu beachten, dass die Verbindung zum Kondensator getrennt werden muss, wenn man den AVR per ISP programmiert, z.B. mit einem Jumper.

 

Bei Verwendung von OC1A und 5.0 Volt Versorgungsspannung erzeugt die Schaltung folgende Spannungswerte, gemessen mit LCD als Last:

PWM Frequenz

LCD-Spannung

Kontrast

glcdContrast(128)

- 3.0V

sehr schwach, Schrift nicht lesbar

glcdContrast(32)

- 4.0V

gut, schwarze Schrift auf weißem Grund

glcdContrast(4)

- 4.3V

etwas zu stark, Hintergrundpixel werden dunkel und sichtbar

 

Interface

Die Datenleitungen D0..D7 des LCD sind mit einem Port des AVR zu verbinden. Bei der Beispielschaltung mit ATmega328p wird PORTD verwendet.

Der Treiber setzt voraus, dass die Steuerleitungen für das LCD ebenfalls alle auf einem Port des AVR liegen. Bei der Beispielschaltung wird PORTC genutzt. Die R/W Leitung zum LCD ist im Headerfile definiert, das LCD wird mit dieser Treiberversion jedoch nur beschrieben, nicht gelesen.

 

Zur Ansteuerung werden die folgenden vier Leitungen genutzt:

LCD-D/I Adresse Data / Instruction Register

LCD-CS1 Chip Select 1 (rechte Hälfte des LCD)

LCD-CS2 Chip Select 2 (linke Hälfte des LCD)

LCD-E Enable Signal

 

Die Reset-Leitung des LCD liegt mit einem Pullup-Widerstand (z.B. 10K) an 5V. Auf dem Testboard ist ein 100K Widerstand eingesetzt, der ebenfalls funktioniert.

Die negative -5V Kontrastspannung wird mit einer Ladungspumpe erzeugt. Das erforderliche Rechtecksignal erzeugt wahlweise Pin PB1 (OC1A) oder PB3 (OC2A).

 

Testaufbau:

foto platine

 

Die Schaltung für die Ladungspumpe findet Ihr auf Wikipedia unter dem Stichwort Spannungsinvertierung:

Externer Link zu Wikipedia: hier

 

Schaltplan:

schematic

 

Textausgabe

Der Treiber enthält einen 5x8 Pixel ASCII Zeichensatz (Code 0..127, keine Umlaute) zur Textausgabe auf dem LCD. Der Zeichensatz liegt im Flash und belegt keinen RAM. Die Zeichen können wahlweise mit 5 oder 6 Pixel Breite ausgegeben werden, so dass 20*8 oder 24*8 Zeichen auf das Display passen. Die Zeichenausgabe ist in die printf() Funktion eingebunden.

 

Bei 20*8 Zeichen Betrieb wird jedes 5 Pixel breite Zeichen mit einer zusätzlichen Leerspalte ausgegeben. In der Betriebsart 24*8 Zeichen erfolgt die Ausgabe ohne zusätzliche Leerspalte. Da die meisten Buchstaben 4 Pixel breit sind, ist der Text trotzdem lesbar (siehe Foto: The quick brown fox...).

Bei gesetztem Bit7 (Zeichencode 128-255) werden die Zeichen invers dargestellt.

 

Grafikausgabe

Der Treiber greift ausschließlich schreibend auf das LCD zu. Echte Grafikfunktionen (z.B. putpixel) sind deshalb nicht implementiert, hierfür wäre weiterer Aufwand erforderlich, z.B. lesender Zugriff auf den LCD Grafikspeicher oder ein Grafikbuffer im RAM des uC.

 

Grafiken können trotzdem einzeln - Byte für Byte - auf dem LCD ausgegeben werden. Das Byte wird an der aktuellen Cursorposition vertikal gezeichnet, das LSB liegt dabei oben. Text kann mit Grafik gemischt werden, da beide jeweils an der Cursorposition zeichnen beziehungsweise schreiben.

Am Ende einer Zeile stopt die Ausgabe. Es gibt keinen automatischen Zeilenumbruch.

 

Funktionsübersicht

 

void glcdInit (void);

LCD Controller initialisieren

void glcdContrast (int contrast);

PWM Frequenz einstellen

void glcdLocate(unsigned char row, unsigned char col);

Cursor auf LCD positionieren (row=0..7, col=0..127)

void glcdPutByte(char dat);

Ein Byte an Cursorposition ausgeben

void glcdClrRow(char row);

Eine Zeile löschen (0..7)

void glcdCls(void);

Bildschirm löschen

void glcdPutc(char c);

Ein Zeichen an Cursorposition ausgeben, wird von printf() genutzt

 

 

Datei glcd_ks0108.h

 

Folgende Zeilen dienen der Auswahl des Counters für die Ladungspumpe der LCD Kontrastspannung (Pin PB1 - OC1A) oder PB3 - OC2A):

 

#define glcdContrastPwmOC1A

#define glcdContrastPwmOC2A

 

Die Auswahl der Zeichenbreite (5 oder 6 Pixel) entscheidet, wieviel Zeichen in eine Zeile passen. Bei einer Breite von 6 Pixel wird jeweils eine Leerspalte zwischen den Zeichen eingefügt.

 

static unsigned char glcdCharWidth=6; // 5=narrow, 6=normal

 

Um die Ausgabe von 20 oder 24 Zeichen zu zentrieren, wird eine neue Zeile per Default an der 4. Spalte begonnen. Man kann den linken Rand auf Spalte 0 setzen, um jeweils 1 Zeichen mehr auf den Bildschirm zu schreiben. Bei Ausgabe eines Zeilenumbruchs mit printf() wird der Cursor auf den eingestellten linken Rand gesetzt (Beispiel: printf("\n");)

Der eingestellte linke Rand hat keinen Einfluss auf die Cursorpositionierung mit glcdLocate(). Mit "glcdLocate(0, glcdLBorder);" setzt man den Cursor für die Textausgabe auf die "home" Position.

 

static unsigned char glcdLBorder=4; // first character left position for text output

 

Einfacher Testaufbau

 

Das folgende Bild zeigt einen einfachen Testaufbau. Die Schaltung passt komplett hinter die LCD-Platine.

 

foto platine 2

 

Gelb

ISP Programmieranschluss

Blau

Jumper zur Auswahl von Pin PB1 - OC1A) oder PB3 - OC2A

2 Dioden und 2 Kondensatoren bilden die Ladungspumpe

Grau

Abblockkondensatoren an VCC und AVCC.

Ein Kondensator an AREF

Rot

Reset Widerstand für LCD

Grün

Jumper für Hintergrundbeleuchtung mit optionalem Widerstand 100R in Serie an 5V

 

 

Anschluss des LCD an den AVR Mikrocontroller

 

Pinout ATmega328p

 

Left side:

 

 

1

(PCINT14/RESET) PC6

ISP

2

(PCINT16/RXD) PD0

LCD-D0

3

(PCINT17/TXD) PD1

LCD-D1

4

(PCINT18/INT0) PD2

LCD-D2

5

(PCINT19/OC2B/INT1) PD3

LCD-D3

6

(PCINT20/XCK/T0) PD4

LCD-D4

7

VCC

 

8

GND

 

9

(PCINT6/XTAL1/TOSC1) PB6

Q

10

(PCINT7/XTAL2/TOSC2) PB7

Q

11

(PCINT21/OC0B/T1) PD5

LCD-D5

12

(PCINT22/OC0A/AIN0) PD6

LCD-D6

13

(PCINT23/AIN1) PD7

LCD-D7

14

(PCINT0/CLKO/ICP1) PB0

 

 

 

 

Right side:

 

 

28

PC5 (ADC5/SCL/PCINT13)

LCD-R/W (not used)

27

PC4 (ADC4/SDA/PCINT12)

LCD-D/I

26

PC3 (ADC3/PCINT11)

LCD-CS1

25

PC2 (ADC2/PCINT10)

LCD-CS2

24

PC1 (ADC1/PCINT9)

LCD-E

23

PC0 (ADC0/PCINT8)

LCD-RST (not used)

22

GND

 

21

AREF

 

20

AVCC

 

19

PB5 (SCK/PCINT5)

ISP

18

PB4 (MISO/PCINT4)

ISP

17

PB3 (MOSI/OC2A/PCINT3)

ISP / LCD-Contrast,

-5V Charge Pump

16

PB2 (SS/OC1B/PCINT2)

 

15

PB1 (OC1A/PCINT1)

LCD-Contrast,

-5V Charge Pump

 

Beispiel: Hier ist der kontrast zu schwach eingestellt auf den Wert 128:

foto lcd

 

Maximal eingestellter Kontrast:

foto lcd

 

Von diesem Zeichensatz sind die Codes 0-127 in den Treiber übernommen, also die obere Hälfte:

Zeichensatz

 

Das Projektverzeichnis mit den C-Quellcodes findet sich im Download-Bereich unter der Kategorie Microcontroller.