Forum: Mikrocontroller und Digitale Elektronik ADC am AT90CAN128 funktioniert nicht, Fehler im Code?


von Mike G. (Firma: ixwyc) (balu1980)


Lesenswert?

Moin,

ich möchte den AD Wandler Eingang PA0 am AT90CAN128 auszulesen, und den
gelesenen Wert an der Schnittstelle USART0 auszugeben.

Die Initialisierung und das senden der Zeichenfolge "neu: " der USART
funktoniert sobald ich die zum ADC gehörenden Zeilen in der main routine
ausklammere. Sobald die ADC Zeilen dazu kommen funktioniert nix mehr.

Beschaltet habe ich den AT90CAN128 mit einer externen Referenzspannung 
von
1,55V. An den Eingang PA0 habe ich über einen Tiefpassfilter ein 
Audiosignal gegeben (SS 0,775V), welches über den Spannungsteiler
verschoben wird, da meines Wissens nach der µC die negative Halbwelle 
nicht
erfassen kann. siehe Anhang.

Habe ich im Quelltext einen Fehler, oder waran liegt es?

Ein weiteres Problem was ich habe ist, das die Baudratenberechnung nicht
funktioniert. Trage ich die 8 ein funktioniert es.

Gruß Mike


Code:

#include <avr/io.h>

//---------------------------------------------------------------------- 
----

#ifndef F_CPU
// Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert ist

#define F_CPU 16000000UL
// Quarz mit 16 Mhz definiert

#endif

#define UART_BAUD 115200
// Baudrate auf 115200 Baud gesetzt

#define UART_BAUD_REAL (((F_CPU)/(UART_BAUD*16))-1)
// Kontrollberechnung Baudrate

//---------------------------------------------------------------------- 
----

void UART_init (void)
//  UART initialisieren
{
  UBRR0H = 0;
  UBRR0L = 8;
  //UBRR0L = UART_BAUD_REAL; -->Funktioniert nicht<--
  // Baudrate setzen

  UCSR0C = (0 << UMSEL0) | (0 << UPM0) | (1 << USBS0) | (3 << UCSZ0);
  // Signal Format: 8data, no parity, 2 stop bits

  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  // Aktivieren des Empfängers und des Senders der UART0
}

void UART_send (unsigned char UART_send)
{
  while (!(UCSR0A & (1<<UDRE0)));
  // Warten bis senden bereit

  UDR0 = UART_send;
  //Schreibt Daten auf die Uart
}

//---------------------------------------------------------------------- 
----

void ADC_init(void)
{
  ADMUX = 0;
  // Kanal AD0 gewählt

  ADMUX |= (1 << REFS0);
  // Externe Rferenzspannung verwenden

  ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)
  | (1 << ADATE);
  // ADC aktivieren, Teilungsfaktor auf 128

  ADCSRA |= (1 << ADSC);
  while (ADCSRA & (1 << ADSC))
  {
    ;
  }
  // Eine ADC Wandlung zum Warmlaufen ohne den Wert zu übergeben
}

//---------------------------------------------------------------------- 
----

unsigned int ADC_read()
{
  ADCSRA |= (1<<ADSC);
  // eine Wandlung

    while ( ADCSRA & (1<<ADSC) )
  {
      ; // auf Abschluss der Konvertierung warten
    }

    return ADCW;
  // Wandlungsergebnisse zurückgeben
}

//---------------------------------------------------------------------- 
----

int main (void)
{

  unsigned int ADC_wert;

  UART_init();

  ADC_init();


  for (;;)
  {

    UART_send('N');
    UART_send('E');
    UART_send('U');
    UART_send(':');
    UART_send(' ');

  ADC_wert = ADC_read();

  UART_send (ADC_wert);


   }
}

von Mike G. (Firma: ixwyc) (balu1980)


Angehängte Dateien:

Lesenswert?

habe doch glatt das jpg vergessen

von lkmiller (Gast)


Lesenswert?

Das ist jetzt ja nun nicht der richtige Eingang für den AD-Wandler.
Datenblatt:
>Port A is an 8-bit bi-directional I/O port
AD0 heisst Adresse+Daten Bit 0

Schon besser wäre:
>Port F serves as the analog inputs to the A/D Converter
hier z.B. AIN0

von lkmiller (Gast)


Lesenswert?

Rechne mal von Hand (mit dem Taschenrechner) aus,
was die Baudratenformel hergibt:
7,68055555
Also werden hier 7 eingetragen.

Ich würde da mal behaupten, dass du die 115200 Baud
nicht zuverlässig bekommen wirst (mit 10% Fehler).

Erst mit 38400 werden mit weniger als 1% Fehler erreicht,
das geht sicher.

von Mike G. (Firma: ixwyc) (balu1980)


Lesenswert?

Moin,

vielen dank für deine Antwort lkmiller, wer lesen kann ist klar im 
Vorteil.....

Weis auch nicht was mich da mit dem ADC geritten hat, habe mich in die
irre führen lassen.

So, hab jetzt das Signal auf PF0 umgelötet, und siehe da es funktioniert
etwas. Ich bekomme Aber nur Sonderzeichen über die UART gesendet, der 
Hinweis
"Neu: " kommt wie gewünscht. Danach nur Karos, Herzen, etc.

Wie bekomme ich hier nur vernünftige Zahlenwerte?

Mit der Baudratenberechnung habe ich die 7 mal ausprobiert, es 
funktioniert
nicht.


Gruß Mike

von lkmiller (Gast)


Lesenswert?

>Mit der Baudratenberechnung habe ich die 7 mal ausprobiert, es
>funktioniert nicht.
FULL ACK
Was ich sagen wollte, ist:
Auch mit 8 für 115200 Baud funktioniert es nur sehr zufällig!
An einem anderen PC oder einer anderen RS232-Schnittstelle
geht dann eben ab und an mal was schief.

Erst mit Baudrate 38400 ist die Übertragung sicher.



Klar, dass nach "NEU:  " immer nur 1 (ein) Sonderzeichen kommt.
UART_send verschickt genau 1 Zeichen (Byte).
>  UART_send (ADC_wert);
Nur das Low-Byte vom ADC_wert wird verwendet
und nur ein Teil des Wertebereichs sind lesbare ASCII-Zeichen.

Sieh mal nach itoa() und versuch den Ergebnis-String zu senden.

von Kai G. (runtimeterror)


Lesenswert?

Und informiere dich über Baudratenquarze - dann klappt's auch mit 
den höheren Baud-Raten ;)

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.