www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Reset nach interrupt


Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heyho
ich muss gerade fuer die uni ein batterieladegeraet bauen und bin eg 
schon recht fertig hab nur noch ein problem mit dem interrupt.
Mein interrupt soll jede minute kommen und dann vergleicht es die 
temperaturwerte von der batterie. Nun falls ein gewisser wert 
ueberschritten wird soll der zustand geaendert werden. Aber wenn ich 
meine state variable im interrupt aendere dann resetet der nach dem 
interrupt und ich weis nicht warum vllt koennt ihr mir ja helfen. Danke 
im vorraus

PS die ganzen display sachen koennt ihr natuerlich einfach ignorieren
#include <adc.h>
#include <delays.h>
#include <p18f4550.h>
#include <stdlib.h>
#include <string.h>
#include <timers.h>

/*#pragma config FOSC = INTOSC_HS   
#pragma config PWRT = ON  // AN
#pragma config BOR = OFF
#pragma config WDT = OFF  // Watch Dog AUS
#pragma config LVP = OFF
#pragma config PBADEN = OFF
#pragma config VREGEN = OFF
#pragma config MCLRE = ON  
*/
volatile int state=0;  // Indicates in which state the charger is 0 =Idle , 1 = Fast charge , 2 = Top up charge , 3 = Trickle charge
long Tsum=0;
long BVsum=0;
long BV = 0;  // Battery Voltage in mV
long T = 0;  // Battery Temperature
long Told = 0;  //  Temperature 1 min before
long timer=0;  //  Count up to 30 to determine when 30 mins are over


void Send_Data_Lcd(char data[]);
void Send_Com_Lcd(unsigned char rs,unsigned char seven,unsigned char six,unsigned char five,unsigned char four,unsigned char three,unsigned char two,unsigned char one,unsigned char zero);
void Temperature_Battery(void);
void Voltage_Battery(void);
void Init_Lcd(void);
void LED(unsigned char led1, unsigned char led2, unsigned char led3, unsigned char led4);
void Set_Timer0(void);
void Display_Data(void);


/////////////////////////////////////////////////////////////////////////////////////////////////// Send the Temperatur and Voltage to the display
void Display_Data(void)
{
  char t0[6];
  char t1[6];
  char t3[6];
  char bv[6];
  char tmp1[] = {"V:"};
  char tmp2[] = {" mV"};
  char tmp3[] = {"T:"};
  char tmp4[] = {" in C"};
  char tmp5[] = {"."};
  char tmp6[] = {".0"};
  char tmp7[] = {"Min to end:"};
  itoa(T/100,t0);
  itoa(T%100,t1);
  itoa(BV,bv);
  Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
  Send_Data_Lcd(tmp1);
  Send_Data_Lcd(bv);
  Send_Data_Lcd(tmp2);
  Send_Com_Lcd(0,1,0,1,0,1,0,0,0); 
  if(state==1){
    Send_Data_Lcd(tmp3);
    Send_Data_Lcd(t0);
    if(T%100<10) Send_Data_Lcd(tmp6);
    else Send_Data_Lcd(tmp5);
    Send_Data_Lcd(t1);
    Send_Data_Lcd(tmp4);
  }
  if(state==2){
    Send_Data_Lcd(tmp7);
    itoa(30-timer,t0);
    Send_Data_Lcd(t0);
  }    
}
///////////////////////////////////////////////////////////////////////////////////////////////////  Initialise the display
void Init_Lcd(void)
{
  Delay100TCYx(50);
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
  Delay10TCYx(125);
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
  Delay10TCYx(3);
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
  Send_Com_Lcd(0,0,0,1,1,1,0,0,0);
  Send_Com_Lcd(0,0,0,0,0,1,0,0,0);
  Send_Com_Lcd(0,0,0,0,0,0,0,0,1);
  Send_Com_Lcd(0,0,0,0,0,0,1,1,0);
  Send_Com_Lcd(0,0,0,0,0,1,1,0,0);
}
/////////////////////////////////////////////////////////////////////////////////////////////////// Send data the data to the display
void Send_Data_Lcd(char data[])
{
  int x;
  LATDbits.LATD5 = 1; // RS
  for(x=0;x<strlen(data);x++){
    LATB = data[x];
    LATDbits.LATD7 = 1; // E
    Delay10TCYx(10);
    LATDbits.LATD7=0;
    Delay10TCYx(10);
    if(x==15){
      Send_Com_Lcd(0,1,0,1,0,1,0,0,0); 
      LATDbits.LATD5 = 1;
    }
  }
}
/////////////////////////////////////////////////////////////////////////////////////////////////// Send the commands to the Display
void Send_Com_Lcd(unsigned char rs,unsigned char seven,unsigned char six,unsigned char five,unsigned char four,unsigned char three,unsigned char two,unsigned char one,unsigned char zero)
{
  LATDbits.LATD5 = rs;
  LATBbits.LATB0 = zero;
  LATBbits.LATB1 = one;
  LATBbits.LATB2 = two;
  LATBbits.LATB3 = three;
  LATBbits.LATB4 = four;
  LATBbits.LATB5 = five;
  LATBbits.LATB6 = six;
  LATBbits.LATB7 = seven;
  LATDbits.LATD7 = 1;
  Delay10TCYx(25);
  LATDbits.LATD7=0;
  Delay10TCYx(25);
}

