AVR ADC Gain Differential Mode funktioniert nicht richig!

OP (Firma: google) #1876488
Lesenswert?

Hallo C-Kollegen,

ich möchte gerne die Verstärkungsfunktion des ADC nutzen.

Ich verwende einen AT90Can128 und programmiere in C.
Benutzen will ich ADC2 und ADC3, vorerst mal mit 1facher Verstärkung.
Kann ich auch als Referenzspannung 5V nehmen oder muss es 2,56V sein?
Wird das Ergebniss anders berechnet als beim normalen ADC?

Hier ist mein Code. ich weiß nicht ob die Initialisierungen des ADC alle 
korrekt sind. Vielleicht seht ihr ja gleich den Fehler.
1
// Hier die Variablen definieren, die im Programm verwendet werden sollen
2
int ADCWert, result;
3
int spannung;
4

5

6
// Definitionen für Unterprogramme
7
void init(void);
8

9

10
//###########################################################################################################
11
// Das Unterprogramm init: Hier werden die Initialisierungen vorgenommen
12
void init(void)
13
{
14

15

16
// Port B initialisieren
17
  //DDRB=0b00000111;         // B0 B1 B2 sind Ausgang 
18
  //PORTB=0b00011000;      // Ausgänge auf 0 setzen, Pullups für Taster1 & 2 ein
19
  DDRA = 0b11111111;      // Port A ist alles Ausgang
20
  PORTA = 0b00000001;      // Alle Ausgänge auf 0, Enabled auf 1 (lowactive)
21
  DDRC = 0b01000000;
22
  PORTC = 0b00000000;
23

24

25
  sei();            // Interrupts zulassen (für timer.c wichtig)
26
  adc_init(0b00001100);    // ADC, Kanal 2 aktivieren
27

28
//--------------------------------------------------------------------------------------------------------
29
  UARTInit();     // initialize the UART (serial port)
30
  UCSR1A |= (1<<RXC0);
31
  UCSR0B |= ((1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0));
32
  rprintfInit(UARTSendByte);    //mit rprintf-Funktion verknüpfen
33
//---------------------------------------------------------------------------------------------------------
34

35

36
} // Ende des init- Unterprogramms
37

38

39

40
// Hauptprogramm, muss in jedem C Programm vorhanden sein
41
int main (void) 
42
{ 
43
  init();   // Aufruf des Unterprogramms init, nur einmal zum Programmbeginn notwendig
44
    
45

46
ADCSRA= (1<<ADPS2) | (1<<ADPS1)|  // prescale faktor= 128 ADC l�uft
47

48
    (1 <<ADPS0) |      // mit 14,7456MHz/ 128 = 115,2kHz 
49

50
    (1 << ADEN)|      // ADC an
51

52
    (1 << ADSC);      // Beginne mit der Konvertierung
53

54
      
55

56
  
57
      //Verstärkung x1
58
      ADMUX  = 0b11011011;
59
      ADCSRB = 0b00000000;
60
      sbi(ADCSRA, ADEN);
61
      sbi(ADCSRA, ADSC);
62
      //sbi (ADMUX, MUX4);
63
      //sbi (ADMUX, MUX3);
64
      //cbi (ADMUX, MUX2);
65
      //sbi (ADMUX, MUX1);
66
      //sbi (ADMUX, MUX0);
67

68
  while(1)  // Befehl für Endlosschleife
69
    {
70
  
71
    //ADCWert = adc_read(2);
72
  
73
while ( (ADCSRA & (1<<ADSC)) != 0){} //Warten bis konvertierung beendet
74

75
                // Das sollte 25 ADC-Zyklen dauern!
76

77
                // also 1/4608 s
78

79
  result= ADCL; 
80

81
  result+=(ADCH <<8);  // Ergebnis zusammenbauen
82

83
  _delay_ms(500);
84

85
    rprintf("\r\nErgebniss:  %d",result);
86
    spannung = (5000 / 1023.0) * result;
87
    rprintf("\r\nSpannung: %d mV",spannung);
88

89

90
  } // Ende Endlosschleife
91
} // Ende von main


Vielen Dank für jede Hilfe!!!
martin
OP (Firma: google) #1876547
Lesenswert?

ja, ich habe ja alles unnötige aus dem sichtbarem code entfert um nicht 
zu verwirren, das wird nicht benötigt.

aber es gibt eine Uart-interrupt-routine

