Forum: Mikrocontroller und Digitale Elektronik PIC Probleme mit Empfangsauswertung per UART in ISR


von Jens P. (Gast)


Lesenswert?

Hallo Leute, ich bin gerade dabei einen gewissen Teil eines Protokolls 
(MIDI-Program-Change-Befehle) mit meinem PIC entgegenzunehmen.
Das tut noch nicht so ganz wie ich will.

Der ProgChange-Befehl setzt sich folgendermaßen zusammen:
C nn pp

C= Hex C (bin 12) nn = Channelnumber (in diesem Beispiel noch 0)
pp = Preset von 1 bis 127. Es wird also immer ein Status- und ein 
Datenbyte gesendet.

Schaltung und eigentlicher UART-Empfang funktionieren. Mit folgendem 
Code hab ichs getestet:

ISR    btfss  PIR1, RCIF        ; Pruefen ob Interupt durch Receive 
ausgeloest wurde
    goto  ISREND          ; Wenn nein, gehe zu Ende von ISR
    movfw  RCREG          ; Empfangsregister auslesen
    movwf  preset          ; nach preset schreiben
    call  RS232Send
    bcf    PIR1, RCIF        ; Receive-Interupt-Bit wieder loeschen
ISREND  retfie              ; Zurückkehren aus Interuptroutine



damit kann ich eben eine 3 schicken und bekomme 003 angezeigt usw...



Und dies soll nun die nue ISR mit Auswertung sein, hier passieren 
seltsame, teils unwillkürlich scheinende Dinge. sieht an den 
7-segmentern so aus, also ob teilweise mehrere (alle?) presets 
durchlaufen werden.
Hat vl. jemand einen tip?

ISR    btfss  PIR1, RCIF        ; Pruefen ob Interupt durch Receive 
ausgeloest wurde
    goto  ISREND          ; Wenn nein, gehe zu Ende von ISR
    movfw  RCREG          ; Empfangsregister auslesen
    btfsc  Flags,1          ; Wurde schon ein Statusbyte (Bit1) 
empfangen?
    goto  EmpfangStatusByte    ; Wenn nein gehe zu Empfang Statusbyte
    goto  EmpfangDatenByte    ; Wenn ja, gehe zu Empfan Datenbyte

EmpfangStatusByte
    movwf  Bytetemp        ; Schreibe Empfangsbyte in TempVariable
    movlw  h'C'          ; Als erstes wird der Hexwert "C"(=Programm 
Change)
    subwf  Bytetemp,0        ; vom Sekundären Empfangspuffer abgezogen
    subwf  Channel,0        ; Danach Wird die Kanalnummer abgezogen
    btfss  STATUS,Z        ; Ist das Ergebnis = "0" ?
    goto  MAIN          ; Wenn nein, gehe zurück zu Main

    bsf    Flags,1          ; Markiere dass der erste Teil Empfangen 
wurde
    goto   ISREND          ; Beende ISR

EmpfangDatenByte
    bcf    Flags, 1        ; Setze Empfangsbytezuordnung wieder zurück, 
für die
                    ; Nächste Nachricht
    movwf  Bytetemp        ; Schreibe Empfangsbyte in TempVariable
    sublw  D'127'          ; Ziehe Maximalwert ab
    btfsc  STATUS, Z        ; Ist das Ergebnis Null?
    goto  PresetZuweisung      ; Wenn ja, gehe zur Zuweisung

    btfsc  STATUS, C        ; Ist das Carry-Bit gesetzt?
    goto  PresetZuweisung      ; Wenn ja, gehe zur Zuweisung
    goto   ISREND          ; Wenn nein, dann Wars wohl nix!

PresetZuweisung
    movfw   Bytetemp
    movwf  preset
    goto  ISREND

ISREND  call  RS232Send
    bcf    PIR1, RCIF        ; Receive-Interupt-Bit wieder loeschen
    retfie              ; Zurückkehren aus Interuptroutine



irgendwie versteh ich nicht o ganz wie ich mit dem simulator umgehen 
soll.....

von TK (Gast)


Lesenswert?

Also ich hab nicht den ganzen Code durchforstet, aber der Befehl
GOTO MAIN innerhalb der ISR ist da bestimmt NICHT richtig.
Die ISR sollte eigentlich immer mit RETFIE abgeschlossen werden -
sonst STACK-Overflow und dann undefiniertes Programmverhalten.
Ich würde einfach mal an dieser Stelle weitersuchen.

TK

