Atmel 8 hängt sich auf - trotz Watchdog und WDTON

Gast #1101917
Lesenswert?

Hi,

ich stehe vor dem Problem, dass sich mein Atmel mega8 ab und zu grundlos 
aufhängt - obwohl die Versorgungsspannung aus 3 AA-Batterien noch über 
4V ist, Brown-Out auf 2,7V eingestellt ist, ein Watchdog läuft und sogar 
das WDTON-Fuse gesetzt ist!

Folgender HW-Aufbau:
- Atmel mega8 mit internem 8MHz-Oszillator
- RFM12-Funkmodul, das nur zum Senden verwendet wird
- Ein LDR mit R an ADC0
- An INT0 und INT1 ein Reedschalter (wird 3 Sekunden lang in der 
Hauptschleife entprellt, ein Interrupt setzt aber nur ein Flag zum 
Auswerten)

Ändert sich der AD-Wert siginifikant (im Programm einstellbar, z.B. um 
Wert "80") oder ändert sich was durch einen Reedschalter, wird ein Byte 
gesendet. Das ganze kann tagelang funktionieren und dann plötzlich nicht 
mehr. Ich habe acht von diesen Platinen, das Phänomen tritt nicht bei 
allen gleichmäßig auf.

Was ich vermute: Die Reedschalter hängen über lange Kabel (2-3m) an den 
Atmel-Pins, ohne irgendwelche Filter. Die LDR haben teilweise auch lange 
Kabelverbindungen. Manchmal passiert es, wenn man eine Neonröhre 
einschaltet (LDR-Kabel liegt direkt daneben), dass sich der Controller 
hängt. Dass das ganze kein sauberer Aufbau ist, muss mir keiner sagen. 
Es musste damals schnell und billig gehen und ist auch nur eine 
Übergangslösung.

Mich interessiert nun vielmehr, ob sich der Atmel die Störungen wirklich 
über die lange Kabel einfängt und sich dermaßen hängen kann, dass nicht 
einmal der Watchdog das Ganze mehr neustarten kann? Der Watchdog 
funktioniert im übrigen ab und zu, das sehe ich, indem ich MCUCR 
auswerte und dann ein spezielles Signal funke.

Um auszuschließen, dass das RFM12-Modul sich aufhängt, ist dieses 
normalerweise komplett ausgeschaltet. Dazu hängt der VDD-Pin des 
RFM12-Moduls an einem Atmel-Pin (LOW ausgeschaltet) und alle anderen 
Pins werden auch auf LOW geschaltet. Soll ein Byte gesendet werden, wird 
das RFM12-Modul angeschaltet, komplett (!) neu initialisiert, das Byte 
verschickt und wieder ausgeschaltet.

Vielen Dank schon einmal im voraus für eine Antwort und Tipps, wie ich 
die Leitungen besser anschließen kann...

Sebastian
Gast #1102089
Lesenswert?

Hi,

hier der Quellcode, es gibt nur den Atmel, das RFM12-Modul 
(Anschlusspins im Code ersichtlich), einen LDR an ADC0 und zwei 
Reedschalter an INT0 und INT1 (beide mit internem Pullup), die Masse 
bekommen die Schalter von den jeweiligen Nachbarpins, also PD1 und PD4:
1
/********************************************************************
2
Sende-Knoten
3

4
(c) 2009 by Sebastian Wille
5
**********************************************************************/
6

7

8
//* includes ************************************************
9

10
#include <stdint.h>
11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
#include <avr/sleep.h>
14
#include <avr/wdt.h>
15

16

17
//* defines *************************************************
18

19
#define SDO_PORT PORTB
20
#define SDO_PIN PINB
21
#define SDO_DDR DDRB
22
#define SDO_Nr 6
23
/*#define SDO_PORT PORTC
24
#define SDO_PIN PINC
25
#define SDO_DDR DDRC
26
#define SDO_Nr 5*/
27

