Hallo, ich muss heute Abend noch einmal nerven... und zwar habe ich leider ein Problem in meinem Programm. Ich habe ein Programm auf einem PIC18F1220 geschrieben, welches eine analoge Spannung misst und hinterher den Wert der Spannung auf einer 3-stelligen 7Segmentanzeige ausgibt... Nun funktioniert mein Programm bis zur Ausgabe perfekt. Erst bei der Ausgabe entsteht ein Problem. Hier erstmal der Problematische Teil: Segmente addwf PCL,W,1 retlw b'11000000' ; Zero retlw b'11111001' ; One retlw b'10100100' ; Two retlw b'10110000' ; Three retlw b'10011001' ; Four retlw b'10010010' ; Five retlw b'10000010' ; Six retlw b'11111000' ; Seven retlw b'10000000' ; Eight retlw b'10010000' ; Nine Ich springe also für die Ausgabe des Wertes auf der 7-Segmentanzeige zur Sprungmarke "Segmente". Hier addiere ich den in W-gespeicherten Anzeigewert des jeweiligen Segmentes zum PCL, damit dieser dann zur jeweiligen retlw-Zeile springt, sich den Wert für den PORTB holt und wieder in den Code zurückkehrt. Leider springt das Programm aber immer zur Sprungmarke Zero. Vollkommen egal welcher Wert in W gespeichert ist, es wird immer Zero ausgeführt und dementsprechend Null angezeigt. Meine ADC-Wandlung klappt perfekt und sonst gibt es auch keine Probleme, der ADDWF Befehl funktioniert in anderen Speicherzellen auch sehr gut, ich weiss nicht warum es hier nicht klappt... Habe ich etwas nicht bedacht und einen großen Fehler in der ganzen Sache? Vielleicht kennt jemand das Problem und hat nen Tipp für mich.... LG Fred
Ich vermute, "segmente" liegt recht Nahe an einer Page-Grenze. Beispiel: Wenn segmente = 0x01fd ist, dann springt der Prozessor je nach W zu 0x1fe, 0x1ff, 0x100 (statt 0x200). PCH bleibt 0x1. PCH wird nicht automatisch incrementiert wenn durch deine Addition PCL einen überlauf hat. (Vermute ich nur)
Page Grenze? Du meinst, dass der PCL einen Überlauf hat und daher nicht klarkommt?
Genau, Page Grenze könnte es sein. Weiterhin belegt der RETLW 2 Bytes, also vorher mit 2 multiplizieren onder verschieben. So hab ich das für eine ähnliche Anwendung gelöst, bei mir ein 18F2520 Holger ; ----------------------------------------- ; input: W Zahl 0-7 ; return W mit gesetztem Bit 0-7 get_bit: andlw .7 ; Nur 0- 7 zulässig mullw .2 ; mit 2 multiplizieren movlw HIGH(bits) ; Highteil von Tabelle holen movwf PCLATH movlw LOW(bits) ; Lowteil von Tabelle holen addwf PRODL,w ; Offset dazu btfsc STATUS,C ; Überlauf ? incf PCLATH,f ; ja um eins erhöhen movwf PCL bits: retlw B'00000001' ; gesetztes Bit 0 retlw B'00000010' retlw B'00000100' retlw B'00001000' retlw B'00010000' retlw B'00100000' retlw B'01000000' retlw B'10000000'
Fred schrieb: > Segmente > addwf PCL,W,1 Das ist falsch, richtig wäre: > Segmente > addwf PCL,F Sonst addierst Du den PCF und W, und legst das Ergebnis in W (statt im PCF) ab.
siehe Beitrag "[PIC] Assembler Problem Sprungtabelle in Externer ASM Datei" Du mußt PCLATH auf das high-Byte des Labels "segmente" setzen.
Wenn ich mich recht erinnere, ist die "Page" bei den 18er PICs nur 128 Worte groß. Also ist die Chance ziemlich hoch, einen PCL-Überlauf zu erwischen. Es gibt zwei Möglichkeiten zur Lösung des Problems: 1. Tabelle an den Anfang des Programms legen, direkt hinter die Interuptvektoren 2. Tabelle ans Programmende legen und mit ORG eine runde Adresse festlegen. Alternativ geht auch noch der Befehl TABLRD, dafür muss die Tabelle im Speicher angelegt werden.
Herzlichen Dank für die ganze nette Hilfe und Unterstützung... der Einstieg ist gar nicht so einfach, es gibt immer wieder so Kleinigkeiten die man nicht weiss, vergessen hat oder einfach wissen muss^^ Ihr habt mir damit grad bestimmt mehrere Stunden oder Tage Sucherei erspart. Herzlichen Dank, ich arbeite mich da mal eben etwas durch. Muss das erstmal alles verstehen jetzt hier an Input^^ LG Fred
Hm, anscheinend bin ich doch zu doof dafür... Egal mit welchen Mitteln, es läuft einfach nicht... Habe versucht einen org-Befehl davor zu setzen, dann läuft nix mehr.... Die Lösung von Dir, Holger, habe ich leider nicht richtig verstanden, aber auch versucht. Ich denke die läuft einfach nicht weil ich sie nicht verstanden und mit Sicherheit was falsch gemacht habe... Ich verstehe bei der Lösung nicht, wo HIGH usw herkommt und was das bewirken soll... komme mir grad etwas doof vor... Konnte leider auch bei sprut.de keine weiteren Hinweise finden. Was mich noch vor ein Rätsel stellt: Wie bekomme ich denn überhaupt die Programmadresse raus, in der sich in meinem Programm irgendein Befehl befindet? Ich meine ich habe das vor langer Zeit schonmal gemacht, aber komme nicht mehr darauf.... Ich hoffe, ich nerve nicht zu sehr. Werde gleich auch nochmal inne Bücher schauen ob ich dort was hilfreiches finde, ansosnten bin ich fpr jeden Tipp sehr dankbar. LG Fred
Fred schrieb: > Habe versucht einen org-Befehl davor zu setzen, dann läuft nix mehr.... Kannst Du dann mal posten, wie es jetzt ausschaut? Fred schrieb: > Ich verstehe bei der Lösung nicht, wo HIGH usw herkommt und was das > bewirken soll... HIGH() gibt das höherwertige Byte des Wertes zurück. Mit welchem Assembler arbeitest Du denn eigentlich?
Arbeitest du mit MPLab ? Würde ich dir dringen raten diesen zu nehmen, Der hat auch einen Simulator drin, damit kann man das schön testen. Zu meinem Beispiel, dur brauchst doch nur get_bit: mit deinem Einsprung zu ersetzen (mit CALL aufrufen !!) und die RETLW mit deinen Werten. Poste mal deinen Versuch. Holger
Also wenn ich meien Ausgabe starten will, rufe ich mit CALL "Segmente" auf, dort wird dann der Wert der Anzeigezahl geladen. So sieht es aktuell wieder aus, weil alles andere nicht richtig funktionierte: Segmente addwf PCL retlw b'11000000' ; Zero retlw b'11111001' ; One retlw b'10100100' ; Two retlw b'10110000' ; Three retlw b'10011001' ; Four retlw b'10010010' ; Five retlw b'10000010' ; Six retlw b'11111000' ; Seven retlw b'10000000' ; Eight retlw b'10010000' ; Nine Du meintest jetzt ich sollte deine kompletten Zeilen unterhalb von get_bit mit aufnehmen oder? Ich habe nur noch nicht so richtig verstanden was die machen, also wofür du die benutzt. An sich dachte ich, mit einem "org 0xXX" vor der Segmenttabelle den Speicherort der Tabelle festzulegen, sodass mein PCL keinen Überlauf mehr haben kann. Denn das scheint ja nun das Problem zu sein wenn ich das richtig verstanden habe.... Ich hoffe ich nerve nicht zu sehr. LG Fred
hier wird W mit 2 multipliziert, das Ergebnis steht dann in PRODL (RETLW belegt 2 Bytes) mullw .2 ; mit 2 multiplizieren hier wird der High Teil der Adresse von "bits" in den Adresspeicher geholt HIGH ist eine Hilfe vom Compiler/Assembler, der holt nur den höherwertigen Teil, dieser kommt nach PCLATH movlw HIGH(bits) ; Highteil von Tabelle holen movwf PCLATH gleiches mit dem Niederwertigen Teil, dann gleich noch der Wert aus der Multiplikation dazu, in W steht jetzt der LOW Teil movlw LOW(bits) ; Lowteil von Tabelle holen addwf PRODL,w ; Offset dazu hat es einen Übertrag gegeben, dann wird Carry gesetzt und der High Teil des Programmcounters um eins heraufgesetzt btfsc STATUS,C ; Überlauf ? incf PCLATH,f ; ja um eins erhöhen und hier kommt der Absprung, der Programmcounter wird auf den entsprechenden RETLW gesetzt movwf PCL bits: retlw B'00000001' ; gesetztes Bit 0 retlw B'00000010' retlw B'00000100' retlw B'00001000' retlw B'00010000' retlw B'00100000' retlw B'01000000' retlw B'10000000' Füllst du bei dir W auch richtig ? Teste doch mal wenn du direkt einen Wert reinschreibst mit movlw .1 Welchen Assembler nutzt du ? Holger
Ich nutze MPLAB. Dir erstmal ganz herzlichen Dank für die Erklärung. Die Verwendung von "HIGH" kannte ich noch gar nicht. Jetzt wird einiges klarer! Ich sehe mir das mal grad in der Simulation an^^ Damit umgeht man dann also das Problem der Page-Grenze.... Coole Sache
Okay, es rennt nun, habe das Ganze auch im Großen und Ganzen verstanden wie ich denke. Dir erstmal ganz ganz herzlichen Dank. Woher weiss man als Anfänger denn sowas über HIGH-Befehle und so? Habe das bei sprut und auch in den Büchern die ich hier habe bisher noch nirgends gefunden.... will ja nicht immer andere Leute nerven wenn ich mal was nicht weiss^^ Stehe nun aber noch vor einem anderen Rätsel... ein Segment geht bei meiner Anzeige nie ganz aus, es leuchtet immer ganz leicht nach. Der PIC Pin geht dort auch nicht voll auf´s H-Pegel um es abzuschalten.... Finde da aber leider keinen Grund für, da auch beim Debuggen der PIN definitv auf H ist und alles richtig rennt. Die Hardware ist auch okay, also keinerlei Lötverbindungen oder so.... Aber erstmal ganz herlichen Dank, ich denke ich werde mir die Platine nochmal mit der Lupe ansehen, irgendwo muss es ja herkommen^^ LG Fred
Woher weiss man sowas. Nach Codebeispielen im Internet suchen, Handbuch vom MPLab lesen oder eben hier fragen. Zum Beschreiben der Ports immer dem LATx benutzen, nicht den Port direkt. Holger
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.