Forum: Mikrocontroller und Digitale Elektronik atmega 2560 ADC


von mario (Gast)


Lesenswert?

Hallo, ich versuche mit dem ADC Werte einzulesen und per uart ans 
Terminal zu schicken. Allerdings reagiert der ADC-Eingang auf gar 
nichts. Ich weiß nicht, wo der Fehler ist. Habe den Code hier aus dem 
Tutorial und etwas aus anderen Posts eingefügt. Ans Terminal werden zwar 
Werte gesendet, aber nichts was nach Messwert aussieht.
1
// AVR306: Using the AVR UART in C
2
// Routines for polled USART
3
// Last modified: 02-06-21
4
// Modified by: AR
5
6
/* Includes */
7
#include <avr/io.h>
8
#include "adc.h"
9
#include <util/delay.h>
10
11
12
/* Prototypes */
13
void USART0_Init( unsigned int baudrate );
14
unsigned char USART0_Receive( void );
15
void USART0_Transmit( unsigned char data );
16
void uart_Putc(unsigned char c);
17
void uart_Puts (char *string);
18
19
20
//#ifndef F_CPU
21
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
22
   F_CPU im Makefile definiert werden, eine nochmalige Definition
23
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
24
   #ifndef/#endif 
25
 
26
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
27
   verwendet wird und dort eine andere, nicht zur Hardware passende 
28
   Taktrate eingestellt ist: Dann wird die folgende Definition 
29
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
30
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
31
   noch nicht definiert: */
32
//#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 8000000"
33
#define F_CPU 8000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
34
                         // Ohne ergeben sich unten Fehler in der Berechnung
35
//#endif
36
 
37
#define BAUD 2400UL      // Baudrate
38
 
39
// Berechnungen
40
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
41
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
42
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
43
 
44
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
45
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
46
#endif 
47
48
49
50
/* Main - a simple test program*/
51
int main( void )
52
{
53
char s[20]=" ";
54
uint16_t temp;
55
56
  uint16_t adcval = 0;
57
  ADC_Init();
58
59
60
  USART0_Init( UBRR_VAL ); /* Set the baudrate to 19,200 bps using a 3.6864MHz crystal */
61
62
DDRC |= (1<<PC7)|(1<<PC6)|(1<<PC5)|(1<<PC4);
63
//unsigned char a;
64
PORTC = 0x80;
65
  for(;;)       /* Forever */
66
  {
67
uart_Puts (s);
68
    adcval = ADC_Read(10);  // Kanal 0
69
      // mach was mit adcval
70
71
    //adcval = ADC_Read_Avg(10, 3);  // Kanal 2, Mittelwert aus 4 Messungen
72
      // mach was mit adcval
73
_delay_ms(2000);
74
75
    temp = adcval/1000;
76
    adcval   -= temp*1000;
77
    USART0_Transmit(temp+0x30);
78
    
79
    temp = adcval/100;
80
    adcval   -= temp*100;
81
    USART0_Transmit(temp+0x30);
82
    
83
    temp = adcval/10;
84
    adcval   -= temp*10;
85
    USART0_Transmit(temp+0x30);
86
    
87
    USART0_Transmit(adcval+0x30);
88
89
_delay_ms(2000);
90
91
//uart_Puts ();
92
    //a = USART0_Receive() ;
93
  /*  if (adcval<100) {
94
    PINC = 0x40;
95
    USART0_Transmit(0x48);
96
    }  else { 
97
      USART0_Transmit(0x4C);
98
      PINC = 0x20;}*/
99
    //USART0_Transmit( USART0_Receive() ); /* Echo the received character */
100
  }
101
}
102
103
104
105
106
107
/* Initialize UART */
108
void USART0_Init( unsigned int baudrate )
109
{
110
  /* Set the baud rate */
111
  UBRR0H = (unsigned char) (baudrate>>8);                  
112
  UBRR0L = (unsigned char) baudrate;
113
  
114
  /* Enable UART receiver and transmitter */
115
  UCSR0B = ( ( 1 << RXEN0 ) | ( 1 << TXEN0 ) ); 
116
  
117
  /* Set frame format: 8 data 2stop */
118
  UCSR0C = (0<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);              //For devices with Extended IO
119
  //UCSR0C = (1<<URSEL)|(1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);   //For devices without Extended IO
120
}
121
122
123
/* Read and write functions */
124
unsigned char USART0_Receive( void )
125
{  PORTD = 0x40;
126
  /* Wait for incomming data */
127
  while ( !(UCSR0A & (1<<RXC0)) )   
128
    ;                      
129
  /* Return the data */
130
  return UDR0;
131
}
132
133
void USART0_Transmit( unsigned char data )
134
{
135
  /* Wait for empty transmit buffer */
136
  while ( !(UCSR0A & (1<<UDRE0)) )
137
    ;                       
138
  /* Start transmittion */
139
  UDR0 = data;               
140
}
141
142
void uart_Putc(unsigned char c)
143
{
144
    while (!(UCSR0A & (1<<UDRE0)));     
145
  UDR0 = c; 
146
//   _delay_ms(10);   
147
}//end uart_Putc()
148
149
void uart_Puts (char *string)
150
{
151
    while( *string != '\0' )
152
    {  
153
        uart_Putc(*string);
154
        string++;
155
    }
156
}//end uart_Puts()
1
// Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
2
// unter Verwendung der internen Referenzspannung von nominell 1,1V.
3
// Zur Anpassung an andere AVR und/oder andere Referenzspannungen
4
// siehe Erläuterungen in diesem Tutorial und im Datenblatt
5
 
