[MSP430] Variablenuebergabe an ISR

#1412377
Lesenswert?

Hallo,

ich habe folgendes Problem: In der TimerISR-A wird in Abhaengigkeit 
eines Zaehlers eine LED eingeschaltet.
n_led=0 keine, n_led=1 P1.7, n_led=2 P1.6, n_led=3 P1.5
In der TimerISR- B wird nun der ADC aktiviert und 8-mal abgetastet, ist 
das erledigt, wird die LED abgeschaltet und das ganze geht von vorne 
los.

Ich weiss jedoch einfach nicht, weshalb die Variable n_led in der 
ADC_ISR mit der aus den TimerISRs nicht uebereinstimmt. Reduziere ich in 
der TimerA-ISR die Anzahl auf der n_led Elemente auf 3 durch entfernen 
der Messung ohne LED, funzt alles wunderbar. Weshalb wird die Variable 
n_led nicht korrekt an die ADC_ISR weitergegeben?

Vielen Dank
1
void timera_isr()
2

3
{  
4
  
5
   if(n_led == 0)
6
  { 
7
  P1OUT = 0x00;
8
  }
9
    if(n_led == 1)
10
   {
11
   P1OUT |= 0x80;      //P1.7 einschalten   
12
   }
13
    if(n_led == 2)
14
   {
15
   P1OUT |= 0x40;    //P1.6 einschalten 
16
         }
17
    if(n_led == 3)
18
   {
19
   P1OUT |= 0x20;    //P1.5 einschalten  1300nm
20
   }
21
   
22
   TBCCR0 = 0x15;    //Timer_B starten (wirksam erst nach dem ersten
23
        
24
   TBCTL |= MC_1;    //Timer_B erstmalig starten
25
}
26

27

28

29
void timerb_isr()
30

31
{   
32
   
33
    n_tb++;       //Inkrement des Timer_B Periodenzählers
34
   
35
    if(n_tb == 8)     //8 Durchlaeufe (n_tb=8)
36
   {  P1OUT = 0x00;  // LED ausschalten  
37
     
38
      TBCCR0 = 0;    //Timer_B stoppen
39
      n_tb = 0;    //Rücksetzen des Timer_B Periodenzählers
40
            n_led++;          // Zaehler naechste LED
41
    if(n_led == 4)
42
      { 
43
        n_led = 0;
44
      }
45
   }
46

47
   ADC12CTL0 |= ADC12SC; //SC = Start Conversion
48
    while ((ADC12CTL1 & ADC12BUSY) == 1);
49
  
50
}
51

52
void adc_isr()
53
{  
54
   Messwerte[n_mw] = ADC12MEM0;;  
55
  n_mw++;
56
  
57
  if(n_mw == 8)
58
  {
59
    n_mw = 0;
60

61
    if(n_led == 0)
62
    { 
63
      mitteln();
64
      
65
    }
66
    if(n_led == 1)
67
    { 
68
      mitteln(); 
69
      senden0();
70
      
71
    }
72
    if(n_led == 2)
73
    { 
74
      mitteln();
75
      senden1();
76
     }
77
    if(n_led == 3)
78
    { 
79
      mitteln(); 
80
      senden2();
81
    }
82
    
83
    
84
  }
85
  
86
  
87
  ADC12IFG = 0x0000;
88

89
}
#1414858
Lesenswert?

hier die Variablendeklaration:
1
#include <msp430x16x.h>
2

3
#include <msp430def.h>
4

5
#pragma interrupt_handler timera_isr: TIMERA0_VECTOR  timera_isr: TIMERA1_VECTOR
6
#pragma interrupt_handler timerb_isr: TIMERB0_VECTOR  timerb_isr: TIMERB1_VECTOR
7
#pragma interrupt_handler    adc_isr: ADC_VECTOR
8
#pragma interrupt_handler   sio0_isr: USART0TX_VECTOR
9

10
void init_Clock();
11
void timera_init();
12
void timerb_init();
13
void mittel();
14
void init_DAC();
15
void init_SIO();
16
void init_ADC();
17
//void wait_05ms();
18
void wait_250us(unsigned int ui_Faktor);
19

20
unsigned int temp;
21
unsigned int val_DAC;
22
unsigned char n_tb = 0;
23
volatile n_led = 0;
24
unsigned char n_mw = 0;
25
unsigned int Messwerte[4];
26
unsigned int Messwerte_LED0[4];
27
unsigned int Messwerte_LED1[4];
28
unsigned int Messwerte_LED2[4];
29
unsigned long Summe;
30
unsigned long dunkel;
31
unsigned char Ziffern[4];
32
unsigned int ui_Faktor;
33
unsigned char text[1] = "A";
34
unsigned char text2[1] = "B";
35
unsigned int *ptr_mw0;
36
unsigned int *ptr_mw1;
37
unsigned int *ptr_mw2;
38
unsigned int *ptr_mw;
39
unsigned int mw = 0;
40
unsigned int mw0 = 0;
41
unsigned int mw1 = 0;
42
unsigned int mw2 = 0;
43
unsigned int mw0_a;
44
unsigned int mw0_b;
45
unsigned long value;
46
unsigned char split[2];
47
unsigned char n_send = 0;
48
unsigned char Ziffern_send[4];
49
unsigned long Mittelwert_send = 0;
50

51
void main(void)
52
{
53
....
#1414871
Lesenswert?

Sachmal du weist wirklich nicht was das Wörtchen Volatile bedeutet?

Das Schlüsselwort volatile teilt dem Compiler mit, daß die mit name 
bezeichnete Variable mit dem Datentyp typ durch Ereignisse außerhalb der 
Kontrolle des Programms verändert werden kann.
Der Wert der Variablen muß deshalb vor jedem Zugriff neu aus dem 
Hauptspeicher eingelesen werden, d.h. er darf nicht in einem Register 
des Prozessors zwischengespeichert werden.

Der Compiler arbeitet bei mit volatile deklarierten Variablen ohne jede 
Optimierung, d.h. läßt die entsprechenden Werte bei jedem Zugriff neu 
aus dem Hauptspeicher laden und sorgt bei Veränderungen dafür, daß die 
neuen Werte ohne Verzögerung dort sofort abgelegt werden.

Du must der Variable wenigstens noch einen datentyp Spendieren.
So geht dat jedenfalls nicht
#1414873
Lesenswert?

Bernd Krause schrieb:
> hier die Variablendeklaration:

> unsigned char text[1] = "A";
> unsigned char text2[1] = "B";

Zu kurz.
Die Strings "A" bzw. "B" sind 2 Zeichen lang.
Überlass dem Compiler in solchen Fällen das Abzählen! Der macht keine 
Fehler.

unsigned char text[] = "A";
unsigned char text2[] = "B";

> unsigned char split[2];
> unsigned char Ziffern_send[4];

Möglich, dass ich mich täusche. Aber du hast da ein paar sehr klein 
dimensionierte Arrays, deren Namen für mich danach klingt, als ob sie 
für Stringverarbeitung benutzt werden. Ziffern_send klingt für mich zb. 
danach. Und nach dem Fehler von weiter oben halte ich einen 
Array-Overflow irgendwo für durchaus möglich.

Poste mal alles, damit man den C-Code mal auf grobe Schnitzer durchsehen 
kann.
#1414905
Lesenswert?

Bin fuer jeden Ratschlag dankbar
1
#include <msp430x16x.h>
2

3
#include <msp430def.h>
4

5
#pragma interrupt_handler timera_isr: TIMERA0_VECTOR  timera_isr: TIMERA1_VECTOR
6
#pragma interrupt_handler timerb_isr: TIMERB0_VECTOR  timerb_isr: TIMERB1_VECTOR
7
#pragma interrupt_handler    adc_isr: ADC_VECTOR
8
#pragma interrupt_handler   sio0_isr: USART0TX_VECTOR
9

10
void init_Clock();
11
void timera_init();
12
void timerb_init();
13
void mittel();
14
void init_DAC();
15
void init_SIO();
16
void init_ADC();
17
//void wait_05ms();
18
void wait_250us(unsigned int ui_Faktor);
19

20
unsigned int temp;
21
unsigned int val_DAC;
22
unsigned char n_tb = 0;
23
volatile n_led = 0;
24
unsigned char n_mw = 0;
25
unsigned int Messwerte[4];
26
unsigned int Messwerte_LED0[4];
27
unsigned int Messwerte_LED1[4];
28
unsigned int Messwerte_LED2[4];
29
unsigned long Summe;
30
unsigned long dunkel;
31
unsigned char Ziffern[4];
32
unsigned int ui_Faktor;
33
unsigned char text[1] = "A";
34
unsigned char text2[1] = "B";
35
unsigned int *ptr_mw0;
36
unsigned int *ptr_mw1;
37
unsigned int *ptr_mw2;
38
unsigned int *ptr_mw;
39
unsigned int mw = 0;
40
unsigned int mw0 = 0;
41
unsigned int mw1 = 0;
42
unsigned int mw2 = 0;
43
unsigned int mw0_a;
44
unsigned int mw0_b;
45
unsigned long value;
46
unsigned char split[2];
47
unsigned char n_send = 0;
48
unsigned char Ziffern_send[4];
49
unsigned long Mittelwert_send = 0;
50

51
void main(void)
52
{
53
    _STOP_WATCHDOG();    //definiert in "msp430def.h"
54
   
55
   ptr_mw  = &mw; 
56
   ptr_mw0 = &mw0; 
57
   ptr_mw1 = &mw1; 
58
   ptr_mw2 = &mw2;    
59
  
60
   P1SEL = 0x00;      //Std.IO
61
   P1DIR = 0xFF;        //alles Ausgänge
62
   P1OUT = 0x00;        // at startup all outputs off
63
   P1OUT |= 0x10;        // Verstaerkung -1 
64
   //P1OUT |= 0x01;
65
   P2SEL = 0x00;      //Std.IO
66
   P2DIR = 0xFF;      //alles Ausgänge
67
   
68
   P5SEL = 0xFF;      //Std.IO
69
   
70
   P3SEL = 0xf0;     //P3.0..3 Standard I/O; P3.4..7 Peripheral Modul Function (UART)
71
   P3DIR = 0x00;     //P3.0..3 Ausgaenge; P3.4..7 = x
72

73
   P6SEL = 0xFF;        //Peripheral Modul Function (ADC12)
74
   
75
   init_Clock();
76
   timera_init();
77
   timerb_init();
78
   init_DAC();
79
   init_ADC();
80
   init_SIO();
81
   
82
  
83
   //Interruptfreigaben
84
   //ADC12IE = 0xFFFF;  //Int-Freigabe für das Ergebnisregister ADC12MEM0
85
   //ADC12IE = ADC12IE2;   
86
   //ADC12IE = 0x0004;             // ADC12 memory 0,2, 
87
   ADC12IE = 0x0001; 
88
   TACCTL0 |= CCIE;   //Timer A C/C Int Enable (für TACCR0)
89

90
   TBCCTL0 |= CCIE;   //Tiemr_B C/C Int Enable (für TBCCR0)
91
   
92
   IE1     |= UTXIE0;   //SIO0 TX-Int freigeben
93
   
94
   _BIS_SR(GIE);     //GIE = 1, globale Interruptfreigabe
95
  
96

97
   TACTL |= MC_1;    //Timer_A starten
98
   // CPU Takt
99
   DCOCTL = DCO0 + DCO1 + DCO2;
100
   BCSCTL1 = RSEL0 + RSEL1 + RSEL2 + DIVA_0;
101
   BCSCTL2 = SELM_2 + DIVM_0 + DIVS_0 + SELS;
102
    
103
  
104
   while(1);  //Endlosschleife - Warten auf Interrupts
105

106
}
107

108

109
void init_Clock( void )
110
{ unsigned char i = 0;
111
  // Turning XT1 (32kHz) on
112
  _BIC_SR (OSCOFF);           // Turn on XT1
113
  BCSCTL1 &= ~XTS;          // LF mode
114
  for (i = 0xFFFF; i > 0; i--);   // Time for osc. to set
115
  // XT1 is on
116

117
  // Turning XT2 (8MHz) on
118
  BCSCTL1 &= ~XT2OFF;         // Turn on XT2
119
  do
120
  {                       // pruefroutine, ob 8 Mhz-oszillator schon stabil ist
121
    IFG1 &= ~OFIFG;       // OSCFault flag loeschen (zeigt oszillatorfehler an)
122
    for (i=0xFF;i>0;i--); // warten, ob es wieder gesetzt wird
123
  }
124
  while ((IFG1 & OFIFG) != 0);   // OSCFault immer noch gesetzt?
125

126
}
127

128

129
void timera_init()
130
{
131
  TACTL = TASSEL_2 | ID_3;   //SourceClock = SMCLK
132

133
   TACCR0 = 0x3000;    
134
            
135
}            
136

137
                        
138
void timerb_init()
139
{
140
     
141
    TBCTL = TBSSEL_1 | ID_0;    //SourceClock = ACLK
142

143
    TBCCR0 = 0x15;          
144
}
145

146

147
void init_DAC(void)
148
{
149
  DAC12_0CTL = DAC12IR + DAC12SREF_2 + DAC12AMP_5 + DAC12ENC;   // 1 reference voltage, medium speed
150
  DAC12_1CTL = DAC12IR + DAC12SREF_2 + DAC12AMP_5 + DAC12ENC;   // 1 reference voltage, medium speed 
151
}
152

153
void init_ADC(void)
154
{
155
   ADC12CTL0 = SHT0_14 + ADC12ON ;
156
  ADC12CTL1 =  CSTARTADD_0 + SHS_0 + SHP + ADC12DIV_0 + ADC12SSEL_2 + CONSEQ_0;
157
  //ADC12MCTL0 = SREF_2 + INCH_2;    //ADC12MEM0, A2 PIN62
158
  ADC12MCTL0 = SREF_2 + INCH_3;    //ADC12MEM0, A3 PIN5
159
  ADC12CTL0 |= ENC;  //ADC startfähig machen
160

161
}
162

163
void init_SIO(void)
164
{
165
//SIO0
166
  ME1 |= UTXE0;                 //Transmitter enablen
167
  U0CTL |= CHAR;                //8 data bits, 1 stop bit, no parity (8N1)
168
  //U0TCTL |= 0x10;              //ACLK als UCLK festlegen
169
    U0TCTL |= SSEL1;           // SMCLK als UCLK festlegen
170
    //UBR00=0xA0; UBR10=0x01; UMCTL0=0x00; /* uart0 8000000Hz 19198bps */
171
  //UBR00=0x41; UBR10=0x03; UMCTL0=0x09; /* uart0 8000000Hz 9600bps */
172
    UBR00=0x45; UBR10=0x00; UMCTL0=0xAA; /* uart0 8000000Hz 115107bp */
173
  //UBR00=0x45; UBR10=0x00; UMCTL0=0xD6; /* uart0 8000000Hz 114942bps */
174

175
    //UBR00=0x22; UBR10=0x00; UMCTL0=0xDD; /* uart0 8000000Hz 230547bps */
176

177

178
  U0BR1 = 0x00;                 
179
  
180
  U0CTL &= ~SWRST;              //USART freigeben
181

182
//  IFG1 &= ~UTXIFG0;             //initales Int-Flag löschen
183
}
184

185
void sio0_isr(void)
186

187
{    
188

189
  if(n_send < 4)
190

191
  {   
192
     
193
     U0TXBUF = Ziffern[n_send];
194
    
195
    n_send++;
196
        
197
  }
198

199
  else
200

201
  {
202

203
     n_send = 0;
204
      
205

206
  }
207

208
}
209
 
210
void write_DAC0(unsigned int val_DAC)
211
{
212
  DAC12_0DAT = val_DAC;
213
}
214
void write_DAC1(unsigned int val_DAC2)
215
{
216
  DAC12_1DAT = val_DAC2;
217
}
218
void timera_isr()
219

220
{   /////// Initphase ////
221
    /// sekunden einlesen.. mitteln .. wert in unteres drittel des Wertebereichs ziehen, offset spannung waehlen und setzen,..verstaerkung auf Grundwert zurueck rechnen
222
     ///DAC1 Ref 2.5V  
223

224
     //TESTOV:
225
   write_DAC0(0xa00);
226
  
227
    if(n_led == 0)
228
   {
229
   P1OUT = 0x00; 
230
    
231
   }
232
    if(n_led == 1)
233
   {
234
   P1OUT |= 0x80;      //P1.7 einschalten 
235
   write_DAC1(0xa00);
236
    
237
   }
238
    if(n_led == 2)
239
   {
240
   P1OUT |= 0x40;    //P1.6 einschalten 
241
   write_DAC1(0x851); //LED
242
      
243
   }
244
    if(n_led == 3)
245
   {
246
   //write_DAC0(0x00); 
247
   //a00  1,5V, 334 0.5V, 670 1V
248
   P1OUT |= 0x20;    //P1.5 einschalten  
249
   write_DAC1(0xfff); //LED
250
   }
251
   
252
   TBCCR0 = 0x15;    //Timer_B starten (wirksam erst nach dem ersten
253
        
254
   TBCTL |= MC_1;    //Timer_B erstmalig starten
255
   //P2OUT &= 0xfe;
256
}
257

258

259

260
void timerb_isr()
261

262
{   
263
    //P2OUT |= 0x02;
264
    n_tb++;       //Inkrement des Timer_B Periodenzählers
265
   
266
    if(n_tb == 8)     //4 Durchlaeufe (n_tb=4)
267
   {  P1OUT = 0x00;    //P1 ausschalten  
268
      write_DAC1(0x00);
269
      P1OUT |= 0x10; //verstaerkung -1 an
270
    //P1OUT |= 0x01; //
271
      TBCCR0 = 0;    //Timer_B stoppen
272
      n_tb = 0;    //Rücksetzen des Timer_B Periodenzählers
273

274
    n_led++;          // Zaehler naechste LED
275
    if(n_led == 4)
276
    { 
277
      n_led = 0;
278
    }
279
   }
280

281
   ADC12CTL0 |= ADC12SC; //SC = Start Conversion
282
    while ((ADC12CTL1 & ADC12BUSY) == 1);
283
   //P2OUT &= 0xfd;
284
}
285

286
void adc_isr()
287
{  
288
  //P2OUT |= 0x04; //Pin4
289
    Messwerte[n_mw] = ADC12MEM0;;  
290
  n_mw++;
291
  
292
  if(n_mw == 8)
293
  {
294
    
295
    n_mw = 0;
296
    if(n_led == 0)
297
    { 
298
      mitteln();
299
     
300
      
301
    }
302
    
303
    if(n_led == 1)
304
    { 
305
      mitteln();
306
      to_ascii(); 
307
      senden0();
308
      
309
    }
310
    if(n_led == 2)
311
    { 
312
      mitteln();
313
      to_ascii(); 
314
      senden1();
315
     }
316
    if(n_led == 3)
317
    { 
318
      mitteln();
319
      to_ascii(); 
320
      senden2();
321
    }
322
    
323
    
324
  }
325
  
326
  
327
  
328
  ADC12IFG = 0x0000;
329
  
330
}
331

332

333

334

335

336

337
void senden0(unsigned long value)
338

339
{
340
   //split[0]= mw0 ;  // low byte
341
  //split[1]= mw0/256; // high byte
342
   U0TXBUF = 0x23;   //initiales Senden  #
343
}
344

345
void senden1(unsigned long value)
346

347
{
348
     //split[0]= mw1 ;  // low byte
349
  //split[1]= mw1/256; // high byte
350
    U0TXBUF = 0x21;   //initiales Senden  "
351
}
352

353
void senden2(unsigned long value)
354

355
{   
356
   //split[0]= mw2;  // low byte
357
  //split[1]= mw2/256; // high byte
358
   //mw2=0x600;
359
   U0TXBUF = 0x25;   //initiales Senden  %
360
}
361

362
void mitteln()
363

364
{
365

366
  unsigned char i = 0;
367

368
  
369

370
  Summe = 0;
371

372
  
373

374
  for(i=0; i<8; i++)
375

376
  {
377

378
    Summe += Messwerte[i];
379

380
  }
381

382

383

384
  Summe /= i;
385
  
386
  
387
  i = 0;
388

389
}
390

391

392

393

394

395
void to_ascii()
396

397
{
398

399
  unsigned char i;  
400

401

402

403
  //Beschreiben des Ziffern-Arrays mit ASCII-Nullen
404

405
  for(i=0; i<4; i++)
406

407
  {
408

409
    Ziffern[i] = 0x30;
410

411
  }  
412

413

414

415
  //Algorithmus zur Zerlegung des Spannungswertes in die einzelnen Ziffern
416

417
  while(Summe > 999)   //1.000er Stelle abspalten
418

419
  {
420

421
    Summe -= 1000;
422

423
    Ziffern[0]++;
424

425
  }
426

427
  
428

429
  while(Summe > 99)   //100er Stelle abspalten
430

431
  {
432

433
    Summe -= 100;
434

435
    Ziffern[1]++;
436

437
  }
438

439
  
440

441
  while(Summe > 9)  //10er Stelle abspalten
442

443
  {
444

445
    Summe -= 10;
446

447
    Ziffern[2]++;
448

449
  }
450

451
  
452

453
  while(Summe > 0)  //1er Stelle abspalten
454

455
  {
456

457
    Summe -= 1;
458

459
    Ziffern[3]++;
460

461
  }
462

463
}
#1414924
Lesenswert?

Ähm
1
unsigned int Messwerte[4];
2

3
...
4

5

6
    Messwerte[n_mw] = ADC12MEM0;;  
7
  n_mw++;
8
  
9
  if(n_mw == 8)
10
  {
11
    n_mw = 0;
12
    ....

n_mw kann also Werte von 0 bis 7 annehmen. Messwerte besitzt aber nur 4 
Elemente.

Du gehst jetzt her und korrigierst diese Out-Of-Bounds Array Zugriffe 
erst mal. Das machst du so
1
#define NR_MESSWERTE  4
2
unsigned int Messwerte[ NR_MESSWERTE ];
3

4
....
5

6
   Messwerte[n_mw] = ADC12MEM0;
7

8
   n_mw++;
9
   if( n_mw == NR_MESSWERTE )
10
   {
11
     n_mw = 0;
12
     ...

sprich:
Du führst dir für diverse konstante Zahlenwerte, vornehmlich 
Arraygrößen, sprechende Namen in Form eines #define ein und gehst dann 
dein Programm durch, welcher konstanter Zahlenwert in deinem Programm in 
Wirklichkeit einem dieser #define entspricht bzw. davon abhängt und 
sorgst erst mal dafür, dass du nirgends mehr auf ein Array ausserhalb 
seiner Grenzen zugreifst.
#1414928
Lesenswert?

Solche Dinge
1
void senden0(unsigned long value)
2
{
3
   //split[0]= mw0 ;  // low byte
4
  //split[1]= mw0/256; // high byte
5
   U0TXBUF = 0x23;   //initiales Senden  #
6
}

ersetzt du ebenfalls. Es gibt hier keinen Grund den ASCII Code für # 
anzuführen
1
void senden0(unsigned long value)
2
{
3
   //split[0]= mw0 ;  // low byte
4
  //split[1]= mw0/256; // high byte
5
   U0TXBUF = '#';
6
}

und schon sieht man im Code was hier passiert und ist nicht mehr auf 
einen Kommentar angewiesen, der gerne auch einmal falsch sein kann.
#1416102
Lesenswert?

Hallo,

ich hab den Quelltext jetzt entruempelt, danke fuer eure Tips. Jedoch 
stehe ich immer noch vor dem Problem, dass die Variable n_led in der 
Timer_A Routine und der ADC_ISR nicht uebereinstimmen. Das macht sich 
jetzt so bemerkbar, dass das setzen von (P1OUT |= 0x20;//P1.5 
einschalten ) in der ADC_ISR nicht registriert wird.
Koennt ihr den Fehler entdecken?
Vielen Dank
Bernd
Angehängte Dateien:
Gast #1416429
Lesenswert?

Bernd Krause (berndk) schrieb:

> ich hab den Quelltext jetzt entruempelt, [...]

Ich sehe da noch jede Menge Variablen, auf die in den ISRs zugegriffen 
bzw. welche dort auch verändert werden, z.B. n_mw, n_send, Ziffern[] 
usw.

Auch sind globale Variablen, die Du in Unterfunktionen, welche von den 
ISRs aufgerufen werden, davon betroffen, wie z.B. die Variable "Summe".

All diese Variablen solltest Du als volatile deklarieren.

Merkwürdigerweise hast Du die Tipps, die Du bekommen hast, immer nur auf 
die konkreten Fälle angewandt, aber nicht bei den weiteren 
Vorkommnissen, wie z.B.

   Ziffern[4]
statt
   Ziffern[NR_ZIFFERN]

oder auch
   Ziffern[i] = 0x30;
statt
   Ziffern[i] = ' ';

Insgesamt ist der Source wegen der vielen Leerzeilen und wegen der nicht 
immer korrekten Einrückungen ziemlich unleserlich. Macht nicht viel 
Freude, den Code zu lesen und verstehen zu wollen.

Gruß,

Frank
#1416472
Lesenswert?

Frank M. schrieb:

> Merkwürdigerweise hast Du die Tipps, die Du bekommen hast, immer nur auf
> die konkreten Fälle angewandt, aber nicht bei den weiteren
> Vorkommnissen, wie z.B.
>

Oder auch hier.
1
void mitteln()
2

3
{
4
  unsigned char i = 0;
5
  Summe = 0;
6
    for(i=0; i<8; i++)
7

8
  {
9
    Summe += Messwerte[i];
10
  }
11
  Summe /= i;
12
  i = 0;
13

14
}

Anstelle der 8 sollte eigentlich NR_MESSWERTE stehen.
Aber na gut, kein Meister ist vom Himmel gefallen. Zumindest sind jetzt 
die offensichtlichen 'Wild in den Speicher'-Schreiborgien weg.
#1416488
Lesenswert?

Ich habe mir jetzt die Fehlerbeschreibung noch einmal durchgelesen. Und 
je öfter ich das tue, desto mehr komme ich zur Erkenntnis, dass ich die 
Fehlerbeschreibung nicht verstehe.

Also: Wie ist das beobachtbare Verhalten? Inwieweit unterschiedet sich 
das von dem was du erwartest?
(Sag jetzt bitte nicht, dass n_led irgendwie magisch den falschen Wert 
hat. Das ist eine Diagnose von dir. Diese Diagnose kann richtig sein 
oder auch nicht. Ich will wissen: was passiert, wie stellst du den 
Fehler fest? Und danach und mit dem Quelltext stelle ich dann meine 
eigene Diagnose auf)
#1417177
Lesenswert?

Hallo,

ich habe mal den funktionierenden Code zum Vergleich angehaengt. Der 
Unterschied besteht darin, dass ich den Zaehler n_led in Timer_A bis 4 
laufen lasse, anstatt bis drei. Im falle des nicht funktionierenden 
Codes geschieht folgendes:
Im falle von n_led == 3 ist  P1.5 aktiviert(LED eingeschaltet), jedoch 
geschieht das nicht. Die ADC_ISR (abtasten einer Photodiode) sendet bei 
n_led=3 die werte einer deaktivieren LED.

BSP n_led bis 3 (funktioniert wie es soll)

2.5V (senden0)
2.5V (senden1)
2.5V (senden2)

nun bis n_led =4

2.5V  (senden0)
2.5V  (senden1)
0V    (senden2)   da bei n_led= 0 alle LEDs abgeschaltet sind und nicht 
bei n_led= 3 ist hier der Fehler, sollte in diesem Fall auch 2.5V sein

Ich hoffe ich habe den Fehler verstaendlich beschrieben...

Vielen Dank
Bernd
Angehängte Dateien:
Moderator Persönliche Seite #1417634
Lesenswert?

Bernd Krause (berndk) schrieb:

> ich habe mal den funktionierenden Code zum Vergleich angehaengt. [...]

Ich habe mal den nicht-funktionierenden Code (4er Version) mit der 
funktionierenden 3er Version verglichen und finde da u.a. den folgenden 
Unterschied in Funktion timera_isr():

3er Version:
1
   if(n_led == 0)
2
   {
3
      P1OUT |= 0x80;      //P1.7 einschalten 
4
      write_DAC1(0xa00);
5
   }

4er Version:
1
   if(n_led == 0)
2
   {
3
     P1OUT = 0x00;   
4
   }

das heisst, dass der Aufruf von write_DAC1() in der 4er Version fehlt.

Trotzdem solltest Du die gestrigen Ratschläge beherzigen und die in den 
ISR-Routinen veränderten Variablen als volatile deklarieren, sonst sind 
weitere böse Überraschungen vorprogrammiert.

Ich würde Deine langen if-Ketten auch in switch-Statements umwandeln: 
erstens effektiver, zweitens lesbarer. Oder zumindest if-else-if 
verwenden, damit der arme µC sich weitere Vergleiche sparen kann, sobald 
der Vergleich mit n_led erfolgreich war.

Gruß,

Frank
Gast #1417940
Lesenswert?

... und Du bist Dir auch sicher, dass Deine Interrupts alle zur 
richtigen Zeit ausgelöst werden und sich nicht irgendwie ineinander 
"verheddern"?
-> Timingdiagramm aufmalen und gucken, wann jeweils ein IRQ feuert und 
wie lange seine Ausführung dauert.

BTW: Wenn ich das richtig sehe, clockst Du den ADC12 mit 8MHZ?!
Erlaubt sind max. 6,3MHz!
#1420140
Lesenswert?

Hallo,

zunaechst danke das ihr mich so tatkraeftig unterstuetzt.

@Stefan
Den ADC12 Takt habe ich nun auf 4Mhz reduziert. Das Timing habe ich 
nochmal uberprueft und noch veraendert. .. siehe Taktdiagramm Anhang.

@ukw
Der Unterschied bei n_led=0 war beabsichtigt. Das Programm mit lediglich 
3 LEDs laeuft bestens, jedoch wollte ich vor dem einschalten der jeweils 
3 LEDs eine Leermessung mit dem ADC machen. Dieses Ergebnis wollte ich 
dann von den spaeteren Messungen der anderen LEDs abschalten.

Die Variablen sind jetzt alle als volatile deklariert, jedoch komme ich 
damit immer noch nicht weiter. Die uebermittelten Werte bei "n_led=3" 
der ADC12_ISR  sind quasi 0. Diese sollten jedoch bei n_led=0 auftreten.
Hat jemand noch eine Idee woran das liegen koennte?

Danke
Bernd
Angehängte Dateien:
Gast #1420279
Lesenswert?

UART passt soweit eigentlich, nur
1
UBR00=0x45; 
2
UBR10=0x00; 
3
UMCTL0=0xAA;
4
U0BR1 = 0x00;  identisch mit UBR10=0x00, also doppelt!
macht aber nix.

In der TMR_B_ISR:
1
ADC12CTL0 |= ADC12SC; //SC = Start Conversion
2
while ((ADC12CTL1 & ADC12BUSY) == 1);  <-- unnötig!
Warteschleife unnötig, dafür gibt's ja die ADC12_ISR!

Ich glaube auch, ich habe Deine Anwendung noch nicht ganz kapiert, ist 
aber vielleicht auch schwierig zu erklären...?!

Eines fällt mir auf (ist das gewollt oder nicht?):
Du startest in TMR_A_ISR mit n_led = 0.
Darauf folgt TMR_B_ISR 4x mit 4 ADC-Messungen. Sind alle 4 Messungen 
vorbei, wird in TMR_B_ISR n_led um 1 erhöht. Damit (also mit n_led == 1) 
wird dann ADC12_ISR final aufgerufen!
D.h. die Messungen mit n_led==0 werden in der ADC12_ISR unter n_led==1 
verarbeitet, usw...
Ausserdem setzt Du in TMR_B_ISR schon vor der 4. Messung P1OUT = 0, DAC1 
= 0 und P1OUT |= 0x10... sollte das nicht erst nach der 4. messung 
passieren?

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