Forum: Compiler & IDEs ADC Free Running (nur 1x)


von Anfänger_Tobias (Gast)


Lesenswert?

Hi,

ich bekomm den ADC einfach nicht in den Free Running mode bzw. erhalte 
ich keine INterrupts mehr. Im Datenblatt hab ich nichts gefunden und in 
der Suche nru 1 das aber kein wirklicher Free Running Mode ist (Timer 
interrupt startet ADC).

Ich verwende AVR Studio 4.18 mit WinAVR 20100110
Mein µC ist ein ATtiny 25

Ich möchte das der ADC dauernd läuft, nach jeder Wandlung möchte ich den 
ADC Wert auslesen und abhängig davon "etwas" tun.
Mit meinem momentanen Programm wird der Interrupt nur 1 mal ausgeführt.

Ist mit dem Interrupt was falsch oder mti dem Free Running Mode? Und was 
ist falsch..

MfG
Tobais

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

volatile uint16_t ADC_wert;

ISR(ADC_vect)
{  ADC_wert = ADCW;
}

int main(void)
{  SREG  |=  (1<<7);    //Global Interrupt enable
  DDRB  &=  ~(1<<PB3);  //PB3 als Eingang
  DDRB  |=  ((1<<PB0) | (1<<PB1));  //PB0 & PB1 als Ausgang

  ADMUX  |= ((1<<REFS2) | (1<<REFS1) |  (1<<MUX1) | (1<<MUX0));
  ADMUX  &= ~((1<<REFS0) | (1<<ADLAR) | (1<<MUX3) | (1<<MUX2));
  ADCSRA  |= ((1<<ADEN) | (1<<ADATE) | (1<<ADIE));

  ADC_wert = 0;
  ADCSRA  |= (1<<ADSC);  //Start des AD-Wandlers
  while(1)
  {
    //etwas tun
  }
  return 0;
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Das Bitgewurschtel ist zwar bissel undurchsichtig (wenn du ein
Register initial beschreibst, lohnt sich |= bzw. &= ~ nicht wirklich,
denn du kannst stattdessen das ganze Register auf einmal zuweisen),
aber funktionieren sollte das.

SREG  |=  (1<<7) heißt übrigens besser sei(). Steht in
<avr/interrupt.h>, die du für die ISR sowieso einbinden musst.

von Anfänger_Tobias (Gast)


Lesenswert?

Hi,

danke für die Hinweise.
Allerdings habe ich bei einem anderen Beitag den Tip bekommen es so zu 
machen mit den Registern. Bisher hab ich immer 0xYY geschrieben.

Die <avr/interrupt.h> hab ich eingebunden und wenn ich sei() anstelle 
SREG  |=  (1<<7) schreibe bleibt mein Problem bestehen!

MfG
Tobias

von Anfänger_Tobias (Gast)


Lesenswert?

Ich meine herausgefunden zu haben, dass es nicht an den Interrupts liegt 
sondern an dem Free Running Mode.
Wenn ich es so schreibe

ISR(ADC_vect)
{
  ADC_wert = ADCW;
  ADCSRA  |= (1<<ADSC);
}

funktioniert es. Allerdings würde es mich trotzdem interessieren warum 
es nicht geht mit dem Free Running Mode.

MfG
Tobias

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

Hi

nimm das 1<<ADATE raus damit lässt du den ADC auf eine nicht 
eingestellte Trigger Quelle warten.

dann sollte das laufen


PS: das Löschen von Bits die im Reset zustand eh 0 sind kannst du dir 
sparen, löscht der Compiler eh.

MfG

Tec

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Anfänger_Tobias schrieb:

> Allerdings habe ich bei einem anderen Beitag den Tip bekommen es so zu
> machen mit den Registern. Bisher hab ich immer 0xYY geschrieben.

Das solltest du ja auch nicht tun. ;-)

Einfacher wäre halt nur:
1
  DDRB  =  ((1<<PB0) | (1<<PB1));  // PB0 & PB1 als Ausgang, alles andere
2
                                   // ist Eingang
3
4
  // 2.56 V reference without external bypass,
5
  // ADC3 (aka. PB3) single-ended input
6
  ADMUX  = ((1<<REFS2) | (1<<REFS1) |  (1<<MUX1) | (1<<MUX0));
