www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega88 - ADC - free running mode


Autor: Schmidt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ihr Lieben

ich möchte den ADC im ATmega88 im Free running Modus betreiben, aber es 
geling mir nicht. Bei der Simulation mit AVR-Studio wird beim ADC-Enable 
einmal das ADC-Interrupt bei fertiger Messung aufgerufen und dann nicht 
mehr. Er scheint nicht im Freerunning mode zu sein. Ich habe das 
Datenblatt Stück für Stück abgearbeitet. Irgend etwas muss ich übersehen 
haben oder ich mache eine groben Fehler.

Vielleicht sieht einer von euch den Fehler und kann mir helfen. Vielen 
Dank.
///[...]
/* ADC */
#define ADC_PRESCALER 2

//[...]
/* DataPins */
#define PIN_DATAIN (1<<PC4)
#define PIN_DATAOUT (1<<PC5)

/* DisplayPins */
#define PIN_OUTERDSPL (1<<PD1)
#define PIN_INNERDSPL (1<<PD0)

/* TasterPins */
#define PIN_TASTER1 (0<<PD0)

#define DEBUG
#define ADCTEST



#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include "timer1/timer1.c"
#include "adc/adc.c"
#include "io/io.c"
//#include <util/delay.h>


int main (void) {

  /* Initialisation */

    /* DataOUT/IN */
      DDRC |= PIN_DATAOUT; //Define Pin as Output
      DDRC &= ~PIN_DATAIN; //Define Pin as Input
    
      //DDRB = 0b11111111; //Set all Pins as Output
      //PORTB = 0b00000000;
  
    /* DisplayOUT */
      DDRD |= PIN_OUTERDSPL; //Define Pin as Output
      DDRD |= PIN_INNERDSPL; //Define Pin as Output

      #ifdef DEBUG
        DDRD |= (1<<PD3)|(1<<PD4); //Define Pin as Output
      #endif
  
    /* Taster */
    
    /* Timer */
//      Timer1_init();
  
    /* ADC */
      ADC_init();
      ADC_SetChannel(7);

  /* END Initialisation */
  
  /* Referenzwerte Messen */
    sei(); //Global Enable Interrupts
    //messen
    //auswerten
    //messen
    //auswerten
    

  ADC_Enable();
  ADC_StartConversion();


    while(1) {
    if( (PINC & PIN_DATAIN) != PIN_DATAIN ){ //Wenn low
      PORTD |= PIN_OUTERDSPL;
    }else{
      PORTD &= ~PIN_OUTERDSPL;
    }

    //ADC-Werte Berechnen;
  }

  return 0;
}



//[...]

ISR(ADC_vect){
  #ifdef DEBUG
    PORTD |= (1<<PD3);
  #endif
  
  /* ADC Conversion Complete Interrupt */
  //Messdaten speichern
  ADC_GetHData();

  #ifdef DEBUG
    PORTD &= ~(1<<PD3);
  #endif
}

adc.c:
#include <stdint.h>

void ADC_init(void){
  /* Voltage Reference for the ADC: */
    ADMUX |= (0<<REFS1) | (0<<REFS0); //AREF, Internal Vref turned off
    //ADMUX |= (0<<REFS1) | (1<<REFS0); //AVcc with external capacitor at AREF pin
    //ADMUX |= (1<<REFS1) | (1<<REFS0); //Internal 1.1V Voltage Reference with external capacitor at AREF pin
  
  
  /* ADC Left Adjust Result: */
    ADMUX |= (1<<ADLAR); //Write one to left adjust the result. Otherwise, the result is right adjusted.
  
  
  /* ADC Control and Status Register A: */
    /* ADC Auto Trigger Enable: */
    ADCSRA |= (1<<ADATE); //When this bit is written to one, Auto Triggering of the ADC is enabled. The ADC will start a conversion on a positive edge of the selected trigger signal. The trigger source is selected by setting the ADC Trigger Select bits, ADTS in ADCSRB.
    
    /* ADC Interrupt Flag */
  
    /* ADC Interrupt Enable */
    ADCSRA |= (1<<ADIE);  //When this bit is written to one and the I-bit in SREG is set, the ADC Conversion Complete Interrupt is activated.
  
    /* ADC Prescaler Select Bits */
  #ifndef ADC_PRESCALER
    #define ADC_PRESCALER 128
  #endif
  #if ADC_PRESCALER == 2
    ADCSRA |= (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); //Division Factor: 2
  #elif ADC_PRESCALER == 2
    ADCSRA |= (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0); //Division Factor: 2
  #elif ADC_PRESCALER == 4
    ADCSRA |= (0<<ADPS2) | (1<<ADPS1) | (0<<ADPS0); //Division Factor: 4
  #elif ADC_PRESCALER == 8
    ADCSRA |= (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); //Division Factor: 8
  #elif ADC_PRESCALER == 16
    ADCSRA |= (1<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); //Division Factor: 16
  #elif ADC_PRESCALER == 32
    ADCSRA |= (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0); //Division Factor: 32
  #elif ADC_PRESCALER == 64
    ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0); //Division Factor: 64
  #else
    ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); //Division Factor: 128
  #endif
  
  /* ADC Control and Status Register B: */
    /* ADC Auto Trigger Source */
    ADCSRB |= (0<<ADTS2) | (0<<ADTS2) | (0<<ADTS2); //Trigger Source: Free Running mode
    //ADCSRB |= (0<<ADTS2) | (0<<ADTS2) | (1<<ADTS2); //Trigger Source: Analog Comparator
    //ADCSRB |= (0<<ADTS2) | (1<<ADTS2) | (0<<ADTS2); //Trigger Source: External Interrupt Request 0
    //ADCSRB |= (0<<ADTS2) | (1<<ADTS2) | (1<<ADTS2); //Trigger Source: Timer/Counter0 Compare Match A
    //ADCSRB |= (1<<ADTS2) | (0<<ADTS2) | (0<<ADTS2); //Trigger Source: Timer/Counter0 Overflow
    //ADCSRB |= (1<<ADTS2) | (0<<ADTS2) | (1<<ADTS2); //Trigger Source: Timer/Counter1 Compare Match B
    //ADCSRB |= (1<<ADTS2) | (1<<ADTS2) | (0<<ADTS2); //Trigger Source: Timer/Counter1 Overflow
    //ADCSRB |= (1<<ADTS2) | (1<<ADTS2) | (1<<ADTS2); //Trigger Source: Timer/Counter1 Capture Event
        
  /* Digital Input Disable Register 0: */
        
}