///////////////////////////////////////////////////////////////////////////////////////////////////  Use the ADC to measure the temperature of the battery
void Temperature_Battery(void)
{
  double DV;  // The output from the op amp to measure the diagonal voltage
  double V0;  // The input voltage of the Wheatstone bridge
  double deltaR;
    
  OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST & ADC_2_TAD, ADC_CH1 & ADC_INT_OFF & ADC_VREFPLUS_EXT & ADC_VREFMINUS_VSS,0);                                                                                                                                                                                                                                                                                                                   OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST & ADC_2_TAD, ADC_CH1 & ADC_INT_OFF & ADC_VREFPLUS_EXT & ADC_VREFMINUS_VSS,0);
  Delay10TCYx(5);
  ConvertADC();
  while(BusyADC());
  V0 = ReadADC();
  CloseADC();
  V0 = ((V0*3)/1023);  // ADC result converted in the real voltage and displayed in mV
  OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST & ADC_2_TAD, ADC_CH2 & ADC_INT_OFF & ADC_VREFPLUS_EXT & ADC_VREFMINUS_VSS,0);
  Delay10TCYx(5);
  ConvertADC();
  while(BusyADC());
  DV = ReadADC();
  CloseADC();
  DV = ((DV*3/1023)/63.0);// ADC result converted in the real voltage and displayed in mV
  deltaR = ((2*DV+V0)/(V0-2*DV)-1)*100;
  T = ((100/38.5)*deltaR)*100; // Temperature
}
/////////////////////////////////////////////////////////////////////////////////////////////////// Use the ADC to get the voltage across the battery
void Voltage_Battery(void)
{
  OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST & ADC_2_TAD, ADC_CH0 & ADC_INT_OFF & ADC_VREFPLUS_EXT & ADC_VREFMINUS_VSS,0);
  Delay10TCYx(5);
  ConvertADC();
  while(BusyADC());
  BV = ReadADC();
  CloseADC();
  BV = ((BV *1000*3)/1023);  // ADC result converted in the real voltage and displayed in mV
}
/////////////////////////////////////////////////////////////////////////////////////////////////// Sets the LEDs for the indictation of the state
void LED(unsigned char led1, unsigned char led2, unsigned char led3, unsigned char led4)
{
  LATDbits.LATD2 = led1;
  LATDbits.LATD3 = led2;
  LATCbits.LATC6 = led3;
  LATCbits.LATC7 = led4;

}
/////////////////////////////////////////////////////////////////////////////////////////////////// Sets the LEDs for the indictation of the state
void MOSFET(unsigned char mosfet1, unsigned char mosfet2, unsigned char mosfet3)
{
  LATEbits.LATE2 = mosfet1;
  LATEbits.LATE1 = mosfet2;
  LATEbits.LATE0 = mosfet3;
}
/////////////////////////////////////////////////////////////////////////////////////////////////// Sets the timer for the 1 min interrupt
void Set_Timer0()
{
  OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256);
  WriteTimer0(0x1B1D);
  INTCONbits.GIEH = 1;
}

