Atmega2560 ADC auslesen

OP #1990770
Hallo,

ich besitze ein STK600 und versuche gerade, ein paar kleine Programme zu 
schreiben.
Mein jetziges Ziel ist es, einen analogen Pegel auszulesen.
Ich lege an den PIN PF0 eine analoge Spannung. Diese wird intern in 
einen 10Bit Wert gewandelt. Die untern 8 Bit sollen an den PORTB 
ausgegeben werden.
1
#include <avr/io.h>
2

3
// inernet Takt 128kHz
4
// Port E hat ADC  (ADC0) PF0
5
// Ausgänge sind negiert
6

7
   
8
  int main(void)
9

10
{
11

12
 
13
#include <avr/io.h>
14

15
// Internet Takt 128kHz
16
// Der ADC ist an PortF angeschlossen, ADC0 --> PF0
17
// Ausgänge des PortB sind negiert
18

19
   
20
  int main(void)
21

22
{
23

24
  ADCSRA= 0b11100000; // Free running mode mit Takt: 128/2khz
25
  ADCSRB= 0b00000000; // Letzen 3 Bits stehen auch für free running mode
26
  ADMUX = 0b11100000; // Referenz ADLAR und Eingang // ADLAR gesetzt
27
  char Wert = 0xff;
28
  DDRB = 0b11111111; // Port B ist ein Ausgang 0b11111111 = 0xff
29

30

31
  while(1)
32
  {
33
    Wert = ~ADCH;
34
    PORTB = Wert;
35
  }
36
  
37

38
return 0;
39
}

Dieser Code funktioniert!
Wenn ich jedoch ADLAR ausschalte (Bit --> 0), so dass die untern 8 Bits 
in dem Register ADCL stehen sollten und ich schreibe:
1
  while(1)
2
  {
3
    Wert = ~ADCL;
4
    PORTB = Wert;
5
  }

Dann funktioniert das Programm nicht mehr!
Aus irgendeinem Grund kann ich nur das Register ADCH und nicht das 
Register ADCL auslesen. Hat jemand hierfür eine Erklärung?
Der Grund dafür ist im Datenblatt erklärt:
When ADCL is read, the ADC Data Register is not updated until ADCH is 
read

Also einfach einen Dummy-Read von ADCH hinterher machen, oder ADCW lesen 
und nur die unteren 8Bit verwenden.
OP
>Der Grund dafür ist im Datenblatt erklärt:
>When ADCL is read, the ADC Data Register is not updated until ADCH is
>read

Danke!
Wenn ich danach suche, dann finde ich das auch.
Habe irgendwie nur bis zur Grafik geschaut.

>oder ADCW lesen und nur die unteren 8Bit verwenden.

Hast du einen Vorschlag, wie man das etwas einfacher machen kann?

>Tip für später:
>außerdem könntest du auch noch warten bis der neue Wert gewandelt wurde
>(oder einen Interrupt verwenden)

Danke,
das warten habe ich schon eingebaut.
In Interrupts muss ich mich beim Atmega noch einlesen.

1
#include <avr/io.h>
2

3
// Internet Takt 128kHz
4
// Der ADC ist an PortF angeschlossen, ADC0 --> PF0
5
// Ausgaege des PortB sind negiert
6

7
   
8
  int main(void)
9

10
{
11

12
  ADCSRA= 0b11100000; // Free running mode mit 128/2khz
13
  ADCSRB= 0b00000000; // Letzen 3 stehen auch für free running mode
14
  ADMUX = 0b11000000; // Referenz ADLAR und Eingang // ADLAR nicht gesetzt
15
  DDRB = 0b11111111; // Port B ist ein Ausgang 0b11111111 = 0xff
16

17
/* 
18
// Staendige Abfrage nicht notwendig
19
    char Wert = 0xff;
20
  char Dummy = 0x00;
21
  while(1)
22
  {
23
    Dummy = ADCH;
24
    Wert  = ~ADCL;
25
    PORTB = Wert;
26
  }
27
*/
28

29
// Interrupt-Flag abfragen
30

31
  short s_Wert = 0;
32
  char c_Wert= 0;
33
  while(1)
34
  {
35
    if((ADCSRA & 0b00010000)==0b00010000)
36
    {
37
      s_Wert= ADCW;
38
      c_Wert= ~(s_Wert & 0xFF); 
39
      PORTB = c_Wert;
40
    }
41
  }
42
  
43

44
return 0;
45
}
Gast
A. R. schrieb:
> if((ADCSRA & 0b00010000)==0b00010000)

wenn statt kryptischer Bitfolgen die bekannten Konstanten verwendest,
ist das Programm für Dich und vor allem auch andere leichter 
verständlich

du schreibst ja auch nicht anstatt ADCSRA irgendeine Zahl hin
OP
Für mich wars so einfacher, weil ich genau weiß, welches Bit gemeint 
ist. Währe bei 2^5 (32) wohl auch erstichtlich gewesen.
Aber dies ist wohl eher die Preferenz des jeweiligen Programmierers.

Kann es sein, das GCC nicht mit Arrays arbeiten kann?

Folgender Code wird bei mir komplett übersprungen.
1
char array[100];
2
int i = 0;
3
while(i<100)
4
{
5
array[i]=0;
6
i++;
7
}
A. R. schrieb:
> Für mich wars so einfacher, weil ich genau weiß, welches Bit gemeint
> ist. Währe bei 2^5 (32) wohl auch erstichtlich gewesen.

Davon war aber auch nicht die Rede!
Jedes Bit hat einen Namen! Der wird im Datenblatt verwendet und durch 
die Header Files ist dieser Name auch für dein C-Programm verfügbar.

Die meisten Programmierer wollen nämlich gar nicht wissen, welche 
Bitnummer abgefragt wird, der symbolische Name ist völlig ausreichend. 
Das hat dann auch den Vorteil, dass der Compiler die Anpassung vornimmt, 
wenn dieses Bit bei einem anderen Prozessor zwar an anderer Stelle aber 
noch im gleichen Register beheimatet ist. Der Programmierer muss sich 
dann nicht darum kümmern.

> Kann es sein, das GCC nicht mit Arrays arbeiten kann?

Ehe wir hier weitermachen:
In 99.999% aller Fälle, in denen Programmierer den Compiler eines 
Fehlers bezichtigen, stellt sich hinten nach raus, dass die Kentnisse 
der Programmierer lückenhaft, wenn nicht gar fehlerhaft sind.

Also: Ehe du den Compiler eines Fehlers bezichtigst, stell sicher, dasss 
nicht du der mit dem Fehler bist.

>
> Folgender Code wird bei mir komplett übersprungen.
>
>
1
> char array[100];
2
> int i = 0;
3
> while(i<100)
4
> {
5
> array[i]=0;
6
> i++;
7
> }
8
>

Der Compiler kann ja auch rausgefunden haben, dass der Nettoeffekt darin 
besteht, dass Array komplett auf 0 zu setzen. Und der Compiler mag dafür 
bessere, schnellere Methoden haben, als das was du da hingeschrieben 
hast. Im Debugger siehst du dann keine 1 zu 1 Korrelation mehr zwischen 
den abgearbeiteten Anweisungen und dem was auf dem µC tatsächlich 
passiert. Solange das Endergebnis aber dasselbe ist, darf der Compiler 
das.
OP
>>if (ADCSRA & (1<<ADIF))

>>oder so:

>>if (ADCSRA & _BV(ADIF))

>>ist so denke mal viel leserlicher, oder ?

Danke für den Hinweis.

>Die meisten Programmierer wollen nämlich gar nicht wissen, welche
>Bitnummer abgefragt wird, der symbolische Name ist völlig ausreichend.
>Das hat dann auch den Vorteil, dass der Compiler die Anpassung vornimmt,
>wenn dieses Bit bei einem anderen Prozessor zwar an anderer Stelle aber
>noch im gleichen Register beheimatet ist. Der Programmierer muss sich
>dann nicht darum kümmern.

Klingt logisch!
Also sind für die Namen wie DDB0, DDB1, ADLAR etc. die jeweiligen 
Wertigkeiten hinterlegt. Bzw. die Wertigkeit n-1. Also für ADIF (2^5) 
ist eine 4 hinterlegt.

>Also: Ehe du den Compiler eines Fehlers bezichtigst, stell sicher, dasss
>nicht du der mit dem Fehler bist.

Da hast du vollkommen recht!
Deswegen habe ich hier nachgefragt, ob GCC arrays beherrscht bzw. wo der 
Fehler sein könnte.
Ich habe nun folgendes Programm erstellt.

Es soll eine 2 Dimensionale Matrix mit der Größe 3600Bytes erstellt 
werden.
1
#include <avr/io.h>
2
  int main(void)
3
{
4
  char array[360][10];
5
  for(int i=0;i<360;i++)
6
  {
7
    for(int k = 0; k<10; k++)
8
    {
9
      array[i][k]= 0x7E;
10
    }
11
  }
12
return 0;
13
}

Beim offline Debugging überspringt er die komplette Schleife.
Meinst du, dass der Compiler so intelligent ist?
OP
Der Compiler ist so intelligent!
Wenn später nicht auf das Array zugreife, so wird es erst gar nicht 
angelegt.

Wenn ich später eine Abfrage ergänze so klappt alles wie gewollt.
1
#include <avr/io.h>
2

3

4
  int main(void)
5
{
6
  char array[360][10];
7
  for(int i=0;i<360;i++)
8
  {
9
    for(int k = 0; k<10; k++)
10
    {
11
      array[i][k]= 0x7E;
12
    }
13
  }
14
  DDRB= 0xFF;
15
  PORTB = array[23][4];
16
return 0;
17
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 15 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.