Hallo, ich habe einen PIC18F2685 vorliegen, der u.a. seriell kommunizieren kann. Die serielle Kommunikation ist über Interrupts gelöst. Mein Problem besteht aktuell darin, dass nach Senden des Stopbits des letzten Byte die TX-Leitung nochmal kurz (ca. 10 µs) auf 0 gezogen wird, bevor diese in Ruhelage = 1 geht. Nachfolgende Schaltungen (MAX232) geben diese weiter, und der Empfänger hat damit ein Problem. Daher habe ich mich auf die Suche gemacht, woher dieses Verhalten kommt. Andere PICs, die ich kenne (PIC16) haben dieses Verhalten nicht. Ich vermute, dass es vielleicht ein Reihenfolgenproblem mit dem Interrupt oder dem Setzen von den notwendigen Registern ist. Ich versuche, den wesentlichen Teil der Kommunikation herauszulösen, um das nachvollziehbar darzustellen: void interruptGlobalLow() { //rs232 byte send if(TXIF) { rs232Com_check(); TXIF = 0; } } void rs232_Init() { TRISC=0b.1000.0011; TXIE = 0; RCIE = 0; CREN = 0; SPEN = 0; SYNC = 0; BRGH = 1; BRG16 = 1; ADDEN=0; ABDEN=0; WUE=0; RCIF=TXIF=0; // clear interrupt flags //Baudrateneinstellung (9600,8,'n',1) SPBRGH=4; SPBRG=16; RX9 = 0; // no 9th bit (parity) TX9 = 0; TXIE = 1; RCIE = 1; CREN = 1; RCIF=TXIF=0; SPEN = 1; TXIP = RCIP = 0; // low interrupts RCIF=TXIF=0; } void rs232Com_check() { if (rs232_sending==0) return; if (rs232_inxSendBuffer>rs232_sizeSendBuffer) { rs232_sending=0; TXEN = 0; } else { uns8 send = rs232_sendBuffer[rs232_inxSendBuffer]; ++rs232_inxSendBuffer; send_with_parity( send ); } } rs232Com_StartSend() { // rs232_inxSendBuffer = Index des Sendepuffers // rs232_sendBuffer = Sendepuffer, wird woanders gefüllt und es ist sichergestellt, dass dieser zu dieser Zeit auf gefüllt ist rs232_sizeSendBuffer = rs232_inxSendBuffer; rs232_inxSendBuffer=1; rs232_sending=1; // start send first byte TXEN = 1; TXREG = rs232_sendBuffer[0]; } void main() { while(1) { if(rs232_sending == 0) { rs232Com_StartSend(); } } } Anbei noch 2 Screenshots der Oszi-Kommunikation. Letztes Byte ist 0xEF, danach sieht man den negativen Peak, der meiner Meinung hier nicht hergehört. Hat jemand ne Idee, woran das liegen kann. Ich habe mir das Datenblatt schon mehrfach angeschaut, komme aber aktuell nicht weiter. Vielen Dank.
:
Es hat sich im zusammenkopieren des Quellcodes noch ein Fehler eingeschlichen. Nachdem ich keinen "Editieren"-Button gefunden habe, hier nochmal der aktuelle Stand: void interruptGlobalLow() { //rs232 byte send if(TXIF) { rs232Com_check(); TXIF = 0; } } void rs232_Init() { TRISC=0b.1000.0011; TXIE = 0; RCIE = 0; CREN = 0; SPEN = 0; SYNC = 0; BRGH = 1; BRG16 = 1; ADDEN=0; ABDEN=0; WUE=0; RCIF=TXIF=0; // clear interrupt flags //Baudrateneinstellung (9600,8,'n',1) SPBRGH=4; SPBRG=16; RX9 = 0; // no 9th bit (parity) TX9 = 0; TXIE = 1; RCIE = 1; CREN = 1; RCIF=TXIF=0; SPEN = 1; TXIP = RCIP = 0; // low interrupts RCIF=TXIF=0; } void rs232_send(uns8 byte) { TXEN = 1; TXREG = byte; } void rs232Com_check() { if (rs232_sending==0) return; if (rs232_inxSendBuffer>rs232_sizeSendBuffer) { rs232_sending=0; TXEN = 0; } else { uns8 send = rs232_sendBuffer[rs232_inxSendBuffer]; ++rs232_inxSendBuffer; rs232_send( send ); } } rs232Com_StartSend() { // rs232_inxSendBuffer = Index des Sendepuffers // rs232_sendBuffer = Sendepuffer, wird woanders gefüllt und es ist sichergestellt // dass dieser zu dieser Zeit auf gefüllt ist rs232_sizeSendBuffer = rs232_inxSendBuffer; rs232_inxSendBuffer=1; rs232_sending=1; // start send first byte rs232_send(rs232_sendBuffer[0]); } void main() { while(1) { if(rs232_sending == 0) { rs232Com_StartSend(); } } }
Vielleicht liegt es daran, dass der Transmitter komplett abgeschaltet wird (TXEN = 0). Hast du schon mal probiert, das über das TXIE zu lösen?
Ja, das hatte ich auch schon probiert. Wenn ich TXIE nutze, sehe ich schon vor dem Senden mehrmals das TXIF=1 gesetzt wird. Auch nach dem Senden wird TXIF=1 sehr oft gesetzt, obwohl keine Kommunikation mehr stattfindet.
Beitrag #6155633 wurde von einem Moderator gelöscht.
Beitrag #6155634 wurde von einem Moderator gelöscht.
Beitrag #6155638 wurde von einem Moderator gelöscht.
Beitrag #6155639 wurde von einem Moderator gelöscht.
Beitrag #6155642 wurde von einem Moderator gelöscht.
Beitrag #6155645 wurde von einem Moderator gelöscht.
Beitrag #6155647 wurde von einem Moderator gelöscht.
Beitrag #6155653 wurde von einem Moderator gelöscht.
Beitrag #6155659 wurde von einem Moderator gelöscht.
Beitrag #6155666 wurde von einem Moderator gelöscht.
Beitrag #6155674 wurde von einem Moderator gelöscht.
Beitrag #6155677 wurde von einem Moderator gelöscht.
Beitrag #6155679 wurde von einem Moderator gelöscht.
Net F. schrieb: > Auch nach dem Senden wird TXIF=1 sehr oft gesetzt, obwohl > keine Kommunikation mehr stattfindet Genau dafür ist es ja da. (TXIF zeigt an, dass das TXREG frei ist und mit einem neuen Byte befüllt werden kann) Wenn mehrere Bytes gesendet werden sollen, dann schiebt man das erste in TXREG und aktiviert den Interrupt mit TXEN = 1. Sobald TXREG frei wird, wird der IR ausgelöst und in diesem schiebt man das nächste Byte in TXREG. Handelt es sich dabei um das letzte zu übertragende Byte, dann deaktiviert man den IR wieder (TXIE = 0)
if(TXIF) sollte eher if ((TXIF) && (TXIE)) prinzipiell solltest du den TXIF flag meiner Meinung nach nicht löschen. Sondern eher: - Im Interrupt Daten schicken - Wenn es keine Daten mehr gibt dann den TXIE auf 0 setzen Daten verschicken sollte über einen Ringbuffer gehen. Versenden guckt ob der Transmitt schon läuft, wenn ja dann daten richtung Ringbuffer schreiben, wenn nicht, dann daten ins TX register schreiben. void putCharRS232(unsigned char data) { if (ringBuffer_addItem(&myRingBuffer_rs232_tx, data) != -1) { if (PIE1bits.TXIE == 0) { PIE1bits.TXIE = 1; } } else { missedTxCharRS232++; } } int isrSerialTx(void) { unsigned char data = 0; if (ringBuffer_getItem(&myRingBuffer_rs232_tx, &data) != -1) { TXREG = data; } else { PIE1bits.TXIE = 0; } return 0; }
Beitrag #6155684 wurde von einem Moderator gelöscht.
Beitrag #6155688 wurde von einem Moderator gelöscht.
Beitrag #6155699 wurde von einem Moderator gelöscht.
Beitrag #6155700 wurde von einem Moderator gelöscht.
kyrk schrieb: > sollte eher > if ((TXIF) && (TXIE)) > > prinzipiell solltest du den TXIF flag meiner Meinung nach nicht löschen. Guter Einwand mit dem zusätzlichen TXIE. Mache ich auch immer, damit ich es nicht vergesse, falls ein zweiter IR in diesem Vektor behandelt werden soll. TXIF ist übrigens read-only und kann nicht gelöscht werden. Es geht automatisch auf 0, wenn das TXREG beschrieben wird und auch automatisch wieder auf 1, sobald TXREG frei wird.
Beitrag #6155703 wurde von einem Moderator gelöscht.
Beitrag #6155704 wurde von einem Moderator gelöscht.
Beitrag #6155707 wurde von einem Moderator gelöscht.
Beitrag #6155709 wurde von einem Moderator gelöscht.
Volker S. schrieb: > kyrk schrieb: >> sollte eher >> if ((TXIF) && (TXIE)) >> >> prinzipiell solltest du den TXIF flag meiner Meinung nach nicht löschen. > > Guter Einwand mit dem zusätzlichen TXIE. Mache ich auch immer, damit ich > es nicht vergesse, falls ein zweiter IR in diesem Vektor behandelt > werden soll. > > TXIF ist übrigens read-only und kann nicht gelöscht werden. > Es geht automatisch auf 0, wenn das TXREG beschrieben wird und auch > automatisch wieder auf 1, sobald TXREG frei wird. Dass TXIF read-only ist, hatte ich in der Doku gelesen. Allerdings ist der Quellcode nicht von mir, den hatte ich geerbt. Ich war der Meinung, dass der TXIF-Interrupt nur gerufen wird, wenn der Sendepuffer wieder frei ist. Ich hatte wie hier schon mehrfach geschrieben, nachdem ich das letzte Byte in TXREG geschoben hatte, TXIE=0 gesetzt. Trotzdem bin ich mehrfach in den TXIF-Interrupt gekommen. Mit der zusätzlichen if ((TXIF) && (TXIE)) - Abfrage sieht das Ganze besser aus. Danke für den Tipp!
Net F. schrieb: > Trotzdem bin ich mehrfach in den TXIF-Interrupt gekommen. > Mit der zusätzlichen if ((TXIF) && (TXIE)) - Abfrage sieht das Ganze > besser aus. Dann gibt es da aber evtl. ein anderes Problem! Der IR wird wohl noch von einer anderen Quelle ausgelöst und das ist dann ganz schlecht, weil er ja nicht behandelt wird. (der kommt immer wieder) Zum Testen einfach eine Endlosschleife in die ISR:
1 | void interruptGlobalLow() |
2 | {
|
3 | //rs232 byte send
|
4 | if(PIE1bits.TXIE && PIR1bits.TXIF) |
5 | {
|
6 | ...
|
7 | return; |
8 | }
|
9 | while(1){ |
10 | Nop(); // ??? Breakpoint ??? |
11 | }
|
12 | }
|
Falls das Programm da rein läuft, muss du die Ursache dafür finden.
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.