Forum: Compiler & IDEs Auswertung Analog/Digitalkonverter Atmega 8


von Tobi (Gast)


Lesenswert?

Hallo,

ich will ein Analogsignal am ADC2 auslesen und diesen über die 
UART-Schnittstelle an den PC übergeben. Hierfür hab ich den unten 
angefügten Code geschrieben.

Beim Ausführen des Codes bekomme ich über den Uart immer die Wert 254 
(für high) und 255 (für low) übermittel, egal welche spannung ich am Pin 
PC1 anlege.

Sieht jemand den Fehler?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define F_CPU 8000000UL  // F_CPU Vielfaches von 1.8432 MHz um einen Kommunikationsfehler von 0,00% zu erhalten, Es findet kein auseinanderdriften der Controller aufrund unterschiedlicher Freuquenzen der Mikrocontroller statt.
5
// F_CPU auch bei den Fusebits einstellen.
6
#include <util/delay.h>
7
8
#define USART_BAUDRATE 38400UL   // Bauddrate
9
#define BAUD_PRESCALE ((F_CPU/(USART_BAUDRATE*16UL))-1)
10
void Start_UART (int asy_syn, int data_length, int paraty );
11
void Send_Uart(int Data);
12
13
14
int main(void)
15
{
16
  
17
  Start_UART(0,8,1); // USART initialisieren
18
  ADMUX = (0<<REFS1)|(0<<REFS0)|(0<<ADLAR)|(0<<MUX2)|(0<<MUX3)|(0<<MUX1)|(1<<MUX0); //Kanal ADC1, Referenzspannung AREF
19
  ADCSR = (1<<ADEN) |(1<<ADFR)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(0<<ADPS0)|(1<<ADSC); //Teiler 64
20
21
22
  sei();
23
24
  // Nichts tun. Die Interrupts erledigten den Rest
25
  while (1)
26
  {
27
    
28
    
29
    
30
  }
31
  
32
  
33
  
34
}
35
36
ISR (ADC_vect)
37
{
38
  int high,low;
39
  
40
  
41
  low = ADCL;
42
  high = ADCH;
43
44
  Send_Uart(low); //Senden über UART an den PC
45
  Send_Uart(high); //Senden über UART an den PC
46
  
47
  _delay_ms(500);
48
}

Zur besseren Übersicht habe ich die Funktionen Send_Uart und Start_Uart 
weggelassen, da diese einbandfrei auch in anderen Projekten 
funktionieren.

von Oliver (Gast)


Lesenswert?

Das ist mal wieder ein typisches Besipiel dafür, wie man mit gut 
gemeinten Kommentaren sich selber und den Rest der Welt vollkommen 
verwirren kann.

Entweder passt du deine KOmmentare an das an, was im Code steht, oder du 
schmeißt die komplett raus.

Zum Problem:
Du solltest dich schon entscheiden, ob du nun ADC2 (steht im Text) oder 
ADC1 (steht im Kommentar) oder ADC0 (steht im Code) auslesen möchtest. 
Sehr vermutlich hast du deine Eingangspannung an ADC4 oder so 
angeschlossen ;)

Dann ist deine ISR für den ADC-freerunning-Mode nicht geeignet. Da kommt 
alle 23 Zyklen ein Interrupt, deine ISR dauert dagegen ein Ewigkeit. Ab 
dem zweiten Durchlauf liest die den ADC irgendwann mitten in der 
Wandlung, das ergibt dann halt Müll.

Wenn du die DAten eh nur ausgeben willst, mach eine einzelne Wandlung, 
warte auf deren Ende, gib die aus, und danach starte eine neue.

Oliver

von Tobi (Gast)


Lesenswert?

Sorry für die verwirrende Bezeichnung der analogen Eingänge. Ich will 
auf adc1 einlesen. Hierfür muss ich doch im ADMUX Register die Bits MUX1 
MUX2 MUX3 auf 0 setzten und MUX0 auf 1 oder?

Mein langfristiges Ziel ist es ein kontinuierliches einlesen der werte 
zu erreichen, um diese zu speichern und nach der Beendigung des einlesen 
an den pc zu übertragen. Wie kann ich das realisieren?

von Oliver (Gast)


Lesenswert?

Tobi schrieb:
> Ich will
> auf adc1 einlesen. Hierfür muss ich doch im ADMUX Register die Bits MUX1
> MUX2 MUX3 auf 0 setzten und MUX0 auf 1 oder?

Was steht denn dazu in der Registerbeschreibung im Datenblatt?

> Mein langfristiges Ziel ist es ein kontinuierliches einlesen der werte
> zu erreichen, um diese zu speichern und nach der Beendigung des einlesen
> an den pc zu übertragen. Wie kann ich das realisieren?

Das geht dann schon im free-running-Mode. Eine Wert aus dem ADC lesen 
und abspeichern dauert in der ISR ja nicht so lange, aber deine jetzige 
ISR ist halt viel zu lang.

Oliver

von DomeG (Gast)


Lesenswert?

Speichere die Werte mit der ISR in einer globalen Variable oder Array 
(mit Zählvariable) und übertrage die Werte per UART in der 
While-Schleife...

Gruß Dome

von Karl H. (kbuchegg)


Lesenswert?

Tobi schrieb:

> Mein langfristiges Ziel ist es ein kontinuierliches einlesen der werte
> zu erreichen,

Trotzdem ist es eine gute Idee, erst mal mit getesteten und 
funktionierenden Funktionen anzufangen, wie sie zb im AVR-GCC-Tutorial 
Abschnitt ADC vorliegen.

Das hier
1
    .... ADMUX = (0<<REFS1)|(0<<REFS0) ...
stellt eine externe Referenzspannung ein. Hast du an AREF eie 
Referezspannung angeschlossen?


>  Ich will auf adc1 einlesen. Hierfür muss ich doch im
> ADMUX Register die Bits MUX1 MUX2 MUX3 auf 0 setzten
> und MUX0 auf 1 oder?

Wenn du dir die Bits ansiehst, dann hat Atmel die sinnvollerweise genau 
so angeordnet, dass die jeweilige Bitbelegung genau der Binärdarstellung 
der Kanalummer entspricht. Wenn du also vom ADC1 einlesen willst, dann 
oderst du einfach das Bitmuster für 1 in ADMUX ein und hast damit genau 
den Kanal 1 eingestellt
1
   ADMUX = (0<<REFS1)|(0<<REFS0) | 1;

willst du den Kanal 5, dann eben
1
   ADMUX = (0<<REFS1)|(0<<REFS0) | 5;
etc. etc.


es gibt keinen Grund, da jetzt grossartig zu künsteln.

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.