Forum: Mikrocontroller und Digitale Elektronik PIC, String aus dem Flash ausgeben


von Werner F. (frewer)


Lesenswert?

Hallo,

ich möchte einen längeren String auf das LCD ausgeben und finde zZt nur 
die Lösung mit der retlw-Tabelle oder jeden Buchstaben schicken.
Mein Problem: Wie kann ich den String aus dem Flash mit Hilfe eines 
Zeigers auslesen?
Im Beispiel (16F8xx) wird ADDRL und ADDRH als bekannt vorausgesetzt. 
Aber wie komme ich an die Adresse im Flash? Habe es probiert mit
Tab:
  movlw  3
  addwf PCL,w
  movwf ADDRL
  return
 dt "Teststring",0
Dachte, dass ich den Programmzähler (+3) - das müsste der Anfang des 
Stringa sein - in ADDRL abspeichere und damit dann EEADR und EEADRH 
lade.
Danach
  BSF STATUS, RP0 ;Bank 3
  BSF EECON1, EEPGD ;Point to Program memory
  BSF EECON1, RD ;Start read operation
  NOP ;Required two NOPs
  NOP ;
  BCF STATUS, RP0 ;Bank 2
müsste man ja das 1. Byte in EEDATA vorfinden.
Ich finde da was, aber 0x65,0x34, was mit meinem Text kaum etwas zu tun 
hat.

Hat jemand schon das Problem gelöst?
mfG frewer

von Erich (Gast)


Lesenswert?

>0x65,0x34

Mit asm bei Pic befasse ich mich nicht, nur mit C.

Kann dir aber sagen, daß Tabellen beim Pic in "Retlw" Orgien angelegt 
werden.
Der Opcode 0x34 kommt mir bekannt vor, das ist der "Retlw" Opcode.
Das macht der Compiler automatisch mit "const" Tabellen; es ist 
letztlich einfacher in C zu programmieren.

0x65 ist dementsprechend die Konstante, als Ascii interpretiert das "e".
Dazu muss man auch wissen, daß Pics nur "word" Werte in Flash ablegen, 
wobei das "word" ein 14-Bit-Wert ist (bei Pic16).
Im .HEX file ist es little endian Reihenfolge, somit kommt die Konstante 
als 8-Bit-Wert zuerst (0x65), dann die restlichen 6 Bits (0x34).

Gruss

von Werner F. (frewer)


Lesenswert?

zunächst mal vielen Dank für Deine Erklärung. Was mich dennoch wundert 
ist, dass im Datenblatt des PIC16F8xx die beschriebene Routine zwecks 
Lesen aus dem Flash vorhanden ist - wie gesagt es fehlt halt die 
Ermittlung der Adresse der Tabelle im Beispiel.
Natürlich liegst Du mit C richtig, aber das ist ja viel zu einfach und 
wenn es in C ohne Orgie geht, dann müsste es doch auch in Ass gehen.
Die retlw Orgien sind ja furchtbar aufwendig. Wenn ich mir da eine 
Wertetabelle vorstelle!!

Werde mal weiter forschen.
mfG frewer

von Erich (Gast)


Lesenswert?

Nachtrag Syntax für C

const char * const Stringtabelle1[] =
 {
  "Demo Text1" ,
  "das ist der zweite Text" ,
  "und so weiter"
  };

Siehe auch ...
https://www.microchip.com/forums/m650370-print.aspx
http://forum.allaboutcircuits.com/archive/index.php/t-72502.html

von Chris B. (dekatz)


Lesenswert?

Zum Beispiel so ( <data> ist Name/Label der Daten)

BANKSEL <data>
movlw   <data>
BANKSEL EEADRH
movwf   EEADRH
BANKSEL <data>
movlw   HIGH <data>
BANKSEL EEADR
movwf   EEADR

Beispiel stammt für einen 16F690

von Chris B. (dekatz)


Lesenswert?

MIST!!! Natürlich umgekehrt

BANKSEL <data>      ;LSB der Adresse
movlw   <data>
BANKSEL EEADR
movwf   EEADR
BANKSEL <data>      ;MSB der Adresse
movlw   HIGH <data>
BANKSEL EEADRH
movwf   EEADRH
.
.
.
und dann weiter wie im Datasheet.

von Werner F. (frewer)


Lesenswert?

herzlichen Dank für die vielen Informationen. Ich habe den 16F877. Nach 
einigen Nachforschungen im Flash-Speicher habe ich gesehen, dass die 
Direktive 'dt' das Feld selbst in einen Block retlw 'T', retlw 'e' usw 
aufteilt. Dann funktioniert das Einlesen des Strings ganz einfach:

