Forum: Mikrocontroller und Digitale Elektronik Tabellen im PIC auslesen


von jmoney (Gast)


Lesenswert?

Ich habe grade erst angefangen, mich mit PICs auseinanderzusetzen.
Ich würde jetzt gern eine Menüroutine schreiben, die ich nur mit dem
Anfang eines Textes füttern muss, um den ganzen Text auf einem LCD
anzeigen zu können. Z.B. eine Schleife, die 16 mal hintereinander einen
Wert abfragt und ausgibt. Eine verlinkte Liste also im Prinzip. Das
muss eigentlich noch nicht mal verlinkt sein, wenn ich in einem immer
ein Hilfsregister als Adressspeicher incrementieren würde. Auslesen
kann man dann ja über PCL, wie bei
http://www.ic.unicamp.br/~celio/mc404/pic/pic_for_programmers.html sehr
schön beschrieben.
Bleibt die Frage, wie ich die Daten in den Programmspeicher bekomme.
Einfach Eintippen ist ja nicht..
Außerdem: Sehe ich das richtig, dass man beim PIC nur ganze Register
testen kann, wenn man zB ein Literal davon abzieht und STATUS, Z
testet? Byte-Tests oder sowas gibt es ja nicht in dem Sinn.
Kennt jemand eine Lösung für eins meiner Probleme (in Assembler)? Bitte
so einfach wie möglich schreiben, weil ich total neu in Assembler und
Programmieren generell bin, mal von einfachen Delphiprogrammen
abgesehen.

von Dominik S. Herwald (Gast)


Lesenswert?

Ich habe zwar auch nicht viel Ahnung von ASM (schreibe die Programme in
Pascal) aber einen wichtigen Befehl hab ich mir dann doch angeeignet:

dt 15,'bla','blubb',10,'ein Text',17,45,145,235;

Mit DT = Define Table kann man beliebige Byte Werte bequem im Speicher
ablegen...

MfG,
Dominik S. Herwald

von jmoney (Gast)


Lesenswert?

Danke vielmals, das hat mir schon sehr geholfen. Es hat mich vor allem
auf die unglaublich abwegige Idee gebracht, mir mal die MPLAB Hilfe
anzuschauen ;)

von Peter D. (peda)


Lesenswert?

"...unglaublich abwegige Idee..."

scheint wirklich sehr abwegig zu sein, die DT-Anweisung nutzt nämlich
fast niemand.

Sie wird vom Assembler in die RETLW-Anweisung übersetzt, ist also nur
eine viel bequemere Schreibweise.

Man sieht leider oft PIC-Texte mit seitenlangen RETLWs (für jedes Byte
extra). Schade um die viele Schreibarbeit und viel Vergnügen, wenn da
mal ein Text geändert werden muß.


Und nicht vergessen, der PIC ist segmentiert !!!
Wenn also Deine Tabelle über eine oder mehrere Segmentgrenzen geht,
reicht es nicht mehr, nur PCL mit dem Index zu laden, Du must dann auch
noch das Segment richtig einstellen.
Gab schon viele Leute, die sich wunderten, warum ab einer bestimmten
Tabellengröße das RETLW abstürzt.


Peter

von Ingo Henze (Gast)


Lesenswert?

Segmentierter Speicher?
Und ich dachte, das war nur so eine bösartige Erfindung von Intel aus
den Ur-x86er Zeiten :-)
Kann mich nich gut an die CS DS ES und SS Register erinnern...

von Peter D. (peda)


Lesenswert?

Hier nochmal ein Beispiel mit 2 Tabellen:

http://www.mikrocontroller.net/forum/read-4-24512.html#57487

Die kleine muß komplett im gleichen Segment stehen und die große ist
mit Segmentberechnung:

Bei beiden das "Achtung..." durchlesen, damit sie auch richtig
funktionieren.


Peter

von jmoney (Gast)


Lesenswert?

Danke, eins der beiden müsste für meine Zwecke funktionieren. Erst mal
einarbeiten..

von jmoney (Gast)


Lesenswert?

Ich habe mir das Beispiel angesehen und ich denke auch verstanden. Dann
habe ich in Anlehnung daran meine eigene Version neu geschrieben. Die
funktioniert auch soweit ganz gut. Ich kann einen Bildschrim anzeigen
und per Steuerzeichen macht er auch Zeilenumbrüche. Nur bei der
Subroutine, die mir den Anfang des gesuchten Bildschirms aus der
Tabelle fischen soll, haperts und ich finde einfach nicht den Fehler.
Wäre nett, wenn sich das mal jemand erfahrenes anschauen könnte.

Das Problem ist folgendes: Wenn ich den Akku mit .0 lade und die
Routine aufrufe, zeigt er "Hallo" an, wie er soll. Bei .1 zeigt er
"1. Zeile<Umbruch>2. Zeile" an. Nur bei allem was danach kommt, will
er irgendwie nicht mehr und beendet die Routine mit dem 2. Bildschirm
(1. Zeile...) in den Adressbytes.

Ich bin dankbar für jeden Tipp!

von jmoney (Gast)


Lesenswert?

hab scheinbar den codeausschnitt vergessen..

von jmoney (Gast)


Lesenswert?

Die Forumsoft mag mich nicht. Hier der Code:

Get_Screen_Adr          ;Anfangsadresse des Screens rausfinden
    movf  snr,0
    call  OutLcdDaten
    call  WAIT
    incf  snr,1      ;Screennummer auf Schleife vorbereiten
    movf  snr,0
    call  OutLcdDaten
    call  WAIT
    movlw  high Screen_Tab  ;Anfang der verketteten Liste holen
    movwf  AdrH
    movlw  low Screen_Tab
    movwf  AdrL
