mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Programm springt nicht aus ISR


Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich verwende den LPC2148 auf dem Evaluationsboard MCB2140 von Keil. Zum 
Debuggen verwende ich das Programm Hitop 5.

Mein Problem ist, dass mein Programm nach Aufruf der Startfunktion nicht 
mehr aus der ISR heraus springt, sondern immer wieder nach abarbeiten 
der ISR wieder in die selbige springt.

Hier der Code im wesentlichen:
int main (void)
{

  i2cMaster_init();
  while(1)
  {
    start(0x90);  
  }
  return 0;

}

void i2cMaster_init(void)
{
  MEMMAP = 0x2;
  
  PINSEL0 = 0;
  PINSEL1 = 0;
  PCONP |= (1 << I2C_POWER);

  PINSEL0 |=(1 << SCL0_PINSEL) | (1 << SDA0_PINSEL); //SDA und SCL Pins auf I2C-MOdus

  I20CONCLR = (1 << STO) | (1 << AA) | (1 << STA) | (1 << SI);
  I20CONSET = (1 << I2EN) ;//  //enable the I2C function.

  I20SCLH = 100;
  I20SCLL = 58;

  VICIntSelect = 0;
  temp = VICIntSelect;

  VICVectCntl0 = (DWORD)(IRQ_SLOT_EN | IE_I2C);
  VICVectAddr0 = (DWORD) I2C_ISR;  
}



void i2c_start(int addr)
{  
  slaveaddr = addr;  
  VICIntEnable = (1 << IE_I2C);  
  I20CONSET = (1 << STA) ;      //  set STA  
}

void I2C_ISR(void) 
{  int temp1 = 0;
  temp1 = I20STAT;
  I20CONCLR = (1 << SIC);
  
  switch(temp1)
  {
    
    case 0x08:
    {  
      I20DAT = slaveaddr; //addr
      temp1 = I20DAT;
      
      break;
    }
    case 0x10:
    {
      I20DAT = slaveaddr;
      break;
    }
  }
  VICVectAddr = 0;
    
}


Autor: jimjack jimjack (jimjack)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm...

gehören die "breaks" nicht jeweils ausserhalb der geschweiften Klammern?

Ich kennne jetzt den LPC nicht, aber hast Du, wenn benötigt das 
Interrupt-Flag vom I2C zurückgesetzt? Bei manchen Controller ist das 
händisch zu machen.

Steffen

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. D. schrieb:

> Mein Problem ist, dass mein Programm nach Aufruf der Startfunktion nicht
> mehr aus der ISR heraus springt, sondern immer wieder nach abarbeiten
> der ISR wieder in die selbige springt.

Üblicherweise bedeutet das, dass die interruptauslösende Bedingung dann 
nicht beseitigt wurde.
Meistens ist es so, dass eine ISR diese Bedingung automatisch 
zurücksetzt. Aber gerade bei Kommunikations-ISR ist es oft so, dass man 
das Datenregister des Bausteins auslesen muss, damit das entsprechende 
Interrupt-Flag gelöscht wird.
Wie das bei deinem Prozessor ist, weiß ich nicht. Aber einen Versuch 
wäre es wert.
Sprich: Wenn dir der Aufruf der ISR schon anzeigt, dass ein Byte 
eingetrudelt ist, dann solltest du es auch abholen. Selbst dann, wenn 
ein anderes Flag dir eine Fehlerbedingung anzeigt.

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HI Steffen

ja das Interrupt-flag lösche ich mit folgernder Zeile,
I20CONCLR = (1 << SIC);

Gruß Michael

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Johnny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat nur indirekt mit Deinem Problem zu tun, aber dennoch:
Mit festen Zuweisungen solltest Du vorsichtig sein, wenn Du eigentlich 
nur Bitoperationen machen willst. Es funktioniert zwar schon, wenn man 
weiss was man tut. Aber meist gibts weniger Fehler, wenn Du Bits 
folgendermassen setzt oder löschst...

Beispiele:

SIC Bit setzen
I20CONCLR |= (1 << SIC);

SIC Bit löschen
I20CONCLR &= ~(1 << SIC);

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johnny schrieb:
> Mit festen Zuweisungen solltest Du vorsichtig sein, wenn Du eigentlich
> nur Bitoperationen machen willst.


Ne, das stimmt schon, der ARM7 hat spezielle Löschregister.
Eine 1 löscht, eine 0 hat keinen Effekt.

Das ist als Krücke gedacht, da er nicht wie der ARM-Cortex-M3 
Bitoperationen kann.


Peter

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok ,habe das mit dem break geändert, ändert aber leider nichts
am Programmablauf.

Zu |= kann ich nur sagen, dass ich vor diesem Problem faat 10 Tage an 
einem anderen Problem hing und nichts lief, da ich |= verwendet habe bei 
einem Register dass man nur schreiben kann und ich deswegen Probleme 
ohne Ende hatte. Deswegen bin ich damit vorsichtig.

