Forum: Mikrocontroller und Digitale Elektronik [MSP430] Variablenuebergabe an ISR


von Bernd K. (berndk)


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
}

von Falk B. (falk)


Lesenswert?

Siehe Interrupt, Stichwort volatile.

von Karl H. (kbuchegg)


Lesenswert?

volatile ?

von Timo P (Gast)


Lesenswert?

wo wird die Variable denn angelegt?

von Timo P (Gast)


Lesenswert?

im Übrigen:

gefällt mir folgendes Zitat:
"C Kurs - too many ifs - I think I switch"


siehe:
http://www.peacesoftware.de/ckurs7.html

von Bernd K. (berndk)


Lesenswert?

derzeit ist die Variable als "unsigned char" deklariert. Ich werde es 
mal mit volatile probieren und mich dann melden.

Bei 3 oder 4 Variablen ist es eigentlich egal, ob man if oder switch 
nimmt, meine Meinung :)

von Bernd K. (berndk)


Lesenswert?

Ich habs jetzt mal mit volatile probiert, jedoch aendert sich das 
Verhalten nicht. Was kann ich da uebersehen haben?

von Tobias K. (kurzschluss81)


Lesenswert?

Nochmal die Frage wo ist die Variable deklariert. Diese Variable sollte 
nämlich schon eine Globale sein wenn mehrere, besonders ISR, Teile der 
Software drauf zugreifen.

von Bernd K. (berndk)


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

von Tobias K. (kurzschluss81)


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

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


Lesenswert?

Tobias Korrmann schrieb:

> Du must der Variable wenigstens noch einen datentyp Spendieren.
> So geht dat jedenfalls nicht

Doch das geht.
In C ist alles was du nicht explizit mit einem Datentyp versiehst ein 
int.

von Bernd K. (berndk)


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
}

von Falk B. (falk)


Lesenswert?

@  Bernd Krause (berndk)

>Bin fuer jeden Ratschlag dankbar

Na dann lies mal was hier drüber steht!

"Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"

Siehe auch Netiquette

MFG
Falk

von Karl H. (kbuchegg)


Lesenswert?

Erster Eindruck:
tu dir selbst einen Gefallen und reduziere die Anzahl der Leerzeilen. 
Wenn eine Leerzeile zwischen 2 Funktionsblöcken dir keine Übersicht 
bringt, dann tun es auch mehrere Leerzeilen nicht. Allerdings ziehen 
mehrere Leerzeilen den Code nur unnötig in die Länge und verringern die 
Übersicht.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


Lesenswert?

Und dann gehst du her und durchsuchst deine globalen Variablen, welche 
davon nicht mehr gebraucht werden und löscht sie raus. Einige davon 
werden nur von einer Funktion benutzt und sind dann dort als lokale 
Variable besser aufgehoben.

von Bernd K. (berndk)


Angehängte Dateien:

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

von Frank M. (Gast)


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

von Frank M. (Gast)


Lesenswert?

Frank M. (Gast) schrieb:

> Ziffern[i] = ' ';

Sorry, vertippert, meinte natürlich:

Ziffern[i] = '0';

Gruß,

Frank

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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)

von Bernd K. (berndk)


Angehängte Dateien:

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

von Frank M. (ukw) (Moderator) Benutzerseite


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

von Stefan (Gast)


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!

von Bernd K. (berndk)


Angehängte Dateien:

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

von Karl H. (kbuchegg)


Lesenswert?

Kann es sein, dass das Problem bei der UART Übertragung entsteht? Die 
Ausgabe auf die UART erscheint mir da ziemlich unkoordiniert zu laufen.

von Bernd K. (berndk)


Lesenswert?

Die Datenuebetragung kann ich ausschliessen. Schalte ich bei dem 
Programm mit drei LEDs eine ab, wird das auch richtig detektiert. Zeit 
zum senden ist auch ausreichend vorhanden. Weshalb meinst du ist das 
unkoordiniert?

von Stefan (Gast)


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?

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.