Forum: Mikrocontroller und Digitale Elektronik ADC im Auto Trigger Mode mit Timer.0


von Martin28 (Gast)


Lesenswert?

Hallo zusammen,

Ich probiere schon seit einiger Zeit meinen AD-Wandler zum laufen zu 
bekommen. habe auch schon echt viel mit IR-Bit enable/disable 
rumprobiert, aber irgendwie läuft der net richtig. Nach Angaben im 
Datenblatt habe ich eigentlich alles richtig konfiguriert, aber der 
läuft leider immer noch nicht.

Habe hier mal ein Auszug meines programmes.
1
int main(void)
2
{
3
4
DDRC  |= (0<<PC5)|(0<<PC4)|(0<<PC3)||(0<<PC2)|(0<<PC1)|(0<<PC0); 
5
// AD-Channels  
6
7
DDRD |= (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0);
8
// LED´s
9
10
while(1)
11
  {        
12
       Init_Timer0();
13
       AD_INIT_Test();  
14
  
15
  }    
16
  
17
  return(0);
18
}
19
20
void AD_INIT_Test(void)
21
{
22
  
23
  ADMUX |= (0<<REFS1)|(1<<REFS0);
24
  ADMUX |= (0<<ADLAR);                
25
                            
26
  
27
  ADMUX |= (0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0);    // ADC - 5
28
  //ADMUX |= (0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(0<<MUX0);  // ADC - 4
29
  
30
  ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);
31
      
32
// Set ADC Scaler to 125KHz Sample rate @ 8MHz 
33
// 8MHz / 64 = 125kHz || 110 = 64
34
  
35
  
36
  //ADCSRA &= ~(1 << ADATE);          // Disable free running Mod
37
  
38
  //ADCSRB |= (0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);// 000 Free Running Mode
39
  ADCSRB |= (0<<ADTS2)|(1<<ADTS1)|(1<<ADTS0);// 011 Compare Match TIMER.0 
40
  //ADCSRB |= (1<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);// 100 --> Timer.0 Overflow
41
  ADCSRB |= (0<<ACME);                
42
43
  ADCSRA |= (1<<ADEN);                // ADC Enable 
44
  ADCSRA |= (1<<ADATE);               // Auto trigger Mode enabled
45
  //ADCSRA |= (1<<ADSC);              // Start Single Conversion
46
  
47
  while (ADCSRA & (1<<ADSC))          // Wait for result
48
  {}
49
    
50
  PORTD = ADCL;                       // Write result on Port.D --> LED   
51
            
52
  ADCSRA |= (1<<ADIE);                // Enable ADC Interrupt
53
}
54
55
56
57
ISR(ADC_vect)
58
{   
59
     
60
   ADCSRA &= ~(1<<ADIE);     // Disable ADC Interrupt --> Stop
61
   ADCSRA |= (1 << ADIE);    // Enable ADC Interrupt
62
   ADCSRA |= (0 << ADIF);     // Reset Interrupt Flag
63
   
64
    // ADCSRA |= (1 << ADSC);  // Start single conversion
65
}
66
67
void Init_Timer0(void)
68
{
69
  
70
  
71
  TCCR0A |= (0<<WGM02)|(1<<WGM01)|(1<<WGM00);    // Fast PWM Mode
72
  TCCR0A |= (1<<COM0A1)|(0<<COM0A0);   // clear OC0A @ Compare Match 
73
  
74
    TCCR0B =  (1<<CS02)|(0<<CS01) |(1<<CS00);      
75
// Clock Division: clk/1024 --> 8.MHz / 1024 = 7812.5 Hz / 255 = 30Hz 
76
                         
77
                            
78
  TIMSK0|= (1<<OCIE0A);                // Enable Output Compare Flag
79
  TIMSK0|= (1<<TOIE0);                // Enable Overflow Flag
80
81
  OCR0A = 1;                      // shortest edge width   
82
}
83
84
85
86
//--------------------------------------------------------------------------------------------------------------------
87
// ISR Timer.0
88
//--------------------------------------------------------------------------------------------------------------------
89
90
91
ISR(TIMER0_COMPA_vect)
92
{
93
  // clear Compare Flag
94
  
95
  TIFR0 = (0<<OCF0A);
96
  
97
}
98
99
ISR(TIMER0_OVF_vect)
100
{
101
  // clear Overflow Flag
102
  
103
  TIFR0 = (0<<TOV0);    
104
  
105
}

