Forum: Mikrocontroller und Digitale Elektronik SPI für Kommunikation mit EA DOGM128


von Trillian (Gast)


Lesenswert?

Hallo,

ich versuche ein EA DOGM128 mit dem ATMega64 zum Laufen zu bringen. 
Bisher tut sich leider nichts. Da dies nicht nur mein erster Kontakt mit 
diesem Display, sondern auch mit der SPI-Schnittstelle ist, möchte ich 
erstmal ausschließen, dass der Fehler in meiner SPI Routine liegt. Habe 
mich beim Takt an das Schaubild zur Datenübertragung im Display 
Datenblatt gehalten (http://www.lcd-module.de/deu/pdf/grafik/dogm128.pdf 
--> Seite 5). Also das hoffe ich jedenfalls. Wäre dankbar, wenn 
vielleicht mal jemand rüberschauen könnte, ob die SPI Routine so 
funktioniert.
1
; ************ write 8 bit to mosi/si *************
2
;
3
WRITE_SPI:
4
    push  temp1
5
    push  r2
6
7
    ldi    temp1, 8  ; bit counter
8
    mov    r2, temp1
9
10
    mosi_low  
11
12
loop_8bit:
13
    clock_high      
14
    lsl    spi_data  
15
16
    brcs  high_mosi
17
    mosi_low
18
    rjmp  bit_sent
19
high_mosi:
20
    mosi_high    ; if brcs is false, the number of clocks is 1(lsl)+1(brcs)+5(mosi_low)+2(rjmp) = 9 clocks
21
    nop        ; if brcs is true, the number is 1(lsl)+2(brcs)+5(mosi_high)+1(nop) = 9 clocks
22
bit_sent:
23
    clock_low
24
25
    nop
26
    nop
27
    nop
28
    nop
29
    nop
30
    nop
31
32
    dec    r2
33
    brne  loop_8bit  ; 6*1(nop)+1(dec)+2(brne) = 9 clocks
34
        
35
    pop    r2
36
    pop    temp1
37
38
    ret

Die Makros (mosi_high, mosi_low ...) sehen so aus:
1
.macro  clock_low
2
    lds    temp1, PORTF      ; 2 Takte
3
    andi   temp1, ~(1<<clk)    ; 1 Takt
4
    sts    PORTF, temp1      ; 2 Takte
5
.endm
6
7
.macro  clock_high
8
    lds    temp1, PORTF      ; 2 Takte
9
    ori    temp1, (1<<clk)      ; 1 Takt
10
    sts    PORTF, temp1      ; 2 Takte
11
.endm
12
13
.macro  mosi_low
14
    lds    temp1, PORTF
15
    andi   temp1, ~(1<<mosi)
16
    sts    PORTF, temp1
17
.endm
18
19
.macro  mosi_high
20
    lds    temp1, PORTF
21
    ori    temp1, (1<<mosi)
22
    sts    PORTF, temp1
23
.endm

Danke im Voraus für Eure Antworten :)

von Swen (Gast)


Lesenswert?

Sorry, zzt. nur alter Codeschnipsel verfügbar.

... das hier funktioniert z.B. mit DOGM128 3- Zeilig, läßt sich bequem 
anpassen.

Delays müssen noch ergänzt werden, dort kann man noch viel falsch machen 
;-), die Displays wollen es nicht "zu schnell"...


also zuerst SPI MaterInit und danach lcd_init ausführen,

Zeichen werden z.B. mit

ldi temp1,'*'
out SPDR,Temp1
rcall delay50ms

ausgegeben.


----------------------------------------------------------------------

lcd_init:
    rcall  SPI_MasterInit
    rcall delay5ms

    ldi    temp1,0b00111001    ;Function set 
(8Bit,2Lines,DoubleHight,IS[2:1])
    rcall    SPI_MasterTransmit
    rcall delay5ms

    ldi    temp1,0b00111001    ;Function set 
(8Bit,2Lines,DoubleHight,IS[2:1])
    rcall    SPI_MasterTransmit
    rcall delay5ms

    ldi    temp1,0b00010100    ;Bias Set (1/4Bias,FX)
    rcall    SPI_MasterTransmit
    rcall delay5ms

    ldi    temp1,0b01010101    ;Booster Set (C5,C4)Contrast Set 
(C3,C2,C1,C0)
    rcall    SPI_MasterTransmit
    rcall delay5ms

    ldi    temp1,0b01101101    ;Follower (Follower,Rab2,Rab1,Rab0)
    rcall    SPI_MasterTransmit
    rcall delay5ms

    ldi    temp1,0b01111000    ;Contrast Set
    rcall    SPI_MasterTransmit
    rcall delay5ms

    ldi    temp1,0b00001100    ;Display ON (Entire ON,Cursor 
OFF,Blinking OFF)
    rcall    SPI_MasterTransmit
        rcall delay5ms

    ldi    temp1,0b00000001      ;Clear Display
    rcall    SPI_MasterTransmit
    rcall delay5ms

    ldi    temp1,0b00000110    ;Auto Increment
    rcall    SPI_MasterTransmit
        rcall delay5ms

ret

