PIC18 connected to RN42

Gast #3839007
Lesenswert?

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
Angehängte Dateien:
#3839394
Lesenswert?

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
#3839658
Lesenswert?

> 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).
Gast #3839754
Lesenswert?

#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??
#3839767
Lesenswert?

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
Gast #3839774
Lesenswert?

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)
Gast #3839797
Lesenswert?

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
  }
#3839813
Lesenswert?

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
Gast #3839815
Lesenswert?

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.
#3839836
Lesenswert?

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.
Gast #3839844
Lesenswert?

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?
Gast #3839860
Lesenswert?

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?
Gast #3839873
Lesenswert?

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.
Angehängte Dateien:
Gast #3839882
Lesenswert?

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?
#3839886
Lesenswert?

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
Gast #3839899
Lesenswert?

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?
Gast #3840259
Lesenswert?

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?
Gast #3840263
Lesenswert?

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?
#3840346
Lesenswert?

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".

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren