Hi ! :) Ich verwende den PIC18f14k22. Dieser ist mit dem Bluetooth-Modul (RN42) verbunden (RX "RN42" --> TX "µC"). Ich möchte über einen Bluetooth Terminal per Smartphone z.B.: "A" senden .... dieses soll eine LED aktivieren. Leider schaff ich es nur die "RCIF-flag" zu setzen ... der decimal Wert bleibt aber immer 48 (A ist 41). Kann mir jemand helfen das Problem zu lösen?? mfg Peb
Du könntest das RCIE auf '1' setzten und das Interrupt damit aktivieren. Die ISR musst du nicht in der main aufgerufen, sie wird automatisch ausgeführt wenn das entsprechende Ereignis auftritt. Um Daten vom BT-Modul an den uC zu senden musst du Tx des BT-Molduls mit Rx des uCs verbinden. Tx: Transmit Rx: Receive
Peb schrieb: > (RX "RN42" --> TX "µC") Hier hab ich mich verschrieben .. :/ Max H. schrieb: > Du könntest das RCIE auf '1' Sobald ich RCIE auf "1" setz... kann die RCIF flag nicht mehr gesetzt werden Ich hab das Programm überarbeitet .. es bleibt dieses mal im RCREG hängen.
"RCONbits.IPEN = 1; IPR1bits.RCIP = 0, PIE1bits.RCIE = 1; INTCONbits.GIEL = 1; INTCONbits.GIEH = 1; " Interrupts sind enabled, aber wo ist die Interruptroutine dafür??
So? #pragma code IntVectLow=0x18 void IntVectLow (void) { _asm GOTO uart_rec _endasm } #pragma code #pragma interrupt uart_rec
> PIE1bits.RCIE
Welcher Compiler?
Du müsst dich aber entscheiden, ob du die Funktion uart_rec(void) in der
main oder als ISR aufrufen willst und wenn Zweiteres das
while(!PIR1bits.RCIF); rausschmeißen und durch eine
1 | if(PIR1bits.RCIF&&PIE1bits.RCIE) |
2 | {
|
3 | ...
|
4 | }
|
ersetzen und das return RCREG; auch rausschmeißen. Peb schrieb: > Sobald ich RCIE auf "1" setz... kann die RCIF flag nicht mehr gesetzt > werden Das muss auch nicht gesetzt werden, das mach die Hardware automatisch wenn ein Zeichen ankommt (und sie richtig konfiguriert ist).
Max H. schrieb: > ersetzen und das return RCREG; auch rausschmeißen. Im Datenblatt steht doch, dass man nach dem RCIF das RCREG lesen soll.
Peb schrieb: > Max H. schrieb: >> Welcher Compiler? > > Ich verwende den C18 compiler. Dann müsste das mit dem Interrupt so passen. Peb schrieb: > Im Datenblatt steht doch, dass man nach dem RCIF das RCREG lesen soll. Eine ISR hat aber keinen return Wert, wohim sollte die auch etwas returnen? Nimm dafür eine globale volatile Variable.
#pragma code IntVectLow=0x18 void IntVectLow (void) { _asm GOTO uart_rec _endasm } #pragma code #pragma interrupt uart_rec void uart_rec() { volatile unsigned char x; if(PIR1bits.RCIF&&PIE1bits.RCIE) { if(RCSTAbits.FERR == 1) { RCSTAbits.CREN = 0; x = RCREG; RCSTAbits.CREN = 1; } if(RCSTAbits.OERR == 1) { RCSTAbits.CREN = 0; x = RCREG; RCSTAbits.CREN = 1; } x = RCREG; return x; } } Wie mach ich das in der Hauptfunktion --> Endlosscheife??
Peb schrieb: > return x; Eine ISR hat immer noch keinen return Wert, wohin sollte die auch etwas returnen? Peb schrieb: > Wie mach ich das in der Hauptfunktion --> Endlosscheife?? Wenn du sonst nichts zu tun hast, dann ja. Dann könnte man auf das Interrupt aber auch komplett verzichten und in der main pollen.
Ich möchte dann das gesendete "A" in der Endlosschleife "verarbeiten".... also: if(data == 'A') { LATC=0x01; //Led ein } Aber ich muss doch irgendwas vor "if" schreiben oder??
Max H. schrieb: > Eine ISR hat immer noch keinen return Wert, wohin sollte die auch etwas > returnen? Soll ich das return x weg lassen?
Peb schrieb: > void uart_rec() > { > volatile unsigned char x; x ist so eine lokale variable. Peb schrieb: > Ich möchte dann das gesendete "A" in der Endlosschleife > "verarbeiten".... > Aber ich muss doch irgendwas vor "if" schreiben oder?? Ich würde es in eine while(1) setzen:
1 | while(1) |
2 | {
|
3 | if(data == 'A') |
4 | {
|
5 | LATC=0x01; //Led ein |
6 | }
|
7 | }
|
Peb schrieb: > Soll ich das return x weg lassen? genau
Das funktioniert so nicht :/ Mittels der Watch-Funktion in MPLAB sehe ich, dass der Decimal Wert "48" ist... Laut ASCII-Tabelle ist "A" --> 41 Ebenso bleib ich in der Endlosschleife hängen (Interrupt wird nicht ausgelöst)
1 | C-Code#include <p18f14k22.h> |
2 | #include <usart.h> |
3 | |
4 | #pragma config FOSC = IRC
|
5 | #pragma config IESO = OFF, PLLEN = OFF, FCMEN = OFF, PCLKEN = OFF
|
6 | #pragma config BOREN = SBORDIS, BORV = 19, PWRTEN = OFF, WDTEN = OFF
|
7 | #pragma config MCLRE = OFF, HFOFST = OFF, DEBUG = OFF, STVREN = ON
|
8 | #pragma config XINST = OFF, BBSIZ = OFF, LVP = OFF
|
9 | #pragma config CP0 = OFF, CP1 = OFF
|
10 | #pragma config CPD = OFF, CPB = OFF
|
11 | #pragma config WRT0 = OFF, WRT1 = OFF
|
12 | #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
|
13 | #pragma config EBTR0 = OFF, EBTR1 = OFF
|
14 | #pragma config EBTRB = OFF
|
15 | |
16 | void pic_init(void); |
17 | void uart_rec(); |
18 | |
19 | void main(void) |
20 | {
|
21 | unsigned char data; |
22 | pic_init(); |
23 | |
24 | while(1) |
25 | {
|
26 | |
27 | if(data == 'A') |
28 | {
|
29 | LATC = 0x01; |
30 | }
|
31 | else if(data == 'b') |
32 | {
|
33 | LATC = 0x00; |
34 | }
|
35 | }
|
36 | }
|
37 | |
38 | void pic_init(void) |
39 | {
|
40 | OSCCON = 0b01110000; //16 Mhz --> Internal OSCI --> 9600 Baud Rate |
41 | TRISC = 0x00; |
42 | TRISBbits.TRISB5 = 1; //RB5 (RX --> INPUT) |
43 | TRISBbits.TRISB7 = 0; //RB7 (TX --> OUTPUT) |
44 | ANSELHbits.ANS11=0; // RB5 IO |
45 | |
46 | SPBRG = 103; //9600 Baud Rate for 16 MHz |
47 | |
48 | TXSTAbits.TX9 = 0; // 8-bit transmission |
49 | TXSTAbits.TXEN = 1; // Disabled transmission |
50 | TXSTAbits.SYNC = 0; // Asynchronous mode |
51 | TXSTAbits.BRGH = 1; |
52 | /***************************/
|
53 | RCSTAbits.SPEN = 1; // Enable serial port |
54 | RCSTAbits.RX9 = 0; // 8-bit reception |
55 | RCSTAbits.CREN = 1; // Enable reception |
56 | /***************************/
|
57 | BAUDCONbits.BRG16 = 0; // 8-bit Bau Rate Generator is used |
58 | BAUDCONbits.WUE = 1; // Wake-up Enable bit |
59 | /********************/
|
60 | RCONbits.IPEN = 1; |
61 | IPR1bits.RCIP = 0, |
62 | INTCONbits.GIEL = 1; |
63 | INTCONbits.GIEH = 1; |
64 | }
|
65 | |
66 | #pragma code IntVectLow=0x18
|
67 | void IntVectLow (void) |
68 | {
|
69 | _asm GOTO uart_rec _endasm |
70 | }
|
71 | #pragma code
|
72 | #pragma interrupt uart_rec
|
73 | |
74 | |
75 | void uart_rec() |
76 | {
|
77 | volatile unsigned char x; |
78 | |
79 | if(PIR1bits.RCIF&&PIE1bits.RCIE) |
80 | {
|
81 | if(RCSTAbits.FERR == 1) |
82 | {
|
83 | RCSTAbits.CREN = 0; |
84 | x = RCREG; |
85 | RCSTAbits.CREN = 1; |
86 | }
|
87 | if(RCSTAbits.OERR == 1) |
88 | {
|
89 | RCSTAbits.CREN = 0; |
90 | x = RCREG; |
91 | RCSTAbits.CREN = 1; |
92 | }
|
93 | x = RCREG; |
94 | }
|
95 | }
|
Das löst das Problem mit dem nicht ausgelösten Interrupt zwar nicht, aber data und x sind beides lokale Variablen die nix voneinander wissen. data hat also keine Chance irgendwie an den Inhalt von RCREG zu kommen.
Ich hab jetzt "volatile unsigned char x;" außerhalb der "Hauptfunktion" geschrieben.
Peb schrieb: > Ich hab jetzt "volatile unsigned char x;" außerhalb der "Hauptfunktion" > geschrieben. Und hoffentlich das x auch in die if-Abfrage. Peb schrieb: > BAUDCONbits.WUE = 1; // Wake-up Enable bit Zitat Datenblatt: > WUE: Wake-up Enable bit > Asynchronous mode: > 1 = Receiver is waiting for a falling edge. No character will be > received but RCIF will be set on the falling edge. WUE will > automatically clear on the rising edge. > 0 = Receiver is operating normally
Max H. schrieb: > Und hoffentlich das x auch in die if-Abfrage. ja hab ich. Max H. schrieb: > Zitat Datenblatt: >> WUE: Wake-up Enable bit >> Asynchronous mode: >> 1 = Receiver is waiting for a falling edge. No character will be >> received but RCIF will be set on the falling edge. WUE will >> automatically clear on the rising edge. >> 0 = Receiver is operating normally Ich hab das Bit auf 0 gesetzt.
Oder soll ich in der vor der If-Abfrage auf das RCIF warten "while(!PIR1bits.RCIF); ?
Peb schrieb: > Oder soll ich in der vor der If-Abfrage auf das RCIF warten > "while(!PIR1bits.RCIF); ? Das wird eine Endlosschleife, sobald das bit 1 wird springt der µC in die ISR und dort wird es wieder gelöscht, es ist also immer aus 0 während das while ausgeführt wird. Hast du mal überprüft ob die Siganle auch beim Rx-Pin ankommen.
Das wären mir viel zu viele Baustellen auf einmal: Mach es doch erst mal ohne Interrupt in der main schleife Dann kannst du besser eingrenzen wo der Fehler her kommt. Aber auch da alles Schritt für Schritt Also prüfen: 1. ob ein Zeichen empfangen wurde 2. ob das richtige empfangen wurde 3. ob das nächste auch empfangen wird Anschließend ob das ganze auch mit dem Interrupt funzt Deinen Compiler kenne ich nicht aber der PIC18 hat in der Regel mehrerer U(S)ARTS Woher weiß der Compiler welcher gemeint ist? So auf die schnelle sehe ich auch nicht wo der Peripherial Interrupt Enabled (PEIE) wird?
Max H. schrieb: > Hast du mal überprüft ob die Siganle auch beim Rx-Pin ankommen. Ich hab mich mit einem Oszi + Tastkopf auf RX gehängt und hab das Signal gesehen.
Der Rächer der Transistomorde schrieb: > der PIC18 hat in der Regel mehrerer U(S)ARTS Dieser nicht. > So auf die schnelle sehe ich auch nicht wo der Peripherial Interrupt > Enabled (PEIE) wird? Das ist wenn man priorisierte Interrupts aktiviert hat nicht nötig.
Der Rächer der Transistomorde schrieb: > So auf die schnelle sehe ich auch nicht wo der Peripherial Interrupt > Enabled (PEIE) wird? PEIE ist laut Datenblatt das gleiche wie, GIEL. "PEIE/GIEL: Periperial Interrupt When IPEN = 0: 1 = Enables all unmasked peripheral interrupts 0 = Disable all peripheral interrupts When IPEN = 1; 1= Enables all low priority interrupts 0 = Disables all low priority interrupts" Der Rächer der Transistomorde schrieb: > der PIC18 hat in der Regel mehrerer U(S)ARTS Wie meinst du das?
Max H. schrieb: > Das ist wenn man priorisierte Interrupts aktiviert hat nicht nötig. Beim Pic 18 hast ist das Interruptmodel einfach in Low und high gespiegelt. Da musst du PEIE setzen egal auf welchen du deinen Interrupt routest. Das Bild hab ich von http://www.foxytronics.com/learn/microcontrollers/pic18/pic18-interrupts/interrupt-priority Peb schrieb: > Ich finde im Datenblatt nur "USART". Dann hat er auch nur einen > PEIE ist laut Datenblatt das gleiche wie, GIEL. Dann ist das auch ok, Aber ohne Interrupt kannst du den Fehler einfacher eingrenzen.
Der Rächer der Transistomorde schrieb: > Beim Pic 18 hast ist das Interruptmodel einfach in Low und high > gespiegelt. Da musst du PEIE setzen egal auf welchen du deinen Interrupt > routest. Ich hab "INTCONbits.PEIE = 1;" hinzugefügt. Wie lös ich den Fehler mit der Hauptfunktion, das diese nicht den Interrupt auslöst bzw. die Daten vom RCREG ausliest?
Peb schrieb: > Ich hab mich mit einem Oszi + Tastkopf auf RX gehängt und hab das Signal > gesehen. Hast du eigentlich geprüft welche Funktionen noch auf dem Port liegen? Würde ich bei Pics immer machen weil einige Funktionen vorrang haben Z.b. AD Eingänge bei RX liegt laut Datenblatt ADC11 mit drauf. Ist der deaktiviert?
Peb schrieb: > Wie lös ich den Fehler mit der Hauptfunktion, das diese nicht den > Interrupt auslöst bzw. die Daten vom RCREG ausliest? Welchen Fehler? Das ist eigentlich normal, dass das Interrupt von der Hardware ausgelöst wird und das RCREG in der ISR ausgelesen wird (wenn man mit Interrupts arbeitet). Der Rächer der Transistomorde schrieb: > AD Eingänge bei RX liegt laut Datenblatt ADC11 mit drauf. > > Ist der deaktiviert? Peb schrieb: > ANSELHbits.ANS11=0; // RB5 IO
Max H. schrieb: > Welchen Fehler? Das ist eigentlich normal, dass das Interrupt von der > Hardware ausgelöst wird und das RCREG in der ISR ausgelesen wird (wenn > man mit Interrupts arbeitet). Ja aber ich kann ich schaffe es ja nicht den Interrupt auszulösen Der Rächer der Transistomorde schrieb: > Ist der deaktiviert? ADCON0 = 0b00101100; // Der ADC sollte jetzt deaktiviert sein
Aber ich schaffe es ...* Vlt muss man den ADC noch zusätzlich mit "ADCON0 = 0b00101100;" deaktivieren
Peb schrieb: > Wie lös ich den Fehler mit der Hauptfunktion, das diese nicht den > Interrupt auslöst bzw. die Daten vom RCREG ausliest? Du fragst einfach das receiver interrupt flag ab. Wenn gesetzt machst du irgendwas z.B. n Port toggeln und löscht es danach wieder. Dann siehst du auf deinem Oszi gleich ob das ganze ankommt. Von der PIC Philosophie her wird der Interrupt nicht von der Hauptroutine ausgelöst sondern es ist ein Software Interrupt den der Receiver setzt. Dann wird der aktuelle Maschinenbefehl abgearbeitet, der Programmzähler und n paar Register gerettet und einfach an der Interrupt Adress weiter gemacht. Mehr ist das gar nicht alles andere musst du selbst machen. Beim RTI ist es einfach umgedreht. Peb schrieb: > ADCON0 = 0b00101100; // Der ADC sollte jetzt deaktiviert sein und nu gehts?
Der Rächer der Transistomorde schrieb: > und nu gehts? Nein :( Wie soll ich in der main... das RCIF abfragen?? if(PIR1bits.RCIF == 1) ??
Seit ich das "Wake-Up-Bit" auf 0 gesetzt hab ... Kann ich die RCIF nicht mehr setzen.
Peb schrieb: > Kann ich die RCIF nicht > mehr setzen. Das musst du auch nicht setzten, das macht die Hardware für dich sobald ein Byte ankommt.
Max H. schrieb: > Das musst du auch nicht setzten, das macht die Hardware für dich sobald > ein Byte ankommt. Macht es aber nicht O.o ...
Peb schrieb: >> Das musst du auch nicht setzten, das macht die Hardware für dich sobald >> ein Byte ankommt. Dann kommt einfach nichts an ;-)
Peb schrieb: > Laut Oszi kommt was an :O Dann liegt der Fehler dazwischen (den eigenen Ohren) ;-) Macht das nochmal komplett neu und RTFM! Da steht dann z.B.: 15.1.2.9 Asynchronous Reception Set-up: 1. Initialize the SPBRGH:SPBRG register pair and the BRGH and BRG16 bits to achieve the desired baud rate (see Section 15.3 “EUSART Baud Rate Generator (BRG)”). 2. Enable the serial port by setting the SPEN bit and the RX/DT pin TRIS bit. The SYNC bit must be clear for asynchronous operation. 3. If interrupts are desired, set the RCIE interrupt enable bit and set the GIE and PEIE bits of the INTCON register. 4. If 9-bit reception is desired, set the RX9 bit. 5. Set the DTRXP if inverted receive polarity is desired. 6. Enable reception by setting the CREN bit. 7. The RCIF interrupt flag bit will be set when a character is transferred from the RSR to the receive buffer. An interrupt will be generated if the RCIE interrupt enable bit was also set. 8. Read the RCSTA register to get the error flags and, if 9-bit data reception is enabled, the ninth data bit. 9. Get the received 8 Least Significant data bits from the receive buffer by reading the RCREG register. 10. If an overrun occurred, clear the OERR flag by clearing the CREN receiver enable bit. Hast du das alles gemacht?
Peb schrieb:
1 | > #pragma code IntVectLow=0x18 |
2 | > void IntVectLow (void) |
3 | > { |
4 | > _asm GOTO uart_rec _endasm |
5 | > } |
6 | > #pragma code |
7 | > #pragma interrupt uart_rec |
8 | >
|
9 | > void uart_rec() |
10 | < ..... |
Sag mal wie funzt das eigentlich beim C18 Wenn du dem wie oben in der Interrupt routine ezählst er soll auf den Anfang einer von dir erstellten hüpfen, woher weiß er dann wann er aus dem Interrupt zurück soll?
Der Rächer der Transistomorde schrieb: > Peb schrieb: >
1 | >> #pragma code IntVectLow=0x18 |
2 | >> void IntVectLow (void) |
3 | >> { |
4 | >> _asm GOTO uart_rec _endasm |
5 | >> } |
6 | >> #pragma code |
7 | >> #pragma interrupt uart_rec |
8 | >>
|
9 | >> void uart_rec() |
10 | > < ..... |
11 | >
|
12 | >
|
> > Sag mal wie funzt das eigentlich beim C18 > > Wenn du dem wie oben in der Interrupt routine ezählst er soll auf den > Anfang einer von dir erstellten hüpfen, woher weiß er dann wann er aus > dem Interrupt zurück soll? Durch "#pragma interrupt uart_rec" weiss der Compiler das es sich bei der Funktion "uart_rec" um eine Interruptroutine handelt und fügt am Ende automatisch ein RETFIE 0 oder RETFIE 1 ein. Daher funkteoniert auch ein "return()" u.ä. nicht weil damit der Interrupt nicht wieder freigeschaltet wird und auch diverse, automatisch beim Interrupeintritt gesicherte Register, nicht wiederhergestellt werden (zum. wenn mit Shadow-Register gearbeitet wurde.....). btw. vielleicht verwirft der Compiler ein "return" in einer ISR automatisch!?!?...ist schon länger her das ich den C18 verwendet habe da ohnehin nicht mehr "supported".
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.