6
7
#include <avr/io.h>
8
9
/* ADC initialisieren */
10
void ADC_Init(void) {
11
12
DDRK  = 0x00; //Define as Input
13
14
 
15
  uint16_t result;
16
 
17
  // interne Referenzspannung als Refernz für den ADC wählen:
18
  ADMUX = (1<<REFS1) | (1<<REFS0);
19
  
20
  // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
21
  // schon auf 0, also single conversion
22
  ADCSRA = (1<<ADPS2) |(1<<ADPS1) | (0<<ADPS0);     // Frequenzvorteiler
23
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
24
 
25
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
26
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
27
 
28
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
29
 ADCSRB=0x08|ADCSRA;
30
 DIDR2=0xFF;  
31
  while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
32
  }
33
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
34
     Wandlung nicht übernommen. */
35
  result = ADCW;
36
}
37
 
38
/* ADC Einzelmessung */
39
uint16_t ADC_Read( uint8_t channel )
40
{
41
  // Kanal waehlen, ohne andere Bits zu beeinflußen
42
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
43
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
44
  while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
45
  }
46
  return ADCL+ADCH*256;//ADCW;                    // ADC auslesen und zurückgeben
47
}
48
 
49
/* ADC Mehrfachmessung mit Mittelwertbbildung */
50
/* beachte: Wertebereich der Summenvariablen */
51
uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples )
52
{
53
  uint32_t sum = 0;
54
 
55
  for (uint8_t i = 0; i < nsamples; ++i ) {
56
    sum += ADC_Read( channel );
57
  }
58
 
59
  return (uint16_t)( sum / nsamples );
60
}

von Hubert G. (hubertg)


Lesenswert?

Was hast du am Eingang des ADC?
Was wird denn an den PC geschickt?

von Stefan E. (sternst)


Lesenswert?

1
 ADCSRB=0x08|ADCSRA;
Was genau sollte das denn werden?

1
  return ADCL+ADCH*256;
Hier ist nicht sichergestellt, dass die Register in der richtigen 
Reihenfolge ausgelesen werden.

1
    adcval = ADC_Read(10);  // Kanal 0
Was genau willst du überhaupt auswählen? Die "10" ist jedenfalls weder 
Kanal 0, noch Kanal 10.

von mario (Gast)


Lesenswert?

Hubert G. schrieb:
> Was hast du am Eingang des ADC?
> Was wird denn an den PC geschickt?

Da ist ein Funktionsgenerator dran, wo ich einen DC einstellen kann. An 
den PC kamen jetzt 4-stellige Dezimalzahlen an, aber die sind quasi quer 
über den Wertebereich verteilt.

Stefan Ernst schrieb:
> ADCSRB=0x08|ADCSRA;Was genau sollte das denn werden?

Weiß ich auch nicht so genau, wofür das sein soll, hatte ich hier 
irgendwo gesehen in einem Code, der funktionieren sollte.

>   return ADCL+ADCH*256;Hier ist nicht sichergestellt, dass die Register in der 
richtigen
> Reihenfolge ausgelesen werden.

Wie müsste das denn sinnvollerweise gemacht werden? Hatte vorher ADCW, 
aber das kann ich so nicht einfach übertragen.

>     adcval = ADC_Read(10);  // Kanal 0Was genau willst du überhaupt auswählen? 
Die "10" ist jedenfalls weder
> Kanal 0, noch Kanal 10.

Hm ich hatte das so verstanden, dass man so ADC10 wählt.

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.