von Karl H. (kbuchegg)


Lesenswert?

Martin28 schrieb:
> Hallo zusammen,
>
> Ich probiere schon seit einiger Zeit meinen AD-Wandler zum laufen zu
> bekommen. habe auch schon echt viel mit IR-Bit enable/disable
> rumprobiert, aber irgendwie läuft der net richtig.

Wie wärs, wenn du den erst mal konventionell, zb laut 
AVR-GCC-Tutorial zum Laufen bringst.

In deinem Code sind so viele Stolpersteine, dass man gar nicht weiß, wo 
man anfangen soll mit der Korrektur.

> int main(void)
> {
>
> DDRC  |= (0<<PC5)|(0<<PC4)|(0<<PC3)||(0<<PC2)|(0<<PC1)|(0<<PC0);
> // AD-Channels
>
> DDRD |=
> (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0);
> // LED´s
>
> while(1)
>   {
>        Init_Timer0();
>        AD_INIT_Test();
>
>   }

Was soll das bringen, ADC und Timer ständig neu zu initialisieren? Lass 
doch die Dinge arbeiten, wenn sie erst mal richtig konfiguriert sind!

>
>   return(0);
> }
>
> void AD_INIT_Test(void)
> {
>
>   ADMUX |= (0<<REFS1)|(1<<REFS0);
>   ADMUX |= (0<<ADLAR);
>
>
>   ADMUX |= (0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0);    // ADC - 5
>   //ADMUX |= (0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(0<<MUX0);  // ADC - 4
>
>   ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0);
>
> // Set ADC Scaler to 125KHz Sample rate @ 8MHz
> // 8MHz / 64 = 125kHz || 110 = 64
>
>
>   //ADCSRA &= ~(1 << ADATE);          // Disable free running Mod
>
>   //ADCSRB |= (0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);// 000 Free Running Mode
>   ADCSRB |= (0<<ADTS2)|(1<<ADTS1)|(1<<ADTS0);// 011 Compare Match
> TIMER.0
>   //ADCSRB |= (1<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);// 100 --> Timer.0
> Overflow
>   ADCSRB |= (0<<ACME);
>
>   ADCSRA |= (1<<ADEN);                // ADC Enable
>   ADCSRA |= (1<<ADATE);               // Auto trigger Mode enabled
>   //ADCSRA |= (1<<ADSC);              // Start Single Conversion
>
>   while (ADCSRA & (1<<ADSC))          // Wait for result
>   {}
>
>   PORTD = ADCL;                       // Write result on Port.D --> LED

L lesen alleine reicht nicht.
Du MUSST das H Register lesen! Zwingend.

>
>   ADCSRA |= (1<<ADIE);                // Enable ADC Interrupt
> }
>
>
>
> ISR(ADC_vect)
> {
>
>    ADCSRA &= ~(1<<ADIE);     // Disable ADC Interrupt --> Stop
>    ADCSRA |= (1 << ADIE);    // Enable ADC Interrupt
>    ADCSRA |= (0 << ADIF);     // Reset Interrupt Flag

Interrupt Flags werden anders gelöscht. Ausserdem passiert das in der 
ISR alles automatisch. Lass doch den ADC enabled. Was soll das bringen, 
den jedesmal ein bzw. auszuschalten.

Viel wichtiger wäre es, sich das Ergebnis abzuholen. Aber ausgerechnet 
das tust du nicht.
>
>     // ADCSRA |= (1 << ADSC);  // Start single conversion
> }
>
> void Init_Timer0(void)
> {
>
>
>   TCCR0A |= (0<<WGM02)|(1<<WGM01)|(1<<WGM00);    // Fast PWM Mode
>   TCCR0A |= (1<<COM0A1)|(0<<COM0A0);   // clear OC0A @ Compare Match
>
>     TCCR0B =  (1<<CS02)|(0<<CS01) |(1<<CS00);
> // Clock Division: clk/1024 --> 8.MHz / 1024 = 7812.5 Hz / 255 = 30Hz
>
>
>   TIMSK0|= (1<<OCIE0A);                // Enable Output Compare Flag
>   TIMSK0|= (1<<TOIE0);                // Enable Overflow Flag
>
>   OCR0A = 1;                      // shortest edge width
> }
>
>
>
> //---------------------------------------------------------------------- 
----------------------------------------------
> // ISR Timer.0
> //---------------------------------------------------------------------- 
----------------------------------------------
>
>
> ISR(TIMER0_COMPA_vect)
> {
>   // clear Compare Flag
>
>   TIFR0 = (0<<OCF0A);
>

Lass das Flag in Ruhe. (So löscht du es sowieso nicht). Das wird schon 
ganz von alleine gelöscht, sobald die ISR betreten wird. Darum brauchst 
du dich nicht kümmern.

> }
>
> ISR(TIMER0_OVF_vect)
> {
>   // clear Overflow Flag
>
>   TIFR0 = (0<<TOV0);

Detto.

>
> }



Wozu brauchst du die ISR, wenn du sowieso nichts da drinnen machst?
Sind nur potentielle Fehlerquellen.

Die Bits für den Auto Trigger des ADC hab ich nicht kontrolliert. Wie 
gesagt: bring halt erst mal den ADC ganz konventionell zum Laufen.

von spess53 (Gast)


Lesenswert?

Hi

sei() oder wie das in C heisst fehlt auch. Ohne sieht es mau mit 
interrupts aus.

MfG Spess

von Martin28 (Gast)


Lesenswert?

Danke das dir mal zeit genommen hast drüberzuschauen...

Karl Heinz Buchegger schrieb:
> L lesen alleine reicht nicht.
> Du MUSST das H Register lesen! Zwingend.

Ja habe auf meinem Board, leider nur 8 Led´s von den es mir vorerst 
reicht nur die unteren 8 für die Testzwecke zu lesen.

Karl Heinz Buchegger schrieb:
> Lass doch den ADC enabled. Was soll das bringen,
> den jedesmal ein bzw. auszuschalten.

War noch von meinem anderen Programm so drinne, da Ich genau zwischen 
diesen 2 Zeilen Disable/Enable den ADC Kanal umstelle. Was Ich auch 
wieder einfügen werde sobald Ich den mal richtig zum laufen gebracht 
habe...aber vorerst hast auf jeden Fall recht. Weg damit!

Karl Heinz Buchegger schrieb:
> Viel wichtiger wäre es, sich das Ergebnis abzuholen. Aber ausgerechnet
> das tust du nicht.

Ist es also sinnvoller in der ISR das Ergebnis an eine 
Variable,Port,etc. zu übergeben? Da es bei mir ja nur in der Init 
Methode abgeholt worden ist...

Karl Heinz Buchegger schrieb:
> Wozu brauchst du die ISR, wenn du sowieso nichts da drinnen machst?
> Sind nur potentielle Fehlerquellen.

Geb Ich dir vollkommen recht.

spess53 schrieb:
> sei() oder wie das in C heisst fehlt auch. Ohne sieht es mau mit
> interrupts aus.

Stimmt. Bei den meisten sind ja 2 Anforderungen für freigabe des IR 
nötig. I-Bit SREG und das IR freigabe bit der Einheit

von Karl H. (kbuchegg)


Lesenswert?

Martin28 schrieb:
> Danke das dir mal zeit genommen hast drüberzuschauen...
>
> Karl Heinz Buchegger schrieb:
>> L lesen alleine reicht nicht.
>> Du MUSST das H Register lesen! Zwingend.
>
> Ja habe auf meinem Board, leider nur 8 Led´s von den es mir vorerst
> reicht nur die unteren 8 für die Testzwecke zu lesen.

