ADC/Timer läuft nicht zusammen

Gast #2848917
Lesenswert?

Hallo zusammen,

Habe ein kleines Problem meinen Timer sowie meinen ADC zusammen laufen 
zu lassen. Also Timer alleine läuft. Genauso wie der ADC...jedoch wenn 
Ich beide laufen lassen will, kommt komischerweise nur der Timer. Der 
ADC wandelt dann dummerweise nicht mehr!?

Hat da jemand einen Rat?

Grüße Martin
Gast #2848919
Lesenswert?

//---------------------------------------------------------------------- 
-----------------------------
//            Interrupt Service Routine --> AD - Converter
//---------------------------------------------------------------------- 
-----------------------------

ISR(ADC_vect)
{

  uint8_t AD_LOW;
  uint8_t AD_HIGH;

  ADCSRA |= (0<<ADIE);        // Disable ADC Interrupt

      if (ADC_Active_Channel == 6)
      {
        ADC_Active_Channel = 0;
      }

        switch(ADC_Active_Channel)
        {
            case 0:break;  // ADC0 unused
            case 1:break;  // ADC1 unused
            case 2:break;  // ADC2 unused

            case 3:
                LEM_Result = ADCW;
            break;

            case 4:
                //VD_Output_Result = ADCW;
                AD_LOW = ADCL;
                AD_HIGH = ADCH;
                PORTD = AD_LOW;
            break;

            case 5:
                VD_Input_Result = ADCW;
            break;

            default:break;
        }


            ADC_Active_Channel++;
            ADMUX = (0b11111111 & ADC_Active_Channel);  // Set next 
channel

      ADCSRA |= (1<<ADIE);  // Enable
      ADCSRA |= (1<<ADSC);  // Start Conversion
}
Gast #2848920
Lesenswert?

int main(void)
{

  /***** Ports ******/ //0 = Input ; 1 = Output

  // The Port B Data Direction Register
  DDRB  |= (1<<PB2)|(1<<PB1);
  DDRC  |= (0<<PC5)|(0<<PC4)|(0<<PC3); 
//|(0<<PC2)|(0<<PC1)|(0<<PC0);
  DDRD  |= 
(1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0);


  /***** Timer *****/
  //---------------------------------------------------------------------- 
-------------------------------------------------

  Inital_Timer = 34;

  TCCR1A |= (1<<WGM11)|(0<<WGM10);
  TCCR1B |= (1<<WGM13)|(0<<WGM12);
  TCCR1B |= (0<<CS12)|(0<<CS11)|(1<<CS10);

  ICR1H = 00;
  ICR1L = 136;

  TCCR1A |= (1<<COM1A1)|(0<<COM1A0);
  TCCR1A |= (1<<COM1B1)|(1<<COM1B0);

  OCR1AH = 00;
  OCR1AL = Inital_Timer;

  OCR1BH = 00;
  OCR1BL = (Inital_Timer + 5);

  TIMSK1 |= (1<<ICIE1);
  TIMSK1 |= (1<<OCIE1B);
  TIMSK1 |= (1<<OCIE1A);
  TIMSK1 |= (1<<TOIE1);


  /***** AD Converter *****/
  //---------------------------------------------------------

  ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);
  // 8MHz / 64 = 125kHz || 110 = 64

  ADMUX  |= (0<<REFS1)|(1<<REFS0);
  ADMUX  |= (0<<ADLAR);

  ADC_Active_Channel = 0;
  ADMUX = (0b11111111 & ADC_Active_Channel);

  //ADCSRB |= (0<<ACME)|(1<<ADTS2)|(1<<ADTS1)|(0<<ADTS0);  // Timer.1 
Overflow

  //ADCSRA |= (0<<ADATE);
  ADCSRA |= (1<<ADEN);    // ADC Enable
  ADCSRA |= (1<<ADSC);    // Start Single Conversion
  ADCSRA |= (1<<ADIE);    // Enable ADC Interrupt

  sei();  // set all Interrupts free

  while(1)
  {
    //state_Machine();
    //change_States();
  }

  return(0);
}
Gast #2848941
Lesenswert?

Thomas Eckmann schrieb:
>> ADCSRA |= (0<<ADIE);        // Disable ADC Interrupt
> Was erwartest du denn davon?

