www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD mit 2 Controllern via Assembler ansteuern klappt nicht.


Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich stell das Thema jetzt nochmal unter meinem Login und unter nem 
besseren Titel rein. Also ich habe für mein 4x40 Display mit assembler 
nen bissl was geschrieben in Anlehnung an das Tutorial hier. Das Problem 
ist jetzt, dass ich jetzt immer Abwechselnd oben oder Unten nen 
schwarzen Balken aufm Display habe und an der Jeweils anderen Seite 2x 
hintereinander Test. hier der Code:
.include "m32def.inc"

.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def lcdno = r19


           ldi temp1, LOW(RAMEND)      ; LOW-Byte der obersten
RAM-Adresse
           out SPL, temp1
           ldi temp1, HIGH(RAMEND)     ; HIGH-Byte der obersten
RAM-Adresse
           out SPH, temp1

           ldi temp1, 0xFF    ; Port D = Ausgang
           out DDRD, temp1

           cbr lcdno, 0
           rcall lcd_init     ; Display initialisieren
           rcall lcd_clear    ; Display löschen
           sbr lcdno, 0
           rcall lcd_init     ; Display initialisieren
           rcall lcd_clear    ; Display löschen


           cbr lcdno, 1
           ldi temp1, 'T'     ; Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 'e'     ; Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 's'     ; Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 't'     ; Zeichen anzeigen
           rcall lcd_data



           sbr lcdno, 1
           ldi temp1, 'T'     ; Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 'e'     ; Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 's'     ; Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 't'     ; Zeichen anzeigen
           rcall lcd_data

loop:
           rjmp loop

.include "lcd-routines.asm"            ; LCD-Routinen werden hier eingefügt



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                 LCD-Routinen                ;;
;;                 ============                ;;
;;              (c)andreas-s@web.de            ;;
;;                                             ;;
;; 4bit-Interface                              ;;
;; DB4-DB7:       PD0-PD3                      ;;
;; RS:            PD4                          ;;
;; E:             PD5                          ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


.equ LCD_PORT = PORTD
.equ LCD_DDR  = DDRD
.equ PIN_E    = 5
.equ PIN_E2   = 6
.equ PIN_RS   = 4
.equ XTAL  = 16000000

 ;sendet ein Datenbyte an das LCD
lcd_data:
           mov temp2, temp1             ; "Sicherungskopie" für
                                        ; die Übertragung des 2.Nibbles
           swap temp1                   ; Vertauschen
           andi temp1, 0b00001111       ; oberes Nibble auf Null setzen
           sbr temp1, 1<<PIN_RS         ; entspricht 0b00010000
           out LCD_PORT, temp1          ; ausgeben
           rcall lcd_enable             ; Enable-Routine aufrufen
                                        ; 2. Nibble, kein swap da es
schon
                                        ; an der richtigen stelle ist
           andi temp2, 0b00001111       ; obere Hälfte auf Null setzen
           sbr temp2, 1<<PIN_RS         ; entspricht 0b00010000
           out LCD_PORT, temp2          ; ausgeben
           rcall lcd_enable             ; Enable-Routine aufrufen
           rcall delay50us              ; Delay-Routine aufrufen
           ret                          ; zurück zum Hauptprogramm


 ; sendet einen Befehl an das LCD

lcd_command:                            ; wie lcd_data, nur RS=0
           mov temp2, temp1
           swap temp1
           andi temp1, 0b00001111
           out LCD_PORT, temp1
           rcall lcd_enable
           andi temp2, 0b00001111
           out LCD_PORT, temp2
           rcall lcd_enable
           rcall delay50us
           ret



 ; erzeugt den Enable-Puls
lcd_enable:
           sbrs lcdno, 1
       sbi LCD_PORT, PIN_E          ; Enable high
       sbrc lcdno, 1
       sbi LCD_PORT, PIN_E2          ; Enable high
           nop                          ; 3 Taktzyklen warten
           nop
           nop
           cbi LCD_PORT, PIN_E          ; Enable wieder low
       cbi LCD_PORT, PIN_E2
           ret
                                ; Und wieder zurück



 ; Pause nach jeder Übertragung
delay50us:                              ; 50us Pause
           ldi  temp1, ( XTAL * 50 / 4 ) / 1000000
delay50us_:
           dec  temp1
           nop                          ; tu nichts
           brne delay50us_
           ret

 ; Längere Pause für manche Befehle
delay5ms:                               ; 5ms Pause
           ldi  temp1, ( XTAL * 5 / 607 ) / 1000
WGLOOP0:   ldi  temp2, $C9
WGLOOP1:   dec  temp2
           brne WGLOOP1
           dec  temp1
           brne WGLOOP0
           ret                          ; wieder zurück
; wieder zurück

 ; Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
lcd_init:
           ldi   temp1, 0xFF            ; alle Pins am Ausgabeport auf
Ausgang
           out   LCD_DDR, temp1

           ldi   temp3,6
powerupwait:
           rcall delay5ms
           dec   temp3
           brne  powerupwait
           ldi   temp1,    0b00000011   ; muss 3mal hintereinander
