ATmega 8 Problem mit ADC und Uart

Gast #2044230
Lesenswert?

Folgender Code soll von den ersten 3 ADC des Mega8 den 8-Bit wert lesen 
und diesen dann per Uart an meinem PC sendet. Dort kommen aber nur 3 
Fragezeichen an. Entweder habe ich einen Fehler im Code oder einen 
Fehler im Zeichensatz des Testprogramms.
1
#define F_CPU 16000000
2
#define ADC0 0
3
#define ADC1 (1 << MUX0)
4
#define ADC2 (1 << MUX1)
5

6

7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11

12
char ADCConvert8Bit(char channel)
13
{
14
  ADMUX &= ~((1 << MUX0) | ( 1 << MUX1) | (1 << MUX2) | (1 << MUX2) | (1 << MUX3));
15
  ADMUX |= channel;
16
  ADCSRA |= (1 << ADSC);
17
  while(ADCSRA & (1 << ADSC)){}
18
  return ADCW;
19
}
20

21
void SendData(char data)
22
{
23
  while(!(UCSRA & (1 << UDRE)));
24
  UDR = data;
25
}
26

27
int main(void)
28
{
29
  DDRC = 0;
30
  DDRD = (1 << PD1);
31
  PORTC = 0;
32
  PORTD = 0;
33
  DDRB = 0xff;
34
  PORTB = 0;
35
  char X = 0, Y = 0, Z = 0, result = 0;
36

37
  ADMUX = (1 << REFS1) | (1 << REFS0) | (1 << ADLAR);
38
  ADCSRA = (1 << ADEN);
39

40
  ADCSRA |= (1<<ADSC);
41
  while (ADCSRA & (1<<ADSC) ) {}
42
  result = ADCW;
43

44
  UCSRB = (1 << TXEN);
45
  UBRRL = 51;
46

47
  while(1)
48
  {
49
    X = ADCConvert8Bit(ADC0);
50
    Y = ADCConvert8Bit(ADC1);
51
    Z = ADCConvert8Bit(ADC2);
52
    SendData('X');
53
    SendData('Y');
54
    SendData('Z');
55
    SendData(X);
56
    SendData(Y);
57
    SendData(Z);
58
  }
59

60

61
  return 0;
62
}
Ich denke es ist mal wieder ein dummer Fehler, der mir nicht auffallen 
will...
Ich hoffe man kann mir helfen und bedanke mich mal für Hilfe im voraus 
;)

MfG J. Hebeler
#2044253
Lesenswert?

J. Hebeler schrieb:
> SendData('X');
>
>     SendData('Y');
>
>     SendData('Z');
>
>     SendData(X);
>
>     SendData(Y);
>
>     SendData(Z);

Die ersten 3 Zeichen sind Ascii-Zeichen, die dein PC auch versteht.
Die letzten sind irgendwelche Zahlenwerte(Hex), die er versucht als 
Ascii zu interpretieren, aber meistens nicht versteht.

Da musst du jeweils zwei Ascii-Zeichen draus machen.

mfg.
Gast #2044258
Lesenswert?

Hi

>  return ADCW;

Bei ADLAR=1 ist nur ADCH relevant.

>void SendData(char data)
>{
>  while(!(UCSRA & (1 << UDRE)));
>  UDR = data;
>}

Und du meinst, das das dir einen Wert in ASCII ausgibt?

MfG Spess
Gast #2044290
Lesenswert?

>>Ascii zu interpretieren, aber meistens nicht versteht.
Ist mir klar, sollte aber zumindest bei Wertänderung des ASCII Zeichens 
am Computer bewirken, der zeigt mir aber nur Fragezeichen an. Wenn das 
das Problem wäre, würde ich anstelle der ASCII-Zeichen schnell die 
Hexwerte ausgeben lassen.
>>Und du meinst, das das dir einen Wert in ASCII ausgibt?
Es werden Daten binär übertragen, es ist mir egal ob es ASCII Zeichen 
sind.
Ich will mir nur nicht stundenlang mit Debugging verbringen, um dann 
einen einfachen Fehler in der Firmware zu Korrigieren.

MfG J. Hebeler.
Gast #2044671
Lesenswert?

Hi

>Zum Wandeln der Int Werte in ASCII Code kannst du die Funktion
>itoa(int,char*,Basis); aus der stdlib.h hernehmen.