; -------------------------------------------------------------------

SPI_MasterInit: ; für SPI- Display TExt 3x16
    sbi    PortB,RS
    sbi    PortB,CSB
    ldi   Temp2,(1<<SPE)|(1<<MSTR)|(1<<SPR0)
    ; Enable SPI, Master, set clock rate fck/16
    out   SPCR,Temp2
ret

; -------------------------------------------------------------------

SPI_MasterTransmit: ; für SPI- Display Text 3x16
    cbi    PortB,RS
    cbi    PortB,CSB
    out   SPDR,temp1          ; Start transmission of data (Temp1)
  Wait_Transmit:              ; Wait for transmission complete
    sbis   SPSR,SPIF
    rjmp   Wait_Transmit
    sbi    PortB,RS
    sbi    PortB,CSB
ret

; -------------------------------------------------------------------

von Swen (Gast)


Lesenswert?

Äh, sorry, wer lesen kann ist immer noch klar im Vorteil. Die Routine 
für diese _Grafik_- Displays habe ich leider nur in C. Der SPI- Teil ist 
aber prinzipiell der gleiche, die einzelnen Steps der Initialisierung 
liefert das Datenblatt. Sonst: auf das Timing achten (Delays).

von Matthias L. (Gast)


Lesenswert?

Mal so ne Frage:

Warum nimmst du nicht die Hardware-SPI Schnittstelle?

von Marja K. (trillian)


Lesenswert?

@Swen: Oh das is ja mehr als erwartet ;) Danke für Deine Bemühungen aber 
das Problem ist, dass ich nicht die Hardware SPI vom AVR benutze sondern 
versuche, die SPI in Software zu realisieren. Zur Initialisierung: Ich 
vermute Deine Sequenz ist für den ST7036 Controller - in dem 128er 
DOG-Display ist aber der ST7565 drin. Bei dem muss die 
Initialisierungssequenz innerhalb von max 5ms abgeschlossen sein. Ich 
vermute also dass ich keine zusätzlichen Pausen benötige.

@Matthias Lipinsky: Ja das würd ich auch gerne, aber das war vom 
Platinenlayout leider nicht möglich. Ich habe nur 4 Pins des F Ports zur 
Verfügung um mit dem Display zu kommunizieren.

Mein aktueller Fortschritt: Null. Da sich an meinem Display aber auch 
wirklich garnichts tut, befürchte ich, dass es an der Kommunikation 
hapert. Habe da noch einige Fragen zur SPI:

1. Eine Periode meines SPI Clocks dauert 18 AVR-Takte (9 Takte low, 9 
Takte high). Das entspricht bei mir ca 1MHz. Meiner Meinung nach ist es 
vollkommen egal, welche Frequenz der SPI Master an die Slaves sendet - 
solange die max Frequenz des Slaves nicht überschritten wird. Ist das 
richtig?

2. Der Slave/Chip-Select Pin meines Displays ist mit der Masse 
verbunden, bekommt also ein Dauer-Low bzw. "lauscht" ständig am SPI Bus. 
Geht das so überhaupt?

Gruß

von Bensch (Gast)


Lesenswert?

1. Im Prinzip ja...

2. Nein, lies das Datenblatt des Display-Controllers.

von Marja K. (trillian)


Lesenswert?

Hallo Bensch

ja das hab ich getan, habe aber daraus geschlossen, dass der CS ruhig 
auf Masse liegen kann, da ich ja eh nur diesen einen Slave habe und wenn 
Daten über den SPI Bus kommen, dann sind die immer und auf jeden Fall 
für diesen Slave (Display). Oder was erfüllt der CS noch für eine 
Funktion?

von Swen (Gast)


Lesenswert?

... vielleicht helfen Dir die Codeschnipsel aus meiner funktionierenden 
C- Routine weiter:





#define DDR_SPI DDRB
#define DD_MOSI PORTB3
#define DD_SCK PORTB5

#define LCD_A0 PORTB1
#define LCD_CSB PORTB2

-.-


  // set directions for A0 and CSB
  DDRB |= (1<<LCD_A0) | (1<<LCD_CSB);
  PORTB |= (1<<LCD_A0) | (1<<LCD_CSB);

  SPI_MasterInit();

#if LCD_TYPE == DOGM128
  lcd_cmd(ST7565R_Set_Start_Line);
  lcd_cmd(ST7565R_Select_ADC_Reverse);
  lcd_cmd(ST7565R_Set_COM_Normal);
  lcd_cmd(ST7565R_Display_Normal);
  lcd_cmd(ST7565R_Set_Bias_1to8);      // Set bias 1/9 (Duty 1/65)
  lcd_cmd(ST7565R_Set_Power_Controller | (1<<ST7565R_Voltage_regulator) 
| (1<<ST7565R_Voltage_follower));
  lcd_cmd(ST7565R_Set_Resistor_Ratio | 7);
  lcd_cmd(ST7565R_Go_To_Volume_Set_Mode);  // Contrast set (2 byte 
command)
  lcd_cmd(0x16);              // data byte for contrast
  lcd_cmd(ST7565R_Static_Indicator_Off);  // no indicator
  lcd_cmd(ST7565R_Display_On);      // Display on

