Ansteuerung von LCD-Modul, Textausgabe, Zahlenausgabe
Programmierkurs für PIC-Mikrocontroller in C (CC5X Compiler) Teil 6


Bei programmieren eines Mikrocontrollers ist es seltsam das es kein Print- Befehl gibt. Wen man mit einer neuer Programmiersprache anfängt lernt man als erstes Ausgabebefehle und Eingabebefehle. Mikrokontroller hat keine Ein/Ausgabegeräte. Deswegen wollen wir ein anschlissen. In frage kommen dabei: Pesowandler, LEDs, Siebensegment-Anzeigen, LCD. Aber als Preisgünstigste und dabei mit fielen Einsatzmöglichkeiten haben sich Alphanumerische LCD Displays erwiesen. Ich benutze LCD 162F (LED LCD-MODUL 16X2 M.BEL. für 18.65 Euro bei Reichelt).Wen es um messen geht, kann man Zahlen mit viel stellen und Messeinheiten anzeigen. Auch Menüs und kurze Mitteilungen lassen sich bequem mit LCD-Anzeige ausgeben.
Diese LCD- Modul hat einen HD44780 Controller, der ist in letzte Zeit Standard Controller für LCD-Displays geworden. LCD-Modul hat 8 Datenleitungen, und 3 Steuerleitungen CS, RS, R/W. LCD-Module können im 4Bit-Modus arbeiten, dabei werden 4 Datenleitungen, CS(Clock),RS(Befehl/Zeichen) benutzt. Bei einem Mikrocontrollerport sind dann noch 2 Pins für andere Zwecke verwendbar.
Im WWW gibt es einige Programme zum Ansteuerung von LCD-Module im Assembler und C. Eine davon hat Holger Klabunde geschrieben. Sein Quellcode musste ich an einigen stellen verändern, um es auf dem PIC16F84 (4MHz) und PIC16F871(20MHz) laufen zu lassen. Außerdem musste bei Initialisierung des LCD ein zusätzlicher Byte rein, sonst ging nicht. Und es ist jetzt möglich beliebige 8Bit-Port des Mikrocontrollers zum Kommunikation mit LCD einzustellen.
Anschlussplan zum Programm. Foto des Versuchsaufbau.
Hier ist Beispielprogramm für PIC16F84.

// Ansteuerung von LCD-Anzeige 4MHz

// Testprogramm

// Michael Dworkin

// 02.06.2003

// Compiler CC5x

 

#include <C:\cc5\16F84.H>

#pragma config |= 0b.1111.1111.0010      // Konfigurations-Wort

 

#define LCD_RS    0b.00000001             //RS-Pin ist Bit0, LCD Register Select

#define LCD_CS    0b.00001000             //E-Pin ist Bit3, LCD Chip Select

#pragma char PORTQ @ PORTB               //PORT auswählen, DB7-Bit7, DB6-Bit6, DB5-Bit5, DB4-Bit4

#include "delay4.c"

#include "lcd.c"

 

void main(void)                          // Hauptprogramm

{

PORTB=0x00;

TRISB=0b00000000;                  //Alles Ausgänge

lcdport=0;

Delay1ms(1000);                    // 1s warten

LCDInit();                         // LSD Initialisieren

anfang:

 

LCDCls();                          // Bildschirm löschen

LCDPos(1,0);                       // Position der ersten Zeichen 1 Zeile, Position 0

LCDString("Programmierer");        // String Anzeigen

LCDPos(2,0);                       // Position der ersten Zeichen 2 Zeile, Position 0

LCDString("Michael Dworkin");      // String Anzeigen

Delay1ms(2000);                    // Warte 2s zeit zum lesen.

 

LCDCls();

LCDPos(1,0);

LCDString("Mischa_D@mail.ru");

LCDPos(2,2);

LCDString("CC5X.DE.VU");

Delay1ms(2000);

 

LCDCls();                          // Umlaute Testen

LCDPos(2,3);                       // Zeile 2, Position 3

LCDString("ÜüÄäÖöß");

Delay1ms(2000);

goto anfang ;

}