void ADC_SetChannel(uint8_t channel){
  if(0<= channel && channel <= 7){
    /* ADC Multiplexer Selection Register */
      //ADMUX |= (0<<MUX3) | (1<<MUX2) | (1<<MUX1) | (1<<MUX0);
      ADMUX |= channel;
  }
}

void ADC_Enable(void){
  /* ADC Control and Status Register A */
  ADCSRA |= (1<<ADEN); //Writing this bit to one enables the ADC. By writing it to zero, the ADC is turned off. Turning the ADC off while a conversion is in progress, will terminate this conversion.
}

void ADC_Disable(void){
  /* ADC Control and Status Register A */
  ADCSRA &= ~(1<<ADEN); //Writing this bit to one enables the ADC. By writing it to zero, the ADC is turned off. Turning the ADC off while a conversion is in progress, will terminate this conversion.
}

void ADC_StartConversion(void){
  /* ADC Control and Status Register A */
  ADCSRA |= (1<<ADSC); //In Single Conversion mode, write this bit to one to start each conversion. In Free Running mode, write this bit to one to start the first conversion.
}

uint8_t ADC_GetHData(void){
  /* ADC Data Register - Highbyte*/
  return ADCH;
}




Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielleicht den ADMUX mal auf 0 setzen und nicht immer bloss die Bits 
rein odern?

Autor: Schmidt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

ich verstehe nicht ganz was du meinst. Standart-Anfanagswert von ADMUX 
ist 0. Ich oder dann Einsen hinein, wenn nötig. (Übersichtshalber oder 
ich manchmal auch Nullen hinein, aber das ist ja gleichgültig)

Ist irgendwo ein Fehler, oder ein potenzieller Fehler?

Welchen Teil genau meinst du? Die MUX-Kanalwahl?

Danke dir.

Autor: Günter Jung (gjung)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wenn Du Bits auf 0 setzen willst, dann must Du ein
AND mit dem Komplement machen, ein OR mit 0 ist ein NOP.

siehe
ADMUX |= (0<<REFS1) | (0<<REFS0);
und ähnliche Zeilen.

Also richtig wäre:
ADMUX &= ~((1<<REFS1) | (1<<REFS9));

Gruß,
Günter

Autor: Schmidt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank.

Ja, ich weiß, dass so keine Bits gelöscht werden.
ADMUX |= (0<<REFS1) | (0<<REFS0);

Da das Register as Defaultwert mit Nullen initialisiert ist, wäre das 
Löschen überflüssig.Somit die Zeilen auch überflössig. Ich habe die 
Zeilen des Verständnisses und der Übersicht wegen trotzdem 
hingeschrienen. Aber ihr habt recht, sicher ist sicher, ich werde es 
ändern.

Die Register bits haben also trotzdem die gewünschten Werte gehabt und 
der Free running mode lässt auf sich warten.

Habt ihr eine Idee, weshalb der ADC nicht losrennen will?

Ich vermute stark, dass es an einem Fehler im Code liegt und kein bug 
des AVR-Studio-Simulators ist. Aber mit gewissheit kann ich es natürlich 
nicht sagen.

Ich wäre euch sehr dankbar.

Schmidt

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schmidt schrieb:
> Ich vermute stark, dass es an einem Fehler im Code liegt und kein bug
> des AVR-Studio-Simulators ist. Aber mit gewissheit kann ich es natürlich
> nicht sagen.
Du könntest im AVR Studio mal unter den Bekannten Einschränkungen 
nachsehen...

Ansosnten hatte ich auch mal das Problem das im Freerunning Mode das 
interuptbit nicht automatisch von der HW zurückgesezt wurde.

Autor: Schmidt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für den Hinweis mit dem ADC Interupt Flag.

Folgendes habe ich festgestellt:

Nach einem ADC Start Conversation (ADSC = 1) startet eine Messung.
Nach der Messung wird und bleibt das ADSC Flag aber gelöscht.
Wenn ich es im Simulator wieder auf ADSC=1 setzte, dann tritt wieder 
eine Messung ein. ADSC wird aber immer wieder nach der Messung gelöscht. 
Laut Datenblatt sollte es (ich hoffe ich irre mich nicht) im Free 
Running Mode jedoch auf 1 bleiben.

Das ADC Interrupt Flag (ADIF wird laut Anzeige im Simulator garnicht 
gesetzt. Vielleicht wird es nur nicht angezeigt, wer weiß. Scheint 
jedoch kein Problem darzustellen.)

So, nun haben wir erkannt, woran es scheinbar liegt. Das ADSC wird nach 
der Messung gelöscht.

Nun bleibt die Frage WARUM?

Ist das Problem jemandem bekannt? Lösungsidee? Habe ich etwas falsch 
eingestellt?

Danke.

Autor: Jean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich würde das mal auf deinem µC testen und nicht nur im Avr-Studio.
Da gibt es genug Bugs im Studio.

Gruß

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.