Forum: Mikrocontroller und Digitale Elektronik USART_Interrupt_verlassen_funktioniert_nicht


von Alex X. (behindi)


Lesenswert?

Hallo

ich hab nen keleines Problem und es wäre super wenn mir jemand weiter 
helfen könnte:) , danke im vorsus für jede Hilfe

ich verwende den PIC18F46K20. Der PIC soll einen Interrupt auslösen wenn 
ein Byte über die USART enpfangen wird. Das Problem ist dass der 
Interrupt in einer Endlosschleife ausgeführt wird trotz dass das Flagbit 
gelöscht wird.??
Das Byte sende ich vom PC aus. Die USART und die kommunikation mit dem 
PC funktioniert. Hat von euch jemand ne idee was ich falsch mache?
hier der code
1
#pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF
2
#pragma config PWRT = ON, BOREN = OFF, BORV = 18
3
#pragma config WDTEN = OFF, WDTPS = 1
4
#pragma config MCLRE = ON, HFOFST = OFF, LPT1OSC = OFF, PBADEN = OFF
5
#pragma config CCP2MX = PORTBE, STVREN = OFF, LVP = OFF, XINST = OFF, DEBUG = OFF
6
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
7
#pragma config CPB = OFF, CPD = OFF
8
#pragma config EBTR0 = OFF
9
#pragma config EBTR1 = OFF
10
#pragma config EBTR2 = OFF
11
#pragma config EBTR3 = OFF
12
13
#define USE_OR_MASKS
14
15
#include "p18f46K20.h"
16
#include "delays.h"
17
#include "usart.h"
18
19
unsigned char i,j;
20
21
#pragma code
22
23
void PORT_INIT(void);
24
void UART_CONFIG(void);
25
26
void ISH(void);
27
void ISL(void);
28
void INT_UART_INIT(void);
29
30
#pragma code IVH = 0x08      // Interrupt-Vektor fuer hohe Prioritaet (HP)
31
void IVH(void)
32
{
33
  _asm              // So werden Assembler-Befehle in C eingebettet
34
    goto ISH          // Interrupt Service Routine fuer HP
35
  _endasm
36
}
37
38
#pragma code IVL = 0x18      // Interrupt-Vektor fuer niedere (low) Prioritaet (LP)
39
void IVL(void)
40
{
41
  _asm
42
    goto ISL          // Interrupt Service Routine fuer LP
43
  _endasm
44
}
45
46
void main(void)
47
{
48
  PORT_INIT();
49
  UART_CONFIG();
50
    INT_UART_INIT();
51
    LATD=0x00;
52
    Delay10KTCYx(100);
53
54
  while(1);
55
}
56
57
void PORT_INIT(void)
58
  {
59
  OSCCONbits.IRCF2 = 1;
60
  OSCCONbits.IRCF1 = 0;           // 16MHz
61
  OSCCONbits.IRCF0 = 1;
62
63
    TRISD=0x00;
64
  }
65
66
void UART_CONFIG(void)
67
  {
68
  unsigned char config = 0, baudconfig = 0;
69
  unsigned int spbrg = 0;
70
71
    CloseUSART();
72
73
  config = USART_TX_INT_OFF | USART_RX_INT_ON | USART_ASYNCH_MODE | USART_EIGHT_BIT | USART_CONT_RX | USART_BRGH_LOW;
74
  spbrg =25;                      // 2400 Baud
75
  OpenUSART(config, spbrg);
76
77
  baudconfig = BAUD_8_BIT_RATE | BAUD_AUTO_OFF;
78
  baudUSART(baudconfig);
79
  }
80
81
void INT_UART_INIT(void)
82
    {
83
    PIE1bits.RCIE=1;                // enable USART resieve interrupts
84
    IPR1bits.RCIP=1;                 // high priority
85
86
    RCONbits.IPEN = 1;          // Interrupt-Prioritaeten deaktiviert
87
    INTCONbits.GIE = 1;          // Interrupts global aktiviert
88
    INTCONbits.PEIE = 1;        // Periphere Interrupts aktiviert
89
    }
90
91
#pragma interrupt ISH
92
void ISH(void)
93
    {
94
    LATD++;
95
    PIR1bits.RCIF = 0;                                               
96
    }
97
98
#pragma interruptlow ISL
99
void ISL(void) {}

von Conny G. (conny_g)


Lesenswert?

> Das Problem ist dass der
> Interrupt in einer Endlosschleife ausgeführt wird trotz dass das Flagbit
> gelöscht wird.??

Also auf jeden Fall steht auf Seite 243 des Datasheet:

"The RCIF interrupt flag bit is read-only, it cannot be set or cleared 
by software."
(gleich am Anfang der Seite)

Der Code scheint momentan in der ISR nichts weiter zu machen, vielleicht 
MUSS man das Byte lesen oder den Interrupt anders resetten?
Es gibt auch einen Buffer Overrun, vielleicht schlägt der zu?

Ansonsten ist die ISH ja eine allgemeine Routine und nicht nur für den 
USART, vielleicht passiert da ja noch was anderes wie ein Timer 
Interrupt?

von B. S. (bestucki)


Lesenswert?

Konrad hat recht, steht auch auf Seite 112:
> bit 5 RCIF: EUSART Receive Interrupt Flag bit
> 1 = The EUSART receive buffer, RCREG, is full (cleared when RCREG is
> read)
> 0 = The EUSART receive buffer is empty

Du musst RCREG lesen, dann erledigt sich die Sache von selbst. Das ist 
eines der wenigen Falgs, das man nicht manuell löschen muss.


Nachtrag:
Falls du später vor hast Daten zu senden; auch da gibts ne Falle. Dann 
löst das Interrupt immer aus, wenn der Buffer (TXREG) leer ist. Also 
auch dann, wenn du gar nichts senden willst. Daher musst du das erste 
Byte manuell in TXREG kopieren, Interrupt einschalten und den Rest 
kannst du dann im Interrupt erledigen. Hast du keine Daten zum senden 
mehr, so musst du das Interrupt wieder ausschalten.

von Alex X. (behindi)


Lesenswert?

Danke für deine Hilfe,

habs im Datenblatt auch gelesen, aber
in einem Example von der C18 lib steht das zwar auch so:D
1
....
2
/*  66 */        */
3
/*  67 */       putsUSART (data[10]);
4
/*  68 */
5
/*  69 */       /* Display value received on LEDs */
6
/*  70 */       PORTB = c;
7
/*  71 */     }
8
/*  72 */
9
/*  73 */     /* Clear the interrupt flag */
10
/*  74 */     PIR1bits.RCIF = 0;
11
/*  75 */ }

naja löschen lässts sich jedenfalls nicht

Konrad G. schrieb:
> vielleicht
> MUSS man das Byte lesen

jo muss man :)

jetzt funktioniert es, danke für die Hilfe

mgf

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
Noch kein Account? Hier anmelden.