Davon würde Ich erwarten das der AD Wandler in dieser Zeit bis das ADIE 
bit wieder 1 gesetzt wird nicht mit ner neuen Wandlung beginnt. In 
dieser Zeit schreibe Ich mein Ergebnis der Wandlung aus dem 
Datenregister.

Thomas Eckmann schrieb:
>> ADMUX = (0b11111111 & ADC_Active_Channel);
> Oder davon?

Den Multiplexer auf den nächsten Kanal umstellen...

Das es nicht funktioniert habe Ich ja auch schon erwähnt. Aber Merci für 
den Link...
#2848965
Lesenswert?

Martin28 schrieb:
> 0b11111111 & ADC_Active_Channel
ADC_Active_Channel = 0;

 1111 1111
&0000 0000
=0000 0000
Damit stellst du MUX auf 0 und schaltest die Referenz auf AREF, also 
extern.

Du darfst im Register nur die Mux-Bits verändern.

Martin28 schrieb:
> ADCSRA |= (0<<ADIE);
Das verändert gar nichts. Wenn du etwas mit 0 ODER-verknüpfst, ändert 
sich der Wert nicht. Das ist ja auch der "Trick", mit dem man ein 
einzelnes Bit setzt.
 0101 0101
|0000 0010
=0101 0111
        ^

Wenn das "ADCSRA |= (0<<ADIE)" so wie du dir das vorstellst 
funktionieren würde, wäre das Ergebnis dieses Beispiels aber
 0000 0000

Arbeite den Link intensiv durch. Das ist elementar. Im Moment 
interpretierst du diesen Quatsch (XYZ |= (0 << ABC), den man leider 
andauernd sieht, auch noch vollkommen falsch.

mfg.
Gast #2851315
Lesenswert?

Habe das mit dem umstellen des Multiplexers geändert.

Sieht jetzt so aus:

ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F);

Die übrigen ISR Routinen wie oben erwähnt eingebaut:
(zur Vollständigkeit) damit kein Softreset durchgeführt wird.

ISR(TIMER1_CAPT_vect
{
  TIFR1 |=(1<<ICF1);
}

ISR(TIMER1_COMPA_vect)
{
  TIFR1 |=(1<<OCF1A);
}

ISR(TIMER1_COMPB_vect)
{
  TIFR1 |=(1<<OCF1B);
}

ISR(TIMER1_OVF_vect)
{
  TIFR1 |=(1<<TOV1);
}

Aber komischerweise laufen die immer noch nicht zusammen...wo könnte 
noch eine Fehlerquelle sein?

Bin hier grad bisschen am verzweifeln

Grüße Martin
#2851382
Lesenswert?

Wenn du vernünftige Hilfe willst, dann poste den ganzen Code. 
Vollständig.

Wir können uns natürlich noch 25 andere Szenarien ausdenken, was in 
deinem Code noch alles schief gegangen sein könnte. Einfacher ist es 
aber für dich und für uns, wenn du ganz banal dein C-File nimmst und als 
Anhang anhängst.
#2851385
Lesenswert?

Aber mal ein Schnellschusss
1
  ADCSRA |= (1<<ADEN);    // ADC Enable
2
  ADCSRA |= (1<<ADSC);    // Start Single Conversion
3
  ADCSRA |= (1<<ADIE);    // Enable ADC Interrupt

Ich würde das mal aus logischen Gründen umdrehen.
Erst den ADC einschalten
dann den ADC konfigurieren
und erst dann, wenn eingeschaltet und konfiguriert ist, erst dann starte 
ich den ADC.

Ich weiß nicht, ob es was ändert. Aber es wäre zumindest erst mal DIE 
logische Reihenfolge der Ereignisse. Und im Zweifelsfall hat es sich 
noch immer bewährt, wenn man sich erst mal daran hält.
Gast #2851392
Lesenswert?

int main(void)
{

  /***** Ports ******/ //0 = Input ; 1 = Output

  // The Port B Data Direction Register
  DDRB  |= (1<<PB2)|(1<<PB1);
  DDRC  |= (0<<PC5)|(0<<PC4)|(0<<PC3);
  DDRD  |= 
(1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0);


  /***** Timer *****/
  //---------------------------------------------------------------------- 
------------

  Inital_Timer = 17;

  TCCR1A |= (1<<WGM11)|(0<<WGM10);
  TCCR1B |= (1<<WGM13)|(0<<WGM12);
  TCCR1B |= (0<<CS12)|(0<<CS11)|(1<<CS10);

  ICR1H = 00;
  ICR1L = 69;

  TCCR1A |= (1<<COM1A1)|(0<<COM1A0);
  TCCR1A |= (1<<COM1B1)|(1<<COM1B0);

  OCR1AH = 00;
  OCR1AL = Inital_Timer;

  TIMSK1 |= (1<<ICIE1);
  TIMSK1 |= (1<<OCIE1B);
  TIMSK1 |= (1<<OCIE1A);

  /***** AD Converter *****/
  //---------------------------------------------------------------------- 
-----------

  ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);      /
  // 8MHz / 64 = 125kHz || 110 = 64

  ADMUX  |= (0<<REFS1)|(1<<REFS0);
  ADMUX  |= (0<<ADLAR);

  ADC_Active_Channel = 0;
  ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F);


  //ADCSRB |= (0<<ACME)|(1<<ADTS2)|(1<<ADTS1)|(0<<ADTS0);  // Timer.1 