Ist egal.
Du MUSST das H-Register lesen.

Wird das L-Register gelesen, wird der komplette ADC gegen Updates 
gesperrt. Erst das lesen des H-Registers löst diese Sperre wieder.
Kein Lesen vom H-Register ... keine Updates.

von Karl H. (kbuchegg)


Lesenswert?

Martin28 schrieb:

>> Viel wichtiger wäre es, sich das Ergebnis abzuholen. Aber ausgerechnet
>> das tust du nicht.
>
> Ist es also sinnvoller in der ISR das Ergebnis an eine
> Variable,Port,etc. zu übergeben? Da es bei mir ja nur in der Init
> Methode abgeholt worden ist...

Du musst unterscheiden zwischen

  * Initialisierung
  * laufender Betrieb

Initialisierung sind alle Schritte, die notwendig sind, um eine 
Komponente in einen lauffähigen Zustand zu versetzen

der laufende Betrieb macht das was sein Name sagt: Was gibt es in der 
Hauptschleife zu tun.

Initialisiert wird normalerweise nur einmal!


> Stimmt. Bei den meisten sind ja 2 Anforderungen für freigabe des IR
> nötig. I-Bit SREG und das IR freigabe bit der Einheit


Nicht bei den meisten.
JEDE Komponente hat eine speziell auf sie abgestimmte 
Interrupt-Freigabe. Und dann gibt es noch die globale 
Interrupt-Freigabe. Ist die auf 'aus' gibts keine Interrupts.

