Hallo,
ich benutze einen AT90CAN128 um damit Analogwerte einzulesen und per CAN
zu versenden.
Bei ADC0-ADC3 ist das kein Problem, aber ADC4 liefert mir immer nur
1023. Obwohl auf Grund der Spannung an dem Pin etwas anderes
herauskommen müsste.
Der PF4 wird auch noch als TCK für das JTAG verwendet, aber das habe ich
in den Fuses deaktiviert.
Aus Verzweiflung habe ich schon eine 2 Schaltung aufgebaut, weil ich
dachte der µC wäre defekt. Aber dabei ist es genauso! :-(
Habe ich sonst noch was vergessen???
Gruß
Dennis schrieb:> Der PF4 wird auch noch als TCK für das JTAG verwendet, aber das habe ich> in den Fuses deaktiviert.
Wie hast du den deaktiviert? Was passiert, wenn du den Gegentest machst:
ändert sich was, wenn du den JTAG aktivierst?
Das Bild war blöd, oder? :-)
Ich habe es natürlich programmiert...
Im Datenblatt finde ich dazu auch nichts weiteres.
Mich verwirrt auch das es bei 2 Controllern so ist... :-(
Dennis schrieb:> Wäre aber auch logisch, weil dann der Pull Up aktiv ist...
Ich würde da einfach mal eine definierte Spannung ungleich 5V oder 0V
anlegen...
Lothar Miller schrieb:> Ich würde da einfach mal eine definierte Spannung ungleich 5V oder 0V> anlegen...
Ich habe bereits 2 verschiedene Spannungen getestet.
Einmal konnte ich mit dem Multimeter 100mV und einmal 2,3V messen.
Leider war der ADC-Wert immer 1023! :-(
>Einmal konnte ich mit dem Multimeter 100mV und einmal 2,3V messen.>Leider war der ADC-Wert immer 1023! :-(
Dann liegts an der Software. Falschen Kanal gemessen.
Boah, das ist ja eine tödliche Vorgehensweise den ADC auszulesen.
Jedes Mal doppelt wandeln und mit Busy-Wait warten?
Damit stellt sich der Controller bei jedem Aufruf für etwa 210µs tot
und verbrennt dabei maximale Leistung.
> // Select the prescaler of 128> ADCSRA = (1<<ADPS2 | 1<<ADPS1);
Der Prescaler ist damit 64.
> ADCSRA &= ~(1<<ADATE); //FreeRunningMode OFF
Das bewirkt garnichts, durch die Zuweisung drüber ist das Bit sowieso
nicht gesetzt.
> return((ADCL + (ADCH<<8))); //return value
return(ADC);
Die 16 Bit Register können vielfach direkt verwendet werden, der
Compiler kümmert sich dann um den korrekten Zugriff.
Das könnte hier zum Beispiel falsch laufen, wäre aber dann für alle
Kanäle so.
Was da konkret schief läuft fällt mir aber so auch nicht auf.
Rudolph schrieb:> Jedes Mal doppelt wandeln und mit Busy-Wait warten?
Im Datenblatt steht das man einmal wandeln soll damit er sich
stabilisiert. Muss ich dann nicht auch auf die Wandlung warten?
Das Bit für FreeRunningMode ist hier noch drin, weil ich den zu
Testzwecken auch mal aktiviert habe.
Wenn aber alles richtig ist, warum geht dann nur der ADC4 nicht?
Dennis schrieb:>> Jedes Mal doppelt wandeln und mit Busy-Wait warten?>> Im Datenblatt steht das man einmal wandeln soll damit er sich> stabilisiert.
Nein, im Datenblatt steht, dass man die erste Wandlung nach dem Wechseln
der Referenz verwerfen sollte, da steht nicht drin, dass die erste
Wandlung nach dem Wechseln des Kanals fehlerhaft ist.
Das kann man einmal zur Initalisierung machen aber doch nicht immer
wieder wenn man nur einen Kanal lesen will.
> Muss ich dann nicht auch auf die Wandlung warten?
Nein, muss man nicht, die Wandlung wird auch fertig wenn der Controller
noch nebenbei was sinnvolles macht, das erfordert aber auch
grundsätzliches Umdenken zur Struktur eines Mikrocontroller-Programms.
1
while(1)
2
{
3
PORTB |= (1<<PB7); // test!
4
5
triplock = roundtrip;
6
7
if( (ADCSRA & (1<<ADSC)) == 0) // letzte Wandlung fertig? - nächste Wandlung wird mit dem Sleep angestossen
calc = ADCH; // einmal lesen um ADC freizuschalten
25
calc = calc; // Compiler-Warnung loswerden
26
ADMUX = (1<<REFS0) | (1<<MUX0); // ADC1 als nächstes
27
break;
28
}
29
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // re-konfigurieren ohne zu starten, Wandlung wird mit Sleep gestartet
30
}
31
32
if(roundtrip == 0)
33
{
34
}
35
36
if(roundtrip == 1)
37
{
38
}
39
40
if(roundtrip == 2)
41
{
42
}
43
44
if(roundtrip == 3)
45
{
46
}
47
48
while(triplock == roundtrip) // verhindern, das IRQs den Controller wach machen
49
{
50
/* für den Rest der Zeit-Scheibe schlafen legen */
51
cli();
52
sleep_enable();
53
sei();
54
sleep_cpu();
55
sleep_disable();
56
}
57
}
Dazu läuft bei mir ein Timer der den Controller alle 250µs aus dem
Schlaf holt und die Variable Roundtrip von 0-3 zählt, mit drei AD-Werten
wird also jeder Messwert alle 750µs aktualisiert.
Wenn einer der vier Blöcke einen der Werte braucht nimmt er einfach den
aktuellen.
Alternativ kann man auch einen ADC-Interrupt anlegen und dort die Daten
wegspeichern und den Kanal umstellen, damit würde man mehr Wandlungen
pro Sekunde machen können.
Da ich die Messwerte in aller Regel aber nicht so schnell brauche wie
der AD-Wandler sie selbst mit größtem Prescaler zur Verfügung stellen
kann und andererseits der AD-Interrupt sich mit der Nutzung des
Sleep-Modus ein wenig beisst, bevorzuge ich das wie oben dargestellt.
Hallo,
ich muss mich bei alle entschuldigen!
Ich habe einen ganz dummen Flüchtigkeitsfehler gemacht!
Gestern Abend habe ich meinen Fehler entdeckt...
Ich habe die Messkanäle von 1-8 durchnummeriert, die ADCs beginnen aber
bei 0. Dadurch habe ich den Kanal 4 auf ADC4 gemessen, es musste aber
ADC3 sein! Wie blöd!
Gruß
Eine eigene Frage?
Dieser Thread ist über 12 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.