Interrupt löst dauernd aus

OP #3260685
Lesenswert?

Hallo,
Ich habe nur einen Interrupthandler. Dieser ist für drei interrupts 
zuständig. (SPI)
Er löst die ganze Zeit und es kommt zu dem Watchdogfehler, das Programm 
kehrt nicht in die Main zurück. Leider kann ich den Fehler nicht finden.
1
// Includes ----------------------------------------------------------------------------------------
2
#include <hidef.h> /* for EnableInterrupts macro */
3
#include "derivative.h" /* include peripheral declarations */
4
#include "SPIDriver.h"
5

6

7
// Variablen ---------------------------------------------------------------------------------------
8
uint8 c_Data = 0x02;
9
static int sbufferpos = 0;
10

11
// Prototypen --------------------------------------------------------------------------------------
12
void SendeTakt(int takt);
13

14
// Main --------------------------------------------------------------------------------------------
15
void main(void) {
16

17
  
18

19
    spi_init();
20
    spi_setMode(Master, RisingEdge, LeadingEdge, LSBfirst);
21
    spi_selectChip(true);
22
    spi_enableInterrupt(true);
23
    
24
  
25
      for(;;)
26
      {
27
        __RESET_WATCHDOG();
28
        if(spi_checkComplete() == true)
29
        {
30
          c_Data = spi_receiveData();
31
          SendeTakt(27);
32
          
33
        }
34
      }  
35
   } 
36

37
__interrupt VectorNumber_Vspi1 void ISR_SPI() {
38

39
  uint8 Temp;
40
  if(sbufferpos==32) {
41
  sbufferpos = 0;
42
  } 
43
  else{
44
     sbufferpos = sbufferpos +1;
45

46
   if(SPI1S_SPRF == 1) {
47
      c_Data = spi_receiveData();
48
   } 
49
   else if(SPI1S_SPTEF == 1) {
50
      Temp = SPI1D;
51
      SendeTakt(27);    
52
   } 
53
   else{
54
      //Fehler
55
   }
56
   
57
  }
58
}
59

60
// Funktionen -----------------------------------------------------------------------------------------
61
void SendeTakt(int takt) {
62

63
  byte buffer[32];
64
  if(takt== 27) { //Wertzuweisung von buffer
65
 
66
  } 
67
  else if(takt == 26){  //Wertzuweisung von buffer
68
 
69
  } 
70
  else {
71
  }
72
    spi_sendData(buffer[sbufferpos]);
73
   
74
}
OP #3260800
Lesenswert?

Ein Bit bzw. Flag bekomme ich nicht gelöscht.

"This bit is set when there is room in the transmit data buffer. It is 
cleared byreading SPI1S with SPTEF set, followed by writing a data value 
to the transmit buffer at SPI1D. SPI1S must be read with SPTEF = 1 
before writing data to SPI1D or the SPI1D write will be ignored. SPTEF 
generates an SPTEF CPU interrupt request if the SPTIE bit in the SPI1C1 
is also set. SPTEF is automatically set when a data byte transfers from 
the transmit buffer into the transmit shift register. For an idle SPI 
(no data in the transmit buffer or the shift register and no transfer in 
progress), data written to SPI1D is transferred to the shifter almost
immediately so SPTEF is set within two bus cycles allowing a second 
8-bit data value to be queued into the transmit buffer. After completion 
of the transfer of the value in the shift register, the queued value 
from the
transmit buffer will automatically move to the shifter and SPTEF will be 
set to indicate there is room for new data in the transmit buffer. If no 
new data is waiting in the transmit buffer, SPTEF simply remains set and 
no data moves from the buffer to the shifter.
0 SPI transmit buffer not empty
1 SPI transmit buffer empty"

Hier ein auszug aus dem Datenblatt.
Sobald ich keine neuen Daten mehr schreiben will, und das SPTEF Flag 
gesetzt bleibt, löst die ganze Zeit das Interrupt aus.

"SPTEF simply remains set..." Genau das versuche ich eigentlich...

Jemand eine Idee?


#Nachtrag:
1
__interrupt VectorNumber_Vspi1 void ISR_SPI() {
2

3
    uint8 Temp;
4
    uint8 Tempo1;
5
    uint8 Tempo2;
6
    
7
    
8
    
9
  //Flags speichern
10
  Tempo1 = SPI1S_SPRF;
11
  Tempo2 = SPI1S_SPTEF;
12
  
13
  //Flags löschen
14
  SPI1S_SPRF = 0;
15
  SPI1S_SPTEF = 0;
16

17

18
   if(Tempo1 == 1) {
19
      
20
      Temp = spi_receiveData();
21
   } 
22
   else if(Tempo2 == 1) 
23
   {
24
      //schreibbereit    
25
   } 
26
   else{
27
      //Fehler
28
   }
29

30
}

So versuche ich es mittlerweile, leider auch ohne Erfolg. Einfach 0 
setzen geht nicht.
OP #3260821
Lesenswert?

