Hi Leute!
Ich versuche schon seit geraumer Zeit den internen ADC des Atmega32 zum
laufen zu bekommen.
Ich benutze das STK500. Die Frequenz ist bei internen 4 Mhz.
Bei diesem Code habe ich testweise die interne Referenzspannungsquelle
ausgewählt, um zu sehen obs klappt. Aber an dem AREF Pin liegt keine
Spannung an. Woran könnte das liegen?
Hier ist mein Code:
1
#include<avr/io.h>
2
3
#define LOOP 5
4
#define COMM_ANODE_R 1
5
#define COMM_ANODE_M 1
6
#define COMM_ANODE_L 1
7
8
uint16_treadout();
9
voidsev_segm_l(uint16_tnumber);
10
voidsev_segm_m(uint16_tnumber);
11
voidsev_segm_r(uint16_tnumber);
12
13
unsignedchardigits[]={0b00111111,// 0
14
0b00000110,// 1
15
0b01011011,// 2
16
0b01001111,// 3
17
0b01100110,// 4
18
0b01101101,// 5
19
0b01111101,// 6
20
0b00000111,// 7
21
0b01111111,// 8
22
0b01101111,// 9
23
0b01000000// alles andere
24
};
25
26
27
28
voidmain()
29
{
30
31
DDRB=0xFF;// als Ausgang
32
DDRC=0xFF;
33
DDRD=0xFF;
34
35
uint16_terg;
36
37
erg=readout();
38
//einmal zum Warmlaufen
39
40
while(1)
41
{
42
43
for(inti=0;i<LOOP;i++)
44
erg+=readout();
45
46
erg/=LOOP;//Durchschnittswert aus LOOP Durchgängen
47
48
erg/=10;
49
50
sev_segm_l(erg/100);
51
// die letzte Stelle des Ergebnises
52
sev_segm_m((erg%100)/10);
53
// die mittlere Stelle...
54
sev_segm_r(erg%10);
55
// usw.
56
57
}
58
}
59
60
uint16_treadout()
61
{
62
63
uint16_terg;
64
65
ADCSRA|=(1<<ADEN);// ADC wird aktiviert
66
67
ADCSRA|=(1<<ADPS2)|(1<<ADPS0);// Frequenzteiler von 32 (4Mhz/32=125khz)
Tobi schrieb:
> ADCSRA |= (0<<ADEN);//ADC deaktivieren>> diese Zeile macht nicht, was sie soll!>> Ein Bit wird so gelöscht:> ADCSRA &= ~(1<<ADEN);//ADC deaktivieren>> MfG
Sry, da hab' ich nicht nachgedacht...
Aber an dem liegts nicht...
Dann ist halt der ADC die ganze Zeit eingeschaltet ;)
Mfg
>Aber an dem AREF Pin liegt keine>Spannung an. Woran könnte das liegen?
das sie intern ist. versuch doch einfach mal was einzulesen und das mit
einer messung mit multimeter zu vergleichen.
gast schrieb:
>>Aber an dem AREF Pin liegt keine>>Spannung an. Woran könnte das liegen?> das sie intern ist. versuch doch einfach mal was einzulesen und das mit> einer messung mit multimeter zu vergleichen.
Das verstehe ich nicht ganz. Wird die zu messende Spannung am AREF-Pin
ausgegeben? Wohl eher nicht oder? ;)
Nach meinem Code gibt der ATmega32 eine Dezimale 8 aus, unabhängig davon
was ich einlese. Habe ich im Code irgendeinen Denkfehler?
Mfg
Hi
>das sie intern ist. versuch doch einfach mal was einzulesen und das mit>einer messung mit multimeter zu vergleichen.
VREF liegt am entprechenden PIN an (wenn richtig eingestellt), und muss
dort auch zu messen sein.
MfG Spess
Hallo,
Du solltest die Initialisierung und den Wandler-Vorgang des ADC
voneinander trennen. Es macht keinen Sinn, bei jedem Aufruf von
"readout()" den Wandler neu zu initialisieren. Das macht man einmal beim
Start des Programms in "main". Auch das Abschalten des ADC nach jeder
Wandlung ist nicht sinnvoll; er bleibt an und ist so lange inaktiv, bis
eine neue Conversion (ADEN=1) gestartet wird.
Nur wenn sich der Eingangs-Kanal ändert, wird ADMUX mit dem neuen
Kanalwert beschrieben.
spess53 schrieb:
> Hi>>>das sie intern ist. versuch doch einfach mal was einzulesen und das mit>>einer messung mit multimeter zu vergleichen.>> VREF liegt am entprechenden PIN an (wenn richtig eingestellt), und muss> dort auch zu messen sein.>> MfG Spess
Genau deshalb wundere ich mich ja dass an dem AREF-Pin keine Spannung
anliegt.
Stimmen die Einstellung die ich vorgenommen habe?
Meine derzeitige Konfiguration:
An Vcc --> +5V
An GND --> GND
An AVcc -->+5V
An AGND --> GND
So müsste es doch klappen wenn ich als Referenzquelle AVCC einstelle
oder irre ich mich?
Wie sieht es mit den Fusebits usw aus? Habe ich die richtig gesetzt? (im
1. Beitrag habe ich Screens angehängt)
Mfg
Christoph
Spezi schrieb:
> Hallo,>> Du solltest die Initialisierung und den Wandler-Vorgang des ADC> voneinander trennen. Es macht keinen Sinn, bei jedem Aufruf von> "readout()" den Wandler neu zu initialisieren. Das macht man einmal beim> Start des Programms in "main". Auch das Abschalten des ADC nach jeder> Wandlung ist nicht sinnvoll; er bleibt an und ist so lange inaktiv, bis> eine neue Conversion (ADEN=1) gestartet wird.> Nur wenn sich der Eingangs-Kanal ändert, wird ADMUX mit dem neuen> Kanalwert beschrieben.
Okay, danke für den Tipp.
Aber an es müsste doch trotzdem funktionieren oder? xD
Mfg
>So müsste es doch klappen wenn ich als Referenzquelle AVCC einstelle>oder irre ich mich?
Wenn du AVCC einstellst kommt an AREF nichts raus.
Wozu auch?
>#define COMM_ANODE_R 1> if(COMM_ANODE_R)> {> }> else> {}
Schönen toten Code hast du dir da gebastelt.
if(COMM_ANODE_R) ist immer wahr. Das else kommt
nie zum Zug. Bestenfalls optimiert der Compiler
den else Zweig komplett weg.
> while(1)> {>> for(int i=0;i<LOOP;i++)> erg+=readout();
erg in der main() Loop sollte auch irgendwann
mal wieder auf 0 gesetzt werden. Sonst addierst du
da immer wieder Reste deiner Rechnung mit auf.
> ADMUX |= (1<<REFS0) | (1<<REFS1); // Interne Referenz
Damit wird die interne Referenz-Spannung ausgewählt (2.56V). AVcc als
Referenz ist eine andere Einstellung. (REFS0 = 1, REFS1 = 0)
> VREF liegt am entprechenden PIN an (wenn richtig eingestellt), und muss> dort auch zu messen sein.
Dies gilt für Vref = AVcc und für Vref = 2.56V intern. Siehe
Blockschaltbild des ADC im Datenblatt.
Hast Du den richtigen A/D-Eingangskanal ausgewählt, der für das STK500
passt? Zumindest sind laut Software alle Pins von Port A auf Eingang
geschaltet ...
Läuft der Rest des Programmes denn korrekt?
Holger wrote:
>Wenn du AVCC einstellst kommt an AREF nichts raus.>Wozu auch?
Dann schau Dir das ADC-Blockschaltbild an, wann Aref Spannung führt (FET
ist eingeschaltet). Dann sollte die Antwort, die ich oben nannte, klar
sein. (Spannung liegt an Aref an, wenn REFS0 = 1 ist.) Sonst würde der
empfohlene externe Kondensator an diesem Pin auch wenig Sinn machen ...
holger schrieb:
>>So müsste es doch klappen wenn ich als Referenzquelle AVCC einstelle>>oder irre ich mich?>> Wenn du AVCC einstellst kommt an AREF nichts raus.> Wozu auch?
Hmm, ich glaube so ganz habe ich die Funktion von dem AREF nicht
kapiert.
Ist das jetzt ein Ein- oder Ausgang?
Könntest du mir die Funktion des Pins bitte erklären?
holger schrieb:
>>#define COMM_ANODE_R 1>>> if(COMM_ANODE_R)>> {>> }>> else>> {}>> Schönen toten Code hast du dir da gebastelt.> if(COMM_ANODE_R) ist immer wahr. Das else kommt> nie zum Zug. Bestenfalls optimiert der Compiler> den else Zweig komplett weg.
^^
Es sei denn ich ändere das define, wenn ich Siebensegm.Anzeigen habe die
nicht COMM-ANODE sind, verstehst du? xD
Somit muss ich es nicht in allen 3 Funktionen umändern wenn ich den Code
vearbeiten will.
holger schrieb:
>erg in der main() Loop sollte auch irgendwann>mal wieder auf 0 gesetzt werden. Sonst addierst du>da immer wieder Reste deiner Rechnung mit auf.
Danke!
Ich glaube du hast damit voll ins Schwarze getroffen..
Ich hatte schon eine Vermutung dass ich irgendeinen schweren Denkfehler
eingebaut habe...
Ausprobieren kann ich es allerdings heute nicht mehr, jeder braucht
seinen Schlaf ;)
Also dann Gute Nacht, ich meld' mich morgen wieder obs geklappt hat!
Mfg
Schande über mich, dass mit dem ADC funktioniert immer noch nicht.
Ich habe auch nicht weiter daran herumgewerkelt, ich hatte andere
Projekte am laufen.
Hier nochmal mein neuer Code:
1
#include<avr/io.h>
2
3
//#define COMM_ANODE_R 0
4
//#define COMM_ANODE_M 0
5
//#define COMM_ANODE_L 0
6
7
voidADC_init(void);
8
uint16_tADC_read(uint8_tkanal);
9
10
//void sev_segm_l(uint16_t number);
11
//void sev_segm_m(uint16_t number);
12
//void sev_segm_r(uint16_t number);
13
14
unsignedchardigits[]={0b00111111,// 0
15
0b00000110,// 1
16
0b01011011,// 2
17
0b01001111,// 3
18
0b01100110,// 4
19
0b01101101,// 5
20
0b01111101,// 6
21
0b00000111,// 7
22
0b01111111,// 8
23
0b01101111,// 9
24
0b01000000// alles andere
25
};
26
27
28
29
voidmain()
30
{
31
32
//Ports als Ausgänge/Eingänge definieren
33
DDRA=0x00;
34
DDRB=0xFF;
35
DDRC=0xFF;
36
DDRD=0xFF;
37
38
uint16_terg;
39
40
//ADC initalisieren
41
ADC_init;
42
43
while(1)
44
{
45
erg=ADC_read(0);
46
//Auch wenn PORTB nur 8 Ausgänge hat
47
//muss es trotzdem was anderes
48
//als 0 ausgeben
49
PORTB=erg;
50
}
51
}
52
53
54
55
voidADC_init(void)
56
{
57
//Diese Funktion aktiviert den ADC
58
59
ADCSRA|=(1<<ADEN);//ADC aktivieren und
60
61
ADCSRA|=(1<<ADPS2)|(1<<ADPS1);//Teilungsfaktor auf 8 stellen
62
}
63
64
uint16_tADC_read(uint8_tkanal)
65
{
66
ADMUX=kanal;//Kanal des Multiplexers wählen:
67
68
ADMUX|=(1<<REFS0);//AVCC als Referenz
69
70
ADCSRA|=(1<<ADSC);//Messung starten
71
72
while(bit_is_set(ADCSRA,ADSC));// Auf Ergebnis warten:
73
74
returnADCW;
75
}
76
77
78
/*
79
80
void sev_segm_l(uint16_t number)
81
{
82
83
if(COMM_ANODE_L)
84
{
85
if( number < 10 )
86
PORTD = ~digits[number];
87
else
88
PORTD = ~digits[10];
89
}
90
else
91
{
92
if( number < 10 )
93
PORTD = digits[number];
94
else
95
PORTD = digits[10];
96
}
97
}
98
99
100
void sev_segm_m(uint16_t number)
101
{
102
if(COMM_ANODE_M)
103
{
104
if( number < 10 )
105
PORTC = ~digits[number];
106
else
107
PORTC = ~digits[10];
108
}
109
else
110
{
111
if( number < 10 )
112
PORTC = digits[number];
113
else
114
PORTC = digits[10];
115
}
116
}
117
118
void sev_segm_r(uint16_t number)
119
{
120
121
if(COMM_ANODE_R)
122
{
123
if( number < 10 )
124
PORTB = ~digits[number];
125
else
126
PORTB = ~digits[10];
127
}
128
else
129
{
130
if( number < 10 )
131
PORTB = digits[number];
132
else
133
PORTB = digits[10];
134
}
135
}
136
137
*/
Egal was ich an den Pin0 am PORTA anlege, alle Ausgänge des PORTB
bleiben auf Low.
Hier meine Beschaltung;
VCC=5V
GND=GND
AVCC=5V
AGND=GND
PINA0=Analoge Spannung
Doch dieses Mal liegt am AREF-Pin AVCC an. Das heißt die
Referenzspannung müsste da sein.
Mfg
Da ihr zu dem Code nichts zu sagen habt, gehe ich davon aus dass er in
Ordnung ist.
Dann kann es also nur an der Umgebung liegen.
Den ATMega32 habe ich dem linken roten Slot des STK500 drinnen.
Was muss ich bei dem Setzten der FUSEBITS beachten? Gibt es welche die
den ADC im Weg stehen könnten?
Mfg
ADMUX=kanal;//Kanal des Multiplexers wählen und Ref auf Extern!
4
5
ADMUX|=(1<<REFS0);//AVCC als Referenz
6
7
ADCSRA|=(1<<ADSC);//Messung starten
8
9
while(bit_is_set(ADCSRA,ADSC));// Auf Ergebnis warten:
10
11
returnADCW;
12
}
Dadurch schaltest du die Referenz bei jeder Messung einmal um. Das macht
Probleme, da man nach dem Umschalten kurz (125µs oder so) warten muss.
Besser:
1
uint16_tADC_read(uint8_tkanal)
2
{
3
ADMUX=kanal|(1<<REFS0);//Kanal des Multiplexers wählen und Ref auf AVCC
4
5
ADCSRA|=(1<<ADSC);//Messung starten
6
7
while(bit_is_set(ADCSRA,ADSC));// Auf Ergebnis warten:
8
9
returnADCW;
10
}
Und ich bin grad unsicher, aber muss es nicht "ADC_init();" statt
"ADC_init;" heißen?
Andreas R. schrieb:
> Ich hab mal deinen Code kommentiert:>>
1
>uint16_tADC_read(uint8_tkanal)
2
>{
3
>ADMUX=kanal;//Kanal des Multiplexers wählen und Ref auf Extern!
4
>
5
>ADMUX|=(1<<REFS0);//AVCC als Referenz
6
>
7
>ADCSRA|=(1<<ADSC);//Messung starten
8
>
9
>while(bit_is_set(ADCSRA,ADSC));// Auf Ergebnis warten:
10
>
11
>returnADCW;
12
>}
13
>
>> Dadurch schaltest du die Referenz bei jeder Messung einmal um. Das macht> Probleme, da man nach dem Umschalten kurz (125µs oder so) warten muss.
Echt unglaublich wieviele Genies sich hier in den Foren aufhalten. (Das
ist jetzt kein Sarkasmus^^)
Die Funktion ist jetzt so umgeändert, dass der Kanal automatisch 0 ist.
Ich glaube damit hast du mein Problem gelöst, bin mir noch nicht ganz
sicher..
Ich melde mich wieder! (diesmal sicher xD)
Also es sieht so aus als ob es funktionert ;)
Ich glaube die grobe Wandlung von 10bit in 8bit macht dem µC Probleme.
Dafür muss ich noch eine Lösung finden. Aber schonmal vielen Dank!!
Hier ist mein derzeitiger Code:
1
voidmain()
2
{
3
4
//Ports als Ausgänge/Eingänge definieren
5
DDRA=0x00;
6
DDRB=0xFF;
7
DDRC=0xFF;
8
DDRD=0xFF;
9
10
uint8_terg;
11
12
//ADC initalisieren
13
ADC_init();
14
15
while(1)
16
{
17
erg=ADC_read();
18
//Auch wenn PORTB nur 8 Ausgänge hat
19
//muss es trotzdem was anderes
20
//als 0 ausgeben
21
PORTB=erg;
22
}
23
}
24
25
26
27
voidADC_init()
28
{
29
//Diese Funktion aktiviert den ADC
30
31
ADCSRA|=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);//ADC aktivieren und
32
33
ADMUX|=(1<<REFS0);//AVCC als Referenz
34
35
}
36
37
uint16_tADC_read()
38
{
39
40
ADCSRA|=(1<<ADSC);//Messung starten
41
42
while(bit_is_set(ADCSRA,ADSC));// Auf Ergebnis warten: