Forum: Mikrocontroller und Digitale Elektronik Reset nach interrupt


von Alex K. (xcyrusx)


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
1
#include <adc.h>
2
#include <delays.h>
3
#include <p18f4550.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <timers.h>
7
8
/*#pragma config FOSC = INTOSC_HS   
9
#pragma config PWRT = ON  // AN
10
#pragma config BOR = OFF
11
#pragma config WDT = OFF  // Watch Dog AUS
12
#pragma config LVP = OFF
13
#pragma config PBADEN = OFF
14
#pragma config VREGEN = OFF
15
#pragma config MCLRE = ON  
16
*/
17
volatile int state=0;  // Indicates in which state the charger is 0 =Idle , 1 = Fast charge , 2 = Top up charge , 3 = Trickle charge
18
long Tsum=0;
19
long BVsum=0;
20
long BV = 0;  // Battery Voltage in mV
21
long T = 0;  // Battery Temperature
22
long Told = 0;  //  Temperature 1 min before
23
long timer=0;  //  Count up to 30 to determine when 30 mins are over
24
25
26
void Send_Data_Lcd(char data[]);
27
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);
28
void Temperature_Battery(void);
29
void Voltage_Battery(void);
30
void Init_Lcd(void);
31
void LED(unsigned char led1, unsigned char led2, unsigned char led3, unsigned char led4);
32
void Set_Timer0(void);
33
void Display_Data(void);
34
35
36
/////////////////////////////////////////////////////////////////////////////////////////////////// Send the Temperatur and Voltage to the display
37
void Display_Data(void)
38
{
39
  char t0[6];
40
  char t1[6];
41
  char t3[6];
42
  char bv[6];
43
  char tmp1[] = {"V:"};
44
  char tmp2[] = {" mV"};
45
  char tmp3[] = {"T:"};
46
  char tmp4[] = {" in C"};
47
  char tmp5[] = {"."};
48
  char tmp6[] = {".0"};
49
  char tmp7[] = {"Min to end:"};
50
  itoa(T/100,t0);
51
  itoa(T%100,t1);
52
  itoa(BV,bv);
53
  Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
54
  Send_Data_Lcd(tmp1);
55
  Send_Data_Lcd(bv);
56
  Send_Data_Lcd(tmp2);
57
  Send_Com_Lcd(0,1,0,1,0,1,0,0,0); 
58
  if(state==1){
59
    Send_Data_Lcd(tmp3);
60
    Send_Data_Lcd(t0);
61
    if(T%100<10) Send_Data_Lcd(tmp6);
62
    else Send_Data_Lcd(tmp5);
63
    Send_Data_Lcd(t1);
64
    Send_Data_Lcd(tmp4);
65
  }
66
  if(state==2){
67
    Send_Data_Lcd(tmp7);
68
    itoa(30-timer,t0);
69
    Send_Data_Lcd(t0);
70
  }    
71
}
72
///////////////////////////////////////////////////////////////////////////////////////////////////  Initialise the display
73
void Init_Lcd(void)
74
{
75
  Delay100TCYx(50);
76
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
77
  Delay10TCYx(125);
78
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
79
  Delay10TCYx(3);
80
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
81
  Send_Com_Lcd(0,0,0,1,1,0,0,0,0);
82
  Send_Com_Lcd(0,0,0,1,1,1,0,0,0);
83
  Send_Com_Lcd(0,0,0,0,0,1,0,0,0);
84
  Send_Com_Lcd(0,0,0,0,0,0,0,0,1);
85
  Send_Com_Lcd(0,0,0,0,0,0,1,1,0);
86
  Send_Com_Lcd(0,0,0,0,0,1,1,0,0);
87
}
88
/////////////////////////////////////////////////////////////////////////////////////////////////// Send data the data to the display
89
void Send_Data_Lcd(char data[])
90
{
91
  int x;
92
  LATDbits.LATD5 = 1; // RS
93
  for(x=0;x<strlen(data);x++){
94
    LATB = data[x];
95
    LATDbits.LATD7 = 1; // E
96
    Delay10TCYx(10);
97
    LATDbits.LATD7=0;
98
    Delay10TCYx(10);
99
    if(x==15){
100
      Send_Com_Lcd(0,1,0,1,0,1,0,0,0); 
101
      LATDbits.LATD5 = 1;
102
    }
103
  }
104
}
105
/////////////////////////////////////////////////////////////////////////////////////////////////// Send the commands to the Display
106
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)
107
{
108
  LATDbits.LATD5 = rs;
109
  LATBbits.LATB0 = zero;
110
  LATBbits.LATB1 = one;
111
  LATBbits.LATB2 = two;
112
  LATBbits.LATB3 = three;
113
  LATBbits.LATB4 = four;
114
  LATBbits.LATB5 = five;
115
  LATBbits.LATB6 = six;
116
  LATBbits.LATB7 = seven;
117
  LATDbits.LATD7 = 1;
118
  Delay10TCYx(25);
119
  LATDbits.LATD7=0;
120
  Delay10TCYx(25);
121
}
122
123
///////////////////////////////////////////////////////////////////////////////////////////////////  Use the ADC to measure the temperature of the battery
124
void Temperature_Battery(void)
125
{
126
  double DV;  // The output from the op amp to measure the diagonal voltage
127
  double V0;  // The input voltage of the Wheatstone bridge
128
  double deltaR;
129
    
130
  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);
