Hallo, ich habe eine frage wenn ich jetzt an den PIC über rs232 2 bytes hintereinander sende werden die hardwaremäßig gepuffert ? und wenn ja wie lese ich das zweite byte aus ? oder muss ich einfach zweimal hintereinader das RCREG auslesen und in zwei verschiednen ram registern speichern ? RS232in btfss PIR1,RCIF ; sind Daten da ? goto RS232in ; nein, noch keine Daten da movfw RCREG ; RS232-Register auslesen movwf Zeichen ; und in den Speicher nach 'Zeichen' schreiben movfw RCREG movwf Zeichen2 könnte das so klappen ?? wenn nur ein zeichzen gesendet wird müssten dann ja in Zeichen2 nur nullen stehen also 0x00 , oder habe ich da jetzt einen denkfehler und mein programm würde an der stelle hängen bleiben ? kanns gerade leiter nicht testen, deswegen frage ich hier mal die spezialisten ;-) PS: Was ich noch vergass , der pic läuft mit 20mhz und es ist eine baud von 9600 eingestellt ... was mir aber gerade durch den kopf ging sollte ich dann für die folgenden zeichen nicht lieber eine schleife machen die halt nur x mal das PIR1 register abfragt ob daten da sind ? es werden maximal 4 bytes direkt hintereinader gesendet mfg
Marcel Klug schrieb: > oder muss ich einfach zweimal hintereinader das RCREG auslesen und in > zwei verschiednen ram registern speichern ? Genau so. Allerdings solltest du vor jeder Leseoperation das Interuptflag RCIF abfragen. Wenn nur ein Zeichen empfangen wurde, wird es nach dem ersten Auslesen zurückgesetzt, bei zwei Bytes nach dem zweiten Auslesen. Was passiert, wenn du zweimal RCREG ausliest, obwohl nur ein Byte drin steht, kann ich dir jetzt nicht beantworten.
Mach am beste den I/O-Verkehr per Interrupt und Ringpuffern:
Auszug aus der Interrupt-Routine:
....
SKIP RCIF
GOTO i1
; Byte von SIO wurde empfangen
BCF RCIF
MOVF RCSTA,W ; Test auf Rx Fehler
ANDLW B'00000110'
SKIP NZ
GOTO i_rxb
BCF CREN
NOP
BSF CREN
GOTO i1
i_rxb: MOVF rx_ip,W ; Zeichen in den
ANDLW 7 ; Empfangs-Ringpuffer
ADDLW RxBuf ; schreiben
MOVWF FSR
MOVF RCREG,W
MOVWF Indirect
INCF rx_ip,W
ANDLW 7
MOVWF rx_ip
i1: SKIP TXIF
GOTO i2
; SIO Sender kann nächstes Byte vertragen
; (TXIF kann man nicht löschen! - nur mit TXIE=0 verbieten)
MOVF tx_ip,W
XORWF tx_op,W
SKIP Z
GOTO i_send_next
BSF RP0 ; Bank 1
BCF TXIE ; wenn es nix zu tun gibt, löschen wir
TXIE
BCF RP0
GOTO i2
i_send_next:
MOVF tx_op,W
ADDLW TxBuf
MOVWF FSR
MOVF Indirect,W
MOVWF TXREG
INCF tx_op,W
ANDLW 63
MOVWF tx_op
i2: ....
Und hier die UP, die vom normalen Programm aufgerufen werden:
; V.24 In/Out-Funktionen
; Test, ob empfangene Zeichen verfügbar sind.
; ZERO, wenn nix anliegt
CharAvail:
MOVF rx_ip,W
XORWF rx_op,W
RETURN
; liefert empfangenes Zeichen
GetChar: MOVF rx_ip,W
XORWF rx_op,W
SKIP NZ
GOTO GetChar ; wartet auf Zeichen!!
MOVF rx_op,W
ADDLW RxBuf
MOVWF FSR
INCF rx_op,W
ANDLW 7
MOVWF rx_op
MOVF Indirect,W
RETURN
; sendet Zeichen
PutChar: BCF GIE
MOVWF PHudl ; Zeichen retten
__put1: INCF tx_ip,W
XORWF tx_op,W
ANDLW 63
SKIP Z
GOTO __put2
BSF RP0 ; Puffer ist voll, also warten
BSF TXIE
BCF RP0
BSF GIE
GOTO __put1
__put2: BCF GIE
MOVF tx_ip,W
ANDLW 63
ADDLW TxBuf
MOVWF FSR
MOVF PHudl,W
MOVWF Indirect
INCF tx_ip,W
ANDLW 63
MOVWF tx_ip
BSF RP0
BSF TXIE
BCF RP0
MOVF PHudl,W ; Zeichen zurück nach W
BSF GIE
RETURN
So, das sollte ausreichen.
W.S.
Wie wärs, wenn man sich im Datenblatt die Funktionsweise des USART Receivers durchliest? Sie befindet sich im Kapitel 10.2.2.
Marcel Klug schrieb: > wenn ich jetzt an den PIC über rs232 2 bytes > hintereinander sende werden die hardwaremäßig gepuffert ? Nö der 16f876a hat nur ein Schieberegister für den Empfang und ein Datenregister. Er kann also maximal 1 Byte gerade Empfangen während das vorherige von der Software weiterverarbeitet wird. Marcel Klug schrieb: > wenn nur ein zeichzen gesendet wird müssten dann ja in Zeichen2 nur > nullen stehen also 0x00 , oder habe ich da jetzt einen denkfehler Du liest 2 hintereinander das Datenregister aus also 2 denselben Wert. Marcel Klug schrieb: > es werden maximal 4 bytes direkt hintereinader gesendet Da ist eine Interruptroutine mit Ringpuffer und eine Statemachine für den Empfang nicht verkehrt. Gruß Anja
@ Anja okay aber im Datenblatt steht dass das RCREG ein doppelter puffer ist. Würde ich so verstehen dass das RCREG 2 bytes speichern kann. Weiter steht noch im Datenblatt wenn das 3. byte kommt und das stop bit angekomment ist und dabei der RCREG noch nicht leer ist , dass das 3 byte verloren ist und das OERR bit gesetzt wird. dieses OERR bit kann nur gelöscht werden indem man die UART resetet (CREN) So da ich ja weiß das maximal 4 bytes nacheinander ohne pause kommen werde ich das einfach so machen : RS232in btfss PIR1,RCIF ; sind Daten da ? goto RS232in ; nein, noch keine Daten da movfw RCREG ; RS232-Register auslesen movwf Zeichen ; und in den Speicher nach 'Zeichen' schreiben MOVLW 20 ; 20 ins Arbeitsregister laden MOVWF 0x20 ; die 20 wird in die Speicherzelle 0x20 kopiert byte2 ; eine Einsprungmarke btfss PIR1,RCIF ; sind Daten da ? goto byte2_no ; nein, noch keine Daten da movfw RCREG ; RS232-Register auslesen movwf Zeichen2 ; und in den Speicher nach 'Zeichen' schreiben goto byte_3 byte2_no DECFSZ 0x20,1 ;der Wert in der Sp.Zelle 20h wird um 1 verringert GOTO byte2 ; Sprung zur Marke LOOP goto Main ; hier geht das eigtl. Programm weiter byte_3 MOVLW 20 ; 20 ins Arbeitsregister laden MOVWF 0x20 ; die 20 wird in die Speicherzelle 0x20 kopiert byte3 ; eine Einsprungmarke btfss PIR1,RCIF ; sind Daten da ? goto byte3_n ; nein, noch keine Daten da movfw RCREG ; RS232-Register auslesen movwf Zeichen3 ; und in den Speicher nach 'Zeichen' schreiben goto byte_4 byte3_no DECFSZ 0x20,1 ;der Wert in der Sp.Zelle 20h wird um 1 verringert GOTO byte3 ; Sprung zur Marke LOOP GOTO Main byte_4 ..... da schreibe ich jetzt mal nicht weiter ^^ so müsste das ja klappen und dauert bei einem PIC tackt von 20mhz ja eigentlich auch nicht lange Mit Freundlichen Grüßen
Marcel BesondersKlug schrieb: > So da ich ja weiß das maximal 4 bytes nacheinander ohne pause kommen > werde ich das einfach so machen : Hmm.. wozu fragst du eigentlich nach Rat? W.S.
@ W.S. entschuldige da habe ich mich falsch ausgedrückt ! eigentlich wollte ich wissen ob man das so machen kann ...
Hi,
falls es jemanden interessiert, ich habe mal selbst ein bisschen
überelegt und gelesen und habe mir jetzt auch dank eurer tollen hilfe
hier im forum eine kleine Interrupt routine gebastelt.
;RS232-Empfänger-Interrupt?
btfss PIR1,RCIF
goto intEnde ; Interrupt kam von wo anders
movfw RCREG ; RS232-Register auslesen
movwf temp
goto Ringpuffer ; und in den Speicher nach 'Zeichen' schreiben
Ringpuffer_fertig
bsf DatenSindDa,0 ; Kennzeichen für gültige Daten setzen
bcf PIR1,RCIF ; interrupt-Flag löschen
goto intEnde
Ringpuffer
movlw 5
subwf puffer_zähler, w
btfsc STATUS,Z
goto Zeichen_0
movlw 4
subwf puffer_zähler, w
btfsc STATUS,Z
goto Zeichen_1
movlw 3
subwf puffer_zähler, w
btfsc STATUS,Z
goto Zeichen_2
movlw 2
subwf puffer_zähler, w
btfsc STATUS,Z
goto Zeichen_3
movlw 1
subwf puffer_zähler, w
btfsc STATUS,Z
goto Zeichen_4
Zeichen_0
movfw temp
movwf Zeichen0
decf puffer_zähler, 1
goto Ringpuffer_fertig
Zeichen_1
movfw temp
movwf Zeichen1
decf puffer_zähler, 1
goto Ringpuffer_fertig
Zeichen_2
movfw temp
movwf Zeichen2
decf puffer_zähler, 1
goto Ringpuffer_fertig
Zeichen_3
movfw temp
movwf Zeichen3
decf puffer_zähler, 1
goto Ringpuffer_fertig
Zeichen_4
movfw temp
movwf Zeichen4
movlw 5
movwf puffer_zähler
goto Ringpuffer_fertig
intEnde ; geretteten Status wieder zurückschreiben
swapf status_temp,w
movwf STATUS
swapf w_temp,f
swapf w_temp,w
retfie
Bei der Init meines pics lade ich natürlich 5 in den puffer_zähler.
Jetzt will ich noch die DTR line an RB0 anschliesen (natürlich über
MAX232) und RB0 auch auf Interrupt stellen und wenn jetzt die RB0 High
geht soll die 5 in den puffer_zähler laden. Ich weiß das ist umständlich
aber der Puffer funktioniert so schon mal für mich ganz gut.
Im Hauptprogramm frage ich jetzt einfach immer DatenSindDa ab wenn das
bit gesetzt ist gebe ich dem pic noch ein paar ms zeit damit der
empänger interrupt in ruhe weiter arbeiten kann und ich alle empfangenen
zeichen sicher um puffer habe und dann geht mein eigentliches programm
weiter.
Hm bis auf das Call besser ist als goto und du in der schleife den ISR nicht deaktivierst ist es ok. z.b. wie im Anhang. edit: http://grautier.com/temp/fifo.txt
okay mit dem goto habe ich gedacht mache ich es lieber so weil er ja sonst nachdem er zeichen0 geschrieben hat mit einem call befehl wieder in den puffer_zähler zurück springt und unnötig weitere befehle ausführt ... das war mein gedanlke ! Was meinst du mit ich deaktiviere die ISR nicht ?? mfg
Was ich noch wissen wollte in MPLAB bekomme ich beim kompelieren diesen fehler Register in operand not in bank 0. Ensure that bank bits are correct. wo er ja uach recht hat ADCON1 ist in BANK 1 und ich schalte ja auch vorher mit bsf STATUS, RP0 in Bank1 ich hänge mal mein programm an was ich bis jetzt habe ... Trozdem baut er die Hex und sie läuft auch
Marcel Klug schrieb: > Was ich noch wissen wollte in MPLAB bekomme ich beim kompelieren diese > fehler > Register in operand not in bank 0. Ensure that bank bits are correct. Das ist keine Fehlermeldung (error) sondern nur ein Hinweis (message). Leider eine unglückliche Lösung die schon bei vielen Leuten für Verwirrung gesorgt hat.
aaahh okay danke aber kannst du mir erklären warum das so ist ? muss ja irgendwie an mir liegen , denn wenn ich von sprut ein programm nehme zeigt er mir es nicht an ... mfg
Hy, ich habe die antwort auf meiner Frage selbst gefunden ! Ich muss einfach am anfang meines Assemblercodes das hier eintragen ERRORLEVEL -302 ;remove message about using proper bank hatte ich auch hatte es aber deaktiviert ;ERRORLEVEL -302 ;remove message about using proper bank mfg sunny
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.