Autor Thema: Assembler: 2x16 Display effektiver ansteuern?  (Gelesen 4143 mal)

Offline Nase

  • Newbie
  • *
  • Beiträge: 15
    • Profil anzeigen
Assembler: 2x16 Display effektiver ansteuern?
« am: November 17, 2013, 20:46:33 Nachmittag »
Hallo in die Runde,

gibt es eigentlich eine bessere (effektivere) Vorgehensweise, ein 2x16 Display anzusteuern?
Mein Programm lehnt sich an die Vorgaben von Sprut, erscheint mir aber etwas umständlich.
hier mal mein momentan verwendeter Code
movlw 0x1 ; Display löschen und cusor home
call OutLcdControl
; Display komplett bescheiben(2x16 Zeichen)
;obere Spalte (Adresse 80 - 8F)
movlw 'S'
call OutLcdDaten
movlw 'y'
call OutLcdDaten
movlw 's'
call OutLcdDaten
movlw 't'
call OutLcdDaten
movlw 'e'
call OutLcdDaten
movlw 'm'
call OutLcdDaten
movlw 'n'
call OutLcdDaten
movlw 'e'
call OutLcdDaten
movlw 'u'
call OutLcdDaten
movlw 's'
call OutLcdDaten
movlw 't'
call OutLcdDaten
movlw 'a'
call OutLcdDaten
movlw 'r'
call OutLcdDaten
movlw 't'
call OutLcdDaten
movlw ' '
call OutLcdDaten
movlw ' '
call OutLcdDaten
;Sprung zur rechten Seite
movlw 0xC0 ; Sprung zur 2. Zeile (Adresse C0 - CF)
call OutLcdControl ;
;untere Spalte
movlw 'Z'
call OutLcdDaten
movlw 'e'
call OutLcdDaten
movlw 'i'
call OutLcdDaten
movlw 't'
call OutLcdDaten
movlw ' '
call OutLcdDaten
movlw 'E'
call OutLcdDaten
movlw 'i'
call OutLcdDaten
movlw 'n'
call OutLcdDaten
movlw 's'
call OutLcdDaten
movlw 't'
call OutLcdDaten
movlw 'e'
call OutLcdDaten
movlw 'l'
call OutLcdDaten
movlw 'l'
call OutLcdDaten
movlw 'e'
call OutLcdDaten
movlw 'n'
call OutLcdDaten
movlw '?'
call OutLcdDaten
return


OutLcdDaten
movwf LcdDaten ; Byte in LcdDaten zwischenspeichern
call LcdBusy ; warten bis Display bereit ist
movf LcdDaten, w ; Byte zurück nach W holen
andlw H'F0' ; low-Teil löschen
movwf LcdPort ; Hi-teil Daten schreiben
bsf LcdRs ; Daten
bsf LcdE ; Enable LcdBus
nop
bcf LcdE ; Disable LcdBus
swapf LcdDaten, w ; Byte verdreht nach W holen
andlw H'F0' ; High Teil löschen
movwf LcdPort ; Low-teil Daten schreiben
bsf LcdRs ; Daten
bsf LcdE
nop
bcf LcdE ; Disable LcdBus
bcf LcdRs ;
return




Für Tipps und Vorschläge wäre ich sehr Dankbar!

Gruß Jens

Offline deKatz

  • Jr. Member
  • **
  • Beiträge: 56
    • Profil anzeigen
Re: Assembler: 2x16 Display effektiver ansteuern?
« Antwort #1 am: November 18, 2013, 13:06:34 Nachmittag »
Das hier soll nur ein Denkanstoss sein, wie man es machen kann.
Dies Variante z.B. ist nicht für mit "\0" terminierte Strings gedacht!!
(habe ich zwar auch, aber gerade nicht auf dem Stick)

1. Zeilenlänge definieren

LcdLineLength equ .16 ;Zeilenlänge des Displays (hier 16 Zeichen)

2. Benötigte Variablen
    cblock  xxxx     ;irgendwo im RAM
        LCD_bufferX : LcdLineLength ;Displaypuffer (1 Zeile)
    ENDC
   
       
    cblock 0x70     ;im Globalen RAM !!!            
charpos             ;Start-Position
charcount             ;Zeichenanzahl zur Ausgabe
                                LcdDaten                    ;auszugebendes Zeichen
    endc
       
3. Ein Macro welches Zeile, Spalte und Textlänge enthält und die enstprechenden
Variablen initialisiert:

SET_LCDram_ptr MACRO line, column, n_char
if (line==1) | (line==3)
movlw b'10000000' + column - 1
movwf charpos
if (line==3)
movlw 0x14
addwf charpos,F
endif
endif
if (line==2) | (line==4)
movlw b'11000000' + column - 1
movwf charpos
if (line==4)
movlw 0x14
addwf charpos,F
endif
endif
movlw n_char
movwf charcount
ENDM
               
