Forum: Mikrocontroller und Digitale Elektronik ks0073 - SPI - ASM


von Christian Z. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich möchte mein EA DIP204B-6 LCD statt wie bisher im 8Bit Modus im SPI 
Mode betreiben, aber es will nicht.
Brücke für das IM Bit ist umgelötet. Mein MCU läuft mit einer MCLK von 
20MHz der SPI Bus mit einem Prescaler von 64 damit also mit 312,5kHz.
Den Quellcode habe ich angehangen.

Datenblätter habe ich schon gewälzt aber ich komme einfach nicht weiter. 
Wär super wenn mir jemand sagen kann wo der/die Fehler liegen.

MfG Christian

von Jörg X. (Gast)


Lesenswert?

- Es reicht völlig, das SPI nur ein Mal zu initialisieren, wenn da keine 
anderen (langsamere/schnellere) Slaves angeschlossen sind
-  In dem Datenblatt, dass ich auf die schnelle gefunden hab steht 
"Serial Clock Cycle Time tc 1 - 20 µs", was ich als 50kHz maximaler 
SPI-Takt lesen würde.
- In der Busy-Flag abfrage musst du noch ein Byte schicken, damit du 
auch tatsächlich was von dem Display kriegst:
1
CHECK_BF:  ;Prepare Command
2
        ;Start Byte
3
    ldi temp_0, 0b00111111
4
        ;Read BF
5
BUSY:
6
    cbi PORTA, CS_LCD
7
        ;Start Byte
8
    out SPDR, temp_0
9
    rcall WAIT_SPI
10
        ; NEU: 2. Byte schicken
11
12
    ldi temp_0, 0 ; im Datenblatt wird eine 0 geschickt
13
    out SPDR, temp_0
14
    rcall WAIT_SPI
15
16
    in temp_1, SPDR
17
    sbi PORTA, CS_LCD
18
    sbrc temp_1, 7
19
    rjmp BUSY
20
    ret
- ach ja, das kann man vereinfachen:
1
WAIT_SPI:  
2
    in temp_2, SPSR
3
    ;bst temp_2,7
4
    ;brts END_WAIT
5
    sbrs temp_2, SPIF
6
    rjmp WAIT_SPI
7
END_WAIT:
8
    ret
