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.
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
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 ;)
"...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
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...
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
Danke, eins der beiden müsste für meine Zwecke funktionieren. Erst mal einarbeiten..
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!
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
  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
  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
  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.
  Na dann sehn wir mal. Unter den Vorraussetzungen müsste deine Routine eigentlich funktionieren. Ich sehe auf Anhieb jedenfalls keinen Fehler. Steffen
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.
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
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
Mit Google-Account einloggen
  Noch kein Account? Hier anmelden.
 Thread beobachten
 Thread beobachten Seitenaufteilung abschalten
 Seitenaufteilung abschalten