hier nochmal der code
1
// Include Dateien erweitern den Sprachumfang von C
2
#include "global.h"    // include our global settings
3
#include "lcd.h"          // Unterstützung für LCD-Anzeige
4
#include "adc.h"  // include printf function library
5
#include "delay.h"
6
#include "compat/deprecated.h"
7
#include "eeprom.h"
8
#include "uart.h"
9
#include "rprintf.h"
10
#include "stdio.h"
11
#include "stdlib.h"
12
#include "interrupt.h"
13
#include "dac8512.h"
14
#include "string.h"
15

16

17
// Hier die Variablen definieren, die im Programm verwendet werden sollen
18
int ADCWert, result;
19
int spannung;
20

21

22
// Definitionen für Unterprogramme
23
void init(void);
24

25

26
//###########################################################################################################
27
// Das Unterprogramm init: Hier werden die Initialisierungen vorgenommen
28
void init(void)
29
{
30

31

32
// Port B initialisieren
33
  //DDRB=0b00000111;         // B0 B1 B2 sind Ausgang 
34
  //PORTB=0b00011000;      // Ausgänge auf 0 setzen, Pullups für Taster1 & 2 ein
35
  DDRA = 0b11111111;      // Port A ist alles Ausgang
36
  PORTA = 0b00000001;      // Alle Ausgänge auf 0, Enabled auf 1 (lowactive)
37
  DDRC = 0b01000000;
38
  PORTC = 0b00000000;
39

40

41
  sei();            // Interrupts zulassen (für timer.c wichtig)
42
  adc_init(0b00001100);    // ADC, Kanal 2 aktivieren
43

44
//--------------------------------------------------------------------------------------------------------
45
  UARTInit();     // initialize the UART (serial port)
46
  UCSR1A |= (1<<RXC0);
47
  UCSR0B |= ((1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0));
48
  rprintfInit(UARTSendByte);    //mit rprintf-Funktion verknüpfen
49
//---------------------------------------------------------------------------------------------------------
50

51

52
} // Ende des init- Unterprogramms
53

54

55

56
// Hauptprogramm, muss in jedem C Programm vorhanden sein
57
int main (void) 
58
{ 
59
  init();   // Aufruf des Unterprogramms init, nur einmal zum Programmbeginn notwendig
60
    
61

62

63
      
64

65
  
66
      //Verstärkung x1
67
      ADMUX  = 0b11011011;
68
      ADCSRB = 0b00000000;
69
      sbi(ADCSRA, ADEN);
70

71

72

73
  while(1)  // Befehl für Endlosschleife
74
    {
75
  
76
    //ADCWert = adc_read(2);
77

78
//------------------------------------------------------------------------------------------------ Brauch ich das?? Kopiert aus adc.h
79

80
  ADCSRA= (1<<ADPS2) | (1<<ADPS1)|  // prescale faktor= 128 ADC l�uft
81

82
    (1 <<ADPS0) |      // mit 14,7456MHz/ 128 = 115,2kHz 
83

84
    (1 << ADEN)|      // ADC an
85

86
    (1 << ADSC);      // Beginne mit der Konvertierung
87
//-------------------------------------------------------------------------------------------------------------------------------
88
  
89
while ( (ADCSRA & (1<<ADSC)) != 0){} //Warten bis konvertierung beendet
90

91
                // Das sollte 25 ADC-Zyklen dauern!
92

93
                // also 1/4608 s
94

95
 
96
  
97
  result= ADCL; 
98

99
  result+=(ADCH <<8);  // Ergebnis zusammenbauen
100

101
    rprintf("\r\nErgebniss:  %d",result);
102
    spannung = (5000 / 1023.0) * result;
103
    rprintf("\r\nSpannung: %d mV",spannung);
104

105
_delay_ms(500);
106
  } // Ende Endlosschleife
107
} // Ende von main


hier ein paar terminal-ergebnisse:

Spannung: 4095 mV
Ergebniss:  978
Spannung: 4780 mV
Ergebniss:  250
Spannung: 1221 mV
Ergebniss:  225
Spannung: 1099 mV
Ergebniss:  971
Spannung: 4745 mV
Ergebniss:  837
Spannung: 4090 mV
Ergebniss:  63
Spannung: 307 mV
Ergebniss:  251
Spannung: 1226 mV
Ergebniss:  1007
Spannung: 4921 mV
Ergebniss:  838
Spannung: 4095 mV