von Martin28 (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wird das L-Register gelesen, wird der komplette ADC gegen Updates
> gesperrt. Erst das lesen des H-Registers löst diese Sperre wieder.
> Kein Lesen vom H-Register ... keine Updates.

Dann ist das glaube Ich mal einer der großen Fehlerquellen die Ich habe. 
Denn Ich habe hier schon die ganze Zeit an meinem Poti rumgedreht und 
der Wert wurde nie aktualisiert.

Werde mal alles verbessern und dann alles nochmal posten.

Vielen Dank erstmal für die ausführliche Hilfe

Gruß Martin

von Martin28 (Gast)


Lesenswert?

Guten Abend nochmal,

also Ich habe es jetzt hinbekommen! Es lag unter anderem auch 
tatsächlich an der allgemeinen IR Freigabe sei()

Noch eine kleine Frage, wie bekomme Ich es hin das mein Programm das Ich 
posten will auch mit einem schönen "weißen" Hintergrund zu sehen ist?^^

Grüße Martin

von Martin28 (Gast)


Lesenswert?

Noch eine Frage,

meine U(Dach) Spannung des Timer.0 sind etwas über 3V. Da mein ADC jetzt 
komischerweise ab einer Spannung von auch etwa 3V jetzt nichts mehr 
messen kann(wird zumindest NICHT) auf die LEDS ausgegeben, habe Ich mir 
gedacht es könnte eben gerade an der Spannung des Timers liegen.

Ist es nicht normal das die Output Amplitude des Timers nicht 5V 
entsprechen sollte?

Grüße Martin

von Rolf Magnus (Gast)


Lesenswert?

Martin28 schrieb:
> Noch eine kleine Frage, wie bekomme Ich es hin das mein Programm das Ich
> posten will auch mit einem schönen "weißen" Hintergrund zu sehen ist?^^

Die Anleitung lesen, die direkt über dem Fenster steht, in das du deinen 
Text eingibst. Die steht ja nicht zum Spaß da...

von Rolf Magnus (Gast)


Lesenswert?

... verstehe allerdings nicht, warum du fragst. Im Ursprungsposting tust 
du das doch schon.

von STK500-Besitzer (Gast)


Lesenswert?

Martin28 schrieb:
> meine U(Dach) Spannung des Timer.0 sind etwas über 3V. Da mein ADC jetzt
> komischerweise ab einer Spannung von auch etwa 3V jetzt nichts mehr
> messen kann(wird zumindest NICHT) auf die LEDS ausgegeben, habe Ich mir
> gedacht es könnte eben gerade an der Spannung des Timers liegen.

> Ist es nicht normal das die Output Amplitude des Timers nicht 5V
> entsprechen sollte?

Wieso sollte den Timer irgendwelcghe Spannungspegel interessiere oder 
diese einen Einfluss auf den ADC haben?
Das dürfte entweder ein Hardwarefehler oder ein Brainerror sein...

von Martin28 (Gast)


Lesenswert?

Rolf Magnus schrieb:
> ... verstehe allerdings nicht, warum du fragst. Im Ursprungsposting tust
> du das doch schon.

Ne das war Ich nicht! Hat glaube der Moderator verändert...
Aber trotzdem Danke für die Info

Rolf Magnus schrieb:
> Die Anleitung lesen, die direkt über dem Fenster steht, in das du deinen
> Text eingibst. Die steht ja nicht zum Spaß da...

Ist was dran...

von Martin28 (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Wieso sollte den Timer irgendwelcghe Spannungspegel interessiere oder
> diese einen Einfluss auf den ADC haben?
> Das dürfte entweder ein Hardwarefehler oder ein Brainerror sein...

Also ist dat ganz normal das der einen Output-Pegel von bissle etwas 
über 3V hat? Habe bisher angenommen, das richtet sich nach der an A(vcc) 
angeschlossenen Spannung, die bei mir 5V entsprechen.

Oder kann mir jemand erkläre warum das gerade 3V sind. Habe dazu im 
Datasheet irgendwie nichts gefunden.

Grüße Martin

von spess53 (Gast)


Lesenswert?

Hi

>Oder kann mir jemand erkläre warum das gerade 3V sind. Habe dazu im
>Datasheet irgendwie nichts gefunden.

Erzähle erst mal, wiedu das gemessen hast.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Martin28 schrieb:

> Oder kann mir jemand erkläre warum das gerade 3V sind. Habe dazu im
> Datasheet irgendwie nichts gefunden.

Du hast da eine PWM an den Output-Pin gekoppelt! D.h. da ist eine 
Wechselspannung drauf! Der SPannungshub am OC-Pin ist nach wie vor 5V, 
aber dein Messgerät zeigt dir nur 3V an, weil die Spannung ständig 0V, 
5V, 0V, 5V, 0V, 5V, etc.... macht.

von Martin28 (Gast)


Lesenswert?

spess53 schrieb:
> Erzähle erst mal, wiedu das gemessen hast.

Also bin da mit nem differetial Tastkopf einmal auf Masse von meinem 
Board und einmal auf dem PIN PB1 was ja dem OC1A Register entspricht.

Habe Timer.0 und Timer.1 im Betrieb und bei beiden wird 3V Peak 
angezeigt. Da ganze wird natürlich über ein Oszi gemessen. Teiler etc. 
sind alles auf 1x eingestellt. Also nicht das Ich da irgendeine division 
drin habe oder ähnliches..

Karl Heinz Buchegger schrieb:
> Du hast da eine PWM an den Output-Pin gekoppelt! D.h. da ist eine
> Wechselspannung drauf! Der SPannungshub am OC-Pin ist nach wie vor 5V,
> aber dein Messgerät zeigt dir nur 3V an, weil die Spannung ständig 0V,
> 5V, 0V, 5V, 0V, 5V, etc.... macht.

Ja gut, aber das müsste mir das Oszi doch anzeigen!?

von Martin28 (Gast)


Lesenswert?

Martin28 schrieb:
> Habe Timer.0 und Timer.1 im Betrieb und bei beiden wird 3V Peak
> angezeigt

Sorry 3.3V

von spess53 (Gast)


Lesenswert?

Hi

Also wenn dein Controller mit 5V läuft, dann müssen bei unbelasteten 
Pins auch 5V herauskommen. Ansonsten ist etwas faul.

MfG Spess

von Martin28 (Gast)


Lesenswert?

Eben, das meine Ich auch...naja wa werde Ich nochmal alles überprüfen 
müssen. Melde mich dann nochmal

Grüße

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.