Aber ich will jetzt nicht in dieses Thema abschweifen.
Habe das Falg schon am Anfang der Rotunie gelöscht, nur habe ich dann 
das Problem, dass das Statusregister, dass ich ja auslesen will, 
verändert wird..

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob die breaks in der Klammer sind oder draussen ist hier komplett 
wurscht. Und die {} für die switch cases sind hier sowieso überflüssig, 
werden nur benötigt, wenn man dort lokale Variablen definieren will.

Nur bringt es u.U. nichts, das SI Bit zu löschen, wenn der eigentliche 
Grund für den Interrupt noch da ist. Es gibt ja mehr Zustände, als du in 
der ISR berücksichtigst. Wenn du meinst, die seien sinnlos, dann 
solltest du dennoch darauf reagieren, Daten abholen und wegwerfen, 
Abbruch (Stop) erzwingen, ...

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Inhalt vom Statusregister lasse ich mir im Debugger anzeigen.
Die Werte die vorkamen, werden von meiner ISR abgehandelt.

Gruß

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch etwas ist mir aufgefallen:
Erst wenn ich das SI-Flag lösche, werden die Änderungen sichtbar, sprich 
bei Abhandlung des Falls "0x08" wird erst nach löschen Von Si, die 
gesaendete Adresse am Oszi sichtbar.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die Werte die vorkamen, werden von meiner ISR abgehandelt.

Und wenn mal was anderes vorkommt als im Test soll das Programm qua 
Vorschrift einfach hängen bleiben oder abstürzen?

Normalerweise müssten da auch ohne Fehler noch andere Stati kommen. 
Beispielsweise wenn die Adresse raus ist und Daten fällig werden. Gibt 
dazu ein paar schöne Tabellen im Manual (Tab148+).

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein ,mir ist schon klar, dass das Programm so nicht optimal ist.
Aber ich meine in meinem konkreten Problemfall sehe ich ja, aus welchem 
Interruptgrund die ISR ausglöst wurde und jetzt habe ich eben das 
Problem dass ich nicht mehr aus der ISR heraus komme.

Ich habe auch schonmal was zu dem thema gesehen als ich das Problem noch 
nicht hatte, habe es aber bisher noch nicht wieder gefunden...
dann werde ich mal weiter suchen.

Wäre dankbar für schnelle Hilfe,

Gruß

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. D. schrieb:

> Erst wenn ich das SI-Flag lösche, werden die Änderungen sichtbar, sprich
> bei Abhandlung des Falls "0x08" wird erst nach löschen Von Si, die
> gesaendete Adresse am Oszi sichtbar.

08/10 heisst ja nur, dass eine Start Condition komplett ist. Solange SI 
nicht gelöscht wird ändert sich am Bus per Definition nichts. Siehe 
Doku, steht da so drin. Und die Adresse hat er ohnehin erst als Reaktion 
auf 08/10, wie sollte die also vorher auf dem Bus sichtbar werden 
können?

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was mich auch wundert, ist dass das SI Flag laut Debugger garnicht 
gelöscht wird.
Hat jemand eine Ahnung woran das liegen könnte?

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich entschuldige mihc, ich habe auf die falsche Speicherstelle geschaut.
Also Si-Flag wird gelöscht, und Slaveadresse und Daten werden korrekt 
ausgegeben, aber die ISR wird eben nie beendet.....

Autor: A. C. (michael1988)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab jetzt mal die komplette ISR drin.
Ganz des Hauptproblem ist eigentlich, dass alles bis zum abarbeiten von 
"0x28" Routine funktionert(Slaveadresse übertragen mit ACK), allerdings
ist der Satuscode nach dem abrbeiten der "0x28"-Routine ="0x10" und dass 
die Daten nicht übertragen werden.
Wenn der Statuscode dann 0x10 ist, springt die ISR wieder in die "0x10" 
Behandlung.

char buf_config[]={0xAC,0x00,11};
char buf_start[]={0xEE,11};
char buf_read[]={0xAA,11};
char receice_buf[1];

int count = 0, i = 0;
int slaveaddr = 0;int data = 0;
void I2C_ISR(void) __irq
{  
  int temp1 = 0;
  temp1 = I20STAT;
  
  switch(temp1)
  {
    
    case 0x08:
    {  
      I20DAT = slaveaddr; //addr
      temp1 = I20DAT;
        
    }
    break;

    case 0x10:
    {
      I20DAT = slaveaddr;
    }
    break;

    case 0x18:
    {    
      i2c_write(buf_config);
      if(*buf != 11)
        I20DAT = *buf++;
      else
        i2c_stop();
    }
    break;

    case 0x20:
    {
      i2c_stop();  
    }
    break;

    case 0x28:
    {
        
      if(*buf != 11)
        I20DAT = *buf++;
      else
        i2c_stop();
    }
    break;

    case 0x30:
    {
      i2c_stop();    
    }
}

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. D. schrieb:

>     case 0x08:
>       I20DAT = slaveaddr; //addr
>       temp1 = I20DAT;   <============

Wozu ist das denn gut?

Wie sehen i2c_stop() und i2c_write() aus?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In Beitrag "Re: Programm springt nicht aus ISR" fehlt

  }
  VICVectAddr = 0;

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.