www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Ansteuerung eines DOGM-LCD mit Atmega8 Hardware SPI


Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bemühe mich gerade ein DOGM163 LCD-Display via SPI laufen zu lassen.
Als SPI-Master verwende ich einen Atmega8 genauer dessen Hardware SPI.

Die Hardware Verschaltung ist folgende:
Atmega     --> DOGM
PB3 (MOSI) --> SI  (Pin28)
PB5 (SCK)  --> CLK (Pin29)
PB7        --> CSB (Pin38)
PB6        --> RS  (Pin39)

Mit folgenden Code-Zeilen gelingt es mir sogar tatsächlich das LCD zu 
initialisieren ;-)
#include </usr/lib/avr/include/avr/io.h>
#include </usr/lib/avr/include/avr/iom8.h>
#include <util/delay.h>

void SPI_MasterInit(void)
{
    /* Set MOSI and SCK output, all others input */
    DDRB = (1<<DDB3)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7);
    /* Enable SPI, Master, set clock rate fck/16 */
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(char cData)
{
    /* Start transmission */
    SPDR = cData;
    /* Wait for transmission complete */
    while (!(SPSR & (1<<SPIF)))
        ;
}

int main(void)
{
    PORTB = (0<<DDB7);
    _delay_ms(200);

    SPI_MasterInit();
    _delay_ms(10);

    SPI_MasterTransmit(0x39);
    _delay_ms(10);

    SPI_MasterTransmit(0x1D);
    _delay_ms(10);

    SPI_MasterTransmit(0x50);
    _delay_ms(10);

    SPI_MasterTransmit(0x6C);
    _delay_ms(10);

    SPI_MasterTransmit(0x7C);
    _delay_ms(10);

    SPI_MasterTransmit(0x38);
    _delay_ms(10);

    SPI_MasterTransmit(0x0F);
    _delay_ms(10);

    SPI_MasterTransmit(0x01);
    _delay_ms(10);

    while (1)
        asm volatile ("nop");
    ;

    return 0;
}

Dadurch erhalte ich einen blinkenden Kursor an erster Stelle der ersten 
Zeile freu

Jetzt zu meinem Problem:

Wie kann ich nun ASCII-Zeichen an das LCD übergeben, um diese dann auch 
an zu zeigen?

Ich habe mich dazu schon durch einige Beiträge und viele Zeilen 
C-Quellcode gelesen doch ein konkretes Beispiel für den Hardware SPI des 
Atmega habe ich leider genau so wenig gefunden, wie eine Schematische 
Beschreibung des Vorganges "Zeichen an LCD übergeben".

Ich würde mich sehr freuen, wenn mir dazu jemand einen Konstruktiven 
Tipp geben könnte.

Gruß Michael

Autor: Thilo M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck' mal hier:
Beitrag "Dog-M / ST7036 Routine für 1-Zeiliges Display SPI-Mode"

Da ist von mir ein Treiber drin, mit Anschlussbeschreibung des Displays. 
;-)

Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Thilo,

danke für die klasse Arbeit, die du schon gemacht hast!

Da du offensichtlich ziemlich gut in die Materie eingearbeitet bist 
hätte ich eine kleine bitte:
Beschreibe mal den prinzipiellen Ablauf, wenn ich Zeichen via SPI auf 
dem LCD Ausgeben möchte.

vorab schon Danke dafür.

Autor: Thilo M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:
> Beschreibe mal den prinzipiellen Ablauf, wenn ich Zeichen via SPI auf
> dem LCD Ausgeben möchte.

AAhhh, ich bin wieder in der Schule!!!  :-))

Zur Sache: ist doch einfach,
- RS auf 'high'
- das Zeichen 'rausschieben (SPDR zuweisen)
- 100µs warten
- RS kurz auf 'low', dann wieder auf 'high' (toggeln)

fertig.

Ist in meinem Treiber recht einfach beschrieben.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

RS auf H
RW auf L

und ASCII-Zeichen senden.

Fertig.

MfG Spess