4. Die eigentlich Ausgaberoutine:
updateDisplayLineX
BANKSEL LCD_bufferX                            ;Pufferanfang
movlw LCD_bufferX ;indirekter RAM-Zugriff
movwf FSR
lineX
movfw charpos                                   ;Wohin im Display?
movwf LcdDaten
PAGESEL OutLcdControl
call OutLcdControl
movfw INDF ;ASCII-Zeichen aus Buffer
movwf LcdDaten
call OutLcdDaten
incf FSR ;Zeiger auf nächstes Zeichen
incf charpos ;Position nächstes Zeichen
decfsz charcount ;alle übetragen??
goto lineX
return
Das wars!
   
Die Anwendung schreibt Zeichen in den Puffer.
Die Ausgabe erfolgt dann durch Angabe der Zeilennumer (1...4),
der Spaltennummer (1...Zeilenlänge) und Anzahl der Zeichen:

    SET_LCDram_ptr 1, 1, 8      ;Zeile 1, Spalte 1, 8 Zeichen
PAGESEL updateDisplayLineX
call updateDisplayLineX
   
oder
    SET_LCDram_ptr 3, 9, 6      ;Zeile 3, Spalte 9, 6 Zeichen
PAGESEL updateDisplayLineX
call updateDisplayLineX
   
oder, oder......

Hinweis: Die Routinen habe ich schnell aus einem Programm Rauskopiert welches
ca. 4000 Zeilen umfasst und mehr als 1 ROM-Page und mehr als 1 RAM-Bank
belegte...daher die BANKSEL und PAGESEL Anweisungen kann man daher bei
kleinen Anwendungen weglassen wenn man sich innerhalb 1 FlashPage bewegt.
 

Offline deKatz

  • Jr. Member
  • **
  • Beiträge: 56
    • Profil anzeigen
Re: Assembler: 2x16 Display effektiver ansteuern?
« Antwort #2 am: November 18, 2013, 13:07:28 Nachmittag »
Ähhhh Sorry, die Formattierung ist etwas suboptimal geworden >:(......

Offline Nase

  • Newbie
  • *
  • Beiträge: 15
    • Profil anzeigen
Re: Assembler: 2x16 Display effektiver ansteuern?
« Antwort #3 am: November 18, 2013, 22:32:38 Nachmittag »
Danke @deKatz,

das mit der Formatierung macht nichts, kann man ja editieren ;-)

Habe schon mal ein wenig damit herumgespielt, sehr Interessante Sache!
Muss dazu sagen, dass ich absoluter Neuling in Sachen Programmierung, insbesondere Macros u.ä. bin.
Mal sehen, ob ich da noch hinter steige.

Ich habe vor, einiges an Text anzeigen zu lassen.
Auf meine Art und Weise ist der Programmspeicher aber in Null,nix voll.
Nun will ich die Texte im EEPROM abspeichern und entsprechend abrufen.

Nachdem ich mich wieder bei Sprut umgeschaut habe, gehe ich mal davon aus,
dass das die (sogenannten) Null- terminierten Strings sind, oder irre ich mich da jetzt.

Offline deKatz

  • Jr. Member
  • **
  • Beiträge: 56
    • Profil anzeigen
Re: Assembler: 2x16 Display effektiver ansteuern?
« Antwort #4 am: November 19, 2013, 11:56:56 Vormittag »
Weiss jetzt nicht auf welchen Sprut-Beitrag du dich beziehst, aber es ist natürlich besser wenn man gleich mit "richtigen" Strings arbeitet - also mit ASCII-NULL ('\0') abgeschlossene Strings wie z.B. in C üblich.
Die Routinen dafür sind aber genau so simpel.
Ich hänge mal ein kurzes Programm dran. Kannst du am Simulator durchsteppen, und dabei die wichtigsten Variablen im Watchwindow und das RAM im FileRegister Window ansehen.
Das MACRO ist etwas überarbeitet und die Ausgaberoutine läßt sich schon beinahe wie in Hochsprache anwenden
also:  < LCDwirteXY  Zeile, Spalte, Teststring >
(beliebige Speicherbänke werden dabei aber nicht berücksichtigt, aber für ne Demo langt es glaube ich).
;**********************************************************************
;                                                                     *
;    Files Required: P16F737.INC                                      *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:   Testprogramm ASCII-NULL terminierte Strings             *
;             an Display senden (mit Positionsangabe bei              *
;   mehrzeiliogen Displays                                  *
;                                                                     *
;**********************************************************************


list p=16f737 ; list directive to define processor
#include <P16F737.inc> ; processor specific variable definitions

__CONFIG    _CONFIG1,  _CP_OFF & _CCP2_RC1 & _DEBUG_OFF & _VBOR_2_0 & _BOREN_0 & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
__CONFIG    _CONFIG2,  _BORSEN_0 & _IESO_OFF & _FCMEN_OFF


;***** VARIABLE DEFINITIONS ************
cblock 0x20
text1 : 20 ;z.b. 2-zeiliges Display
text2 : 20
charx ;wird nur zur Erzeugung der Testtexte verwendet
counter
endc

cblock 0x70
charpos             ;Start-Position
stringstart ;Anfang des Strings
LcdDaten                    ;auszugebendes Zeichen
endc

;********** MACROS *************
LCDwriteXY MACRO line, column, stringadresse
if (line==1) | (line==3)
movlw b'10000000' + column - 1
movwf charpos
if (line==3)
movlw 0x14
addwf charpos,F
endif
endif
if (line==2) | (line==4)
movlw b'11000000' + column - 1
movwf charpos
if (line==4)
movlw 0x14
addwf charpos,F
endif
endif
movlw stringadresse
movwf stringstart
call WriteDisplayXY
ENDM


;**********************************************************************
ORG 0x000 ; processor reset vector
  goto main


ORG 0x004 ; interrupt vector
retfie


main
;*********** Testdaten erzeugen *****************
movlw 'A' ;Erzeugt "ABCDEFGH" in <text_1>
movwf charx
movlw .8 ;Anzahl Zeichen
movwf counter
movlw text1 ;Startadresse wo Zeichen gespeichert werden
movwf FSR
fill_1
movfw charx ;Zeichen via Zeiger (FSR) speichern
movwf INDF
incf FSR ;nächste Position
incf charx ;nächstes Zeichen "berechnen"
decfsz counter ;Zähler auf 0 ??
goto fill_1 ;nein
clrf INDF ;ja, dann ASCII-NULL anhängen

movlw 'p' ;Erzeugt "pqrstuvwxyz{|}" in <text_2>
movwf charx
movlw .14 ;Anzahl Zeichen
movwf counter
movlw text2 ;Startadresse wo Zeichen gespeichert werden
movwf FSR
fill_2
movfw charx ;Zeichen via Zeiger (FSR) speichern
movwf INDF
incf FSR ;nächste Position
incf charx ;nächstes Zeichen "berechnen"
decfsz counter ;Zähler auf 0 ??
goto fill_2 ;nein
clrf INDF ;ja, dann ASCII-NULL anhängen

;********* Eigentliche Ausgabe **************
LCDwriteXY 1, 1, text1
LCDwriteXY 2, 4, text2

goto $ ; = HALT

;-----------------------------------------------------------------
WriteDisplayXY
movfw stringstart ;Zeiger auf String
movwf FSR
lineX
movfw charpos         ;Wohin im Display?
movwf LcdDaten
call OutLcdControl
movfw INDF ;ASCII-Zeichen aus Buffer
bz end_of_string ;Stringende wenn '\0'
movwf LcdDaten
call OutLcdDaten
incf FSR ;Zeiger auf nächstes Zeichen
incf charpos ;Position nächstes Zeichen
goto lineX
end_of_string
return

OutLcdControl ;Dummy zum Testen
return

OutLcdDaten ;Dummy zum Testen
return

END


Offline Nase

  • Newbie
  • *
  • Beiträge: 15
    • Profil anzeigen
Re: Assembler: 2x16 Display effektiver ansteuern?
« Antwort #5 am: November 29, 2013, 19:11:29 Nachmittag »
..hat etwas länger gedauert....

Danke, das hat mich wirklich weitergebracht.

Ich hab's mal für meine Bedürfnisse angepasst, sieht jetzt so aus:
       

org  H'2100'                ; Adresse des EEPROM für den Brenner
de  "Hallo World", 0   ; einen nullterminierten String
de  "Systemtest",0


text1 equ 0x2100
text2 equ 0x210c

;********** MACROS *************
LCDwriteXY MACRO line, column, stringadresse
if (line==1) | (line==3)
movlw b'10000000' + column - 1
movwf charpos
if (line==3)
movlw 0x14
addwf charpos,F
endif
endif
if (line==2) | (line==4)
movlw b'11000000' + column - 1
movwf charpos
if (line==4)
movlw 0x14
addwf charpos,F
endif
endif
movlw stringadresse
movwf stringstart
call WriteDisplayXY
ENDM

;||||||||||||||Hauptroutine|||||||||||||||||||||||||||||||||||||||||||
;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

mainloop
;********* Eigentliche Ausgabe **************
LCDwriteXY 1, 1, text1
LCDwriteXY 2, 1, text2

goto $ ; = HALT


;**************Ausgaberoutine***************
; LCDwriteXY Zeile, Spalte, Startadresse*
;*******************************************
WriteDisplayXY
movfw stringstart ;Zeiger auf String
BSF    STATUS, RP1     ;
        BCF    STATUS, RP0     ;
        MOVWF  EEADR           ;
BCF STATUS, RP1
lineX
movfw charpos         ;Wohin im Display?
movwf LcdDaten
call         OutLcdControl
BSF STATUS, RP1
BSF          STATUS, RP0     ; 
        BCF          EECON1, EEPGD   ; aus dem EEPROM lesen
        BSF          EECON1, RD      ; EEPROM Leseprozess starten
        BCF          STATUS, RP0     ; 
INCF         EEADR
BCF STATUS,Z
        MOVF       EEDATA, W       ; Die Daten der EEPROM Zelle nach W kopieren
BCF STATUS, RP1
BTFSC STATUS,Z
return
call         OutLcdDaten
incf         charpos ;Position nächstes Zeichen
goto     lineX



habe alles unwichtige rausgenommen, damit es Übersichtlicher ist.

 


* Recent Topics