mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ks0073 - SPI - ASM


Autor: Christian Z. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
CHECK_BF:  ;Prepare Command
        ;Start Byte
    ldi temp_0, 0b00111111
        ;Read BF
BUSY:
    cbi PORTA, CS_LCD
        ;Start Byte
    out SPDR, temp_0
    rcall WAIT_SPI
        ; NEU: 2. Byte schicken

    ldi temp_0, 0 ; im Datenblatt wird eine 0 geschickt
    out SPDR, temp_0
    rcall WAIT_SPI

    in temp_1, SPDR
    sbi PORTA, CS_LCD
    sbrc temp_1, 7
    rjmp BUSY
    ret
- ach ja, das kann man vereinfachen:
WAIT_SPI:  
    in temp_2, SPSR
    ;bst temp_2,7
    ;brts END_WAIT
    sbrs temp_2, SPIF
    rjmp WAIT_SPI
END_WAIT:
    ret
hth. Jörg
ps.: Ich hab dieses Datasheet gelesen: 
http://www.trash.net/~luethi/microchip/datasheets/...
pps. ich hoffe, ich hab nicht zuviel Mist geschrieben, denn mein Code 
ist ungetestet :(

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Christian Z. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg,

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

Autor: Christian Z. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
;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:
      ;CS(LCD)
      ldi temp_0, (1<<DDA2)
      out DDRA, temp_0
      ldi temp_0, (1<<PA2)
      out PORTA, temp_0
      ;SPI_SCK, SPI_MOSI, SPI_MOSI
      ldi temp_0, (1<<DDB7)|(0<<DDB6)|(1<<DDB5)
      out DDRB, temp_0
;-------------------------------------------------------------

LCD_INIT:  rcall WAIT_20ms
      rcall SPI_INIT_LCD
      cbi PORTA, CS_LCD
      ;Start Byte
      ldi temp_0, 0b00011111
      out SPDR, temp_0
      rcall WAIT_SPI
      ;Function set - 8 Bit Modus, clear RE Bit
      ldi  temp_0, 0b00110000
      rcall SHIFT_OUT
      rcall WAIT_45us

      ;Entry mode set - increment cursor automaticly after write data
      ldi  temp_0, 0b00000110
      rcall SHIFT_OUT
      rcall WAIT_45us

      ;Function Set - 8 Bit Modus, set RE Bit & enable cursor blink mode BE=1
      ldi  temp_0, 0b00110110
      rcall SHIFT_OUT
      rcall WAIT_45us

      ;Extended function set - enable 4 line modus & invertin cursor
      ldi  temp_0, 0b00001011
      rcall SHIFT_OUT
      rcall WAIT_45us

      ;Function set - 8 Bit Modus, clear RE Bit
      ldi  temp_0, 0b00110000
      rcall SHIFT_OUT
      rcall WAIT_45us

      ;Display ON/OFF control - Display on, cursor off & cursor blink enable
      ldi  temp_0, 0b00001110
      rcall SHIFT_OUT
      rcall WAIT_45us

      ;Clear Display - clear all signs on display and set cursor to column 1, row 1
      ldi  temp_0, 0b00000001
      rcall SHIFT_OUT
      rcall WAIT_SPI
      rcall WAIT_20ms
      sbi PORTA, CS_LCD
      ret

SHIFT_OUT:  mov temp_1, temp_0
      andi temp_0, 0b00001111
      out SPDR, temp_0
      rcall WAIT_SPI
      swap temp_1
      andi temp_1, 0b00001111
      out SPDR, temp_0
      rcall WAIT_SPI
      ret

WAIT_SPI:  in temp_2, SPSR
       sbrs temp_2, SPIF
        rjmp WAIT_SPI
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...

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Christian Z. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Christian Z. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Christian Z. (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
So funkts,
.include "m644def.inc"

.cseg
.equ CS_LCD = 2

.def temp_0 = r16
.def temp_1 = r17
.def temp_2 = r18
.def temp_3 = r19
.def lcddata = r20

.org 0x0000 rjmp MAIN

MAIN:    ldi  temp_0, LOW(RAMEND)
      out  SPL, temp_0
      ldi  temp_0, HIGH(RAMEND)
      out  SPH, temp_0

      ;CS(LCD)
      ldi temp_0, (1<<DDA2)
      out DDRA, temp_0
      ldi temp_0, (1<<PA2)
      out PORTA, temp_0
      ;SPI_SCK, SPI_MOSI, SPI_MOSI
      ldi temp_0, (1<<DDB7)|(0<<DDB6)|(1<<DDB5)|(1<<DDB4)
      out DDRB, temp_0
      
      rcall LCD_INIT

      END:
      rjmp END

SPI_INIT_LCD:    push temp_0
          ldi temp_0, (0<<SPI2X)
          out SPSR, temp_0
          ldi temp_0, (0<<SPIE)|(1<<SPE)|(1<<DORD)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0)
          out SPCR, temp_0
          pop temp_0
          ret


WAIT_20ms:  ldi temp_0,0x34
      Loop3:  ldi temp_1,0x34
        Loop2:  ldi temp_2,0x34
          Loop1:   dec temp_2
              brne Loop1
            dec temp_1
            brne Loop2
          dec temp_0
          brne Loop3
      ret

WAIT_SPI:  in temp_2, SPSR
         sbrs temp_2, SPIF
        rjmp WAIT_SPI
END_WAIT:   ret

LCD_INIT:  rcall WAIT_20ms
      rcall SPI_INIT_LCD
      
      ;Function set - 8 Bit Modus, clear RE Bit
      ldi  lcddata, 0x30
      rcall LCD_COMMAND
      ;Entry mode set - increment cursor automaticly after write data
      ldi  lcddata, 0x06
      rcall LCD_COMMAND
      ;Function Set - 8 Bit Modus, set RE Bit & enable cursor blink mode BE=1
      ldi  lcddata, 0x36
      rcall LCD_COMMAND
      ;Extended function set - enable 4 line modus & invertin cursor
      ldi  lcddata, 0x09
      rcall LCD_COMMAND
      ;set SEGRAM adress (Icons) - set start adress of the icon line
      ldi  lcddata, 0x40
      rcall LCD_COMMAND
      ;write 0x00 16 times to erase the icons
      ldi temp_3, 0x10 ;Loop Counter
NEXT_ICON:  ldi  lcddata, 0x00
      rcall LCD_DATA
      dec temp_3
      brne NEXT_ICON
      ;Function set - 8 Bit Modus, clear RE Bit
      ldi  lcddata, 0x30
      rcall LCD_COMMAND
      ;Display ON/OFF control - Display on, cursor off & cursor blink enable
      ldi  lcddata, 0x0D
      rcall LCD_COMMAND
      ;Clear Display - clear all signs on display and set cursor to column 1, row 1
      ldi  lcddata, 0x01
      rcall LCD_COMMAND
      ret

LCD_DATA:  push temp_0
      cbi PORTA, CS_LCD
      ldi temp_0, 0b01011111
      out SPDR, temp_0
      rcall WAIT_SPI
      rcall SHIFT_OUT
      sbi PORTA, CS_LCD
      pop temp_0
      ret

LCD_COMMAND:  push temp_0
        cbi PORTA, CS_LCD
        ldi temp_0, 0b00011111
        out SPDR, temp_0
        rcall WAIT_SPI
        rcall SHIFT_OUT
        sbi PORTA, CS_LCD
        pop temp_0
        ret

SHIFT_OUT:  mov temp_0, lcddata
      andi lcddata, 0b00001111
      out SPDR, lcddata
      rcall WAIT_SPI
      swap temp_0
      andi temp_0, 0b00001111
      out SPDR, temp_0
      rcall WAIT_SPI
      rcall CHECK_BF
      ret

CHECK_BF:  ldi temp_0, 0b00111111
          out SPDR, temp_0
        rcall WAIT_SPI
          ldi temp_0, 0x00
        out SPDR, temp_0
        rcall WAIT_SPI
        in temp_0, SPDR
        sbrc temp_0, 7
        rjmp CHECK_BF
      ret
.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.

Autor: Jörg X. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

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.