Hallo Forum,
ich bin gerade dabei ein Projekt von ATmega8 (4MHz) auf ATmega168
(18,432MHz) zu transferieren, aber der ADC will nicht so richtig
arbeiten.
Ich lese über den ADC-Eingang einen NTC-Wert, verwende die internen 1,1V
als Referenz und habe dafür die Spannungsteiler (wegen 2,56V beim mega8)
angepasst.
Nach dem Reset bekomme ich beim ersten Lesen des ADC einen plausiblen
Wert, jedes weitere Lesen liefert nur 1023.
Habe schon einiges probiert. Vielleicht könnt ihr mich auf eine
Eigenschaft oder Fehler aufmerksam machen.
Lg,
Tungsten
1
voidinit_adc(){
2
// Set ADC reference
3
ADMUX|=(1<<REFS1)|(1<<REFS0);// Internal 1.1V Voltage Reference with external cap at AREF
@ Spess, danke für den Hinweis, ADATE habe ich hinzugefügt.
@K.H. .. der Allerwerteste ist wichtig, darauf werde ich jetzt achten.
Ich habe die Änderungen eingebracht, leider gleiches Verhalten. Nach dem
Reset liefert das erste read_adc einen Wert (z.B.609) und jedes folgende
read_adc 1023,1023,1023,...
????
1
voidsetchannel_adc(uint8_tchannel)
2
{
3
ADCSRA&=~(1<<ADEN);
4
ADMUX|=(channel&0x0F);//set channel
5
ADMUX|=(1<<REFS1)|(1<<REFS0);// Internal 1.1V Voltage Reference with external cap at AREF
6
ADCSRA|=(1<<ADEN);
7
}
8
9
/*
10
* read from adc channel
11
*/
12
uint16_tread_adc(uint8_tchannel)
13
{
14
setchannel_adc(channel);
15
ADCSRA|=(1<<ADSC);// Start conversion
16
while(!(ADCSRA&(1<<ADIF)));// Wait for conversion to complete
17
uint16_tadc=ADC;
18
ADCSRA|=(1<<ADIF);// Clear ADIF by writing one to it
19
return(adc);
20
}
21
22
voidinit_adc(){
23
// Set ADC reference
24
ADMUX|=(1<<REFS1)|(1<<REFS0);// Internal 1.1V Voltage Reference with external cap at AREF
Mir ist eines nicht klar.
Wozu der ganze Hackmack mit dem Free Running, wenn du dann sowieso in
der read Funktion den ADC händisch triggerst.
Hast du schon mal die ADC Funktionen aus dem AVR-GCC-Tutorial so wie sie
sind (mit der Ausnahme der Referenzspannungseinstellung) benutzt?
AVR-GCC-Tutorial/Analoge Ein- und Ausgabe: Nutzung des ADC
K.H. da hast du schon recht, nach einigen Stunden Fehlersuchen probiert
man alles, egal ob logisch oder nicht...
Jetzt wo es geht werde ich alles redundante weggeben und auch händisch
triggern.
DANKE.
Tungsten schrieb:> K.H. da hast du schon recht, nach einigen Stunden Fehlersuchen probiert> man alles, egal ob logisch oder nicht...> Jetzt wo es geht werde ich alles redundante weggeben und auch händisch> triggern.
Tip:
Lass das ADIF Flag in Ruhe. Du brauchst es nicht, und es macht nur
Arbeit. Die Sache ist ganz einfach: Du setzt das ADSC Bit und wenn der
ADC fertig ist, zieht er es wieder auf 0 zurück.
Siehe Tutorial.
@ Spess, danke für den Hinweis, das war jetzt wirklich schlamping,
wirklich schlampig...
@K.H. Danke, ich habe das geändert.
Vermutlich könnte ich auch ADC direkt zurückgeben und bräuchte die adc
Variable auch nicht.
Schönen Abend noch...
Tungsten
1
uint16_tadc_read(uint8_tchannel)
2
{
3
adc_setchannel(channel);
4
ADCSRA|=(1<<ADSC);// Start conversion
5
while(IS_BIT_SET(ADCSRA,ADIF));// Wait for conversion to complete
> while( IS_BIT_SET(ADCSRA,ADIF) ); // Wait for conversion to complete
ADSC, nicht ADIF
Studier doch bitte die Routinen aus dem Tutorial. Es macht keinen
wirklichen Spass deine ganzen Tippfehler zu korrigieren, wenn du dort
fix fertige, sauber funktionierende Funktionen finden kannst.