Hi,
ich habe folgende Routinen:
#define AD_MUX_CHANNEL(y) ADMUX |= ((y)&0x0f)
void ADC_Init (void)
{
/*
ADMUX
.-----.-----.---....
|REFS1|REFS0|
'-----'-----'---...
| |
| |
| |
.--. |\| |
AVCC | |---------------|0 \ |
'--' | | _|_
| |-------.
.---------------. | | |
| Internal 1.1V |--|1 / |
| Reference | |/ |
'---------------' |
|
.--. | .-------....
AREF | |---------------------------o-----| A/D Conf
'--' '-------....
.---.-------.-------.-----------------------------------------------.
|Nb.| REFS1 | REFS0 | Voltage Reference Selecttion (23.8.1 / P.256) |
.---+-------+-------+-----------------------------------------------.
| 0 | 0 | 0 | AREF, Internal VRef turned off |
.---+-------+-------+-----------------------------------------------.
| 1 | 0 | 1 | AVcc with external cap. at AREF |
.---+-------+-------+-----------------------------------------------.
| 2 | 1 | 0 | Reserverd |
.---+-------+-------+-----------------------------------------------.
| 3 | 1 | 1 | Int. VRef 1.1V with ext. cap. at AREF |
'---'-------'-------'-----------------------------------------------'
*/
ADMUX &=~ (1<<REFS0);
ADMUX &=~ (1<<REFS1); //Referenzquelle wählen
ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
// setzen auf 8 (1)
}
und
uint16_t ADC_ReadChannel(uint8_t mux)
{
uint8_t i;
uint16_t result;
AD_MUX_CHANNEL(mux); //Kanal waehlen
ADCSRA |= (1<<ADEN);
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man
liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu
lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result = ADCW; // ADCW muss einmal gelesen werden,
// sonst wird Ergebnis der nächsten Wandlung
// nicht übernommen.
/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden
Wandlungen */
result = 0;
for( i=0; i<4; i++ )
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
result /= 4; // Summe durch vier teilen = arithm.
Mittelwert
return result;
}
Die Routine hatte ich aus dem Tutorial und dann in init() und read()
aufgetreilt.
Ich habe nach wie vor das Problem, wenn ich sie mit read(5) und dann mit
read(3) aufrufe, dass ich nur noch schrott bekomme, es passiert quasi
keine Werteänderung mehr an ch5.
wenn ich nur ch5 abfrage - kein Problem.
Für einen Tip wäre ich dankbar.
Hannes
Das Problem liegt hier:
1 | #define AD_MUX_CHANNEL(y) ADMUX |= ((y)&0x0f)
|
Mit der &0x0f sorgst du nur dafür, das y kleiner 16 bleibt. Das tust du dann in das Register ADMUX rein-verodern. Aber wenn da vorher schon ein Kanal drinstand, kommt Unsinn raus. Versuch mal das:
1 | #define AD_MUX_CHANNEL(y) ( ADMUX = (ADMUX & 0xF0) | (y&0x0f) )
|
>read(5) und dann mit read(3) aufrufe
Dadurch ensteht im ADMUX der Kanal 7 = 5 OR 3
Hallo, es sei noch auf Atmel AVR126: ADC of megaAVR in Single Ended Mode http://www.atmel.com/dyn/resources/prod_documents/doc8444.pdf verwiesen, dort steht, wann und wie man den Kanal wechseln kann. Wir hatten letzte Woche auch die Frage und habe eine Lösung ohne das Paper AVR126 gefunden - Kein Autotrigger zu verwenden.. So werden nun N-Kanäle über M-Mittelwerte gewandelt, alle X-ms, bei uns 1ms, liegt das Ergebnis für alle ADC-Kanäle vor und wird durch die main() dann verarbeitet.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.