hth. Jörg
ps.: Ich hab dieses Datasheet gelesen: 
http://www.trash.net/~luethi/microchip/datasheets/lcd/ks0073.pdf
pps. ich hoffe, ich hab nicht zuviel Mist geschrieben, denn mein Code 
ist ungetestet :(

von Jörg X. (Gast)


Lesenswert?

oh, sry, den Punkt mit dem SPI-Takt bitte schnell vergessen:
tc 1-20µs heißt natürlich 50kHz-1MHz Takt

sry --Jörg

von Christian Z. (Gast)


Lesenswert?

Hallo Jörg,

Tausend Dank für die Antwort, ich probier das jetzt mal aus.

von Christian Z. (Gast)


Lesenswert?

@Jörg:
Also es läuft leider immer noch nicht. Aber das mit dem Nullbyte habe 
ich ja überhaupt nicht wargenommen, das war auf jeden Fall ein Fehler. 
Sorry das Datenblatt war das richtige aber ich hätte es ja auch anhängen 
können - Vielen Dank für deine Mühen
Die Initialisierung des SPI habe ich wissentlich vorgenommen da die UP´s 
später in ein Programm übernommen werden sollen in denen ich schon 
mehrere SPI Teilnehmer habe - die alle ausnahmslos funktionieren nur 
dieses ******* LCD nicht.

Ich habe jetzt mal wirklich nur die reine Initialisierung des LCD 
vorgenommen ohne BF-Abfrage sondern mit einer großzügigen Zeit von 45µs 
bzw nach CLEAR LCD mit fetten 20ms. Nach der Init müsste letztendlich 
wenigstens der Cursor zu sehen sein aber nix ist.

Die Init ganz schlicht:
1
;Die Definition von DDR und PORT ist hier nur zur Verdeutichung der verwendeten Werte so eingefügt davor und danach stehen noch die nötigen Befehle:
2
      ;CS(LCD)
3
      ldi temp_0, (1<<DDA2)
4
      out DDRA, temp_0
5
      ldi temp_0, (1<<PA2)
6
      out PORTA, temp_0
7
      ;SPI_SCK, SPI_MOSI, SPI_MOSI
8
      ldi temp_0, (1<<DDB7)|(0<<DDB6)|(1<<DDB5)
9
      out DDRB, temp_0
10
;-------------------------------------------------------------
11
12
LCD_INIT:  rcall WAIT_20ms
13
      rcall SPI_INIT_LCD
14
      cbi PORTA, CS_LCD
15
      ;Start Byte
16
      ldi temp_0, 0b00011111
17
      out SPDR, temp_0
18
      rcall WAIT_SPI
19
      ;Function set - 8 Bit Modus, clear RE Bit
20
      ldi  temp_0, 0b00110000
21
      rcall SHIFT_OUT
22
      rcall WAIT_45us
23
24
      ;Entry mode set - increment cursor automaticly after write data
25
      ldi  temp_0, 0b00000110
26
      rcall SHIFT_OUT
27
      rcall WAIT_45us
28
29
      ;Function Set - 8 Bit Modus, set RE Bit & enable cursor blink mode BE=1
30
      ldi  temp_0, 0b00110110
31
      rcall SHIFT_OUT
32
      rcall WAIT_45us
33
34
      ;Extended function set - enable 4 line modus & invertin cursor
35
      ldi  temp_0, 0b00001011
36
      rcall SHIFT_OUT
37
      rcall WAIT_45us
38
39
      ;Function set - 8 Bit Modus, clear RE Bit
40
      ldi  temp_0, 0b00110000
41
      rcall SHIFT_OUT
42
      rcall WAIT_45us
43
44
      ;Display ON/OFF control - Display on, cursor off & cursor blink enable
45
      ldi  temp_0, 0b00001110
46
      rcall SHIFT_OUT
47
      rcall WAIT_45us
48
49
      ;Clear Display - clear all signs on display and set cursor to column 1, row 1
50
      ldi  temp_0, 0b00000001
51
      rcall SHIFT_OUT
52
      rcall WAIT_SPI
53
      rcall WAIT_20ms
54
      sbi PORTA, CS_LCD
55
      ret
56
57
SHIFT_OUT:  mov temp_1, temp_0
58
      andi temp_0, 0b00001111
59
      out SPDR, temp_0
60
      rcall WAIT_SPI
61
      swap temp_1
62
      andi temp_1, 0b00001111
63
      out SPDR, temp_0
64
      rcall WAIT_SPI
65
      ret
66
67
WAIT_SPI:  in temp_2, SPSR
68
       sbrs temp_2, SPIF
69
        rjmp WAIT_SPI
70
END_WAIT:   ret

Wie empfindlich ist den das LCD? Nicht das es beim Umlöten der Brücke 
die Hufe hochgerissen hat. Vorher ging es im 8Bit Mode und jetzt geht es 
immerhin noch an und der Kontrast und die Helligkeit passen auch.

Bin für jeden Tipp dankbar...

von Jörg X. (Gast)


Lesenswert?

Ist das Display wirklich richtig angeschlossen? ;)
Sind die Wartezeiten korrekt (da steht zwar 45us bzw 20ms, aber tun die 
das auch) ? --> Poste deine Warteroutinen

Irgendwie blick ich  nicht ganz, ob man dem Display die 8- oder die 4Bit 
Initialisierung für SPI schicken muss.