Am Anfang des Programms wird 1sekunde abgewartet, das ist eigentlich nicht nötig. Wenn man unterschiedliche Texte ausgibt, darf man nicht vergessen vorher zu löschen, sonst werden Texte überlappen. Man kann löschen ganze Bildschirm oder nur Bereich wo neue Text erscheinen soll. Kann sein dass bei erstem Einschalten LCD-Bildschirm nichts zeigt, versuchen Sie Helligkeit mit dem Potentiometer einzustellen.

LCD-Ansteuerung mit PIC16F871 bei Quarzfrequenz 20MHz
Hauptprogramm bleibt die gleiche. Anstatt des PortB wird, zu Kommunikation mit LCD, PortD benutzt. Treiber für LCD bleibt der gleiche "lcd.c". Nur Unterprogramm für Zeiterzögerung "delay4.c" muss man für 20MHz benutzen "delay20.c". Hier ist Anschlussplan. Hier eine Foto meiner Testplatine für PIC16F871.

 

// Ansteuerung von LCD-Anzeige

// Testprogramm

// Michael Dworkin

// 02.06.2003

// Compiler CC5x

 

#include <C:\cc5\16F871.H>

// Speihersutz121345=aus,Debug11=aus,ProgrammFlash9=an,EEpromRead8=an,NiendervoltProgr7=aus

// NiederVoltReset6=an,EinschaltTimer3=an,WachDogTimer2=aus,Oszilator01=HC

#pragma config |= 0b.11.111101.11.00.10

 

#define LCD_RS    0b.00000001             //RS-Pin ist Bit0, LCD Register Select

#define LCD_CS    0b.00001000             //E-Pin ist Bit3, LCD Chip Select

#pragma char PORTQ @ PORTD               //PORT auswählen, DB7-Bit7, DB6-Bit6, DB5-Bit5, DB4-Bit4,

#include "delay20.c"

#include "lcd.c"

 

 

void main(void)                          //  Hauptprogramm

{

TRISD=0b00000000;                        //Alles Ausgänge

PORTD=0x00;

lcdport=0;

LCDInit();

anfang:

 

LCDCls();

LCDPos(1,0);

LCDString("Programmierer");

LCDPos(2,0);

LCDString("Michael Dworkin");

Delay1ms(2000);

 

LCDCls();

LCDPos(1,0);

LCDString("Mischa_D@mail.ru");

LCDPos(2,2);

LCDString("CC5X.DE.VU");

Delay1ms(2000);

 

LCDCls();

LCDPos(2,3);

LCDString("ÜüÄäÖöß");

Delay1ms(2000);

goto anfang ;

}


Außerdem PIC16F871 hat 8 AD- Wandlern und hat Möglichkeit sein Festwertspeicher zu beschreieben. Auf dieser Platine sehen Sie ein PS/2-Anschluss. Ich habe ein Programm geschrieben, welche ermöglicht eine Tastatureingabe.


Messwerte auf LCD ausgeben

Wie kann ich Inhalt einer Variable als Zahl auf LCD darstellen?

Ich habe Unterprogramm geschrieben die Inhalt einer Integer-Variable auf dem LCD-Bildschirm darstellt .
Es wird 5-stellige Zahl ausgegeben. Die Nullen vorne sind durch Leerzeichen ersetzt.
Zum Beispiel: Zahl 587 wird so angezeigt "__587" , Zahl 3 - "____3", Zahl 12345 - "12345"
Wenn Sie genau wissen Stellenanzahl Ihrer ausgegebener Zahl, dann können Sie Anzahl auszugebenen Stellen einstellen in dem Sie Variable "Dez" mit kleinerem Wert laden. Bei 2 Stellen Dez=10 (Zahlen bis 99), Bei 3 Stellen Dez=100 (Zahlen bis 999), und so weiter.
Wenn Nullen links(nicht besetzte stellen vor der Zahl) erwünscht sind dann ersetzen Sie k=0 gegen k=1.

// Ansteuerung von LCD-Anzeige
// Testprogramm für Zahlenausgabe
// Michael Dworkin
// 26.03.2004
// Compiler CC5x

