Ich verwende einen PIC32MX795F512L. Ich versuche gerade mit UART4 einen Interrupt-gesteuerten Empfang zu realisieren. Ich kann den UART4 initialisieren, sehe die richtigen Sende-Daten. Ich kann Empfangs-Daten via Polling abfragen, nur die Interrupt-Routine wird nicht aufgerufen, wenn Zeichen empfangen werden. Ich habe UART1 und UART2 am Laufen, UART1 auch mit funktionierender Interrupt-Routine (kopierter und für UART4 angepasster Code, hoffentlich mittlerweile nicht kaputt debugged). UART_MODULE SerialUartModule = UART4; /* Initialize Serial Port Returnvalue: a value of 1 if successful negative value if there was an error */ int SerialInit(void) { // Disable UART interrupt, because we (re-)configure UART INTEnable(INT_SOURCE_UART_RX(SerialUartModule), INT_DISABLED); // Disable UART, because we (re-)configure UART UARTEnable(SerialUartModule, UART_DISABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX)); // This is for pins TX and RX only (no RTS/CTS) UARTConfigure(SerialUartModule, UART_ENABLE_PINS_TX_RX_ONLY); // This is for pins TX, RX, RTS, CTS // UARTConfigure(SerialUartModule, UART_ENABLE_PINS_CTS_RTS); // UARTSetFifoMode(SerialUartModule, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY); UARTSetFifoMode(SerialUartModule, UART_INTERRUPT_ON_RX_NOT_EMPTY); // 8N1 UARTSetLineControl(SerialUartModule, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1); // Set Baudrate UARTSetDataRate(SerialUartModule, GetPeripheralClock(), 19200); // Enable UART UARTEnable(SerialUartModule, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX)); // Configure UART RX Interrupt INTEnable(INT_SOURCE_UART_RX(SerialUartModule), INT_ENABLED); INTSetVectorPriority(INT_VECTOR_UART(SerialUartModule), INT_PRIORITY_LEVEL_2); INTSetVectorSubPriority(INT_VECTOR_UART(SerialUartModule), INT_SUB_PRIORITY_LEVEL_0); // Enable multi-vector interrupts INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR); INTEnableInterrupts(); } void __ISR(_UART_4_VECTOR, ipl2) IntUart4Handler(void) { -> Hier ist eine Debug-Ausgabe, die aber nicht kommt } Ich bin leider gezwungen, mit dem alten MPLAB zu arbeiten, mit einem alten C-Compiler, im Legacy-Mode. Legacy ist ein gutes Stichwort: Was hat es damit auf sich, dass die UARTs einmal mit UART1...UART6 bezeichnet werden, dann aber wieder mal mit UART_1A, UART_1B, UART_2A, UART_2B, UART_3A, UART_3B? UART4 muesste UART_2A sein? Ich habe mal den Wert von _UART_x_VECTOR ausgegeben (dezimal): _UART_1_VECTOR=24 _UART_2_VECTOR=32 _UART_3_VECTOR=31 _UART_4_VECTOR=49 _UART_5_VECTOR=51 _UART_6_VECTOR=50 _UART_1A_VECTOR=24 _UART_1B_VECTOR=49 _UART_2A_VECTOR=31 _UART_2B_VECTOR=50 _UART_3A_VECTOR=32 _UART_3B_VECTOR=51 Hier ist 1->1A,2->3A,3->2A,4->1B,5->3B,6->2B. Warum ist jetzt die UART4_VECTOR Nummer 49 aber UART_1B hat auch Nummer 49 und UART4_VECTOR ist nicht gleich mit dem von UART_2A? Ich habe mittlerweile auch mal auf allen UART Interrupt Vektoren eine ISR installiert, aber keine davon wird aufgerufen... Errata habe ich schon durchgeschaut, nichts dazu gefunden. Ich habe auch schon anderen Beispiel-Code probiert, aber leider auch kein Durchbruch, alle verhalten sich gleich, keine Interrupt. Kann hier jemand weiterhelfen und mich vor der Verzweifelung retten?
Für den alten C32 Compiler wirst du dir die UART4-Routinen selbst
schreiben müssen, denn:
pic32-libs/peripheral/uart/legacy enthält nur die Funktionen für UART1
und UART2.
>Hier ist 1->1A,2->3A,3->2A,4->1B,5->3B,6->2B.
In pic32-libs/include/peripheral/uart/legacy/uart_legacy.h finden sich
die
Zuweisungen....habe aber das nicht weiterverfolgt
UART4 geht ja grundsätzlich, nur der Interrupt nicht... Es kann natürlich durchaus sein, dass eine der Interrupt-Funktionen mit dem UART4 nicht zurecht kommt? Ich bin doch aber bestimmt nicht der 1., der den Interrupt mit UART4 auf dem alten Compiler/der alten MPLAB IDE nutzt?
Hallo, als Fehlerquellen fällt mir folgendes ein: - beim PIC32 muss man multi vector Interrupts erst einschalten. Wird das gemacht? - Ich würde mal beim Debuggen schauen, ob die IE-Flags für den Interrupt wirklich gesetzt werden (U4TXIE/U4RXIE= 1) - Schau mal, ob die Interrupt Flags kommen (U4TXIF/U4RXIF = 1) - Ist die Priorität des Interrupts < 7 (U4IP)? Bei 7 passier nichts, wenn ich mich richtig erinnere. - sind irgendwo die Interrupts deaktiviert oder so? Ich muss aber sagen, dass ich ohne Peripheral lib arbeite und daher deren Tücken nicht kenne.
Hi, hier mal mein Code, kannst ja mal schauen ob das mit deinem überein stimmt. PS: habs mal bei mir raus kopiert...
1 | // Init
|
2 | UARTConfigure(UART4, UART_ENABLE_PINS_TX_RX_ONLY); |
3 | UARTSetLineControl(UART4, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1); |
4 | UARTSetDataRate(UART4, GetPeripheralClock(), 38400); |
5 | UARTEnable(UART4, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX)); |
6 | |
7 | UARTSetFifoMode(UART4, UART_INTERRUPT_ON_TX_BUFFER_EMPTY | UART_INTERRUPT_ON_RX_NOT_EMPTY); |
8 | |
9 | // Configure Com1Parameter Interrupt
|
10 | INTEnable(INT_SOURCE_UART(UART4) , INT_DISABLED); |
11 | INTEnable(INT_SOURCE_UART_TX(UART4) , INT_DISABLED); |
12 | INTEnable(INT_SOURCE_UART_ERROR(UART4) , INT_DISABLED); |
13 | INTEnable(INT_SOURCE_UART_RX(UART4) , INT_ENABLED); // <- active |
14 | |
15 | INTSetVectorPriority(INT_VECTOR_UART(UART4), INT_PRIORITY_LEVEL_2); |
16 | INTSetVectorSubPriority(INT_VECTOR_UART(UART4), INT_SUB_PRIORITY_LEVEL_0); |
17 | |
18 | |
19 | void __ISR(_UART_4_VECTOR, ipl2) IntUart4Handler(void) |
20 | {
|
21 | u08 byte; |
22 | // Is this an RX interrupt?
|
23 | if(INTGetFlag(INT_SOURCE_UART_RX(UART4))) |
24 | {
|
25 | // Clear the RX interrupt Flag
|
26 | INTClearFlag(INT_SOURCE_UART_RX(UART4)); |
27 | // .. things to do
|
28 | if (UARTReceivedDataIsAvailable(UART4) != 0) |
29 | {
|
30 | byte= UARTGetDataByte(UART4); |
31 | UART_CharOut(UART4, byte); |
32 | }
|
33 | }
|
34 | |
35 | // We don't care about TX interrupt
|
36 | if ( INTGetFlag(INT_SOURCE_UART_TX(UART4)) ) |
37 | {
|
38 | INTClearFlag(INT_SOURCE_UART_TX(UART4)); |
39 | }
|
40 | |
41 | // We don't care about ERROR interrupt
|
42 | if ( INTGetFlag(INT_SOURCE_UART_ERROR(UART4))) |
43 | {
|
44 | INTClearFlag(INT_SOURCE_UART_ERROR(UART4)); |
45 | }
|
46 | |
47 | // We don't care about this interrupt
|
48 | if ( INTGetFlag(INT_SOURCE_UART(UART4))) |
49 | {
|
50 | INTClearFlag(INT_SOURCE_UART(UART4)); |
51 | }
|
52 | }
|
Also für mich war der PIC32 auch sehr verwirrend. Da Microchip auch kein Interesse hat da die Kunden zu unterstützen, bis du ziemlich auf dich alleine gestellt. (kein Interesse -> hab ich damals sogar per Mail vom Support bekommen!, lol) Versuch im Forum von denen einen Admin zu finden und sprich den direkt an!!! Sonst wird das da auch nichts! viellllll Spasssssssss
@Stephan: Vielen Dank für Hinweise und Beispiel-Code. Leider löst auch dieser bei mir keinen Interrupt aus, aber normaler Empfang mit deinem Code per Polling funktioniert weiterhin. Ich bin mittlerweile auch schon einen Schritt weiter: (aber immer noch kein Interrupt) Ich gebe die IEC0...IEC2 jetzt mal vor // Configure Com1Parameter Interrupt > INTEnable(INT_SOURCE_UART(UART4) , INT_DISABLED); > INTEnable(INT_SOURCE_UART_TX(UART4) , INT_DISABLED); > INTEnable(INT_SOURCE_UART_ERROR(UART4) , INT_DISABLED); > INTEnable(INT_SOURCE_UART_RX(UART4) , INT_ENABLED); // <- active und dann mal hinterher aus, damit ich die Inhalte prüfen kann. Durch den Code auf meiner Maschine/Umgebung wird IEC1 von 0x04000000 auf 0x04000040 verändert. Gebe ich alle Interrupt (der 4 oben genannten von UART4) frei, dann steht 0x040000E0 im Register IEC1. IEC2 bleibt auf 0. Aber UART4 ist laut Datenblatt im IEC2!?! An der Stelle, an der der INTEnable Bit setzt, wäre UART3... Was macht die Zeile in Registern? > INTEnable(INT_SOURCE_UART(UART4) , INT_DISABLED); oder auch > INTClearFlag(INT_SOURCE_UART(UART4)); Welches Bit (welche Bits) wird/werden hier bedient? Vielleicht ist dies mein fehlendes Bit (weil sich INTEnable verrechnet...)... Die Interrupt-Level > INTSetVectorPriority(INT_VECTOR_UART(UART4), INT_PRIORITY_LEVEL_2); > INTSetVectorSubPriority(INT_VECTOR_UART(UART4), INT_SUB_PRIORITY_LEVEL_0); werden aber korrekt in IPC12 Bits U4IP und U4IS reingeschrieben. (IPC12 vorher 0, nachher 0x00000800). Ich habe jetzt statt den (fehlerhaften?) INTEnable direkt das Register beschrieben: IEC2SET = (1 << 4); Damit bleibt jetzt IEC1 wie es ist und IEC2 hat den Wert 0x00000010. Leider kommt dann aber immer noch kein Interrupt. Müssen die Level und Sublevel eigentlich eindeutig sein, oder darf ein anderer UART die gleichen Setting benutzen? @Somebody123 > - beim PIC32 muss man multi vector Interrupts erst einschalten. > Wird das gemacht? Hab ich mittlerweile als erste Aktion gleich in main(), bevor die ganzen Init-Routine aufgerufen werden. Was würde denn passieren, wenn es Code gibt, der es kurz ausschaltet und wieder einschaltet? Werden dann die ganzen Multi-Vector Einstellungen zurückgesetzt? > - Ich würde mal beim Debuggen schauen, ob die IE-Flags > für den Interrupt wirklich gesetzt werden (U4TXIE/U4RXIE= 1) siehe oben, sollte ich jetzt manuell richtig gesetzt haben? > - Schau mal, ob die Interrupt Flags kommen (U4TXIF/U4RXIF = 1) Meintest du U4TXIF und U4RXIF in IFS2? Ich habe die mal ausgegeben, wurden aber nie gesetzt... > - Ist die Priorität des Interrupts < 7 (U4IP)? > Bei 7 passier nichts, wenn ich mich richtig erinnere. Sollte richtig sein > - sind irgendwo die Interrupts deaktiviert oder so? Kann man diese noch irgendwo selektiv deaktivieren? Weil auf einem anderen UART kommen (zeitgleich) die UART-Interrupts, wenn ich Daten empfange. > Ich muss aber sagen, dass ich ohne Peripheral lib > arbeite und daher deren Tücken nicht kenne. Kannst du mir ein Beispiel posten, wie es ohne Peripheral-Lib geht? Hilft mir vielleicht bei Aktionen, die außerhalb des "UART Aufsetzens" stattfinden...
Hallo, ich habe mal ein funktionierendes Beispiel für den PIC24 angehängt, für PIC32 habe ich nichts, auch keine HW mit UART zum testen. Prinzipiell ist das aber meistens das gleiche. Ich würde das für den PIC32 wie folgt initialisieren (RX): [c] U4STAbits.URXISEL = 0b00; //interrupt, if RX-Buffer is not empty IPC9bits.U4IP = 3; //set interrupt priority to 3 IFS2bits.U4RXIF = 0; //reset flag //TODO: flush buffer IEC2bits.U4RXIE = 1; //enable UART4 RX Interrupt [\c] In dem Fall müsste er in die UART 4 ISR springen, wenn er Daten empfangen hat. Das genaue Verhalten stellt man mit UXISL ein. Kann sein, dass die Bits in deinem PIC woanders sind, ich hab das kurz in ein Projekt für einen PIC32MX470 eingetippt - die Flags (U4IP etc) sollten aber gleich heißen. TX müsste analog gehen.
Ich habe es mittlerweile komplett auf Register-Zugriffe umgebaut, so hat es dann funktioniert (U2A mit _UART_2A_VECTOR). Vielen Dank für all eure Hilfe und Tipps! Die Peripheral Lib hat sich je nach IDE/Compiler (MPLAB mit altem Compiler, MPLAB-X mit neuem Compiler) unterschiedlich verhalten, hat dann teilweise auch einen anderen UART bedient, wie ich wollte. Dort scheint es Fehler in der Peripheral Libs zu geben, die ich dann aber nicht näher untersucht habe.
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.