Autor: Thilo M. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Die R/W - Leitung kannst du dir sparen, siehe Anschlussbelegung lt. 
Datenblatt.

Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thilo M. schrieb:
>...
> AAhhh, ich bin wieder in der Schule!!!  :-))
>
> Zur Sache: ist doch einfach,
> - RS auf 'high'
> - das Zeichen 'rausschieben (SPDR zuweisen)
> - 100µs warten
> - RS kurz auf 'low', dann wieder auf 'high' (toggeln)
>...

Hey Thilo,

Genau das Waren die Worte bei denen der Groschen bei mir gefallen ist.
Vielen Dank dafür!!!

Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Als kleiner Beweis, dass ich es auch wirklich hinbekommen habe... ;-)

hier mein Code:
#include </usr/lib/avr/include/avr/io.h>
#include </usr/lib/avr/include/avr/iom8.h>
#include <util/delay.h>
#include <string.h>

void SPI_MasterInit(void)
{
    /* Set MOSI and SCK output, all others input */
    DDRB = (1<<DDB3)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7);
    /* Enable SPI, Master, set clock rate fck/16 */
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(char cData)
{
    /* Start transmission */
    SPDR = cData;
    /* Wait for transmission complete */
    while (!(SPSR & (1<<SPIF)))
        ;
}

void init_LCD(void)
{
    PORTB = (0<<DDB7);
    _delay_ms(100);             //Nicht kleiner als 100ms da sonst keine Funkion des LCD!!!
    SPI_MasterInit();
    _delay_ms(10);
    SPI_MasterTransmit(0x39);
    _delay_ms(10);
    SPI_MasterTransmit(0x1D);
    _delay_ms(10);
    SPI_MasterTransmit(0x50);
    _delay_ms(10);
    SPI_MasterTransmit(0x6C);
    _delay_ms(10);
    SPI_MasterTransmit(0x7C);
    _delay_ms(10);
    SPI_MasterTransmit(0x38);
    _delay_ms(10);
    SPI_MasterTransmit(0x0F);
    _delay_ms(10);
    SPI_MasterTransmit(0x01);
    _delay_ms(10);
}

void print_LCD(char* string)
{
    int i;

    for (i=0;i<strlen(string);i++)
    {
        PORTB = (1 << DDB6); // high
        SPI_MasterTransmit(string[i]);
        _delay_ms(3);
        PORTB &= ~(1 << DDB6); //low
        PORTB = (1 << DDB6); // high
    }
}

int main(void)
{
    init_LCD();
    char* string = "Hallo Welt :-)";

    print_LCD(string);

    while (1)
    {
        asm volatile ("nop");
    }
    return 0;
}

Und Leute,... seid gnädig mit mir!

für mich ist das wirklich ein Erfolg... :-)

schönen Abend allerseits

Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Die Problemchen gehen mir nicht aus... ;-)

Ich hatte die Hintergrundbeleuchtung zuerst fest an 5V angeschlossen, da 
mir das aber irgendwann zu grell wurde habe ich mir gedacht, wäre doch 
nett, diese über ein PWM szeuern zu können...
deshalb habe ich sie flux auf PB1 gelötet.
leider mag das nicht so recht funktionieren...
#include </usr/lib/avr/include/avr/io.h>
#include </usr/lib/avr/include/avr/iom8.h>
#include <util/delay.h>
#include <string.h>

void SPI_MasterInit(void)
{
    /* Set MOSI and SCK output, all others input */
Hier kommts...
    DDRB = (1<<DDB3)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7); // DDB6 und DDB7 wegen der Display-verschaltung.
//  DDRB = (1<<DDB1)|(1<<DDB3)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7); // DDB6 und DDB7 wegen der Display-verschaltung.
Wenn ich die momentan auskommentierte Zeile "Aktiviere" die andere 
natürlich "deaktiviere" funktioniert die initialisierung nicht mehr...
    /* Enable SPI, Master, set clock rate fck/16 */
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(char cData)
{
    /* Start transmission */
    SPDR = cData;
    /* Wait for transmission complete */
    while (!(SPSR & (1<<SPIF)));
}

