mikrocontroller.net

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


Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schaltplan? Programm?

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
/********************************************************************
Sende-Knoten

(c) 2009 by Sebastian Wille
**********************************************************************/


//* includes ************************************************

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>


//* defines *************************************************

#define SDO_PORT PORTB
#define SDO_PIN PINB
#define SDO_DDR DDRB
#define SDO_Nr 6
/*#define SDO_PORT PORTC
#define SDO_PIN PINC
#define SDO_DDR DDRC
#define SDO_Nr 5*/

#define SDO_OUTPUT() SDO_DDR |= (1<<SDO_Nr)
#define SDO_INPUT() SDO_DDR&= ~(1<<SDO_Nr)
#define SDO_LOW() SDO_PORT&=~(1<<SDO_Nr)
#define SDO_is_HI() SDO_PIN&(1<<SDO_Nr)


#define nIRQ_PORT PORTB
#define nIRQ_PIN PINB
#define nIRQ_DDR DDRB
#define nIRQ_Nr 7
/*#define nIRQ_PORT PORTC
#define nIRQ_PIN PINC
#define nIRQ_DDR DDRC
#define nIRQ_Nr 4 */

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


#define DATA_PORT PORTD
#define DATA_PIN PIND
#define DATA_DDR DDRD
#define DATA_Nr 5

#define DATA_OUTPUT() DATA_DDR |= (1<<DATA_Nr)
#define DATA_INPUT() DATA_DDR&= ~(1<<DATA_Nr)
#define DATA_LOW() DATA_PORT&=~(1<<DATA_Nr)
#define DATA_OUT DDR_DATA|=(1<<DATA_Nr)
#define DATA_HI PORT_DATA|=(1<<DATA_Nr)


#define nSEL_PORT PORTD
#define nSEL_PIN PIND
#define nSEL_DDR DDRD
#define nSEL_Nr 6

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


#define SCK_PORT PORTD
#define SCK_PIN PIND
#define SCK_DDR DDRD
#define SCK_Nr 7

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


#define SDI_PORT PORTB
#define SDI_PIN PINB
#define SDI_DDR DDRB
#define SDI_Nr 0

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


#define LED1_PORT PORTD
#define LED1_DDR DDRD
#define LED1_Nr 0

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


#define MODULE_PORT PORTB
#define MODULE_DDR DDRB
#define MODULE_Nr 1

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


#define MASSE0_PORT PORTD
#define MASSE0_DDR DDRD
#define MASSE0_Nr 1

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


#define MASSE1_PORT PORTD
#define MASSE1_DDR DDRD
#define MASSE1_Nr 4

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


#define INT0_PIN PIND
#define INT0_PORT PORTD
#define INT0_DDR DDRD
#define INT0_Nr 2

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


#define INT1_PIN PIND
#define INT1_PORT PORTD
#define INT1_DDR DDRD
#define INT1_Nr 3

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


// Knoten-Parameter
#define NodeID 0b01100000
#define KeepAliveMin 120
#define INT0_delays 12 // x Mal 250ms entprellen
#define INT1_delays 12 // x Mal 250ms entprellen
#define ADC_threshold 85


//* variables ***********************************************

unsigned int timer2counterIntern = 0;
unsigned int timer2counterSec = 0;
unsigned int timer2counterMin = 0;

unsigned int INT0_changed = 0;
unsigned int INT1_changed = 0;

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

unsigned int INT0_old = 0;
unsigned int INT1_old = 0;

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

unsigned int KeepAlive_changed = 0;

unsigned int sendCounter = 0;


uint8_t goBsp=0;


//* functions ***********************************************

void Delay_ms(unsigned char amS){
  unsigned char i;
  unsigned int j;
  //for(i=0;i<amS;i++)for(j=0;j<914;j++);
  for(i=0;i<amS;i++)for(j=0;j<440;j++);
}

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

  nSEL_LOW();
  SDI_LOW();
  SCK_LOW();

  SDO_OUTPUT();
  SDO_LOW();

  nIRQ_OUTPUT();
  nIRQ_LOW();

  DATA_OUTPUT();
  DATA_LOW();
}

void Port_init(void){
  DDRB=0x00;//PB INPUT
  DDRC=0x00;//PC INPUT
  DDRD=0x00;//PD INPUT

  PORTC=0x00;

  LED1_OUTPUT();
  LED1_OFF();

  MODULE_OUTPUT();
  MODULE_OFF();

  MASSE0_OUTPUT();
  MASSE0_LOW();

  MASSE1_OUTPUT();
  MASSE1_LOW();

  INT0_INPUT();
  INT0_HI();

  INT1_INPUT();
  INT1_HI();
}