1
void spi_enableInterrupt(bool b_Option)
2
{
3
  if(b_Option == true)
4
  {
5
    // SPI Interrupt einschalten
6
    SPI1C1 = SPI1C1|(SPI1C1_SPIE_MASK);
7
    SPI1C1 = SPI1C1|(SPI1C1_SPTIE_MASK);
8

9
    // Interrupts freigeben
10
    EnableInterrupts;
11
  }
12
  else
13
  {
14
    // SPI Interrupt abschalten
15
    SPI1C1 = SPI1C1&~(SPI1C1_SPIE_MASK);
16
  }
17
}

EnableInterrupts steht für sei().
Gast #3261399
Lesenswert?

Jan R. schrieb:
> Sobald ich keine neuen Daten mehr schreiben will, und das SPTEF Flag
> gesetzt bleibt, löst die ganze Zeit das Interrupt aus.

Das ist ja auch richtig, damit die Übertragung überhaupt gestartet wird.
Nachdem das letzte Byte übertragen wurde, mußt Du den Interrupt 
abschalten.

Das könnte so aussehen:
spi_enableInterrupt(false);
Gast #3261442
Lesenswert?

Ich kenne Deinen Prozessor nicht, aber "Frage an Radio Eriwan"
Wie wichtig ist die Sequenz:

Temp = SPI1D;

eigentlich?

Ein Compiler, der was auf sich hält, streicht diesen Befehl ersatzlos, 
da Temp in der Folge nicht verwendet wird.

Stichwort: volatile.
OP #3261814
Lesenswert?

M. N. schrieb:
> Das ist ja auch richtig, damit die Übertragung überhaupt gestartet wird.
> Nachdem das letzte Byte übertragen wurde, mußt Du den Interrupt
> abschalten.
>
> Das könnte so aussehen:
> spi_enableInterrupt(false);

Ok, dass wusste ich so nicht. Dann muss ich das Interrupt einfach 
ausschalten.

Bei der jetztigen Codeversion habe ich das Interrupt noch nicht 
ausgeschaltet, aber es funktioniert in dem Sinne von es schreibt die 
ganze Zeit.
1
void main(void) {
2

3
    spi_init();
4
    spi_setMode(Master, FallingEdge, LeadingEdge, MSBfirst);
5
    spi_selectChip(true);
6
    spi_enableInterrupt(true);
7
    
8
      for(;;)
9
      {
10
        __RESET_WATCHDOG();
11

12
          if( spi_checkComplete()==true) {
13
            
14
          SendeTakt(27);
15
          }
16
      }  
17
   } 
18

19
__interrupt VectorNumber_Vspi1 void ISR_SPI() {
20

21
    __RESET_WATCHDOG();
22

23
    if(sbufferpos<32) {
24
        sbufferpos = sbufferpos + 1;
25

26
           if((SPI1S&(SPI1S_SPRF_MASK)) == 0) {
27
           } 
28
           else{
29
              SPI1S;
30
              SPI1D;
31
           }
32
           if((SPI1S&(SPI1S_SPTEF_MASK)) == 0){  
33
           } 
34
            else{
35
              SPI1S;
36
              SendeTakt(27);
37
            }
38
    }
39
    else{
40
       sbufferpos = 0;
41
    }  
42
}

Hier die spi_checkComplete:
1
bool spi_checkComplete()
2
{
3
  uint8 Temp;
4

5
  if((SPI1S&(SPI1S_SPTEF_MASK)) == 0)
6
  {
7
    return false;
8
  }
9
  else
10
  {
11
    // SPI Data Buffer lesen um Interrupt Bit zu leeren
12
    Temp = SPI1D;
13
    return true;
14
  }
15
}

Den Watchdog sollte man ja eigentlich nciht im Interrupt feeden. Wenn 
ich es allerdings nicht mache, wird das Watchdoginterrupt nach etwa 20 
Durchläufen des Sendevorgangs ausgelöst. Ziemlich komisch, es werden 
keine Fehler angezeigt -> COP Watchdog caused a Reset

Hat hier noch jemand eine Idee?

Controller: MC9S08AW60 (freescale)
http://www.freescale.com/files/microcontrollers/doc/data_sheet/MC9S08AW60.pdf


Auf jeden Fall schon mal vielen Dank für die hilfreichen Antworten!
Gast #3261893
Lesenswert?

Datenblatt Seite 179
"
10.6.1 Clearing Timer Interrupt Flags
TPM interrupt flags are cleared by a 2-step process that includes a read 
of the flag bit while it is set (1)
followed by a write of 0 to the bit. If a new event is detected between 
these two steps, the sequence is reset
and the interrupt flag remains set after the second step to avoid the 
possibility of missing the new event.
"
OP #3261916
Lesenswert?

Ich kann euch mitteilen, dass es so ist. Wieso wird bei mir leider 
schwer...

Aber sehe ich das richtig, dass man zwangsläufig in der ISR den 
Schreibvorgang starten muss.

Ein solches Konstrukt funktioniert nicht:
1
main(){
2
    while(sbufferpos < buffergöße)
3
    {
4
    SendeData(bufferpos);
5
    }
6
}
7

8
ISR()
9
{
10
    if(Transmissionbuffer == empty)
11
    {
12
    sbufferpos++; 
13
    } 
14
}

Wenn man es so machen würde, würde das Interrupt ja permanent ausgelöst 
werden, da das Transmissionbufferemptyflag nicht acknowledged wird. Sehe 
ich das richtig?

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