Forum: Mikrocontroller und Digitale Elektronik Atmel 8 hängt sich auf - trotz Watchdog und WDTON


von Sebastian (Gast)


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

von Gast (Gast)


Lesenswert?

Schaltplan? Programm?

von Sebastian (Gast)


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
}

von Gast (Gast)


Lesenswert?

Ich glaub es hackt...

von Sebastian (Gast)


Lesenswert?

Hi,

Du meinst die Fuses sind falsch eingestellt? ;-)

Sebastian

von M. P. (phpmysqlfreak)


Lesenswert?

Ich denke, er meint eher folgende Regel:
1
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Stefan E. (sternst)


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.

von Stefan E. (sternst)


Lesenswert?

Desweiteren müssen INT0_changed und INT1_changed volatile deklariert 
sein. Und dass es unsigned ints sind und keine unsigned chars, ist auch 
nicht gerade günstig.

von Sebastian (Gast)


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

von Marius W. (mw1987)


Lesenswert?

Der Atmel sperrt eingehende Interrupts solange du dich in einer ISR 
befindest. Erst wenn du aus der ISR raus bist, wird die ISR für den 
eingegangenen Interrupt ausgeführt.

MfG
Marius

von Stefan E. (sternst)


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.

von Sebastian (Gast)


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

von Stefan E. (sternst)


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.

von Sebastian (Gast)


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

von Route_66 (Gast)


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.

von Sebastian (Gast)


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

von Sebastian (Gast)


Lesenswert?

Hi,

nach knapp drei Wochen treten immer noch keine Probleme auf - ich denke 
das Problem ist gelöst.

Vielen Dank nochmals, den Fehler werde ich nicht mehr machen!

Sebastian

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.