-.-

Und - ja, einmal warten reicht beim Grafikdisplay. Ich kann mich 
erinnern am Anfang einen Bug mit der ClockPhase gemacht zu haben. Das 
Datenblatt war da wohl ein wenig "komisch" zu interpretieren...

von Marja K. (trillian)


Lesenswert?

Hi Swen,

die Initialisierungsequenz werde ich so übernehmen (natürlich in asm), 
da sie ja von Dir getestet ist ;) Vielen Dank.

Aber bis jetzt krieg ich überhaupt keine Daten zum Display gesendet - 
und es liegt laut Bensch am Chip-Select Pin. Habe nochmal im Controller 
Datenblatt nachgeschaut und doch noch was gefunden:

When the chip select is inactive, D0 to D7 enter a high
impedance state, and the A0, /RD, and /WR inputs are
inactive. When the 4-line SPI interface is selected, the shift
register and the counter are reset.

Also eine weitere Funktion des CS ist das Resetten des Schieberegisters 
und irgendeines counters. Ist das nötig damit das Display die 
empfangenen Daten auswertet?

von Swen (Gast)


Lesenswert?

Noch'n kleiner Tipp:

Vergiss den CS ;-) - er kann(!) benutzt werden wenn andere SPI- Geräte 
mit angeschlossen werden sollen.

Aber die Leitung A0 entscheidet zwischen Daten und Befehl. Das ist 
vielleicht zu beachten...

von Bensch (Gast)


Lesenswert?

Dieses IC scheint eine grosse Ausnahme zu sein und braucht keinen CS. 
Das beinhaltet aber die Gefahr, dass irgendwelcher Sch..., der 
irgendwann auf der CLK passiert z.B. beim Initialisieren den Controller 
durcheinander bringen kann. Und bei einer Software-SPI ist das m.E. sehr 
wahrscheinlich.
Daher die DRINGENDE Empfehlung: benutz den CS!

von Marja K. (trillian)


Lesenswert?

Puuh ok dann werd ich mich jetzt wieder ransetzen. Vielen Dank erstmal 
für Eure Hilfe - ich melde mich später nochmal um zu berichten ;)

LG und einen schönen Tag noch

von Swen (Gast)


Lesenswert?

... sollte nicht heißen das der CS nicht benutzt werden soll wenn ein 
Portpin da ist um ihn anzusteuern ... ;-) andererseits sollte es den 
Display- Controller wenig kümmern wenn z.B. die Clock- Leitung während 
der Initialisierung irgendwo rumbaumelt - das kann auch dem CS- Pin zu 
diesem Zeitpunkt passieren und der Chip sollte irgendwie sowieso nach 
einer gewissen Zeit ohne Takt einen Interface- Reset durchführen (?)

von Marja K. (trillian)


Lesenswert?

Freude Freude :D Es lebt!! Habe es geschafft, dass Display zu 
initialisieren und mir "all display points ON" anzeigen zu lassen.

Wie vermutet, lag der Fehler in meiner SPI - genauer gesagt an deren 
Initialisierung. Diese besteht im Grunde nur darin, den Clock auf high 
zu setzen/halten, solange keine Kommunikation stattfinden soll. 
Höchstwahrscheinlich hat das Display tatsächlich irgendwo am Anfang 
meines Hauptprogrammes ein low auf dem SPI Clock erhalten und irgendein 
Bit vom Mosi ausgelesen, als es das noch garnicht sollte :s

Also zusammenfassend kann ich sagen, dass das Display (in meinem Fall) 
auch ohne Benutzung des CS-Pins funktioniert (dieser ist mit Masse 
verbunden). Funktioniert natürlich nur dann, wenn man mit dem 
Master-Controller auch tatsächlich nur einen SPI-Slave ansprechen will.

Auch die SPI Clock-Frequenz von 1MHz macht komischerweise keine 
Probleme. Auf meinem Testboard wird nämlich die 5V AVR Spannung über 
Widerstände (Spannungsteiler) auf die 3,3V Display Spannung 
runtergesetzt. Das führt dazu, dass die SPI Frequenz die ich vom AVR ans 
Display schiebe nicht grad rechteckig ist, sondern fast dreieckförmig!! 
Trotzdem scheint das dem Display auszureichen :)

Liebe Grüße und vielen Dank nochmal,
Trillian

von Bensch (Gast)


Lesenswert?

Genau meine Vermutung, mit CS wär das nicht passiert ...

> fast dreieckförmig...

Solange Gnd und 3,3V so gerade erreicht werden, ist das ok. Ich hab hier 
470R  und 470pF in den Signalleitungen bei 600kHz und 5V-Pegel, das 
reicht für 1m Leitung zum Display. Aber selbst ein Signal mit Pegeln 
<1,5V und >3,5V spielt einwandfrei- wenn auch mit geringerer 
Störsicherheit.

von Marja K. (trillian)


Lesenswert?

Bensch wrote:
> Genau meine Vermutung, mit CS wär das nicht passiert ...

Ja das stimmt. Hätte mir einiges erspart...

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.