www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART gibt mittendrin Mist aus


Autor: Stefan R. (quark48) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich hab nen Spannungslogger aufm Brotbrett gefrickelt, der den aktuellen 
Spannungswert vom ersten ADC alle 100ms über UART zum PC schickt.

Gut, das ganz funzt schon. Nur mittendrin haut mir der AVR sehr komische 
Zahlenwerte rein, auch die nach dem Schrägstrich immer mitgeschickte 
Quersumme stimmt dann nicht!

Ja, der ATMega8-AVR hängt an nem externen Quarz mit 4 MHz, ist alles mit 
den Fusebits eingestellt, nebenbei ist die Brown-Out-Detection ist 
aktiv, und die CKOPT-Fuse ist angeknipst (Soll den Quarz angeblich mit 
höherer Spannung betreiben).

Wisst ihr vielleicht, woher das kommt?

Vielen Dank schonmal für eure Antworten! :-)

Stefan

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne kompletten minimalen quellcode bei dem der fehler noch auf taucht 
kann ich dir nicht sagen was schiefgeht. Aber wenn der Fehler so oft 
kommt, dann steppe es doch einfach im Debugger durch. Eventuell kommt ja 
ein Interrupt in die quere?

Autor: Stefan R. (quark48) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der ganze Code:
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>

#ifndef F_CPU
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
   F_CPU im Makefile definiert werden, eine nochmalige Definition
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
   #ifndef/#endif 
 
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
   verwendet wird und dort eine andere, nicht zur Hardware passende 
   Taktrate eingestellt ist: Dann wird die folgende Definition 
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
   noch nicht definiert: */
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
                         // Ohne ergeben sich unten Fehler in der Berechnung
#endif

#define BAUD 9600UL      // Baudrate
 
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
 
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
#endif

int uart_putc(unsigned char c);
void uart_puts (char *s);
uint16_t ReadChannel(uint8_t mux);
int quersumme(int zahl);

 
int main(void)
{
    UCSRB |= (1<<TXEN);                // UART TX einschalten
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
 
    UBRRH = UBRR_VAL >> 8;
    UBRRL = UBRR_VAL & 0xFF;

  uint16_t wert;
  char buffer[20];

  while(1)
  {
    
    wert = ReadChannel(0);

    itoa(wert, buffer, 10);
    uart_puts(buffer);

    uart_puts(" / ");

    wert = quersumme(wert);

    itoa(wert, buffer, 10);
    uart_puts(buffer);

    uart_puts("\r\n");

    _delay_ms(100);
  }  
}


// bei neueren AVRs andere Bezeichnung fuer die Statusregister, hier ATmega16:
int uart_putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
    {
    }                             
 
    UDR = c;                      /* sende Zeichen */
    return 0;
}
 
 
/* puts ist unabhaengig vom Controllertyp */
void uart_puts (char *s)
{
    while (*s)
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
        uart_putc(*s);
        s++;
    }
}


//
// Unter Angabe des Kanals gibt diese Funktion den Analogwert zurück.
//
uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result;
 
  ADMUX = mux;                      // Kanal waehlen
  ADMUX |= (1<<REFS0); // interne Referenzspannung nutzen
  ADMUX &= ~(1<<REFS1);
 
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
                               // setzen auf 8 (1) und ADC aktivieren (1)
 
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
  while ( ADCSRA & (1<<ADSC) ) {
     ;     // auf Abschluss der Konvertierung warten 
  }
  result = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.
 
  /* Eigentliche Messung - Mittelwert aus X aufeinanderfolgenden Wandlungen */
  result = 0; 
  for( i=0; i<5; i++ )
  {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
    result += ADCW;        // Wandlungsergebnisse aufaddieren
  }
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
 
  result /= 5;                     // Summe durch X teilen = arithm. Mittelwert
 
  return result;
}



int quersumme(int zahl) {
    int quersumme=0;
    int rest=0;
 
    do {
        rest = zahl%10;
        zahl = zahl/10;
        quersumme=quersumme+rest;
    } while (zahl > 0);
 
    return quersumme;
}

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir gibt zu denken, dass 8192 und 256 so sehr binäre Zahlen sind... :-o

Was passiert, wenn du wert einen definierten Zählerwert zuordnest?
Etwa so:
    wert++;
    itoa(wert, buffer, 10);
    :

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was gast den das Oszi auf dem Bus?

Autor: Stefan R. (quark48) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich möchte das Problem nun auflösen:

Ich hab alles probiert; auch einen festen Text zu verschicken. Immer 
waren mittendrin komische Zeichen, es fehlte was, etc.

Wisst ihr, woran es lag?

Es fehlte der Abblockkondi vom MAX232. Ich habs eigentlich nicht glauben 
können, aber es funzt mit nem kleinen Keramik-Kondensator mit 47nF 
einwandfrei. Und ich Depp hab noch gemeint, dass der MAX232 ohne 
auskommt.

Es lag also nicht am AVR (Der hatte übrigens die ganze Zeit nen 
Kondensator, so wie sich´s gehört!) sondern am Pegelumsetzer! :-)

Eieieieiei...
Man lernt nie aus! ^^

Stefan

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.