void init_LCD(void)
{
    PORTB = (0<<DDB7);
    _delay_ms(200);             //Nicht kleiner als 100ms da sonst keine Funkion des LCD!!!
    SPI_MasterInit();
    _delay_ms(10);
    SPI_MasterTransmit(0x39);
    _delay_ms(10);
    SPI_MasterTransmit(0x1D);
    _delay_ms(10);
    SPI_MasterTransmit(0x50);
    _delay_ms(10);
    SPI_MasterTransmit(0x6C);
    _delay_ms(10);
    SPI_MasterTransmit(0x7C);
    _delay_ms(10);
    SPI_MasterTransmit(0x38);
    _delay_ms(10);
    SPI_MasterTransmit(0x0C);
    _delay_ms(10);
    SPI_MasterTransmit(0x01);
    _delay_ms(50);
}

void print_LCD(char* string)
{
    int i;
    for (i=0;i<48;i++) // Schreiben von 3x16 = 48 Zeichen auf das LCD
    {
        PORTB = (1 << DDB6); // high
        if (i<strlen(string)) SPI_MasterTransmit(string[i]); // Schreiben des Strings aufs LCD
        else SPI_MasterTransmit(' ');  // Auffüllen der nicht genutzten Zeichen mit ' '
        _delay_ms(2);
        PORTB &= ~(1 << DDB6); //low
        asm volatile ("nop");
        PORTB = (1 << DDB6); // high
    }
}

int main(void)
{
    init_LCD();
    char* string1 = "Hallo Welt :-)";
    char* string2 = "Hallo Welt :-|";
    char* string3 = "Hallo Welt :-?";
    char* string4 = "Hallo Welt :-(";

    while (1)
    {
        print_LCD(string1);
        _delay_ms(50);
        print_LCD(string2);
        _delay_ms(50);
        print_LCD(string3);
        _delay_ms(50);
        print_LCD(string4);
        _delay_ms(50);
    }
    return 0;
}

hat jemand eine Idee dazu?

Autor: Thilo M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast die Beleuchtung direkt an den Portpin gehängt?
Ich weiß nicht, welche Farbe du hast, aber ich denke, der mega8 kann den 
Strom nicht treiben. Du solltest einen Transistor dazwischenschalten.

Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Einwand ist berechtigt!
Ich werde also bei Gelegenheit 'nen Transistor spendieren.

Aber eigentlich müsste ich innerhalb des zulässigen Bereiches sein.
Und es sollte also funktionieren.

Autor: Thilo M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Zeller schrieb:
> Aber eigentlich müsste ich innerhalb des zulässigen Bereiches sein.

Denke ich nicht.
Je nach LED-Farbe haben die Dinger >80mA. Der mega8 kann max. 40mA.

Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jup. Und laut Datenblatt des LCD hat die Hintergrundbeleuchtung eine 
Stromaufnahme von 40mA.

Die Hintergrundbeleuchtung kann ich auch über ein kleines Testprogramm 
einschalten und betreiben....
int main(void)
{
    DDRB = (1<<DDB1)|(1<<DDB3)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7); // DDB6 und DDB7 wegen der Display-verschaltung.
    PORTB = (1<<DDB1);

    while (1)
    {
        asm volatile ("nop");
    }
    return 0;
}

Autor: Thilo M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, so im Grenzbereich würde ich den nicht betreiben.
Aber teste doch erst mal die PWM ohne die Displayansteuerung, also nur 
die Beleuchtung.
Dann sollte es zusammen auch funktionieren.

Autor: Michael Zeller (zellm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast absolut recht, Hintergrundbeleuchtung direkt am Pin des Atmega8 
ist keine Dauerlösung! Werde ich beheben, versprochen ;-)

Ich werde mich also gleich mal an die PWM wagen...

Autor: Juppo Nini (juppo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin an alle

Ich habe das Modul DOG S

Ob dieses mit den gleichen Sourcen läuft wie die DOG M ?

Gruß Juppo

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.