Dazu müsste er von 'char ADCConvert8Bit(char channel)' erst mal 
vernünftige Werte bekommen:

>return ADCW;

Er hat mit ADLAR=1 auf linksbündig gestellt. Der Compiler übergibt aber 
(nach meiner Simulation) an 'SendData(X)' ADCL und nicht ADCH.

MfG Spess
Gast #2044682
Lesenswert?

>>Dazu müsste er von 'char ADCConvert8Bit(char channel)' erst mal
vernünftige Werte bekommen:
Jop, hab ich auch getestet, ich hatte es zuerst mit ADCH, dann hab ich 
in eurem Tut ADCW gelesen, das Probiert, hat halt auch net funktioniert, 
jetzt wieder auf ADCH umgestellt.
Hab jetzt mein Testprogramm aufm PC umgeschrieben, das es mir nur noch 
die Zahlenwerte der chars ausgibt. Sehe das XYZ und 3 mal 255 ankommt.
Kann es sein, das die Interne Refernez falsch gewählt ist, bzw falsch 
angesteuert?
Ich habe Signalpegel von 1,6 - 2,3V gemessen und habe an AREF ein C=100n 
gegen GND geschaltet.

MfG J.Hebeler
Gast #2044693
Lesenswert?

Hi

ADMUX = (1 << REFS1) | (1 << REFS0) | (1 << ADLAR);

stellt die 2,56V Referenz ein.

>Sehe das XYZ und 3 mal 255 ankommt. Kann es sein, das die Interne Refernez
>falsch gewählt ist, bzw falsch angesteuert?

Das ist allerdings ein Indiz, das die Eingansspannung >= Vref ist.
Nimm doch einfach mal VCC als Referenz.

MfG Spess
Gast #2045212
Lesenswert?

>>Noch was: Auch wenn du nur 8 Bit haben willst, sind 16MHz für den
ADC-Takt wesentlich zu schnell. Stell mal den Prescaler ein.

Hab ich jetzt mal gemacht

>>Das ist allerdings ein Indiz, das die Eingansspannung >= Vref ist.
Nimm doch einfach mal VCC als Referenz.
Jop, hab ich jetzt auch gemacht, es kommen jetzt andere werte an, Ich 
muss die aber erst gescheit aufbereiten, ansonsten kann ich nicht 
verifizieren, das es die richtigen sind.
Danke für die Hilfe.
Gast #2045226
Lesenswert?

Ja, es funktioniert jetzt. Nochmal der Finale Quellcode, für alle die 
das gleiche Problem haben:
1
#define F_CPU 16000000
2
#define ADC0 0
3
#define ADC1 (1 << MUX0)
4
#define ADC2 (1 << MUX1)
5

6

7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include <stdio.h>
10
#include <stdlib.h>
11

12
char ADCConvert8Bit(char channel)
13
{
14
  ADMUX &= ~((1 << MUX0) | ( 1 << MUX1) | (1 << MUX2) | (1 << MUX2) | (1 << MUX3));
15
  ADMUX |= channel;
16
  ADCSRA |= (1 << ADSC);
17
  while(ADCSRA & (1 << ADSC)){}
18
  return ADCH;
19
}
20

21
void SendData(char data)
22
{
23
  while(!(UCSRA & (1 << UDRE)));
24
  UDR = data;
25
}
26

27
int main(void)
28
{
29
  DDRC = 0;
30
  DDRD = (1 << PD1);
31
  PORTC = 0;
32
  PORTD = 0;
33
  DDRB = 0xff;
34
  PORTB = 0;
35
  char X = 0, Y = 0, Z = 0;
36
  uint16_t result = 0;
37

38
  ADMUX = (1 << REFS0) | (1 << ADLAR);
39
  ADCSRA = (1 << ADEN) | (1 << ADPS1);
40

41
  ADCSRA |= (1<<ADSC);
42
  while (ADCSRA & (1<<ADSC) ) {}
43
  result = ADCW;
44

45
  UCSRB = (1 << TXEN);
46
  UBRRL = 51;
47

48
  while(1)
49
  {
50
    X = ADCConvert8Bit(ADC0);
51
    Y = ADCConvert8Bit(ADC1);
52
    Z = ADCConvert8Bit(ADC2);
53
    SendData('X');
54
    SendData('Y');
55
    SendData('Z');
56
    SendData(X);
57
    SendData(Y);
58
    SendData(Z);
59
  }
60

61

62
  return 0;
63
}

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