void ADC_init_freerunning(uint8_t ch) {
  ADCSRA = 0;
  
  ADMUX = 0;
  ADMUX = ch;                      // Kanal waehlen
  ADMUX |= (1<<ADLAR) | (1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen

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

uint16_t ADC_read_single(uint8_t ch){
  uint8_t i;

  uint16_t result;
 
  ADMUX = 0;
  ADMUX = ch;                      // Kanal waehlen
  ADMUX |= (0<<ADLAR) | (1<<REFS1) | (1<<REFS0); // externe Referenzspannung nutzen
 
  ADCSRA = 0;
  ADCSRA = (1<<ADEN) | (0<<ADSC)| (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

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

  result = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.
 
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  result = 0; 
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
    result += ADCW;        // Wandlungsergebnisse aufaddieren
  }

  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
 
  result /= 4;                     // Summe durch vier teilen = arithm. Mittelwert
 
  return result;
}

void LED1_blink_3x(void){
  unsigned int i;

  for(i=0;i<3;i++){
    Delay_ms(75);
    LED1_ON();
    Delay_ms(75);
    LED1_OFF();
  }
}

unsigned int RFXX_WRT_CMD(unsigned int aCmd){
  unsigned char i;
  unsigned int temp;
  SCK_LOW();
  nSEL_LOW();
  for(i=0;i<16;i++){
    temp<<=1;
    if(SDO_is_HI()){
      temp|=0x0001;
    }
    SCK_LOW();
    if(aCmd&0x8000){
      SDI_HI();
      }else{
      SDI_LOW();
    }
    SCK_HI();
    aCmd<<=1;
  };
  SCK_LOW();
  nSEL_HI();
  return(temp);
}

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

void MODULE_init(void){
  SDO_INPUT();
  
  nIRQ_INPUT();
  
  DATA_INPUT();


  MODULE_ON();
  Delay_ms(200);

  // module ports init
  nSEL_HI();
  SDI_HI();
  SCK_LOW();
  nSEL_OUTPUT();
  SDI_OUTPUT();
  SDO_INPUT();
  SCK_OUTPUT();

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

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

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

  RFXX_WRT_CMD(0xC647);//4.8kbps

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

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

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

  // nIRQ init
  nIRQ_DDR&=~(1<<nIRQ_Nr);
}

void send_Byte(unsigned char dataByte){
  //unsigned char i;
  
  MODULE_init();

  LED1_ON();

  RFXX_WRT_CMD(0x0000);//read status register
  RFXX_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
  
 
  RF12_SEND(0xAA);//PREAMBLE
  RF12_SEND(0xAA);//PREAMBLE
  RF12_SEND(0xAA);//PREAMBLE
  RF12_SEND(0x2D);//SYNC HI BYTE
  RF12_SEND(0xD4);//SYNC LOW BYTE

  //for(i=0;i<10;i++){
    RF12_SEND(dataByte);//DATA BYTE
  RF12_SEND(0xFF-dataByte);//Checksum
    //Delay_ms(2);
  //}

  RF12_SEND(0xAA);//DUMMY BYTE
  RF12_SEND(0xAA);//DUMMY BYTE
  RF12_SEND(0xAA);//DUMMY BYTE
  RFXX_WRT_CMD(0x8201);

  LED1_OFF();

  MODULE_OFF();
}

void send_Byte_multiple(unsigned char dataByte, unsigned char multiple){
  unsigned char i;
  
  MODULE_init();


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

    RFXX_WRT_CMD(0x0000);//read status register
    RFXX_WRT_CMD(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
  
 
    RF12_SEND(0xAA);//PREAMBLE
    RF12_SEND(0xAA);//PREAMBLE
    RF12_SEND(0xAA);//PREAMBLE
    RF12_SEND(0x2D);//SYNC HI BYTE
    RF12_SEND(0xD4);//SYNC LOW BYTE

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

    RF12_SEND(0xAA);//DUMMY BYTE
    RF12_SEND(0xAA);//DUMMY BYTE
    RF12_SEND(0xAA);//DUMMY BYTE
    RFXX_WRT_CMD(0x8201);

    LED1_OFF();
  }

  MODULE_OFF();
}

void sendCounterInc(void){
  sendCounter = sendCounter +1;
  if(sendCounter > 1){
    sendCounter = 0;
  }
}

ISR (SIG_INTERRUPT0)
{
  uint8_t tmp_sreg;

  tmp_sreg = SREG;

  asm("cli");

  INT0_changed=1;

  // muss drin bleiben!
//  LED1_ON();
//  Delay_ms(1);
//  LED1_OFF();

  asm("sei");

  SREG = tmp_sreg;
}


ISR (SIG_INTERRUPT1)
{
  uint8_t tmp_sreg;

  tmp_sreg = SREG;

  asm("cli");

  INT1_changed=1;

  // muss drin bleiben!
//  LED1_ON();
//  Delay_ms(1);
//  LED1_OFF();

  asm("sei");

  SREG = tmp_sreg;
}

ISR (SIG_OVERFLOW2)
{
  uint8_t tmp_sreg;

  tmp_sreg = SREG;

  timer2counterIntern += 1;
  //if(timer2counterIntern == 30){ // 1 Sekunde
  if(timer2counterIntern == 36){ // 1 Sekunde
    timer2counterIntern=0;

  //goBsp=1;
    if(Movement_Timer == Movement_Timer_max){
      //Movement_Timer = Movement_Timer;
  }else{
      Movement_Timer = Movement_Timer +1;
  }

    timer2counterSec += 1;
    if(timer2counterSec == 60){
    timer2counterSec = 0;

      timer2counterMin += 1;
      if(timer2counterMin == KeepAliveMin){
        timer2counterMin = 0;

      KeepAlive_changed = 1;
      }

  }
  }

  SREG = tmp_sreg;
}

void main(void)
{
  //unsigned int i,j;

  uint8_t ADC_readout;
  uint8_t dataByte;
  int16_t i1;

  // Watchdog an
  wdt_enable(WDTO_500MS);

  asm("cli"); // interrupts off

  Port_init();
  //ADC_init_freerunning(0);

  // Externe Interrupts konfigurieren
  MCUCR &= 0b11110000;
  if (INT1_is_Movement == 0){
    MCUCR |= (1<<ISC10)|(1<<ISC00);
  }else{
    MCUCR |= (1<<ISC11)|(1<<ISC00);
  }
  GICR |= (1<<INT1)|(1<<INT0);
  GIFR |= (1<<INTF1)|(1<<INTF0);
  
  asm("sei"); // interrupts on

  //LED1_blink_3x();

  // Normaler oder Watchdog-Reset?
  if ((MCUCSR&(1<<WDRF)) > 0){
    send_Byte_multiple(NodeID, 5);
    MCUCSR = 0;
  }else{
  send_Byte_multiple(NodeID, 3);
  }

  while(1){
    wdt_reset();

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

    /*if(goBsp==1){
    send_Byte('S');
    goBsp=0;
    }*/

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

    i1 = ADC0_old - ADC_threshold;
  if (ADC_readout +1000 < i1){
      ADC0_old = ADC_readout +1000;

    dataByte = NodeID;

      dataByte |= (1<<3);
    
    sendCounterInc();
    dataByte |= sendCounter;

      send_Byte(dataByte);
    //send_Byte(ADC_readout);
  } else
  {
  i1 = ADC0_old + ADC_threshold;
  if (ADC_readout +1000 > i1){
      ADC0_old = ADC_readout +1000;

    dataByte = NodeID;

      dataByte |= (1<<3);

    dataByte |= (1<<1);
    
    sendCounterInc();
    dataByte |= sendCounter;

      send_Byte(dataByte);
    //send_Byte(ADC_readout);
  }
  }

    if(KeepAlive_changed==1){
    KeepAlive_changed = 0;

    dataByte = NodeID;

      dataByte |= (1<<3);
    dataByte |= (1<<2);

    sendCounterInc();
    dataByte |= sendCounter;

      send_Byte(dataByte);
  }

    if(INT0_changed==1){
      // entprellen
    for(i1=0;i1<INT0_delays;i1++){
      Delay_ms(250);
    wdt_reset();
      }

    INT0_changed=0;

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

      dataByte = NodeID;

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

      sendCounterInc();
      dataByte |= sendCounter;

        send_Byte(dataByte);
      }
  }

    if(INT1_changed==1){
      if (INT1_is_Movement == 0){
        // entprellen
    for(i1=0;i1<INT1_delays;i1++){
        Delay_ms(250);
      wdt_reset();
        }

      INT1_changed=0;

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

        dataByte = NodeID;
        dataByte |= (1<<2);

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

        sendCounterInc();
        dataByte |= sendCounter;

          send_Byte(dataByte);
        }
      }else{
        INT1_changed=0;

      if(Movement_Timer == Movement_Timer_max){
          Movement_Timer = 0;

        dataByte = NodeID;
        dataByte |= (1<<2);

        sendCounterInc();
        dataByte |= sendCounter;

          send_Byte(dataByte);
        }
    }
  }

    set_sleep_mode(SLEEP_MODE_IDLE);
  sleep_enable();

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

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

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

  sleep_cpu();
  sleep_disable();
  };
}


Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaub es hackt...

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Du meinst die Fuses sind falsch eingestellt? ;-)

Sebastian

Autor: Marcel Papst (phpmysqlfreak)
Datum:

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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ISR (SIG_INTERRUPT1)
{
  uint8_t tmp_sreg;

  tmp_sreg = SREG;

  asm("cli");

  INT1_changed=1;

  // muss drin bleiben!
//  LED1_ON();
//  Delay_ms(1);
//  LED1_OFF();

  asm("sei");

  SREG = tmp_sreg;
}

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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Marius Wensing (mw1987)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Route_66 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.