im abstand von 500ms gemessen, schwankt total hin und her  ? :(

hilfee
OP (Firma: google) #1876575
Lesenswert?

hallo

der verbesserte code mit gescheiten initialisierungen und ADCW, 
Ergebniss ist aber das gleiche!!
1
//###########################################################################################################
2
// Das Unterprogramm init: Hier werden die Initialisierungen vorgenommen
3
void init(void)
4
{
5

6

7
// Port B initialisieren
8
  //DDRB=0b00000111;         // B0 B1 B2 sind Ausgang 
9
  //PORTB=0b00011000;      // Ausgänge auf 0 setzen, Pullups für Taster1 & 2 ein
10
  DDRA = 0b11111111;      // Port A ist alles Ausgang
11
  PORTA = 0b00000001;      // Alle Ausgänge auf 0, Enabled auf 1 (lowactive)
12
  DDRC = 0b01000000;
13
  PORTC = 0b00000000;
14

15

16
  //sei();            // Interrupts zulassen (für timer.c wichtig)
17
  cli();
18
  adc_init(0b00001100);    // ADC, Kanal 2 aktivieren
19

20
//--------------------------------------------------------------------------------------------------------
21
  UARTInit();     // initialize the UART (serial port)
22
  UCSR1A |= (1<<RXC0);
23
  UCSR0B |= ((1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0));
24
  rprintfInit(UARTSendByte);    //mit rprintf-Funktion verknüpfen
25
//---------------------------------------------------------------------------------------------------------
26

27

28
} // Ende des init- Unterprogramms
29

30

31

32
// Hauptprogramm, muss in jedem C Programm vorhanden sein
33
int main (void) 
34
{ 
35
  init();   // Aufruf des Unterprogramms init, nur einmal zum Programmbeginn notwendig
36
    
37

38

39
      
40

41
  
42
  //Verstärkung x1, Vref = 2,56V
43
  ADMUX |= (1<<REFS1) | (1<<REFS0) | (1 <<MUX4) | (1 << MUX3) | (1 << MUX1) | (1 << MUX0);
44
  ADCSRB = 0x00;
45

46

47

48

49
  ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1 <<ADPS0) | (1 << ADEN);  // prescale faktor= 128 ADC l�uft
50

51
                                  // mit 14,7456MHz/ 128 = 115,2kHz 
52

53
                                  // ADC an
54

55
  while(1)  // Befehl für Endlosschleife
56
    {
57
  
58
    //ADCWert = adc_read(2);
59
  
60
//------------------------------------------------------------------------------------------------ Brauch ich das?? Kopiert aus adc.h
61

62

63

64
  ADCSRA |= (1 << ADSC);      // Beginne mit der Konvertierung
65
//-------------------------------------------------------------------------------------------------------------------------------
66

67

68
while ( (ADCSRA & (1<<ADSC)) != 0){} //Warten bis konvertierung beendet
69

70
                // Das sollte 25 ADC-Zyklen dauern!
71

72
                // also 1/4608 s
73

74

75

76

77

78
  
79
result = ADCW;  // Ergebnis zusammenbauen
80

81
    rprintf("\r\nErgebniss:  %d",result);
82
    spannung = (2560 / 512.0) * result;
83
    rprintf("\r\nSpannung: %d mV",spannung);
84

85
_delay_ms(500);
86
  } // Ende Endlosschleife
87
} // Ende von main


habt ihr nicht so etwas wie ein Beispiel für mich für die Einstellungen

Momentan existiert eig keine Beschaltung ich hab an den Adc2 ein 
Netzteil gehängt und an den ADC3 auch eins, beide mit GND verbunden und 
stelle hier meine spannungen ein.
Da es sich nur um einen Versuch zu Hause handelt und die Schaltung 
selber sich in der Arbeit befindet :)

aber es sollte ja auch so gehen
#1876685
Lesenswert?

Martin 567 schrieb:
> adc_init(0b00001100);    // ADC, Kanal 2 aktivieren

Hierzu fehlt der Code - es ist unbekannt, was adc_init macht. 
Möglicherweise macht es etwas, was durch
1
>  ADMUX |= (1<<REFS1) | (1<<REFS0) | (1 <<MUX4) | (1 << MUX3) | (1 << MUX1) | (1 << MUX0);
und
1
> ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1 <<ADPS0) | (1 << ADEN);
nicht rückgängig gemacht wird, denn bei beiden wird verodert.  Wenn Du 
willst, dass genau dieser Wert drinsteht (wie es bei einer 
Initialisierung üblicherweise der Fall ist), solltest Du besser nicht 
verodern, sondern direkt zuweisen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren