ADC Atmega16 single mode

Gast #4300841
Lesenswert?

Hallo,

ich hatte bisher immer einen single mode beim ADC Atmega8 verwendet. Nun 
wollte ich auf differential mit Atmega16 umstellen. Dabei habe ich auch 
den Programmcode geändert. Da ich es nicht ganz hinbekommen habe wollte 
ich nun zurück zu single mode wechseln. Nun klappt gar nichts mehr -.- 
und ich sehe den Fehler nicht. Kann eventuell einer von euch über den 
Code schauen?

Ich habe momentan GND an ADC0 anliegen. Dennoch wird mir immer der Wert 
276 angezeigt.
1
#include <avr/io.h>
2
#include <util/delay.h>
3

4
void adc_init( void )
5
{ 
6
  ADMUX = (1<<REFS1) | (1<<REFS0);
7
  _delay_us( 10 );
8
 // ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler, Dummyreadout
9
  ADCSRA = (1<<ADPS2);     // Frequenzvorteiler, Dummyreadout
10
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
11
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung
12
  while (ADCSRA & (1<<ADSC)) {         // auf Abschluss der Konvertierung warten
13
  }
14
  (void) ADCW;
15
}
16

17

18
uint16_t ADC_Read_single()
19
{
20

21
  //ADMUX = (0<<MUX4) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);
22
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
23
  while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
24
  }
25
  return ADCW;                    // ADC auslesen und zurückgeben
26
  
27
}

=======================
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdlib.h>
4
#include "lcd-routines.h"
5
#include "myADC.h"
6

7
uint16_t adcval;
8

9
int main(void)
10
{
11
   adc_init();
12
   lcd_init();
13
      
14
  while(1)
15
  {
16
    adcval = ADC_Read_single;  
17

18
    lcd_setcursor(0,1);
19
    
20
    char Buffer[20];
21
    itoa( adcval, Buffer, 10 );
22
    lcd_string( Buffer );
23
    
24
    _delay_us( 100 );
25
  }
26
}
Gast #4300898
Lesenswert?

damit hatte ich zwischen den ADC-Eingängen umgeschaltet aber sollte 
jetzt grundsätzlich auf "0" stehen, sodass nur ADC0 für die single conv. 
verwendet wird.

Hatte ich ursprünglich verwendet, um auf diff-mode umzustellen (dann 
natürlich nicht mit 00000 sondern 01011).
(Firma: CIA) #4300932
Lesenswert?

Wie kommst Du denn auf den Code...? Zusammengewürfelt aus Beispielen, 
oder selber ausgedacht mit Datenblatt zur Hand?

Warum hast Du den Vorteiler so genommen wie Du es getan hast? Warum die 
interne Ref Spannung auf 2,56V Hast Du einen Kondensator am AREF pin?

Mit wieviel MhZ läuft dein Atmega8
Gast #4300949
Lesenswert?

Ich habe mit einem Tutorial hier angefangen und das dann über das manual 
auf meine benötigten Funktionalitäten angepasst (bspw. nur single 
conversion und fest definierten channel).

Die interne Ref Spannung habe ich verwendet um "klein" anzufangen. 
Wollte einfach mal schauen wie das so funktioniert und dafür war Vref 
ausreichend. Einen Kondensator habe ich nicht angeschlossen.

Atmega läuft mit 1 Mhz. Das sollte sich auch mit F_CPU decken, sonst 
würde das LCD nichts anzeigen.
(Firma: CIA) #4300964
Lesenswert?

Hier ein minimalistisches funktionierendes Beispiel, entsprechend an LCD 
anpassen:
1
//*******************************************************************************
2
//*
3
//* ADC single conv demonstration
4
//* Datum: 19/01/2014 Version:
5
//* Autor: Dr. ThXXXXXXXXX
6
//*
7
//* Informationen zur Beschaltung:
8
//* SDK600 SOIC
9
//* Prozessor: ATmega8 Quarzfrequenz: INT  1Mhz
10
//* Eingaenge: PORTC PC0 <- Potentiometer (VCC  PC0   GND)
11
//* Ausgaenge: PORTB 8 LED'S
12
//*
13
//* Informationen zur Funktionsweise: Binäre Ausgabe des HI anteils des ADC auf PORTB
14
//*
15
//*******************************************************************************
16
#define F_CPU 1000000UL
17
#include <avr/io.h>
18

19

20

21

22
int main(void)
23
{
24
  uint8_t adclow;
25
  uint8_t adchigh;
26
  
27
  
28
  //setup PortB output
29
  DDRB  = 0b11111111;
30
  PORTB  = 0b11111111;
31
  //initialisaton of ADC0 Vref = VCC, fCPU/8, left adjusted
32
  ADMUX  |= (1<<REFS0) | (1<<ADLAR);
33
  ADCSRA  |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
34
  
35
  
36
  while(1)
37
    {  
38
        
39
    ADCSRA |= (1<<ADSC);
40
    while(ADCSRA & (1<<ADSC));
41
    
42
    adclow = ADCL;
43
    adchigh= ADCH;
44
    
45
    
46
    
47
    //ausgabe nur wenn unterschied zu vorheriger messung  > 10
48
    
49
    if(abs(PORTB-adchigh)>10)
50
    PORTB = adchigh;
51
    
52
        
53
    }
54
}
55
}
Gast #4301049
Lesenswert?

Ich habe jetzt auf diff mode geswitcht. Funktioniert super.

Nur noch eine Frage zur Versätkrung mit 200x.  Was genau verstärkt er 
hier? Beide Eingänge falls die Differenz im mV Bereich liege um diese 
dennoch zu identifizieren? Sprich sollte ich einen sehr großen 
Unterschied feststellen wird mir ab einer bestimmten Schranke immer 255 
angezeigt, also irgendwann könnte der ADC den Unterschied nicht mehr 
messen da er aufgrund der 200x außerhalb der Range liegt. Ist das so?
(Firma: CIA) #4301554
Lesenswert?

Peter II schrieb:
> oder du?
> (void) ADCW;
>
> ist ok, und macht auch sinn.

Abgesehen von der Tatsache das die Frage darauf abzielte zu evaluieren 
ob der TO weiss was er da macht und in keiner Weise von mir offen, oder 
implizit darauf hingewiesen wurde das diese Instruktion an dieser Stelle 
falsch sei, oder generell keinen Sinn macht, würde mich an dieser Stelle 
aber natürlich interessieren warum das genau "hier" Ok ist und auch noch 
einen Sinn hat. Ich lerne nämlich immer gerne etwas dazu. Vielen Dank im 
Voraus!

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