7
  // enable ADC in free-running mode with interrupts, prescaler 2
8
  ADCSRA  = ((1<<ADEN) | (1<<ADATE) | (1<<ADIE));

> Die <avr/interrupt.h> hab ich eingebunden und wenn ich sei() anstelle
> SREG  |=  (1<<7) schreibe bleibt mein Problem bestehen!

Das war auch nicht zu erwarten, dass sich davon was ändert, davon
wird lediglich das I-Bit zwei Takte schneller eingeschaltet, aber
der Gesamteffekt bleibt natürlich der gleiche.

Was mir beim Durchgucken der Registerbits noch aufgefallen ist ist,
dass du den ADC mit einem Taktteiler von nur 1:2 betreibst.  Das
ist selbst bei 1 MHz CPU-Takt schon jenseits des empfohlenen Bereichs
(aber tolerierbar, wenn du nur 8 Bit Genauigkeit haben willst),
bei 8 MHz ist es aber jenseits von gut und böse.  Ich würde zwar
denken, dass der ADC trotzdem noch wandelt und Interrupts generieren
sollte (also nicht etwa fest geht), halt nur Schrott wandelt.
Trotzdem solltest du nochmal nachgucken, ob du nicht einen anderen
Wert für den Prescaler brauchst.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Tec Nologic schrieb:

> nimm das 1<<ADATE raus damit lässt du den ADC auf eine nicht
> eingestellte Trigger Quelle warten.

Das ist, mit Verlaub, Unsinn.  Wenn man nichts an ADCSRB ändert, ist
die voreingestellte Triggerquelle für den auto-trigger-Modus der
free running mode.

> PS: das Löschen von Bits die im Reset zustand eh 0 sind kannst du dir
> sparen, löscht der Compiler eh.

Nicht der Compiler, sondern der Controller, und zwar bei einem
Hardware-Reset.

von Anfänger_Tobias (Gast)


Lesenswert?

Hi,

danke für den Tip mit dem Prescaler, ich hatte zuvor einen 128kHz Takt, 
deshalb hatte ich keinen Prescaler benötigt. Jetzt hab ich aber Default 
8MHz mit Teiler 1/8 als 1MHz.

Ich hab den Code soweit überarbeitet, allerdings funktioniert der free 
running Mode noch immer (im Debugger!) nicht.

MfG
Tobias

Hier der überarbeitete Code:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

ISR(ADC_vect)
{  if(ADCW>0x00FF) ADC_wert = 0xFF;
  else ADC_wert = ADCW & 0x00FF;
}
ISR(TIM0_OVF_vect)
{  OCR0A = OCR0A_wert;
}

int main(void)
{  sei();        //Global Interrupt enable
  DDRB  =  (1<<PB0);  //PB0 als Ausgang der PWM

  //ADC PB3, 2,56V, Autotrigger, Inerrupt Enable, f/16,
  ADMUX  = ((1<<REFS2) | (1<<REFS1) |  (1<<MUX1) | (1<<MUX0));
    ADCSRA  = ((1<<ADEN) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2));
  ADCSRB = 0;

  //PWM PB0, non inverted PWM, fast PWM, Interrupt Enable, f,
  GTCCR  = ((1<<TSM) | (1<<PSR0));
  TCCR0A  = ((1<<COM0A1) | (1<<WGM01) | (1<<WGM00));
  TCCR0B  = (1<<CS00);
  TIMSK  = (1<<TOIE0);

  ADCSRA  |= (1<<6);  //Start des AD-Wandlers
  GTCCR  &= ~(1<<TSM);  //Start des Timers
  while(1)
  {//CODE
  }
  return 0;
}

von Anfänger_Tobias (Gast)


Lesenswert?

Der Code ist für den Beitrag gekürzt, die
volatile uint8_t ADC_wert;
volatile uint8_t OCR0A_wert;
hab ich aus Versehen auch weg gekürzt. Im vollständigen Code sind sie 
enthalten!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Ich habe deinen Quellcode genommen, noch ein
1
  OCR0A_wert = ADC_wert / 2;

