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?
Ich habe den Haken bei JTAG entfernt. (siehe Pic) Bei der Gegenprobe ändert sich nichts. Wäre aber auch logisch, weil dann der Pull Up aktiv ist...
hast du danach auch die fuses programmiert oder nur das Häkchen geändert? Ja, klingt blöde, ist aber alles schpn passiert :-)
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.
dummy schrieb: > Falschen Kanal gemessen Nö! ADC0-3 & ADC5 gehen. ADC4 gibt mir immer 1023 zurück. Muss ein Einstellungsthema sein...
Hi
>Dann liegts an der Software. Falschen Kanal gemessen.
Oder die Referenzspannung abgeschaltet.
MfG Spess
Die Referenzspannung steht imm auf inter (2.56V) Hier der Code:
1 | void Init_Analog (void) |
2 | {
|
3 | ADMUX |= (1<<REFS1) | (1<<REFS0); |
4 | // Select the prescaler of 128
|
5 | ADCSRA = (1<<ADPS2 | 1<<ADPS1); |
6 | ADCSRA |= (1<<ADEN); |
7 | |
8 | ADCSRA &= ~(1<<ADATE); //FreeRunningMode OFF |
9 | }
|
10 | |
11 | uint16_t ADC_read(uint8_t ADCChannel){ |
12 | ADMUX &= ~0b00011111; //adjust ADC mux |
13 | ADMUX |= ADCChannel&0b00011111; //set MUX |
14 | |
15 | ADCSRA |= (1<<ADSC);//Start DUMMY conversion |
16 | // Wait in a while loop until the bit
|
17 | // clears.
|
18 | while (ADCSRA & (1<<ADSC)); |
19 | |
20 | ADCSRA |= (1<<ADSC); //Start conversion |
21 | while (ADCSRA & (1<<ADSC)); |
22 | return((ADCL + (ADCH<<8))); //return value |
23 | }
|
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?
Was ist mit ADC6 und ADC7? Wenns an JTAG liegt, würden die auch nicht gehen. Ansonsten würde ich eher auf DDR-Register tippen.
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 |
8 | {
|
9 | switch((ADMUX & 0x1f)) |
10 | {
|
11 | case 1: // ADC1 war ausgewählt |
12 | strom1 = ADC; |
13 | ADMUX = (1<<REFS0) | (1<<MUX1); // Referenz = VCC, Input = ADC2 |
14 | break; |
15 | case 2: // ADC2 war ausgewählt |
16 | strom2 = ADC; |
17 | ADMUX = (1<<REFS0) | (1<<MUX1) | (1<<MUX0); // Referenz = VCC, Input = ADC3 |
18 | break; |
19 | case 3: // ADC3 war ausgewählt |
20 | strom3 = ADC; |
21 | ADMUX = (1<<REFS0) | (1<<MUX0); // Referenz = VCC, Input = ADC1 |
22 | break; |
23 | default: // Fehler, ADC auf falschem Kanal |
24 | 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ß
Lustig, genau das hat ein User schon festgestellt aber du wolltest es nicht glauben :-)
Und? den Fehler mit dem Prescaler schon korrigiert oder läuft der Controller mit weniger als 12,8 MHz?
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.