#include <d:\cc5\16F871.H>
#pragma config |= 0b.11.111101.11.00.10
#pragma origin 100                  // Ab Adresse 100 im Programmspeicher
#define LCD_RS  0b.00000001         // RS-Pin ist Bit0, LCD Register Select
#define LCD_CS  0b.00001000         // E-Pin ist Bit3, LCD Chip Select
#pragma char PORTQ @ PORTD          // PORT auswählen, DB7-Bit7, DB6-Bit6, DB5-Bit5, DB4-Bit4,
#include "delay20.c"
#include "lcd.c"

void LCDStringExtra(const char *__putstr,uns16 Zeit)
{
    char __ps;
    __ps = *__putstr;
    while(__ps>0)
    {
        __putstr++;
        if (__ps== 0) break;
        LCDWriteChar(__ps);
        Delay1ms(Zeit);
        __ps = *__putstr;
    }
}

//******* Unterprogramm zum Anzeigen von 16Bit Zahlen auf LCD *****************

void ZalString(uns16 z)
{
    uns16 i,temp,Dez;
    bit k;                      // Merker ob vorne 0 ist
    k=0;
    Dez=10000;                  // Dezimalstellen, z.B. bei 2 Stellen 10 eintragen
    while (Dez)                 // Solange Dezimalstelle nicht 0 ist
    {
        if(Dez==1) k=1;         // Um ein einzige 0 anzeigen können
        i=z/Dez;                // Wert der jeweilige Dezimalstelle bestimmen
        temp=i*Dez;
        z=z-temp;
        if(i||k)                // Damit wir vorne keine Nullen stehen haben.
        {
            LCDWriteChar((char)i+0x30);
            k=1;                // es gab schon eine Zahl die nicht 0 ist
        }
        else                    // wen 0 ist und vorne keine Zahl war, dann
        {
            LCDWriteChar(' ');  // Leerzeichen ausgeben
        }
        Dez=Dez/10;
    }
}

//*******************************************************
// Hauptprogramm
//*******************************************************
void main()
{
    TRISD=0b00000000;       // Alles Ausgänge
    PORTD=0x00;
    lcdport=0;
    Delay1ms(1000);         // 1s abwarten
    LCDInit();              // LCD Initialisieren

    LCDCls();               // Bildschirn löschen
    LCDPos(1,0);            // Position des Textes
    LCDString("Test für Zahlen");   // Text ausgeben
    uns16 X;
    X=0;
    while(1)                // Endlosschleife
    {
        LCDPos(2,0);        // Position der Zahl
        ZalString(X);       // Zahl ausgeben
        X++;                // Hier wird jede 0,5s hochgezählt
        Delay1ms(500);      // 0,5s abwarten
    }
}

Theorie: Wie funktioniert das ?
Wenn man etwas misst und Ergebnisse auf LCD anzeigen möchte, muss man aus Integer - Variable 3 Zeichen bilden.
Zum Beispiel wir wollen Zahl 136 darstellen.
Dafür muss man "1", "3", "6" zum LCD senden. Nach ASCII-Tabelle entsprechen diesen Zeichen folgende ASCII-Code: 49, 51, 54. Wenn wir diese zahlen nacheinander zum LCD senden bekommen wir 136 angezeigt.
Zuerst müssen wir ein Weg finden Zahl 136 auf Dezimalstellen zu zerlegen.
Wir nennen Variablen wie Dezimalstellen:
Hundert
Zen
Eins
Temp - als Zwischenablage

Berechnen:
Hundert = 136/100 =1
Temp = 136 - Hundert * 100 = 36
Zen = Temp/10 =3
Eins = Temp - Zen * 10 = 6

Jetzt haben wir:
Hundert =1
Zen =3
Eins = 6

Und wie kommen wir zu ASCII-Code?
Ganz einfach: wir addieren zu unseren Variablen Zahl 48 !
Hundert = Hundert + 48
Zen = Zen + 48
Eins = Eins + 48

48+1=49
48+3=51
48+6=54

Letzte Änderung 16.06.04