/////////////////////////////////////////////////////////////////////////////////////////////////// the interrupt routine
void InterruptHandlerHigh(){
  char tmp1[] = {"Top up charge is over"};
  char tmp2[] = {"The fast charge is over"};
  if(INTCONbits.TMR0IF){
    if(state==1)
    {
      if(Told <= (T-1)){
        Delay10TCYx(5);
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
        Delay10TCYx(5);
        Send_Data_Lcd(tmp2);
        Delay10KTCYx(250);
        state=2;
      }
      Told = T;
      Set_Timer0();
    }
    else if(state==2)
    {
      if(timer<30) 
      {
        timer++;
        
      }
      else
      {
        timer = 0;
        Delay10TCYx(5);
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
        Delay10TCYx(5);
        Send_Data_Lcd(tmp1);
        Delay10KTCYx(250);
        state=3;
      }
    }  
  INTCONbits.TMR0IF = 0;
  Set_Timer0();
  }
}
/////////////////////////////////////////////////////////////////////////////////////////////////// asm code to use the intterupt
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void){
  _asm
  goto InterruptHandlerHigh
  _endasm
}
#pragma code
///////////////////////////////////////////////////////////////////////////////////////////////////
void main(void)
{
  int x=0;
  TRISA = 15;
  TRISD = 0;
  TRISE = 0;
  TRISC = 0;
  TRISB = 0;
  LED(1,0,0,0);
  MOSFET(0,0,0);
  Init_Lcd();
  Set_Timer0();
  Voltage_Battery();
  Temperature_Battery();
  Told = T;
  while(1)
  {  
    Voltage_Battery();
    Temperature_Battery();
    if(state ==0){
      LED(1,0,0,0);
      MOSFET(0,0,0);
      if(BV<1400){
        state = 1;
      }else if(BV>=1400 && BV<2500){
        char tmp[] = {"Battery is full"};
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
        Delay10TCYx(5);
        Send_Data_Lcd(tmp);
        state = 3;
      }else if(BV>2500){
        char tmp1[] = {"Ready"};
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
        Delay10TCYx(5);
        Send_Data_Lcd(tmp1);
      }
    }
    else if(state ==1){
      LED(0,1,0,0);
      MOSFET(1,0,0);
      if(BV>2500) state = 0;
      if(x!=5){
        Tsum = T+Tsum;
        x++;
      }else{
        T = Tsum/5;
        Display_Data();
        Tsum=0;
        x=0;
      }
    }
    else if(state==2){
      LED(0,0,1,0);
      MOSFET(0,1,0);
      Display_Data();
      if(BV>2500) state = 0;
    }
    else if(state ==3){
      LED(0,0,0,1);
      MOSFET(0,0,1);
      if(BV>2500) state = 0;
    }
  }
  
}