131
  Delay10TCYx(5);
132
  ConvertADC();
133
  while(BusyADC());
134
  V0 = ReadADC();
135
  CloseADC();
136
  V0 = ((V0*3)/1023);  // ADC result converted in the real voltage and displayed in mV
137
  OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST & ADC_2_TAD, ADC_CH2 & ADC_INT_OFF & ADC_VREFPLUS_EXT & ADC_VREFMINUS_VSS,0);
138
  Delay10TCYx(5);
139
  ConvertADC();
140
  while(BusyADC());
141
  DV = ReadADC();
142
  CloseADC();
143
  DV = ((DV*3/1023)/63.0);// ADC result converted in the real voltage and displayed in mV
144
  deltaR = ((2*DV+V0)/(V0-2*DV)-1)*100;
145
  T = ((100/38.5)*deltaR)*100; // Temperature
146
}
147
/////////////////////////////////////////////////////////////////////////////////////////////////// Use the ADC to get the voltage across the battery
148
void Voltage_Battery(void)
149
{
150
  OpenADC(ADC_FOSC_RC & ADC_RIGHT_JUST & ADC_2_TAD, ADC_CH0 & ADC_INT_OFF & ADC_VREFPLUS_EXT & ADC_VREFMINUS_VSS,0);
151
  Delay10TCYx(5);
152
  ConvertADC();
153
  while(BusyADC());
154
  BV = ReadADC();
155
  CloseADC();
156
  BV = ((BV *1000*3)/1023);  // ADC result converted in the real voltage and displayed in mV
157
}
158
/////////////////////////////////////////////////////////////////////////////////////////////////// Sets the LEDs for the indictation of the state
159
void LED(unsigned char led1, unsigned char led2, unsigned char led3, unsigned char led4)
160
{
161
  LATDbits.LATD2 = led1;
162
  LATDbits.LATD3 = led2;
163
  LATCbits.LATC6 = led3;
164
  LATCbits.LATC7 = led4;
165
166
}
167
/////////////////////////////////////////////////////////////////////////////////////////////////// Sets the LEDs for the indictation of the state
168
void MOSFET(unsigned char mosfet1, unsigned char mosfet2, unsigned char mosfet3)
169
{
170
  LATEbits.LATE2 = mosfet1;
171
  LATEbits.LATE1 = mosfet2;
172
  LATEbits.LATE0 = mosfet3;
173
}
174
/////////////////////////////////////////////////////////////////////////////////////////////////// Sets the timer for the 1 min interrupt
175
void Set_Timer0()
176
{
177
  OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256);
178
  WriteTimer0(0x1B1D);
179
  INTCONbits.GIEH = 1;
