Forum: Mikrocontroller und Digitale Elektronik NUR ADC4 an AT90CAN128 tut nicht?


von Dennis (Gast)


Lesenswert?

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ß

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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?

von Dennis (Gast)


Angehängte Dateien:

Lesenswert?

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...

von H.Joachim S. (crazyhorse)


Lesenswert?

hast du danach auch die fuses programmiert oder nur das Häkchen 
geändert? Ja, klingt blöde, ist aber alles schpn passiert :-)

von Dennis (Gast)


Lesenswert?

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... :-(

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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...

von Dennis (Gast)


Lesenswert?

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! :-(

von dummy (Gast)


Lesenswert?

>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.

von Dennis (Gast)


Lesenswert?

dummy schrieb:
> Falschen Kanal gemessen

Nö! ADC0-3 & ADC5 gehen. ADC4 gibt mir immer 1023 zurück.
Muss ein Einstellungsthema sein...

von spess53 (Gast)


Lesenswert?

Hi

>Dann liegts an der Software. Falschen Kanal gemessen.

Oder die Referenzspannung abgeschaltet.

MfG Spess

von Dennis (Gast)


Lesenswert?

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
}

von Rudolph (Gast)


Lesenswert?

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.

von Dennis (Gast)


Lesenswert?

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?

von Fabian F. (fabian_f55)


Lesenswert?

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.

von Rudolph (Gast)


Lesenswert?

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.

von Dennis (Gast)


Lesenswert?

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ß

von kevin (Gast)


Lesenswert?

Lustig, genau das hat ein User schon festgestellt aber du wolltest es 
nicht glauben :-)

von Rudolph (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.