ADC/Timer läuft nicht zusammen

Gast #2848917
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
//---------------------------------------------------------------------- 
-----------------------------
//            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
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
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...
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
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
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.
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
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
//---------------------------------------------------------------------- 
-----------------------------
//            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
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
}
Gast
ADC_Active_Channel++;
ADMUX = (ADMUX & ~(0x1F)) | (ADC_Active_Channel & 0x1F);

Komischerweise hatte Ich das rausgelöscht...Fehler gefunden!

Läuft jetzt!

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.