180
}
181
182
/////////////////////////////////////////////////////////////////////////////////////////////////// the interrupt routine
183
void InterruptHandlerHigh(){
184
  char tmp1[] = {"Top up charge is over"};
185
  char tmp2[] = {"The fast charge is over"};
186
  if(INTCONbits.TMR0IF){
187
    if(state==1)
188
    {
189
      if(Told <= (T-1)){
190
        Delay10TCYx(5);
191
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
192
        Delay10TCYx(5);
193
        Send_Data_Lcd(tmp2);
194
        Delay10KTCYx(250);
195
        state=2;
196
      }
197
      Told = T;
198
      Set_Timer0();
199
    }
200
    else if(state==2)
201
    {
202
      if(timer<30) 
203
      {
204
        timer++;
205
        
206
      }
207
      else
208
      {
209
        timer = 0;
210
        Delay10TCYx(5);
211
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
212
        Delay10TCYx(5);
213
        Send_Data_Lcd(tmp1);
214
        Delay10KTCYx(250);
215
        state=3;
216
      }
217
    }  
218
  INTCONbits.TMR0IF = 0;
219
  Set_Timer0();
220
  }
221
}
222
/////////////////////////////////////////////////////////////////////////////////////////////////// asm code to use the intterupt
223
#pragma code InterruptVectorHigh = 0x08
224
void InterruptVectorHigh(void){
225
  _asm
226
  goto InterruptHandlerHigh
227
  _endasm
228
}
229
#pragma code
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231
void main(void)
232
{
233
  int x=0;
234
  TRISA = 15;
235
  TRISD = 0;
236
  TRISE = 0;
237
  TRISC = 0;
238
  TRISB = 0;
239
  LED(1,0,0,0);
240
  MOSFET(0,0,0);
241
  Init_Lcd();
242
  Set_Timer0();
243
  Voltage_Battery();
244
  Temperature_Battery();
245
  Told = T;
246
  while(1)
247
  {  
248
    Voltage_Battery();
249
    Temperature_Battery();
250
    if(state ==0){
251
      LED(1,0,0,0);
252
      MOSFET(0,0,0);
253
      if(BV<1400){
254
        state = 1;
255
      }else if(BV>=1400 && BV<2500){
256
        char tmp[] = {"Battery is full"};
257
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
258
        Delay10TCYx(5);
259
        Send_Data_Lcd(tmp);
260
        state = 3;
261
      }else if(BV>2500){
262
        char tmp1[] = {"Ready"};
263
        Send_Com_Lcd(0,0,0,0,0,0,0,0,1); 
264
        Delay10TCYx(5);
265
        Send_Data_Lcd(tmp1);
266
      }
267
    }
268
    else if(state ==1){
269
      LED(0,1,0,0);
270
      MOSFET(1,0,0);
271
      if(BV>2500) state = 0;
272
      if(x!=5){
273
        Tsum = T+Tsum;
274
        x++;
275
      }else{
276
        T = Tsum/5;
277
        Display_Data();
278
        Tsum=0;
279
        x=0;
280
      }
281
    }
282
    else if(state==2){
283
      LED(0,0,1,0);
284
      MOSFET(0,1,0);
285
      Display_Data();
286
      if(BV>2500) state = 0;
287
    }
288
    else if(state ==3){
289
      LED(0,0,0,1);
290
      MOSFET(0,0,1);
291
      if(BV>2500) state = 0;
292
    }
293
  }
294
  
295
}

von Jannis C. (kabelwurm)


Lesenswert?

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

von Uwe S. (de0508)


Lesenswert?

Hallo, welcher C Compiler ist den das?

ich denke du solltest in der ISR
kein
1
goto InterruptHandlerHigh

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

.

von Alex K. (xcyrusx)


Lesenswert?

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

von Lutz (Gast)


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.

von Lehrmann M. (ubimbo)


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[]);

von Alex K. (xcyrusx)


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.

von Lehrmann M. (ubimbo)


Lesenswert?

Hast mal einen Schaltplan dann lass ich das kurz mit Proteus 
durchsimulieren ...

von Alex K. (xcyrusx)


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 ;)

von Alex K. (xcyrusx)


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 :>

von Lehrmann M. (ubimbo)


Lesenswert?

Jaja kein Stress - wollt's nur mal sagen ...

von Michael R. (mexman) Benutzerseite


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

von Alex K. (xcyrusx)


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

von Alex K. (xcyrusx)


Lesenswert?

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

von Thomas (kosmos)


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.

von Sebastian Hepp (Gast)


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.

von Thomas (kosmos)


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?

von Peter D. (peda)


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

von Peter D. (peda)


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

von Alex K. (xcyrusx)


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.

von Guru (Gast)


Lesenswert?

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

Schaltung?

von Alex K. (xcyrusx)


Angehängte Dateien:

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

von Alex K. (xcyrusx)


Lesenswert?

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

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.