GSA_Loop
    movf  snr,0
    call  OutLcdDaten
    call  WAIT
    decf  snr,1      ;beim gesuchten Screen angekommen?
    movf  snr,0
    call  OutLcdDaten
    call  WAIT
    incf  snr,0
    decf  snr,0
    btfsc  STATUS,Z
    return
GSA_Loop2
    call  Get_Char

    movwf  pruef
    incf  pruef,1      ;prüfen, ob Ende des Screens
    btfsc  STATUS,Z
    goto  GSA_Loop

    call  Next_Char    ;Wenn nicht, nächstes Zeichen
    goto  GSA_Loop2

Get_Char movf  AdrH,0
    movwf  PCLATH
    movf  AdrL,0
    movwf  PCL
Screen_Tab  DT 'N', "Hallo", 0xff, "1. Zeile", 0xfe , "2.
Zeile", 0xff, "3. Zeile", 0xfe, "4. Zeile", 0xff, "5. Zeile",
0xfe, "6. Zeile", 0xff

von jmoney (Gast)


Lesenswert?

das war jetzt natürlich die falsche version. hier nochmal ohne den müll
zwischendurch, sorry für die vielen postings:

Get_Screen_Adr          ;Anfangsadresse des Screens rausfinden
    incf  snr,1      ;Screennummer auf Schleife vorbereiten
    movlw  high Screen_Tab  ;Anfang der verketteten Liste holen
    movwf  AdrH
    movlw  low Screen_Tab
    movwf  AdrL
GSA_Loop
    decf  snr,1      ;beim gesuchten Screen angekommen?
    incf  snr,0
    decf  snr,0
    btfsc  STATUS,Z
    return
GSA_Loop2
    call  Get_Char

    movwf  pruef
    incf  pruef,1      ;prüfen, ob Ende des Screens
    btfsc  STATUS,Z
    goto  GSA_Loop

    call  Next_Char    ;Wenn nicht, nächstes Zeichen
    goto  GSA_Loop2

Get_Char movf  AdrH,0
    movwf  PCLATH
    movf  AdrL,0
    movwf  PCL
Screen_Tab  DT 'N', "Hallo", 0xff, "1. Zeile", 0xfe , "2.
Zeile", 0xff, "3. Zeile", 0xfe, "4. Zeile", 0xff, "5. Zeile",
0xfe, "6. Zeile", 0xff

von Steffen (Gast)


Lesenswert?

1. Umständlicher geht es ja wohl kaum (sorry, ist nicht böse gemeint)

GSA_Loop
    decf  snr,1      ;beim gesuchten Screen angekommen?
    incf  snr,0      ; snr+1 --> in w?????
    decf  snr,0      ; snr-1 --> in w?????
    btfsc  STATUS,Z
    return

GSA_Loop    decfsz snr,1      ;beim gesuchten Screen angekommen?
            goto   L1
            return
L1          .....

würde so ziehmlich das Gleiche bewirken.

2. Ein Label (Unterprogramm) Next_Char gibt es nicht (in deinem Code).

3. AdrH und AdrL wird in deinem Code nirgendwo geändert. Was soll die
Routine eigentlich machen? Dem Name nach die Adresse finden oder was
sonst.

Steffen

von jmoney (Gast)


Lesenswert?

1. Das eine incf und decf-paar war irgendwie dazu gedacht, snr
zwischendurch auf dem display anzuzeigen, denn nach der display-routine
wäre ja das Z-Bit nicht mehr gesetzt. Trotzdem hätte ich es natürlich
in f schreiben müssen.
Ob ich jetzt
GSA_Loop
    decf  snr,1      ;beim gesuchten Screen angekommen?
    btfsc  STATUS,Z
    return
oder deine Version schreibe kommt denke ich aufs Selbe raus.

2.&3. Das ist nur ein Auszug des Codes. Next_Char incrementiert AdrL
und bei Überlauf auch AdrH.

Trotzdem danke für die Antwort. Ich poste wenn ich heim komme mal die
gesamte Routine.

von Steffen (Gast)


Lesenswert?

Na dann sehn wir mal.
Unter den Vorraussetzungen müsste deine Routine eigentlich
funktionieren. Ich sehe auf Anhieb jedenfalls keinen Fehler.

Steffen

von jmoney (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe jetzt mal die komplette Routine angehängt. Ich hoffe, er lädt
die Datei diesmal hoch..
Kann es sein, dass ich den PIC schon nach grob geschätzt 100-200 mal
flashen kaputtgeflasht habe? Ich dachte 1000 mal halten die locker
aus.. Mittlerweile hört er nämlich nach dem 4. Zeichen auf. Das würde
zu dem unberechenbaren Verhalten passen.. Und wenn ich einen Befehl
irgendwo zwischendrin weglasse, zeigt er ein Zeichen mehr an, also ist
wohl immer das selbe Word im Programmspeicher betroffen.

von Steffen (Gast)


Lesenswert?

100-200 Programmierzyklen sollten eigentlich kein Problem sein. Könnte
es evtl. sein, dass der WDT überläuft?

In deinen Routinen kann ich eigentlich keinen Fehler entdecken. Hast Du
die Routinen mal durch den Simulator gejagt?

Steffen

von jmoney (Gast)


Lesenswert?

simulator hab ich bis jetzt noch nicht benutzt/gefunden.freut mich,dass
mein code keine offensichtlichen fehler enthält, das gibt mir hoffnung.
wdt war glaub ich aus, kann ich aber vor sonntag nicht nachschauen weil
ich 1. nicht daheim sein werde und 2. ist 1. mai, also werde ich wohl
nicht fähig sein;)

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.