Autor: Jannis C. (kabelwurm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
 Wäre es wichtig zu wissen, was für einen Controller du verwendest.
Gruß Jannis

Autor: Uwe S. (de0508)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, welcher C Compiler ist den das?

ich denke du solltest in der ISR
kein
goto InterruptHandlerHigh

verwenden, sondern ein call, bzw. du könntest den Code auch gleich dort 
hineinschreiben.

.

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh man sorry *vorn kop hau
ich nutze einen pic18f4550
programmiere in matlab ide und hab nen pickit2 hier falls das wichtig 
ist

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reset nach Interrupt hört sich spontan nach einem nicht behandelten 
Interrupt an. Mit PIC kenne ich mich nun gar nicht aus, aber gibt es da 
vielleicht sowas wie einen "Universalinterruptcatcher" wie BADISRvect in 
der avr-libc? Wenn ja, den einfach mal einbauen und schauen, ob immer 
noch ein reset kommt.
Andere Idee wäre noch, ob sich nach dem Reset die Resetquelle bei den 
PIC's auslesen läßt, wie z.B. das Register MCUCSR beim AVR.

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex K. schrieb:
> programmiere in matlab ide

wohl eher nicht ... könnte es vielleicht MPLAB heißen ?

- ich hab's gerade leider nicht im Kopf aber es gibt ein Register, 
welches den letzten Resetgrund angibt.

- Stichwort Stack-Overflow-Reset -> Configbits

- Interruptroutine ist komisch. Ich verwende diese: 
http://www.edaboard.com/thread72386.html

- Was für Configbits verwendest du? Du hast die im Code auskommentiert 
also was für welche hast du gesetzt? Hast du sie überhaupts gesetzt oder 
ist der Default vom C18 Compiler noch drin -> MPLAB

- kannst du die Hardware ausschließen (Einbruch der Spannungsversorgung, 
etc...)

- Das da geht eigentlich nicht:

Alex K. schrieb:
> void Send_Data_Lcd(char data[]);

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh jo natürlich mplab war noch nebenbei mit matlab am arbeiten :>

-ich benutze normal die config bits die ich oben auskommentiert hab. 
Hatte aber gerade die bits von mplab setzen lassen.

- die hardware hab ich schon getestet und nichts auffälliges bemerkt.

-das mit dem register muss ich morgen dann mal genauer untersuchen aber 
hab was gelesen das es auch einen reset gibt nach dem interrupt wenn man 
in nen speicherbereich schreibt wo man net darf. Damit konnte ich nur 
leider zurzeit nichts anfangen. Wüsste nicht was ich mehr als volatile 
machen könnte.

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast mal einen Schaltplan dann lass ich das kurz mit Proteus 
durchsimulieren ...

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lehrmann Michael schrieb:

> Alex K. schrieb:
>> void Send_Data_Lcd(char data[]);

ja aer es funktioniert bei mir xD. Aber muss dazu sagen dass das mein 
erstes projekt mit nem mikrocontroller ist daher ist das noch net alles 
100% perfekt ;)

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lehrmann Michael schrieb:
> Hast mal einen Schaltplan dann lass ich das kurz mit Proteus
> durchsimulieren ...

äh könnte ich dir nachher machen habs leider net digital da und bin 
zurzeit aufm heimweg :>

Autor: Lehrmann Michael (ubimbo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jaja kein Stress - wollt's nur mal sagen ...

Beitrag #2104642 wurde vom Autor gelöscht.
Autor: Michael Roek (mexman) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex K. schrieb:
> oh man sorry *vorn kop hau
> ich nutze einen pic18f4550
> programmiere in matlab ide und hab nen pickit2 hier falls das wichtig
> ist

Na, dann kannst Du doch prima im Emulator sehen, wann was 
passiert.....warum fragst Du dann hier?
Brauchst Du eine Anleitung zum Pickit?

Und Uwe S. hat Dir die Loesung doch auch schon geschrieben:

Mit MPLAB kanst Du prima feststellen, was da passiert!


Gruss

Michael

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex K. schrieb:
> Lehrmann Michael schrieb:
>
>> Alex K. schrieb:
>>> void Send_Data_Lcd(char data[]);
>
> ja aer es funktioniert bei mir xD. Aber muss dazu sagen dass das mein
> erstes projekt mit nem mikrocontroller ist daher ist das noch net alles
> 100% perfekt ;)