...und natürlich kann es sein, dass du das Display 'getötet' hast :(

?! --Jörg

von Christian Z. (Gast)


Lesenswert?

Hallo Jörg,

das LCD lebt noch, auf jeden Fall habe ich das DORD Bit falsch gesetzt. 
Ich bekomme nun den Cursor angezeigt aber die Initialisierung haut noch 
nicht richtig hin.
Die Kommentare der einzelnen Init-Schritte sind noch von der 8Bit-Bus 
Variante.
Dort gibt es aber eben nur die Optionen 4- und 8Bit ich habe es erst mal 
auf 8Bit gelassen, werde weiter probieren.
Die Warteschleifen sind nach dem Schema in der txt Datei aufgebaut - die 
20ms sind tatsächlich 21,..ms. Die 8µs sind mehr als 11 und ist nur vom 
rumprobieren reingerutscht. Und die 45µs passen auch, habe ich mit dem 
Oszi überprüft.

Ich denke mal morgen werde ich das LCD zum laufen bekommen, werde dann 
noch mal die korrekte Initialisierungssequenz reinsetzen, die der Bascom 
Beispiele aus der Codesammlung waren bei mir nicht erfolgreich - mal 
sehen.

MfG Christian

von Jörg X. (Gast)


Lesenswert?

Schön zu hören (dass nicht kaputt ist, etc.)!

Ich kann noch eine (AVR-GCC) C-Version (fertig) machen (hab 
Semesterferien und deshalb etwas Zeit ;) ). Dazu müsstest du mir 
verraten wie deine Schaltung aussieht, wenn du nicht selber compilieren 
willst (Ich hab das Display nicht).
Ich weiß, in der Codesammlung gibt's eine C-Version, die finde ich aber 
nicht so toll.

hth. Jörg

von Christian Z. (Gast)


Lesenswert?

Das ist ein feiner Zug von dir, aber ich will es eigentlich alleine 
schaffen - mal abgesehen von den Tipps. Sonst bleibt einfach nicht 
soviel hängen.
Und mit C muss ich mich erst noch beschäftigen. Hab zwar C und ASM im 
Studium gehabt aber leider keine Zeit gehabt mich damit intensiv und 
praktisch auseinander zu setzen. Da ich das aber schon immer lernen 
wollte muss ich da jetzt durch...

von Christian Z. (Gast)


Lesenswert?

So funkts,
1
.include "m644def.inc"
2
3
.cseg
4
.equ CS_LCD = 2
5
6
.def temp_0 = r16
7
.def temp_1 = r17
8
.def temp_2 = r18
9
.def temp_3 = r19
10
.def lcddata = r20
11
12
.org 0x0000 rjmp MAIN
13
14
MAIN:    ldi  temp_0, LOW(RAMEND)
15
      out  SPL, temp_0
16
      ldi  temp_0, HIGH(RAMEND)
17
      out  SPH, temp_0
18
19
      ;CS(LCD)
20
      ldi temp_0, (1<<DDA2)
21
      out DDRA, temp_0
22
      ldi temp_0, (1<<PA2)
23
      out PORTA, temp_0
24
      ;SPI_SCK, SPI_MOSI, SPI_MOSI
25
      ldi temp_0, (1<<DDB7)|(0<<DDB6)|(1<<DDB5)|(1<<DDB4)
26
      out DDRB, temp_0
27
      
28
      rcall LCD_INIT
29
30
      END:
31
      rjmp END
32
33
SPI_INIT_LCD:    push temp_0
34
          ldi temp_0, (0<<SPI2X)
35
          out SPSR, temp_0
36
          ldi temp_0, (0<<SPIE)|(1<<SPE)|(1<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0)
37
          out SPCR, temp_0
38
          pop temp_0
39
          ret
40
41
42
WAIT_20ms:  ldi temp_0,0x34
43
      Loop3:  ldi temp_1,0x34
44
        Loop2:  ldi temp_2,0x34
45
          Loop1:   dec temp_2
46
              brne Loop1
47
            dec temp_1
48
            brne Loop2
49
          dec temp_0
50
          brne Loop3
51
      ret
52
53
WAIT_SPI:  in temp_2, SPSR
54
         sbrs temp_2, SPIF
55
        rjmp WAIT_SPI
56
END_WAIT:   ret
57
58
LCD_INIT:  rcall WAIT_20ms
59
      rcall SPI_INIT_LCD