von Jens (Gast)


Lesenswert?

Hey! Danke! muss natürlich zu ISREND springen. kanns jetzt leider hier 
auf der Arbeit nicht direkt auprobieren ob ds alles war, aber war 
natürlich schon n dämlicher leichtsinsfehler! herzlichen dank!

von Jens P. (Gast)


Lesenswert?

Hi nochmal, bin gerade weiter am rumprobieren, aber irgendwie verbessert 
sich nichts. der aktuelle code ist:

ISR    btfss  PIR1, RCIF        ; Pruefen ob Interupt durch Receive 
ausgeloest wurde
    goto  ISREND          ; Wenn nein, gehe zu Ende von ISR
    movfw  RCREG          ; Empfangsregister auslesen
    movwf  Bytetemp
    btfsc  Flags,1          ; Wurde schon ein Statusbyte (Bit1) 
empfangen?
    goto  EmpfangStatusByte    ; Wenn nein gehe zu Empfang Statusbyte
    goto  EmpfangDatenByte    ; Wenn ja, gehe zu Empfan Datenbyte

EmpfangStatusByte

    movfw   Bytetemp
    sublw  h'C'          ; Konstante C (Prog-Change kennung) abzihen
    subwf  Channel,0        ; Danach Wird die Kanalnummer abgezogen
    btfss  STATUS,Z        ; Ist das Ergebnis = "0" ?
    goto  ISREND          ; Wenn nein, beende empfang

    bsf    Flags,1          ; Markiere dass der erste Teil Empfangen 
wurde
    goto   ISREND          ; Beende ISR

EmpfangDatenByte
    bcf    Flags, 1        ; Setze Empfangsbytezuordnung wieder zurück, 
für die
                    ; Nächste Nachricht
    movfw  Bytetemp
    sublw  D'127'          ; Ziehe Maximalwert ab
    btfsc  STATUS, Z        ; Ist das Ergebnis Null?
    goto  PresetZuweisung      ; Wenn ja, gehe zur Zuweisung

    btfsc  STATUS, C        ; Ist das Carry-Bit gesetzt?
    goto  PresetZuweisung      ; Wenn ja, gehe zur Zuweisung
    goto   ISREND          ; Wenn nein, dann Wars wohl nix!

PresetZuweisung
    movfw   Bytetemp
    movwf  preset
    goto  ISREND

ISREND  call  RS232Send
    bcf    PIR1, RCIF        ; Receive-Interupt-Bit wieder loeschen
    retfie              ; Zurückkehren aus Interuptroutine

von TK (Gast)


Lesenswert?

Also wenn ich mir den Code der ISR mal ansehe, kann ich sonst keine 
gravierenden Probleme mehr erkennen.
Frage:
Wie gehst Du mit Fehlübertragungen um? z.B. Overflow oder FrameError.
 Wenn sowas passiert, dann sollte RCREG nicht mehr verarbeitet werden.
Wenn mehrere Interrupts aktiviert sind, dann sollten alle Interrupts 
verarbeitet werden, bevor man über RETFIE rausspringt, da sonst eben nur
ein INT verarbeitet wird und ein anderer evtl. nicht mehr aktiviert 
werden kann, weil das FLAG durch RETFIE automatisch gelöscht wird.

Was passiert denn genau in deinem Programm? Wie äußert sich der Fehler.
Vielleicht liegts ja auch an der Ausgabe über die Segmentanzeige???
Vielleicht kommt ja ein Interrupt zu einem 'ungünstigen' Zeitpunkt??

Gruß

TK

von TK (Gast)


Lesenswert?

Gleich noch einen hinterher:
Schau mal hier
http://www.piclist.com/techref/microchip/rs232.htm
 Da ist ein Auszug aus der Overflow / FrameError Behandlung
gezeigt. Könnte hilfreich sein.

Gruß

TK

von Jens P. (Gast)


Lesenswert?

es gibt nur diesen einen interupt.

Das mit der Oveflowbehandlung muss ich mir mal genauer anschauen

von Jens P. (Gast)


Lesenswert?

Mein Problem war sehr dummer natur!!!

Das DatenBYTE im Midiprotokoll besteht ja aus zwei hexwerten ich schicke 
also mit kanal null 0xC0 . Dann kann ich natürlich im Programm nicht 
einfach 0xC abziehen!   ich mach ja dann 192-12 = 0 und frag mich warums 
nicht passt.

hab irgendwie den übeblick zwischen nipples und bytes verloren!

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.