ich weiß zurzeit noch nicht wozu das pickit 2 vllt fähig ist aber werde 
ich dann morgen auch nochma googlen danke für die info

zumal das was Uwe S. geschrieben hat hat nicht das problem gelöst... 
leider

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm hab gerade ma die simulation laufen lassen und sofern ich da nichts 
falsch mache macht der genau was er soll

Autor: Thomas O. (kosmos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kenne mich in C nicht aus und mit Pics habe ich auch nichts am Hut. 
Vielleicht kann ich dir aber trotzdem helfen.

Ich vermute das du die Interrupt-Routine nicht richtig beendest sondern 
einfach weiter im Programm verzweigst dadurch läuft irgendwann der Stack 
über also auch der Programmcounter dein Programm läuft irgendwann wieder 
vom Beginn an so als wenn es resettet hätte.

Schau dir mal in der Simulation den Stack an und lass das Programm noch 
weiterlaufen, denke das ist nur eine frage der Zeit bis du zum 
Stacküberlauf kommst.

Autor: Sebastian Hepp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du den 2. Post beachtet?
Ein goto legt keine Rücksprungadresse auf den Stack. Gerade die wird 
aber benötigt wenn du aus der Funktion zurückspringst.

Autor: Thomas O. (kosmos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
außerdem wird versucht ein ASM Befehl auszuführen, GOTO stammt aber eher 
aus der BASIC Ecke

///// asm code to use the intterupt
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void){
  _asm
  goto InterruptHandlerHigh
  _endasm
}
#pragma code
/////


aber wieso erst in C programmieren und dann doch ASM Befehle, läuft das 
ganze etwa zu langsam?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas O. schrieb:
> aber wieso erst in C programmieren und dann doch ASM Befehle, läuft das
> ganze etwa zu langsam?

Das wird wohl beim PIC die Methode sein, einen Interrupthandler zu 
definieren. Da kocht jeder Compilerbauer sein eigenes Süppchen.

Ein Jump vom Vektor zum Handler ist schon richtig, das RETI macht dann 
die C-Funktion.
Man will ja nicht zur Vektortabelle zurück, sondern zum Main-Kontext.

Vielleicht sollte man für den Low-Interrupt noch nen Dummy-Handler 
aufsetzen.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was auffällt, Du machst viel zu viel im Interrupt.

Ein Interrupt ist ne 2.Task, die darf mit dem Main nicht gleichzeitg 
dieselbe Ressource benutzen!

LCD in Main und Interrupt geht schonmal garnicht.
Und gemeinsame Variablen >8Bit müssen im Main atomar zugegriffen werden.


Eine Minute ist auch nichts, was man im Interrupt machen muß. Da setzt 
man im Interrupt nur ein Bit und das Main macht die Sachen, wenn das Bit 
gesetzt ist.
Damit lösen sich alle Konflikte von selber auf.

Interrupts sind für wirklich eilige Sachen (wenige µs bis ms).


Peter

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay hab mitlerweile den fehler gefunden. Es liegt nicht an nem overflow 
sondern das ich im state 2 einen Mosfet mit dem pic ausschalte der 
gerade 1.2A fuehrt. Wenn ich das weg machen laeuft es wunderbar. Nun ist 
aber die frage warum der pic resetet wenn ich den Mosfet ausschalten 
will.

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Nun ist aber die Frage, warum der PIC resetet, wenn ich den
>MOSFET ausschalten will.

Schaltung?

Autor: Alex K. (xcyrusx)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
so hier ist die schaltung die Mosfets sind IRLZ34NPBF
und der Spannungsregler ist ein LM 350
und die mosfets sind ueber pull down widerstaende an den pic 
angeschlossen

aeh die mosfets sind natuerlich andersrum verbunden

und die spannungsquelle am ende soll eine NiMH batterie darstellen

Autor: Alex K. (xcyrusx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat sich schon geklaert vorwiderstand war net mehr richtig dran geloetet 
danke fuer die hilfe =)

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.