gesendet
           out   LCD_PORT, temp1        ; werden zur Initialisierung
           rcall lcd_enable             ; 1
           rcall delay5ms
           rcall lcd_enable             ; 2
           rcall delay5ms
           rcall lcd_enable             ; und 3!
           rcall delay5ms
           ldi   temp1, 0b00000010      ; 4bit-Modus einstellen
           out   LCD_PORT, temp1
           rcall lcd_enable
           rcall delay5ms
           ldi   temp1, 0b00101000      ; 4 Bot, 2 Zeilen
           rcall lcd_command
           ldi   temp1, 0b00001100      ; Display on, Cursor off
           rcall lcd_command
           ldi   temp1, 0b00000100      ; endlich fertig
           rcall lcd_command
           ret



 ; Sendet den Befehl zur Löschung des Displays
lcd_clear:
           ldi   temp1, 0b00000001      ; Display löschen
           rcall lcd_command
           rcall delay5ms
           ret

 ; Sendet den Befehl: Cursor Home
lcd_home:
           ldi   temp1, 0b00000010      ; Cursor Home
           rcall lcd_command
           rcall delay5ms
           ret

kann mir da jemand weiterhelfen?

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
cbr und sbr arbeiten jeweils mit Bitmasken, anstatt mit Bitnummern.

Um z.B. Bit 0 zu löschen musst du schreiben:

cbr flags, 1<<0

setzen erfolgt nach gleichem Schema

sbr flags, 1<<0

Ändere das mal bei dir.

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und wieso flags?

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ersetze "flags" durch ein Register deiner Wahl. War nur ein Beispiel.

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schätze mal, hier liegt der Hund im Pfeffer:

.equ PIN_E    = 5
.equ PIN_E2   = 6
.equ PIN_RS   = 4

Das sollten alles Zweierpotenzen sein, wenn du einzelne Pins selektieren 
willst.

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habs mal geändert ist das korrekt so?
.include "m32def.inc"
 
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def lcdno = r19
 
 
           ldi temp1, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
           out SPL, temp1
           ldi temp1, HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
           out SPH, temp1
 
           ldi temp1, 0xFF    ; Port D = Ausgang
           out DDRD, temp1
 
       sbr lcdno, 1<<0
       rcall lcd_init     ; Display initialisieren
       rcall lcd_clear    ; Display löschen
       cbr lcdno, 1<<0
       rcall lcd_init     ; Display initialisieren
           rcall lcd_clear    ; Display löschen
 

           sbr lcdno, 1<<0
           ldi temp1, 'T'     ; Zeichen anzeigen
           rcall lcd_data
 
           ldi temp1, 'e'     ; Zeichen anzeigen
           rcall lcd_data
           
           ldi temp1, 's'     ; Zeichen anzeigen
           rcall lcd_data
 
           ldi temp1, 't'     ; Zeichen anzeigen
           rcall lcd_data



           cbr lcdno, 1<<0
       ldi temp1, 'T'     ; Zeichen anzeigen
           rcall lcd_data
 
           ldi temp1, 'e'     ; Zeichen anzeigen
           rcall lcd_data
           
           ldi temp1, 's'     ; Zeichen anzeigen
           rcall lcd_data
 
           ldi temp1, 't'     ; Zeichen anzeigen
           rcall lcd_data
 
loop:
           rjmp loop
 
.include "lcd-routines.asm"            ; LCD-Routinen werden hier eingefügt

aber bringen tuts nix...

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh...du hast Bit 0 gestezt in meinem 2. Code war jedoch noch Bit 1...ich 
glaub jetzt gehts...

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, du hast recht.

Du setzt/löscht Bit 0 und prüfst auf Bit 1.

Wenn du dir das bit als Konstante definierst wird das ganze auch besser 
lesbar.

.equ SELECT = 0

sbr lcdno, 1<<SELECT

cbr lcdno, 1<<SELECT

bzw.

sbrs lcdno, SELECT

sbrc lcdno, SELECT

Namen kannst Du dir ja nen passenenden ausdenken.

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja danke...es geht ich hab es auch als konstante definiert...nur steh 
ich jetzt vor der nächsten herausforderung:

http://www.mikrocontroller.net/articles/AVR-Tutori...


konstanter text...so wird das nix mit 2 Controllern ich wüste 
zumindestens nicht wie...

Autor: Thorsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du könntest dir im SRAM ein Speicherbereich nehmen, der so groß wie die 
Zeichenanzahl auf deinem LCD ist.

Alle ausgaben die aufs LCD gehen sollen biegst du dann so um, dass sie 
ins SRAM an die gewünschte Position schreiben.

Den Inhalt vom SRAM gibts du dann von einem Timer gesteuert z.B. alle 
paar ms komplett auf das Display aus. So besteht das Display für dein 
Programm aus einem linear zusammenhängenen Bereich.

Die Aufteilung in Zeilen und Controller macht dann die Routine, die 
alles aufs Display schaufelt.

z.B.

Display mit 4x27 Zeichen (5€-Teil bei Pollin)

Speicher im SRAM ist dann 4x27 = 108 Bytes groß.

Die Schreibroutine selektiert dann zuerst Controller 1, Zeile 1 und 
schaufelt die ersten 27 Bytes raus.
Dann wird auf Zeile 2 umgeschaltet. Addresse und Befehl dafür steht im 
Datenblatt vom Display und raus gehen die nächsten 27 Byte.

gleiches Spiel dann mit Controller 2

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ui...timer so weit bin ich im tutorial noch gar nicht...ich werde wohl 
das Display erstmal 2 Zeilig betreiben und dann später wenn ich mehr 
kann hier weiter machen...

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach noch was...wie kann ich mit Assembler eigene Zeichen erstellen?

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.