Overflow

  ADCSRA |= (1<<ADEN);    // ADC Enable
  ADCSRA |= (1<<ADSC);    // Start Single Conversion
  ADCSRA |= (1<<ADIE);    // Enable ADC Interrupt

  sei();  // set all Interrupts free

  while(1)
  {
    // state_Machine();
    // change_States();
  }

  return(0);
}
Gast #2851393
Lesenswert?

//---------------------------------------------------------------------- 
-----------------------------
//            Interrupt Service Routine --> AD - Converter
//---------------------------------------------------------------------- 
-----------------------------

ISR(ADC_vect)
{

    /*  if (ADC_Active_Channel == 6)
      {
        ADC_Active_Channel = 0;
      }
    */
        switch(ADC_Active_Channel)
        {
            case 0:break;  // ADC0 unused
            case 1:break;  // ADC1 unused
            case 2:break;  // ADC2 unused

            case 3:
                //LEM_Result = ADCW;
                  AD_LOW = ADCL;
                  AD_HIGH = ADCH;
                  PORTD = AD_LOW;
            break;

            case 4:
                VD_Output_Result = ADCW;
            break;

            case 5:
                VD_Input_Result = ADCW;
            break;
            /*
            AD_LOW = ADCL;
            AD_HIGH = ADCH;
            PORTD = AD_LOW;
            */
            default:break;
        }

      ADCSRA |= (1<<ADSC);  // Start Conversion
}


//---------------------------------------------------------------------- 
-----------------------------
//            Interrupt Service Routine --> Timer.1
//---------------------------------------------------------------------- 
-----------------------------

ISR(TIMER1_CAPT_vect)
{
  TIFR1 |=(1<<ICF1);
}

ISR(TIMER1_COMPA_vect)
{
  TIFR1 |=(1<<OCF1A);
}

ISR(TIMER1_COMPB_vect)
{
  TIFR1 |=(1<<OCF1B);
Gast #2851415
Lesenswert?

Manchmal sieht man den Wald vor lauter Bäumen nicht!!!

ISR(ADC_vect)
{

    /*  if (ADC_Active_Channel == 6)
      {
        ADC_Active_Channel = 0;
      }
    */
        switch(ADC_Active_Channel)
        {
            case 0:break;  // ADC0 unused
            case 1:break;  // ADC1 unused
            case 2:break;  // ADC2 unused

            case 3:
                //LEM_Result = ADCW;
                  AD_LOW = ADCL;
                  AD_HIGH = ADCH;
                  PORTD = AD_LOW;
            break;

            case 4:
                VD_Output_Result = ADCW;
            break;

            case 5:
                VD_Input_Result = ADCW;
            break;
            /*
            AD_LOW = ADCL;
            AD_HIGH = ADCH;
            PORTD = AD_LOW;
            */
            default:break;
        }

      ADC_Active_Channel++;
      ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F);

      ADCSRA |= (1<<ADSC);  // Start Conversion
}

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