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
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 | }
|
Hi, Du meinst die Fuses sind falsch eingestellt? ;-) Sebastian
Ich denke, er meint eher folgende Regel:
1 | Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang |
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.
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.
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
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
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.
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
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.
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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.