www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega 8 Problem mit ADC und Uart


Autor: J. Hebeler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

#define F_CPU 16000000
#define ADC0 0
#define ADC1 (1 << MUX0)
#define ADC2 (1 << MUX1)


#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>

char ADCConvert8Bit(char channel)
{
  ADMUX &= ~((1 << MUX0) | ( 1 << MUX1) | (1 << MUX2) | (1 << MUX2) | (1 << MUX3));
  ADMUX |= channel;
  ADCSRA |= (1 << ADSC);
  while(ADCSRA & (1 << ADSC)){}
  return ADCW;
}

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

int main(void)
{
  DDRC = 0;
  DDRD = (1 << PD1);
  PORTC = 0;
  PORTD = 0;
  DDRB = 0xff;
  PORTB = 0;
  char X = 0, Y = 0, Z = 0, result = 0;

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

  ADCSRA |= (1<<ADSC);
  while (ADCSRA & (1<<ADSC) ) {}
  result = ADCW;

  UCSRB = (1 << TXEN);
  UBRRL = 51;

  while(1)
  {
    X = ADCConvert8Bit(ADC0);
    Y = ADCConvert8Bit(ADC1);
    Z = ADCConvert8Bit(ADC2);
    SendData('X');
    SendData('Y');
    SendData('Z');
    SendData(X);
    SendData(Y);
    SendData(Z);
  }


  return 0;
}
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

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: J. Hebeler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Buchstaben XYZ kommen?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was hast du an den ADC Eingängen hängen?

Autor: J. Hebeler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Die Buchstaben XYZ kommen?
Die kommen Normal an, und danach noch ???, also so in etwa:
XYZ???XYZ???XYZ???XYZ???XYZ???

Autor: J. Hebeler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Was hast du an den ADC Eingängen hängen?
Nen Accelerometer, Spannung ist auch da.

Autor: Marco U. (Gast)
Datum:

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

PS: Deklariere deine result Variable mal als INT oder uint8_t.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: J.Hebeler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm dir doch einfach mal die ADC Routinen aus dem
AVR-GCC-Tutorial

Immer diese Rumraterei.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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.

MfG Spess

Autor: J. Hebeler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: J. Hebeler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, es funktioniert jetzt. Nochmal der Finale Quellcode, für alle die 
das gleiche Problem haben:

#define F_CPU 16000000
#define ADC0 0
#define ADC1 (1 << MUX0)
#define ADC2 (1 << MUX1)


#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>

char ADCConvert8Bit(char channel)
{
  ADMUX &= ~((1 << MUX0) | ( 1 << MUX1) | (1 << MUX2) | (1 << MUX2) | (1 << MUX3));
  ADMUX |= channel;
  ADCSRA |= (1 << ADSC);
  while(ADCSRA & (1 << ADSC)){}
  return ADCH;
}

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

int main(void)
{
  DDRC = 0;
  DDRD = (1 << PD1);
  PORTC = 0;
  PORTD = 0;
  DDRB = 0xff;
  PORTB = 0;
  char X = 0, Y = 0, Z = 0;
  uint16_t result = 0;

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

  ADCSRA |= (1<<ADSC);
  while (ADCSRA & (1<<ADSC) ) {}
  result = ADCW;

  UCSRB = (1 << TXEN);
  UBRRL = 51;

  while(1)
  {
    X = ADCConvert8Bit(ADC0);
    Y = ADCConvert8Bit(ADC1);
    Z = ADCConvert8Bit(ADC2);
    SendData('X');
    SendData('Y');
    SendData('Z');
    SendData(X);
    SendData(Y);
    SendData(Z);
  }


  return 0;
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.