28
#define SDO_OUTPUT() SDO_DDR |= (1<<SDO_Nr)
29
#define SDO_INPUT() SDO_DDR&= ~(1<<SDO_Nr)
30
#define SDO_LOW() SDO_PORT&=~(1<<SDO_Nr)
31
#define SDO_is_HI() SDO_PIN&(1<<SDO_Nr)
32

33

34
#define nIRQ_PORT PORTB
35
#define nIRQ_PIN PINB
36
#define nIRQ_DDR DDRB
37
#define nIRQ_Nr 7
38
/*#define nIRQ_PORT PORTC
39
#define nIRQ_PIN PINC
40
#define nIRQ_DDR DDRC
41
#define nIRQ_Nr 4 */
42

43
#define nIRQ_OUTPUT() nIRQ_DDR |= (1<<nIRQ_Nr)
44
#define nIRQ_INPUT() nIRQ_DDR&= ~(1<<nIRQ_Nr)
45
#define nIRQ_LOW() nIRQ_PORT&=~(1<<nIRQ_Nr)
46

47

48
#define DATA_PORT PORTD
49
#define DATA_PIN PIND
50
#define DATA_DDR DDRD
51
#define DATA_Nr 5
52

53
#define DATA_OUTPUT() DATA_DDR |= (1<<DATA_Nr)
54
#define DATA_INPUT() DATA_DDR&= ~(1<<DATA_Nr)
55
#define DATA_LOW() DATA_PORT&=~(1<<DATA_Nr)
56
#define DATA_OUT DDR_DATA|=(1<<DATA_Nr)
57
#define DATA_HI PORT_DATA|=(1<<DATA_Nr)
58

59

60
#define nSEL_PORT PORTD
61
#define nSEL_PIN PIND
62
#define nSEL_DDR DDRD
63
#define nSEL_Nr 6
64

65
#define nSEL_OUTPUT() nSEL_DDR |= (1<<nSEL_Nr)
66
#define nSEL_HI() nSEL_PORT|= (1<<nSEL_Nr)
67
#define nSEL_LOW() nSEL_PORT&=~(1<<nSEL_Nr)
68

69

70
#define SCK_PORT PORTD
71
#define SCK_PIN PIND
72
#define SCK_DDR DDRD
73
#define SCK_Nr 7
74

75
#define SCK_OUTPUT() SCK_DDR |= (1<<SCK_Nr)
76
#define SCK_HI() SCK_PORT|= (1<<SCK_Nr)
77
#define SCK_LOW() SCK_PORT&=~(1<<SCK_Nr)
78

79

80
#define SDI_PORT PORTB
81
#define SDI_PIN PINB
82
#define SDI_DDR DDRB
83
#define SDI_Nr 0
84

85
#define SDI_OUTPUT() SDI_DDR |= (1<<SDI_Nr)
86
#define SDI_HI() SDI_PORT|= (1<<SDI_Nr)
87
#define SDI_LOW() SDI_PORT&=~(1<<SDI_Nr)
88

89

90
#define LED1_PORT PORTD
91
#define LED1_DDR DDRD
92
#define LED1_Nr 0
93

94
#define LED1_OUTPUT() LED1_DDR|=(1<<LED1_Nr)
95
#define LED1_OFF() LED1_PORT&=~(1<<LED1_Nr)
96
#define LED1_ON() LED1_PORT|=(1<<LED1_Nr)
97

98

99
#define MODULE_PORT PORTB
100
#define MODULE_DDR DDRB
101
#define MODULE_Nr 1
102

103
#define MODULE_OUTPUT() MODULE_DDR|=(1<<MODULE_Nr)
104
//#define MODULE_OFF() MODULE_PORT&=~(1<<MODULE_Nr)
105
#define MODULE_ON() MODULE_PORT|=(1<<MODULE_Nr)
106

107

108
#define MASSE0_PORT PORTD
109
#define MASSE0_DDR DDRD
110
#define MASSE0_Nr 1
111

112
#define MASSE0_OUTPUT() MASSE0_DDR |= (1<<MASSE0_Nr)
113
#define MASSE0_LOW() MASSE0_PORT&=~(1<<MASSE0_Nr)
114

