Hallo,
ich bin etwas ratlos aufgrund meines Problems. Ich möchte eine einfache
Single-Channel ADC-Wandlung vornehmen, aber egal ob sich die
Eingangsspannung ändert bleibt der gewandelte Wert konstant. Vielleicht
weiß von Euch jemand rat oder kann mir auf die Spünge helfen was ich
falsch mache.
Ich benutze das STK500 + STK501 + AT90CAN128 + JTAGICEmkII + aktl.
Version AVR-Studio + aktl. Version Win-AVR
Hier "mein" Code:
1 | #include "config.h"
|
2 | #include "uart_lib.h"
|
3 | #include "uart_drv.h"
|
4 | #include "rtc_drv.h"
|
5 |
|
6 | void init(void)
|
7 | {
|
8 | Uart_select(UART_0);
|
9 | uart_init(CONF_8BIT_NOPAR_1STOP,38400);
|
10 |
|
11 | //Liefert die zu messende Spannung
|
12 | DDRB |= (1<<PB0);
|
13 | PORTB |= (1<<PB0);
|
14 | }
|
15 |
|
16 | unsigned int ReadChannel(unsigned char mux)
|
17 | {
|
18 | unsigned char i;
|
19 | unsigned int result;
|
20 |
|
21 | ADMUX = mux; // Kanal waehlen
|
22 | ADMUX |= (0<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
|
23 |
|
24 | ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
|
25 | // setzen auf 8 (1) und ADC aktivieren (1)
|
26 |
|
27 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
|
28 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
29 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
|
30 | while ( ADCSRA & (1<<ADSC) ) {
|
31 | ; // auf Abschluss der Konvertierung warten
|
32 | }
|
33 | result = ADCW; // ADCW muss einmal gelesen werden,
|
34 | // sonst wird Ergebnis der nächsten Wandlung
|
35 | // nicht übernommen.
|
36 |
|
37 | /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
|
38 | result = 0;
|
39 | for( i=0; i<4; i++ )
|
40 | {
|
41 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
|
42 | while ( ADCSRA & (1<<ADSC) ) {
|
43 | ; // auf Abschluss der Konvertierung warten
|
44 | }
|
45 | result += ADCW; // Wandlungsergebnisse aufaddieren
|
46 | }
|
47 | ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
|
48 |
|
49 | result /= 4; // Summe durch vier teilen = arithm. Mittelwert
|
50 |
|
51 | return result;
|
52 | }
|
53 |
|
54 | int main(void)
|
55 | {
|
56 | unsigned int counter, adc, i;
|
57 | counter = adc = 0;
|
58 | init();
|
59 | rtc_int_init();
|
60 |
|
61 | while(1)
|
62 | {
|
63 | for (i = 0; i< 8; i++)
|
64 | {
|
65 | wait_for(500);
|
66 | adc = ReadChannel(i);
|
67 | uart_mini_printf ("\r%04X Spannung(%u):%04X %umV\n", counter++, i, adc, (unsigned int)(((double)adc/1023)*5000));
|
68 | }
|
69 | }
|
70 | return 0;
|
71 | }
|
Die Funktionen wait_for() und rtc_... stammen aus den Atmel-Libs vom
DVK90CAN1-Board.
FOSC = 8 Mhz.
Als Messspannung hab ich den Ausgang von PB0 mit zwei 1k R
runtergeteilt. Als Referenzspannung ist AVCC ausgewählt und auf AREF ist
ein 100nF C dran. Die Spannungen an PB0 und AVCC sind wie erwartet mit
dem Oszi zu messen.
PB0/2 = 2.50V -> PA1
AVCC = 5.01V
Den Jumper AREF vom STK500 hab ich entfernt. Den Chip hab ich auch
bereits getauscht.
Die Schleife in main() hab ich eingebaut, weil mir beim wechseln des
Eingangsports aufgefallen ist, daß auf den anderen Eingangskanälen
ebenfalls "feste" Werte zu messen sind.
Lege ich PA1 auf GND ändert sich an den Ausgabewerten nichts und es ist
definitiv nur ein Kabel vom Spannungsteiler auf dem PA1-Pin gelegt, der
Rest des Port A ist nicht belegt.
Hier die UART-Ausgabe (2 Schleifendurchgänge):
1 | 0038 Spannung(0):034F 4139mV
|
2 | 0039 Spannung(1):02F0 3675mV
|
3 | 003A Spannung(2):02D9 3563mV
|
4 | 003B Spannung(3):02F3 3690mV
|
5 | 003C Spannung(4):03FF 5000mV
|
6 | 003D Spannung(5):03FF 5000mV
|
7 | 003E Spannung(6):03FF 5000mV
|
8 | 003F Spannung(7):03FF 5000mV
|
9 | 0040 Spannung(0):034F 4139mV
|
10 | 0041 Spannung(1):02F0 3675mV
|
11 | 0042 Spannung(2):02D9 3563mV
|
12 | 0043 Spannung(3):02F4 3695mV
|
13 | 0044 Spannung(4):03FF 5000mV
|
14 | 0045 Spannung(5):03FF 5000mV
|
15 | 0046 Spannung(6):03FF 5000mV
|
16 | 0047 Spannung(7):03FF 5000mV
|
Ich hoffe es kann mir jemand helfen. Danke.
MfG
Michael