; NUllterminierten String ausgeben (evtl. 256 Byte Grenze beachten !)

LCD_String:
  movlw   .0           ; zu Beginn Akku auf 0 setzen (1.Zeichen)
  movwf   Adresse
LCD_String_01:
; Adresse wird zum PCter hinzugezählt
  movwf   Adresse      ; aktuelle Stringposition
  call    String       ; <-- hier wird das Zeichen geholt
  andlw   0x0FF        ; Ende der Nachricht wenn NULL
  btfsc   STATUS, Z
  goto    mende        ; Aussprung
  call    Lcd_printc   ; Zeichen ausgeben
  movf    Adresse, W   ; hole Adresse in Akku
  addlw   .1           ; und das nächste Zeichen
  goto    LCD_String_01

mende:
  sleep
  goto   $
;*********************************************************
; hier steht ein ganzer Block mit retlw 'Buchstabe bzw 0' entsprechend 
der
; Stringzeile dt .....
String:
    addwf PCL ,f     ; addiere Akku zum PCtr
dt "Teststring",0    ; im Flash retlw 'T', usw

Mit diesem programmteil hat es bei mir bestens funktioniert. Es ist zwar 
gegenüber dem AVR oder 51 alles ein bisschen kompliziert aber immerhin. 
Jetzt muss ich noch das Problem mit der 256 Byte-Grenze lösen und vor 
allem zuerst mal verstehen.
mfG frewer

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Bei PIC's, die selbst in ihren eigenen Flash schreiben können, ist das 
Ganze doch extrem einfach: Einfach den String als Daten deklarieren und 
hinein in den Code. Wenn du mit ASCII 0..127 auskommst, dann passen dort 
sogar 2 Zeichen hinein. Ich hatte das mal gemacht, um mit nem PIC16F874 
ein Grafik-LCD (Pollin ALPS-LSU) anzusteuern und hatte mir die Ziffern 
als Bitmap in den Flash gelegt.

Schau dir einfach mal das Beispiel an.

W.S.

von Ottmar K. (wil1)


Angehängte Dateien:

Lesenswert?

Hallo Werner,

ich verwende zur LCD-Ausgabe die angehängte Routine. Diese arbeitet mit 
Pointer-H-Byte auf die Page und Pointer Low-Byte auf die Position des 
Ausgabezeichens in der Page. Die Routine habe ich bei 
[http://www.sprut.de] abgespickt und etwas angepasst.

mfG Ottmar

von Peter D. (peda)


Lesenswert?

Werner Freytag schrieb:
> Es ist zwar
> gegenüber dem AVR oder 51 alles ein bisschen kompliziert aber immerhin.

Ja, beim 8051 ist es am einfachsten:
1
  mov    dptr, #adresse  ; zeige auf Array
2
  clr    a               ; Displacement = 0
3
  movc   a, @a+dptr      ; hole Byte
4
...
5
  inc    dptr            ; zeige auf nächstes Byte


Peter

von Werner F. (frewer)


Lesenswert?

Vielen Dank Ottmar und Peter,

Ottmar K. schrieb:
> Die Routine habe ich bei
> [http://www.sprut.de] abgespickt
wo hast Du die Routine bei SPRUT gefunden??????

Deine Routine oder die von SPRUT - dem PCP (PIC Pabst) - ist auch nicht 
viel einfacher als die meine und ich habe nunmehr mit LCD_Anzeige.inc 
eine gute Bedienungsmöglichkeit der gängigen LCD. Dabei werde ich die 
Routine jetzt, nachdem ich mich ein bisschen mehr mit dem PIC auskenne, 
noch so vervollständigen wie meine LCD_Anzeige Routinen für AVR und 
89Cxx51 bzw 89S51. Die laufen bei mir schon lange. D.h. automatische 
Zeilenumschaltung, Erkennen von RETURN, wahlweise oberer oder unterer 
Nibbel eines PORT für die 4Bit Daten, etc.
Dabei habe ich jetzt auch verstanden, dass man in MPLAS ähnlich wie beim 
ASEM 51 einen Bereich für Variablen definieren kann, der bei einer in 
einem anderen Programmteil notwendigen weiteren Definition von Variablen 
ohne nachzudenken?? weiterführen kann. Beim ASEM ist das DSEG 
..Variable: DS Anzahl, beim MPLAS cblock..Variable:Anzahl,... Dabei habe 
ich festgestellt, dass ich den Beginn des Variablenbereiches auch in 
meiner LCD_Anzeige.inc festlegen kann und dann werden die Variablen im 
Hauptprogramm dahinter gehängt.

Weiterhin viel Spass beim PICen oder AVRen (viel einfacher)
mfG frewer

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.