60
      
61
      ;Function set - 8 Bit Modus, clear RE Bit
62
      ldi  lcddata, 0x30
63
      rcall LCD_COMMAND
64
      ;Entry mode set - increment cursor automaticly after write data
65
      ldi  lcddata, 0x06
66
      rcall LCD_COMMAND
67
      ;Function Set - 8 Bit Modus, set RE Bit & enable cursor blink mode BE=1
68
      ldi  lcddata, 0x36
69
      rcall LCD_COMMAND
70
      ;Extended function set - enable 4 line modus & invertin cursor
71
      ldi  lcddata, 0x09
72
      rcall LCD_COMMAND
73
      ;set SEGRAM adress (Icons) - set start adress of the icon line
74
      ldi  lcddata, 0x40
75
      rcall LCD_COMMAND
76
      ;write 0x00 16 times to erase the icons
77
      ldi temp_3, 0x10 ;Loop Counter
78
NEXT_ICON:  ldi  lcddata, 0x00
79
      rcall LCD_DATA
80
      dec temp_3
81
      brne NEXT_ICON
82
      ;Function set - 8 Bit Modus, clear RE Bit
83
      ldi  lcddata, 0x30
84
      rcall LCD_COMMAND
85
      ;Display ON/OFF control - Display on, cursor off & cursor blink enable
86
      ldi  lcddata, 0x0D
87
      rcall LCD_COMMAND
88
      ;Clear Display - clear all signs on display and set cursor to column 1, row 1
89
      ldi  lcddata, 0x01
90
      rcall LCD_COMMAND
91
      ret
92
93
LCD_DATA:  push temp_0
94
      cbi PORTA, CS_LCD
95
      ldi temp_0, 0b01011111
96
      out SPDR, temp_0
97
      rcall WAIT_SPI
98
      rcall SHIFT_OUT
99
      sbi PORTA, CS_LCD
100
      pop temp_0
101
      ret
102
103
LCD_COMMAND:  push temp_0
104
        cbi PORTA, CS_LCD
105
        ldi temp_0, 0b00011111
106
        out SPDR, temp_0
107
        rcall WAIT_SPI
108
        rcall SHIFT_OUT
109
        sbi PORTA, CS_LCD
110
        pop temp_0
111
        ret
112
113
SHIFT_OUT:  mov temp_0, lcddata
114
      andi lcddata, 0b00001111
115
      out SPDR, lcddata
116
      rcall WAIT_SPI
117
      swap temp_0
118
      andi temp_0, 0b00001111
119
      out SPDR, temp_0
120
      rcall WAIT_SPI
121
      rcall CHECK_BF
122
      ret
123
124
CHECK_BF:  ldi temp_0, 0b00111111
125
          out SPDR, temp_0
126
        rcall WAIT_SPI
127
          ldi temp_0, 0x00
128
        out SPDR, temp_0
129
        rcall WAIT_SPI
130
        in temp_0, SPDR
131
        sbrc temp_0, 7
132
        rjmp CHECK_BF
133
      ret
134
.exit

Danke Jörg, wie gesagt das mit der Null schreiben beim BF auslesen hätte 
ich bestimmt noch ein paar Tage ignoriert obwohl es ja logisch ist da 
ich das BF Flag ja sonst gar nicht aus dem LCD bekomme. Ansonsten waren 
es noch haufenweise Strg+C und Strg+V Fehler gepaart mit etwas Dummheit.

von Jörg X. (Gast)


Angehängte Dateien:

Lesenswert?

Ich hab trotzdem weitergemacht ;)
Aber hauptsächlich um mit Doxygen zu spielen.
Das Ergebnis ist für den Anfang recht umfangreich. Im Anhang ist:
- die Library (ks0073.c und ks0073.h)
- eine Demo (lcd_test.c, inkl. Makefile und AVR-Studio-projekt).
- eine Hex-datei, falls du nicht selber kompilieren willst (näheres in 
der readme.txt)

--Jörg

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.