115

116
#define MASSE1_PORT PORTD
117
#define MASSE1_DDR DDRD
118
#define MASSE1_Nr 4
119

120
#define MASSE1_OUTPUT() MASSE1_DDR |= (1<<MASSE1_Nr)
121
#define MASSE1_LOW() MASSE1_PORT&=~(1<<MASSE1_Nr)
122

123

124
#define INT0_PIN PIND
125
#define INT0_PORT PORTD
126
#define INT0_DDR DDRD
127
#define INT0_Nr 2
128

129
#define INT0_INPUT() INT0_DDR&= ~(1<<INT0_Nr)
130
#define INT0_HI() INT0_PORT|= (1<<INT0_Nr)
131

132

133
#define INT1_PIN PIND
134
#define INT1_PORT PORTD
135
#define INT1_DDR DDRD
136
#define INT1_Nr 3
137

138
#define INT1_INPUT() INT1_DDR&= ~(1<<INT1_Nr)
139
#define INT1_HI() INT1_PORT|= (1<<INT1_Nr)
140

141

142
// Knoten-Parameter
143
#define NodeID 0b01100000
144
#define KeepAliveMin 120
145
#define INT0_delays 12 // x Mal 250ms entprellen
146
#define INT1_delays 12 // x Mal 250ms entprellen
147
#define ADC_threshold 85
148

149

150
//* variables ***********************************************
151

152
unsigned int timer2counterIntern = 0;
153
unsigned int timer2counterSec = 0;
154
unsigned int timer2counterMin = 0;
155

156
unsigned int INT0_changed = 0;
157
unsigned int INT1_changed = 0;
158

159
unsigned int INT1_is_Movement = 0;    // 1=ja, Bewegungsmelder statt Reed
160
unsigned int Movement_Timer = 60;
161
unsigned int Movement_Timer_max = 60; // Sekunden
162

163
unsigned int INT0_old = 0;
164
unsigned int INT1_old = 0;
165

166
uint16_t ADC0_old = 1000; // Offset von 1000 wg. +/- ADC_threshold!!!
167
uint16_t ADC1_old = 1000;
168

169
unsigned int KeepAlive_changed = 0;
170

171
unsigned int sendCounter = 0;
172

173

174
uint8_t goBsp=0;
175

176

177
//* functions ***********************************************
178

179
void Delay_ms(unsigned char amS){
180
  unsigned char i;
181
  unsigned int j;
182
  //for(i=0;i<amS;i++)for(j=0;j<914;j++);
183
  for(i=0;i<amS;i++)for(j=0;j<440;j++);
184
}
185

186
void MODULE_OFF(void){
187
  MODULE_PORT&=~(1<<MODULE_Nr);
188

189
  nSEL_LOW();
190
  SDI_LOW();
191
  SCK_LOW();
192

193
  SDO_OUTPUT();
194
  SDO_LOW();
195

196
  nIRQ_OUTPUT();
197
  nIRQ_LOW();
198

199
  DATA_OUTPUT();
200
  DATA_LOW();
201
}
202

203
void Port_init(void){
204
  DDRB=0x00;//PB INPUT
205
  DDRC=0x00;//PC INPUT
206
  DDRD=0x00;//PD INPUT
207

208
  PORTC=0x00;
209

210
  LED1_OUTPUT();
211
  LED1_OFF();
212

213
  MODULE_OUTPUT();
214
  MODULE_OFF();
215

216
  MASSE0_OUTPUT();
217
  MASSE0_LOW();
218

219
  MASSE1_OUTPUT();
220
  MASSE1_LOW();
221

222
  INT0_INPUT();
223
  INT0_HI();
224

225
  INT1_INPUT();
226
  INT1_HI();
227
}
228

