Ansteuerung eines DOGM-LCD mit Atmega8 Hardware SPI

OP #1805064
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 ;-)
1
#include </usr/lib/avr/include/avr/io.h>
2
#include </usr/lib/avr/include/avr/iom8.h>
3
#include <util/delay.h>
4

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

13
void SPI_MasterTransmit(char cData)
14
{
15
    /* Start transmission */
16
    SPDR = cData;
17
    /* Wait for transmission complete */
18
    while (!(SPSR & (1<<SPIF)))
19
        ;
20
}
21

22
int main(void)
23
{
24
    PORTB = (0<<DDB7);
25
    _delay_ms(200);
26

27
    SPI_MasterInit();
28
    _delay_ms(10);
29

30
    SPI_MasterTransmit(0x39);
31
    _delay_ms(10);
32

33
    SPI_MasterTransmit(0x1D);
34
    _delay_ms(10);
35

36
    SPI_MasterTransmit(0x50);
37
    _delay_ms(10);
38

39
    SPI_MasterTransmit(0x6C);
40
    _delay_ms(10);
41

42
    SPI_MasterTransmit(0x7C);
43
    _delay_ms(10);
44

45
    SPI_MasterTransmit(0x38);
46
    _delay_ms(10);
47

48
    SPI_MasterTransmit(0x0F);
49
    _delay_ms(10);
50

51
    SPI_MasterTransmit(0x01);
52
    _delay_ms(10);
53

54
    while (1)
55
        asm volatile ("nop");
56
    ;
57

58
    return 0;
59
}

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
OP
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.
Gast
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.
OP
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!!!
OP
Als kleiner Beweis, dass ich es auch wirklich hinbekommen habe... ;-)

hier mein Code:
1
#include </usr/lib/avr/include/avr/io.h>
2
#include </usr/lib/avr/include/avr/iom8.h>
3
#include <util/delay.h>
4
#include <string.h>
5

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

14
void SPI_MasterTransmit(char cData)
15
{
16
    /* Start transmission */
17
    SPDR = cData;
18
    /* Wait for transmission complete */
19
    while (!(SPSR & (1<<SPIF)))
20
        ;
21
}
22

23
void init_LCD(void)
24
{
25
    PORTB = (0<<DDB7);
26
    _delay_ms(100);             //Nicht kleiner als 100ms da sonst keine Funkion des LCD!!!
27
    SPI_MasterInit();
28
    _delay_ms(10);
29
    SPI_MasterTransmit(0x39);
30
    _delay_ms(10);
31
    SPI_MasterTransmit(0x1D);
32
    _delay_ms(10);
33
    SPI_MasterTransmit(0x50);
34
    _delay_ms(10);
35
    SPI_MasterTransmit(0x6C);
36
    _delay_ms(10);
37
    SPI_MasterTransmit(0x7C);
38
    _delay_ms(10);
39
    SPI_MasterTransmit(0x38);
40
    _delay_ms(10);
41
    SPI_MasterTransmit(0x0F);
42
    _delay_ms(10);
43
    SPI_MasterTransmit(0x01);
44
    _delay_ms(10);
45
}
46

47
void print_LCD(char* string)
48
{
49
    int i;
50

51
    for (i=0;i<strlen(string);i++)
52
    {
53
        PORTB = (1 << DDB6); // high
54
        SPI_MasterTransmit(string[i]);
55
        _delay_ms(3);
56
        PORTB &= ~(1 << DDB6); //low
57
        PORTB = (1 << DDB6); // high
58
    }
59
}
60

61
int main(void)
62
{
63
    init_LCD();
64
    char* string = "Hallo Welt :-)";
65

66
    print_LCD(string);
67

68
    while (1)
69
    {
70
        asm volatile ("nop");
71
    }
72
    return 0;
73
}

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

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

schönen Abend allerseits
OP
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...
1
#include </usr/lib/avr/include/avr/io.h>
2
#include </usr/lib/avr/include/avr/iom8.h>
3
#include <util/delay.h>
4
#include <string.h>
5

6
void SPI_MasterInit(void)
7
{
8
    /* Set MOSI and SCK output, all others input */
Hier kommts...
1
    DDRB = (1<<DDB3)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7); // DDB6 und DDB7 wegen der Display-verschaltung.
2
//  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...
1
    /* Enable SPI, Master, set clock rate fck/16 */
2
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
3
}
4

5
void SPI_MasterTransmit(char cData)
6
{
7
    /* Start transmission */
8
    SPDR = cData;
9
    /* Wait for transmission complete */
10
    while (!(SPSR & (1<<SPIF)));
11
}
12

13
void init_LCD(void)
14
{
15
    PORTB = (0<<DDB7);
16
    _delay_ms(200);             //Nicht kleiner als 100ms da sonst keine Funkion des LCD!!!
17
    SPI_MasterInit();
18
    _delay_ms(10);
19
    SPI_MasterTransmit(0x39);
20
    _delay_ms(10);
21
    SPI_MasterTransmit(0x1D);
22
    _delay_ms(10);
23
    SPI_MasterTransmit(0x50);
24
    _delay_ms(10);
25
    SPI_MasterTransmit(0x6C);
26
    _delay_ms(10);
27
    SPI_MasterTransmit(0x7C);
28
    _delay_ms(10);
29
    SPI_MasterTransmit(0x38);
30
    _delay_ms(10);
31
    SPI_MasterTransmit(0x0C);
32
    _delay_ms(10);
33
    SPI_MasterTransmit(0x01);
34
    _delay_ms(50);
35
}
36

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

52
int main(void)
53
{
54
    init_LCD();
55
    char* string1 = "Hallo Welt :-)";
56
    char* string2 = "Hallo Welt :-|";
57
    char* string3 = "Hallo Welt :-?";
58
    char* string4 = "Hallo Welt :-(";
59

60
    while (1)
61
    {
62
        print_LCD(string1);
63
        _delay_ms(50);
64
        print_LCD(string2);
65
        _delay_ms(50);
66
        print_LCD(string3);
67
        _delay_ms(50);
68
        print_LCD(string4);
69
        _delay_ms(50);
70
    }
71
    return 0;
72
}

hat jemand eine Idee dazu?
Gast
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.
OP
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....
1
int main(void)
2
{
3
    DDRB = (1<<DDB1)|(1<<DDB3)|(1<<DDB5)|(1<<DDB6)|(1<<DDB7); // DDB6 und DDB7 wegen der Display-verschaltung.
4
    PORTB = (1<<DDB1);
5

6
    while (1)
7
    {
8
        asm volatile ("nop");
9
    }
10
    return 0;
11
}
Gast
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.