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


von Michael Z. (zellm)


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 ;-)
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

von Thilo M. (Gast)


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. 
;-)

von Michael Z. (zellm)


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.

von Thilo M. (Gast)


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.

von spess53 (Gast)


Lesenswert?

Hi

RS auf H
RW auf L

und ASCII-Zeichen senden.

Fertig.

MfG Spess

von Thilo M. (Gast)


Angehängte Dateien:

Lesenswert?

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

von Michael Z. (zellm)


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!!!

von Michael Z. (zellm)


Lesenswert?

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

von Michael Z. (zellm)


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...
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?

von Thilo M. (Gast)


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.

von Michael Z. (zellm)


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.

von Thilo M. (Gast)


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.

von Michael Z. (zellm)


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....
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
}

von Thilo M. (Gast)


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.

von Michael Z. (zellm)


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...

von Juppo N. (juppo)


Lesenswert?

Moin an alle

Ich habe das Modul DOG S

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

Gruß Juppo

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.