229
void ADC_init_freerunning(uint8_t ch) {
230
  ADCSRA = 0;
231
  
232
  ADMUX = 0;
233
  ADMUX = ch;                      // Kanal waehlen
234
  ADMUX |= (1<<ADLAR) | (1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen
235

236
  ADCSRA = 0;
237
  ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
238
}
239

240
uint16_t ADC_read_single(uint8_t ch){
241
  uint8_t i;
242

243
  uint16_t result;
244
 
245
  ADMUX = 0;
246
  ADMUX = ch;                      // Kanal waehlen
247
  ADMUX |= (0<<ADLAR) | (1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen
248
 
249
  ADCSRA = 0;
250
  ADCSRA = (1<<ADEN) | (0<<ADSC)| (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
251

252
  // Dummy-Readout
253
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
254
  while ( ADCSRA & (1<<ADSC) ) {
255
     ;     // auf Abschluss der Konvertierung warten 
256
  }
257

258
  result = ADCW;  // ADCW muss einmal gelesen werden,
259
                  // sonst wird Ergebnis der nächsten Wandlung
260
                  // nicht übernommen.
261
 
262
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
263
  result = 0; 
264
  for( i=0; i<4; i++ )
265
  {
266
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
267
    while ( ADCSRA & (1<<ADSC) ) {
268
      ;   // auf Abschluss der Konvertierung warten
269
    }
270
    result += ADCW;        // Wandlungsergebnisse aufaddieren
271
  }
272

273
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
274
 
275
  result /= 4;                     // Summe durch vier teilen = arithm. Mittelwert
276
 
277
  return result;
278
}
279

280
void LED1_blink_3x(void){
281
  unsigned int i;
282

283
  for(i=0;i<3;i++){
284
    Delay_ms(75);
285
    LED1_ON();
286
    Delay_ms(75);
287
    LED1_OFF();
288
  }
289
}
290

291
unsigned int RFXX_WRT_CMD(unsigned int aCmd){
292
  unsigned char i;
293
  unsigned int temp;
294
  SCK_LOW();
295
  nSEL_LOW();
296
  for(i=0;i<16;i++){
297
    temp<<=1;
298
    if(SDO_is_HI()){
299
      temp|=0x0001;
300
    }
301
    SCK_LOW();
302
    if(aCmd&0x8000){
303
      SDI_HI();
304
      }else{
305
      SDI_LOW();
306
    }
307
    SCK_HI();
308
    aCmd<<=1;
309
  };
310
  SCK_LOW();
311
  nSEL_HI();
312
  return(temp);
313
}
314

315
void RF12_SEND(unsigned char aByte){
316
  while(nIRQ_PIN&(1<<nIRQ_Nr));//wait for previously TX over
317
    RFXX_WRT_CMD(0xB800+aByte);
318
}
319

320
void MODULE_init(void){
321
  SDO_INPUT();
322
  
323
  nIRQ_INPUT();
324
  
325
  DATA_INPUT();
326

327

328
  MODULE_ON();
329
  Delay_ms(200);
330

331
  // module ports init
332
  nSEL_HI();
333
  SDI_HI();
334
  SCK_LOW();
335
  nSEL_OUTPUT();
336
  SDI_OUTPUT();
337
  SDO_INPUT();
338
  SCK_OUTPUT();
339

340
  // set parameters
341
  RFXX_WRT_CMD(0x80D7);//EL,EF,12.0pF 433 MHz
342
  //RFXX_WRT_CMD(0x80E7);//EL,EF,12.0pF 868 MHz
343

344
  RFXX_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
345

346
  RFXX_WRT_CMD(0xA640);//A140=430.8MHz
347
  //RFXX_WRT_CMD(0xA6F8);//868,92MHz
348

349
  RFXX_WRT_CMD(0xC647);//4.8kbps
350

351
  RFXX_WRT_CMD(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm
352
  //RFXX_WRT_CMD(0x94B8);//VDI,FAST,134kHz,-20dBm,-103dBm
353

354
  RFXX_WRT_CMD(0xC2AC);//AL,!ml,DIG,DQD4
355
  RFXX_WRT_CMD(0xCA81);//FIFO8,SYNC,!ff,DR
356
  RFXX_WRT_CMD(0xC483);//@PWR,NO RSTRIC,!st,!fi,OE,EN
357
  RFXX_WRT_CMD(0x9850);//!mp,9810=30kHz,MAX OUT
358
  RFXX_WRT_CMD(0xE000);//NOT USE
359
  RFXX_WRT_CMD(0xC800);//NOT USE
360
  RFXX_WRT_CMD(0xC400);//1.66MHz,2.2V
361

362
  // DATA port init
363
  DATA_DDR|=(1<<DATA_Nr);
364
  DATA_PORT|=(1<<DATA_Nr);// SET nFFS pin HI when using TX register
365

366
  // nIRQ init
367
  nIRQ_DDR&=~(1<<nIRQ_Nr);
368
}
369

370
void send_Byte(unsigned char dataByte){
371
  //unsigned char i;
372
  
373
  MODULE_init();
374

375
  LED1_ON();
376

377
  RFXX_WRT_CMD(0x0000);//read status register
378
  RFXX_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
379
  
380
 
381
  RF12_SEND(0xAA);//PREAMBLE
382
  RF12_SEND(0xAA);//PREAMBLE
383
  RF12_SEND(0xAA);//PREAMBLE
384
  RF12_SEND(0x2D);//SYNC HI BYTE
385
  RF12_SEND(0xD4);//SYNC LOW BYTE
386

387
  //for(i=0;i<10;i++){
388
    RF12_SEND(dataByte);//DATA BYTE
389
  RF12_SEND(0xFF-dataByte);//Checksum
390
    //Delay_ms(2);
391
  //}
392

393
  RF12_SEND(0xAA);//DUMMY BYTE
394
  RF12_SEND(0xAA);//DUMMY BYTE
395
  RF12_SEND(0xAA);//DUMMY BYTE
396
  RFXX_WRT_CMD(0x8201);
397

398
  LED1_OFF();
399

400
  MODULE_OFF();
401
}
402

403
void send_Byte_multiple(unsigned char dataByte, unsigned char multiple){
404
  unsigned char i;
405
  
406
  MODULE_init();
407

408

409
  for(i=0;i<multiple;i++){
410
    LED1_ON();
411

412
    RFXX_WRT_CMD(0x0000);//read status register
413
    RFXX_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
414
  
415
 
416
    RF12_SEND(0xAA);//PREAMBLE
417
    RF12_SEND(0xAA);//PREAMBLE
418
    RF12_SEND(0xAA);//PREAMBLE
419
    RF12_SEND(0x2D);//SYNC HI BYTE
420
    RF12_SEND(0xD4);//SYNC LOW BYTE
421

422
    RF12_SEND(dataByte);//DATA BYTE
423
  RF12_SEND(0xFF-dataByte);//Checksum
424

425
    RF12_SEND(0xAA);//DUMMY BYTE
426
    RF12_SEND(0xAA);//DUMMY BYTE
427
    RF12_SEND(0xAA);//DUMMY BYTE
428
    RFXX_WRT_CMD(0x8201);
429

430
    LED1_OFF();
431
  }
432

433
  MODULE_OFF();
434
}
435

436
void sendCounterInc(void){
437
  sendCounter = sendCounter +1;
438
  if(sendCounter > 1){
439
    sendCounter = 0;
440
  }
441
}
442

443
ISR (SIG_INTERRUPT0)
444
{
445
  uint8_t tmp_sreg;
446

447
  tmp_sreg = SREG;
448

449
  asm("cli");
450

451
  INT0_changed=1;
452

453
  // muss drin bleiben!
454
//  LED1_ON();
455
//  Delay_ms(1);
456
//  LED1_OFF();
457

458
  asm("sei");
459

460
  SREG = tmp_sreg;
461
}
462

463

464
ISR (SIG_INTERRUPT1)
465
{
466
  uint8_t tmp_sreg;
467

468
  tmp_sreg = SREG;
469

470
  asm("cli");
471

472
  INT1_changed=1;
473

474
  // muss drin bleiben!
475
//  LED1_ON();
476
//  Delay_ms(1);
477
//  LED1_OFF();
478

479
  asm("sei");
480

481
  SREG = tmp_sreg;
482
}
483

484
ISR (SIG_OVERFLOW2)
485
{
486
  uint8_t tmp_sreg;
487

488
  tmp_sreg = SREG;
489

490
  timer2counterIntern += 1;
491
  //if(timer2counterIntern == 30){ // 1 Sekunde
492
  if(timer2counterIntern == 36){ // 1 Sekunde
493
    timer2counterIntern=0;
494

495
  //goBsp=1;
496
    if(Movement_Timer == Movement_Timer_max){
497
      //Movement_Timer = Movement_Timer;
498
  }else{
499
      Movement_Timer = Movement_Timer +1;
500
  }
501

502
    timer2counterSec += 1;
503
    if(timer2counterSec == 60){
504
    timer2counterSec = 0;
505

506
      timer2counterMin += 1;
507
      if(timer2counterMin == KeepAliveMin){
508
        timer2counterMin = 0;
509

510
      KeepAlive_changed = 1;
511
      }
512

513
  }
514
  }
515

516
  SREG = tmp_sreg;
517
}
518

519
void main(void)
520
{
521
  //unsigned int i,j;
522

523
  uint8_t ADC_readout;
524
  uint8_t dataByte;
525
  int16_t i1;
526

527
  // Watchdog an
528
  wdt_enable(WDTO_500MS);
529

530
  asm("cli"); // interrupts off
531

532
  Port_init();
533
  //ADC_init_freerunning(0);
534

535
  // Externe Interrupts konfigurieren
536
  MCUCR &= 0b11110000;
537
  if (INT1_is_Movement == 0){
538
    MCUCR |= (1<<ISC10)|(1<<ISC00);
539
  }else{
540
    MCUCR |= (1<<ISC11)|(1<<ISC00);
541
  }
542
  GICR |= (1<<INT1)|(1<<INT0);
543
  GIFR |= (1<<INTF1)|(1<<INTF0);
544
  
545
  asm("sei"); // interrupts on
546

547
  //LED1_blink_3x();
548

549
  // Normaler oder Watchdog-Reset?
550
  if ((MCUCSR&(1<<WDRF)) > 0){
551
    send_Byte_multiple(NodeID, 5);
552
    MCUCSR = 0;
553
  }else{
554
  send_Byte_multiple(NodeID, 3);
555
  }
556

557
  while(1){
558
    wdt_reset();
559

560
    //asm("cli"); // interrupts off
561

562
    /*if(goBsp==1){
563
    send_Byte('S');
564
    goBsp=0;
565
    }*/
566

567
  // ADC0 changed?
568
    ADC_readout = (ADC_read_single(0) >> 2) & 0x00FF;
569
  //send_Byte(ADC_readout);
570

571
    i1 = ADC0_old - ADC_threshold;
572
  if (ADC_readout +1000 < i1){
573
      ADC0_old = ADC_readout +1000;
574

575
    dataByte = NodeID;
576

577
      dataByte |= (1<<3);
578
    
579
    sendCounterInc();
580
    dataByte |= sendCounter;
581

582
      send_Byte(dataByte);
583
    //send_Byte(ADC_readout);
584
  } else
585
  {
586
  i1 = ADC0_old + ADC_threshold;
587
  if (ADC_readout +1000 > i1){
588
      ADC0_old = ADC_readout +1000;
589

590
    dataByte = NodeID;
591

592
      dataByte |= (1<<3);
593

594
    dataByte |= (1<<1);
595
    
596
    sendCounterInc();
597
    dataByte |= sendCounter;
598

599
      send_Byte(dataByte);
600
    //send_Byte(ADC_readout);
601
  }
602
  }
603

604
    if(KeepAlive_changed==1){
605
    KeepAlive_changed = 0;
606

607
    dataByte = NodeID;
608

609
      dataByte |= (1<<3);
610
    dataByte |= (1<<2);
611

612
    sendCounterInc();
613
    dataByte |= sendCounter;
614

615
      send_Byte(dataByte);
616
  }
617

618
    if(INT0_changed==1){
619
      // entprellen
620
    for(i1=0;i1<INT0_delays;i1++){
621
      Delay_ms(250);
622
    wdt_reset();
623
      }
624

625
    INT0_changed=0;
626

627
      if(INT0_old != (INT0_PIN&(1<<INT0_Nr))){
628
        INT0_old = (INT0_PIN&(1<<INT0_Nr));
629

630
      dataByte = NodeID;
631

632
      if((INT0_PIN&(1<<INT0_Nr))>0){
633
          dataByte |= (1<<1);
634
      }
635

636
      sendCounterInc();
637
      dataByte |= sendCounter;
638

639
        send_Byte(dataByte);
640
      }
641
  }
642

643
    if(INT1_changed==1){
644
      if (INT1_is_Movement == 0){
645
        // entprellen
646
    for(i1=0;i1<INT1_delays;i1++){
647
        Delay_ms(250);
648
      wdt_reset();
649
        }
650

651
      INT1_changed=0;
652

653
      if(INT1_old != (INT1_PIN&(1<<INT1_Nr))){
654
          INT1_old = (INT1_PIN&(1<<INT1_Nr));
655

656
        dataByte = NodeID;
657
        dataByte |= (1<<2);
658

659
        if((INT1_PIN&(1<<INT1_Nr))>0){
660
            dataByte |= (1<<1);
661
        }
662

663
        sendCounterInc();
664
        dataByte |= sendCounter;
665

666
          send_Byte(dataByte);
667
        }
668
      }else{
669
        INT1_changed=0;
670

671
      if(Movement_Timer == Movement_Timer_max){
672
          Movement_Timer = 0;
673

674
        dataByte = NodeID;
675
        dataByte |= (1<<2);
676

677
        sendCounterInc();
678
        dataByte |= sendCounter;
679

680
          send_Byte(dataByte);
681
        }
682
    }
683
  }
684

685
    set_sleep_mode(SLEEP_MODE_IDLE);
686
  sleep_enable();
687

688
    // Timer2 stellen
689
  TCCR2=0b00000000; // Stop
690
    TCNT2=90; //0;  // so etwas genauer
691
    //ASSR=0b00001000; // AS2 = an (ext. 32,768kHz)
692
  ASSR=0;
693
  TIMSK|=(1<<6);
694

695
    //asm("sei"); // interrupts on
696

697
    TCCR2=0b00000111; // Start, prescaler 1024
698
  //TCCR2=0b00000010; // Start, prescaler 8
699

700
  sleep_cpu();
701
  sleep_disable();
702
  };
703
}
#1102123
Lesenswert?

1
ISR (SIG_INTERRUPT1)
2
{
3
  uint8_t tmp_sreg;
4

5
  tmp_sreg = SREG;
6

7
  asm("cli");
8

9
  INT1_changed=1;
10

11
  // muss drin bleiben!
12
//  LED1_ON();
13
//  Delay_ms(1);
14
//  LED1_OFF();
15

16
  asm("sei");
17

18
  SREG = tmp_sreg;
19
}

Alle Zeilen mit "sreg" und "asm" sind komplett überflüssig und sogar 
gefährlich. Das, was du da versuchst, macht der Prozessor schon 
automatisch. Das gleiche gilt natürlich auch für die anderen Interrupts.
Gast #1102134
Lesenswert?

Hi,

erst einmal Entschuldigung dafür, dass ich nicht den Anhang verwendet 
habe. Ich mache es nächstes Mal besser.

@Stefan:
Meinst Du, der Compiler macht dies oder der Atmel-Mikrocontroller?!? Ich 
war immer der Meinung, der kann innerhalb eines Interrupts zu einem 
anderen springen... Wie auch immer, kann es daran liegen? Das erklärt ja 
aber nicht das aufhängen nach einem Neoröhren-Start...

Vielen Dank dennoch schonmal!

Sebastian
#1102150
Lesenswert?

Sebastian wrote:

> Meinst Du, der Compiler macht dies oder der Atmel-Mikrocontroller?!?

Der Mikrocontroller. Er löscht das Interrupt-Enable-Flag beim Ausführen 
des Interrupt-Codes, und setzt es wieder beim "reti" (also dem 
Verlassen).

> Ich war immer der Meinung, der kann innerhalb eines Interrupts zu einem
> anderen springen...

Nur, wenn du das Interrupt-Enable-Flag in der ISR selber setzt. Und 
genau das tust du am Ende des Interrupts. Du ermöglichst also das, was 
du zu verhindern versuchst. Daher das "gefährlich".

> Wie auch immer, kann es daran liegen?

Dazu hab ich mir den Code nicht detailliert genug angesehen. Aber 
Interrupts, die sich selber oder gegenseitig unterbrechen, sind immer 
eine mögliche Quelle für "interessante" Fehler.
Gast #1102199
Lesenswert?

Hallo Marius und Stefan,

vielen Dank für Eure Erklärungen, das werde ich in Zukunft besser 
machen!

Hat sonst noch irgendjemand einen Hinweis, warum sich der komplette 
Controller - trotz Watchdog hängt? Wie kann ein externen Impuls auf die 
Hardware sowas zum Beispiel bewirken?

Vielen Dank im voraus!

Sebastian
#1102245
Lesenswert?

Sebastian wrote:

> Hat sonst noch irgendjemand einen Hinweis, warum sich der komplette
> Controller - trotz Watchdog hängt? Wie kann ein externen Impuls auf die
> Hardware sowas zum Beispiel bewirken?

Genau deshalb, weil der Interrupt sich laufend selbst unterbricht. Der 
Watchdog nützt da nicht sehr viel, wenn der Prozessor nach dem Reset 
sofort wieder im Dauerinterrupt hängt. Und da in main das "sei" vor dem 
Versenden der Watchdog-Info steht, bekommst du in diesem Fall diese auch 
nicht.
Gast #1102457
Lesenswert?

Hallo Stefan,

OK, ich werde das erstmal austesten, vielen Dank!

Nur um nochmals sicher zu gehen: Kann es zusätzlich zu diesem Problem 
auch sein, dass sich der Controller durch das An-/Ausschalten einer 
Neonröhre hängt und nicht (!) wieder durch den Watchdog in einen 
sicheren Zustand kommt? Oder hat das noch keiner erlebt?

Sebastian
Gast #1102774
Lesenswert?

Hallo!
Watchdogs sind genau so sicher oder auch unsicher wie jede andere 
digitale logische Schaltung. Interne sind nur ein kleiner zusätzliche 
Schutz. Es ist zwar relativ unwahrscheinlich, daß Softwareabstürze 
diesen Überwachungsknecht deaktivieren, aber eben nur relativ!
Bei kritischen Anwendungen werden oftmals externe Wachhunde eingesetzt 
oder gar verlangt. Da kann man durch separate Abblockmaßnahmen - 
Abschirmungen - Leitungsführung - andere Halbleitertechnologie... - 
wesentlich mehr herausholen. Diese können auch durch Softwareabstürze 
nicht plötzlich deaktiviert werden. Für ganz kritische Anwendungen (z.B. 
Medizinelektronik, Kernkraft - oder so) werden auch schon mal mehrere 
kombiniert.
Gast #1111848
Lesenswert?

Hi,

kurzer Zwischenstand:

Ich habe inzwischen bei den Interruptroutinen alle "cel", "sei" und die 
SREG-Sicherung rausgenommen. Außerdem habe ich alle Variablen, die in 
Interruptroutinen modifiziert werden, auf "volatile" gesetzt.

Die letzten fünf Tage hatte ich bei allen acht Schaltungen keinen Hänger 
mehr.

Ich bekomme zwar immer noch normale Resets und Watchdogresets, aber das 
ist ja nun eine andere Sache. Auf jeden Fall hängt kein Programm mehr in 
der Luft.

Ich hoffe, dass es nun keine Hänger mehr gibt und bedanke mich nochmals 
recht herzlich - vor allem bei Stefan Ernst - für die Ratschläge!

Viele Grüße,

Sebastian

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