in die ADC-ISR reingebaut (damit irgendwo auch was passiert), dann
für einen ATtiny25 compiliert, aber in einen ATtiny85 geflasht.
Hatte gerade nur einen '85 als DIP herumliegen, den man bequem in
einen STK500 stöpseln kann.  In dieser Richtung sind die Controller
aber tatsächlich binärkompatibel.

Dann habe ich 1,3 kHz Sinus an den ADC-Eingang gelegt.  Oszillogramm
liegt bei, ich denke, es ist klar, dass der free running mode ganz
prima funktioniert. ;-)

von Anfänger_Tobias (Gast)


Lesenswert?

Wow, Danke für die Mühe...

Dann würde ich behaupten, dass der AVR Debugger das nicht kann, aber der 
µC schon...

MfG
Tobias

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Anfänger_Tobias schrieb:
> Dann würde ich behaupten, dass der AVR Debugger das nicht kann, aber der
> µC schon...

Debugger oder Simulator?

Der Simulator sollte für den Digitalteil eigentlich brauchbar sein
mittlerweile (so du den "V2"-Simulator im AVR Studio benutzt), dem
würde ich nur bei den Analoggeschichten nicht übern Weg trauen.
Das reine Abtasten des ADC ist aber komplett digital und sollte
damit sogar im Simulator funktionieren, alles andere wäre ein Bug.
Irgendwo in den Untiefen des AVR Studio müsste es aber eine
Beschreibung geben, was im Simulator alles nicht ordentlich
funktioniert, kannste ja mal suchen.  (Ich habe hier kein Windows
und damit auch kein AVR Studio, sorry.)

Bitte schreib beim nächsten Mal aber dazu, dass du deine Erkenntnis
nur aus einer Simulation gewonnen hast, das ist nicht unwichtig.
Außerdem solltest du dir mal bitten ansehen, wie man C-Code im Forum.

von Anfänger_Tobias (Gast)


Lesenswert?

Hi,

ähm ok, ich mein natürlich Simulator und ich verwende nicht den 
Simulator2, werd ich aber dann jetzt mal ausprobieren.

Das mit dem nicht unwichtig hab ich mir gedacht, deshalb habe ich 
geschrieben:
"Ich hab den Code soweit überarbeitet, allerdings funktioniert der free
running Mode noch immer (im Debugger!) nicht."
Allerdings war da Debugger das falsche Wort, hätte Simulator heißen 
müssen.

Ich denk mit dem letzten nicht ganz vollständigen Satz wolltest du 
sagen, dass ich die Formatierung verwenden soll?!
1
#include formatierung
2
int main (void)
3
{
4
if(c-Code)
5
}

MfG
Tobias

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Anfänger_Tobias schrieb:

> ähm ok, ich mein natürlich Simulator und ich verwende nicht den
> Simulator2, werd ich aber dann jetzt mal ausprobieren.

Hätte gar nicht gedacht, dass diese relativ neuen Teile überhaupt
noch vom alten Simulator unterstützt werden.

Ja, generell ist der V2-Simulator wohl ein 1:1-Abbild der Digital-
logik, wie sie im AVR tatsächlich implementiert worden ist, d. h.
der ist auf automatischem Weg aus der IC-Beschreibung abgeleitet.
Damit sollte er taktzyklengenau den Digitalteil des ICs wider-
spiegeln.

> Allerdings war da Debugger das falsche Wort, hätte Simulator heißen
> müssen.

Ja, den Debugger kann man auch zusammen mit einem Emulator
benutzen, um am "lebenden Objekt" zu debuggen.

> Ich denk mit dem letzten nicht ganz vollständigen

'tschuldigung.

> Satz wolltest du
> sagen, dass ich die Formatierung verwenden soll?!

Ja.

von Anfänger_Tobias (Gast)


Lesenswert?

Verdammt, unwissenheit schützt echt nicht vor Strafe, hätte ich gleich 
das mti dem Simulator gesagt, hätte ich den SImulator 2 verwendet und 
das Problem wäre sofort gelöst gewesen.
1
Simulator 2 kann den Free Running Mode!!
Danke für den Hinweis!!!

MfG
Tobias

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Anfänger_Tobias schrieb:
> Simulator 2 kann den Free Running Mode!!

Dann wär's ja jetzt Zeit für reale Hardware. ;-)

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
Noch kein Account? Hier anmelden.