Hallo Leute,
ich habe eine Platine mit einem ATMEGA329V.
Ich bin gerade dabei ein ADC zu Programmieren bin aber auf ein Problem
gestoßen, wo ich einfach nicht weiter kommen. Vielleicht könnt ihr mir
ja helfen?!
#include <avr/io.h>
#define F_CPU 4915200 // Quarzfrequenz
void ADC_Init(void)
{
uint16_t ergebnis;
ADMUX = 0b01100000; // Externe Spannung (AREF) AVCC
ADCSRA |= ( 1<<ADPS2 ) | ( 0<<ADPS1 ) | ( 1<<ADPS0 ); // Division Factor
ADCSRA |= ( 1<<ADEN ); // ADC Enable
ADCSRA |= ( 1<<ADSC ); // ADC Start Conversion
while (ADCSRA & (1<<ADSC))
{
}
ergebnis = ADCW;
}
void main(void)
{
ADC_Init();
DDRC = 0xFF;
while( 1 )
{
ADCSRA |= ( 1<<ADSC );
if( ADC > 1023 )
{
PORTD = ( 1<<PD1 );
}
else
{
PORTD = ( 1<<PD0 );
}
}
}
So hier ist das Programm was ich geschrieben habe.
Problem:
ADCSRA |= ( 1<<ADSC ); // ADC Start Conversion
while (ADCSRA & (1<<ADSC))
{
}
ergebnis = ADCW;
Dies soll ja ein "Warmlauf" sein, habe ich heute erst bei der Tutorial
gelesen. Den Grund habe ich verstanden wieso man diesen Warmlauf macht,
aber wenn ich diesen Code anwende springt er beim debuggen nicht mehr
aus der while Schleife raus bzw. übergibt keinen Wert.
Der Untere Teil, die main bin ich mir auch nicht ganz sicher ob dies so
funktioniert. Komme ja mit dem debuggen nicht weiter.
void main(void)
{
ADC_Init();
DDRC = 0xFF;
while( 1 )
{
ADCSRA |= ( 1<<ADSC );
if( ADC > 1023 )
{
PORTD = ( 1<<PD1 );
}
else
{
PORTD = ( 1<<PD0 );
}
}
}
Zu guter letzt habe ich noch die Frage zum Free Running mode / Single
Conversion mode.
Im Datenblatt ist es für mich nicht ersichtlich wie ich diese auswähle.
Also entweder oder.
Grüße
Kevin Honey schrieb:> Dies soll ja ein "Warmlauf" sein, habe ich heute erst bei der Tutorial> gelesen. Den Grund habe ich verstanden wieso man diesen Warmlauf macht,> aber wenn ich diesen Code anwende springt er beim debuggen nicht mehr> aus der while Schleife raus bzw. übergibt keinen Wert.
Moment.
Debuggen
Womit debuggst du?
Der im AVR-Studio eingebaute Debugger simuliert nicht alle Aspekte des
realen IC. Wenn du im Simulator da raus kommen willst, kannst du immer
noch händisch mit einem Mausklick das entsprechende Bit löschen.
> ADCSRA |= ( 1<<ADSC );>> if( ADC > 1023 )
das muss aber wieder genau gleich funktionieren.
Du setzt das ADSC Bits, der ADC beginnt zu arbeiten.
Wenn der ADC fertig ist, löscht er das Bit wieder und erst dann kannst
du dir das Wandlungsergebnis abholen.
> Zu guter letzt habe ich noch die Frage zum Free Running mode / Single> Conversion mode.> Im Datenblatt ist es für mich nicht ersichtlich wie ich diese auswähle.> Also entweder oder.
Ganz ehrlich.
Sieh erst mal zu, dass du den Single Shot in Betrieb kriegst. Für 90%
aller Fälle langt der dicke.
Karl Heinz Buchegger schrieb:>> Zu guter letzt habe ich noch die Frage zum Free Running mode / Single>> Conversion mode.>> Im Datenblatt ist es für mich nicht ersichtlich wie ich diese auswähle.>> Also entweder oder.>> Ganz ehrlich.> Sieh erst mal zu, dass du den Single Shot in Betrieb kriegst. Für 90%> aller Fälle langt der dicke.
Hab mich mal im Datenblatt schlau gemacht.
Den klassischen Free-Running Modus gibt es so direkt nicht mehr. Der
wurde durch etwas universelleres ersetzt. Das nennt sich bei diesem µC
"Auto Trigger" und eine Variante davon ist der Free-Running Mode, bei
dem sich der ADC selber den Auto-Trigger verpasst, sobald er erst mal
läuft (die erste Wandlung muss man 'per Hand' starten)
Vielen Dank für deine schnelle Antwort!
Karl Heinz Buchegger schrieb:> das muss aber wieder genau gleich funktionieren.> Du setzt das ADSC Bits, der ADC beginnt zu arbeiten.> Wenn der ADC fertig ist, löscht er das Bit wieder und erst dann kannst> du dir das Wandlungsergebnis abholen.
Korrigier mich wenn ich falsch liege.
Das Wandlungsergebnis ist im ADCL and ADCH – The ADC Data Register
geschrieben wenn ich das richtig gelesen habe.
Das warten bis der ADC die Coversion fertig hat mache ich mit
(ADCSRA & (1<<ADSC)); richtig?
Muss der Code dann wie folgt aussehen?
void main(void)
{
ADC_Init();
DDRD = 0xFF;
while( 1 )
{
ADCSRA |= ( 1<<ADSC );
(ADCSRA & (1<<ADSC));
if( ADC > 1023 )
{
PORTD = ( 1<<PD1 );
}
else
{
PORTD = ( 1<<PD0 );
}
}
}
Mir ist gerade aufgefallen dass ich nicht direkt gesagt habe was ich
eigentlich vor habe.
Ich will durch ein Poti das an ADC0 angeschlossen ist über den Schleifer
den Analogen Wert auslesen und Digitaltalisieren. Das wiederum visuell
ausgeben.
Karl Heinz Buchegger schrieb:> Hab mich mal im Datenblatt schlau gemacht.> Den klassischen Free-Running Modus gibt es so direkt nicht mehr. Der> wurde durch etwas universelleres ersetzt. Das nennt sich bei diesem µC> "Auto Trigger" und eine Variante davon ist der Free-Running Mode, bei> dem sich der ADC selber den Auto-Trigger verpasst, sobald er erst mal> läuft (die erste Wandlung muss man 'per Hand' starten)
Ah okay alles klar, ich bin da nicht so ganz durch gestiegen.
Ich habe gesehen dass ich den Free Runing Mode im ADCSRB – ADC Control
and Status Register B einstellen kann unter ADC Auto Trigger Source
Selections.
Bin nur irretiert gewesen weil unter ADSC: ADC Start Conversion stand:
In Single Conversion mode, write this bit to one to start each
conversion.
Ich dachte ich muss ein Bit setzen um auszuwählen ob ich Free runing
Mode oder Single Conversion haben will.
Aber dann ist standartmäßig einfach Single Conversion.
Vielen Dank :)
Kevin Honey schrieb:> Korrigier mich wenn ich falsch liege.>> Das Wandlungsergebnis ist im ADCL and ADCH
richtig.
> – The ADC Data Register> geschrieben wenn ich das richtig gelesen habe.
Das ist ein Service, den dir der C-Compiler anbietet.
Du schreibst
i = ADC;
(bzw. i = ADCW;)
und der COmpiler kümmert sich darum, dass ADCH und ADCL in der richtigen
Reihenfolge ausgelesen werden und die beiden Bytes zu einem 16 Bit Wert
zusammengesetzt werden.
> Das warten bis der ADC die Coversion fertig hat mache ich mit> (ADCSRA & (1<<ADSC)); richtig?
genau so wie du es in der Init Funktion auch gemacht hast.
> Muss der Code dann wie folgt aussehen?>> void main(void)> {> ADC_Init();> DDRD = 0xFF;>> while( 1 )> {> ADCSRA |= ( 1<<ADSC );> (ADCSRA & (1<<ADSC));
nö
while( ADCSRC & (1<<ADSC) )
;
'Auf etwas warten' impliziert, dass es da irgendeine Form von Schleife
geben muss, in der regelmässig überprüft wird, ob das Ereignis schon
eingetreten ist.
Ich dachte, du hättest das Tutorial bzw. den Tutorialscode studiert?
> Mir ist gerade aufgefallen dass ich nicht direkt gesagt habe was ich> eigentlich vor habe.> Ich will durch ein Poti das an ADC0 angeschlossen ist über den Schleifer> den Analogen Wert auslesen und Digitaltalisieren. Das wiederum visuell> ausgeben.
Schon ok.
Single Shot ist da schnell genug. So schnell kannst du nicht am Poti
drehen, dass du den µC da in Verlegenheit bringen könntest.
Und: Funktionen machen!
Genauso wie es eine Init Funktion gibt, solltest du dir eine
Auslese-Funktion machen. Siehe zb den Tutoriumscode.
sorry, aber das Programm ist kompletter Käse und wird sich nicht Mal
übersetzen lassen.
Geh es im Kopf Schritt für Schritt durch und überleg dir was passiert.
oder nimm einfach den Code aus dem Tutorial.
Walter S. schrieb:> sorry, aber das Programm ist kompletter Käse
Dem stimme ich zu.
> und wird sich nicht Mal> übersetzen lassen.
Doch. Übersetzen lässt es sich. Ich denke allerdings nicht, dass der TO
auch nur den Hauch eines Schimmer hat, was er da aus Sicht seines
Compilers geschrieben hat.
Das hier
if( Ausgabe > 5*1023/5 )
so seltsam es auch aussieht, wird zu einer Warnung führen. Aber es ist
erst mal kein Syntax Error. Es macht zwar nicht das, was er sich
vorgestellt hat, noch nicht mal annähernd, aber es ist compilierbar.
Denn: Auch Funktionen haben Adressen. Und die kann man vergleichen.
> Geh es im Kopf Schritt für Schritt durch und überleg dir was passiert.> oder nimm einfach den Code aus dem Tutorial.
Wo denkst du hin?
Das wär doch viel zu einfach. Und wenn man dann auch noch C erst mal
zumindest ein wenig gelernt hätte, dann könnte man die
himmelschreiendsten Fehler sogar selber sehen.
Sowas:
1
voidAusgabe()
2
{
3
intAusgabe;
4
Ausgabe=ADCW;
5
}
ist natürlich ein Kleinod im kabarettistischen Himmel des Unsinns.