Forum: Mikrocontroller und Digitale Elektronik UART gibt mittendrin Mist aus


von Stefan R. (quark48) Benutzerseite


Angehängte Dateien:

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

von Ulrich (Gast)


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?

von Stefan R. (quark48) Benutzerseite


Lesenswert?

Der ganze Code:
1
#include <avr/io.h>
2
#include <avr/delay.h>
3
#include <avr/interrupt.h>
4
5
#ifndef F_CPU
6
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
7
   F_CPU im Makefile definiert werden, eine nochmalige Definition
8
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
9
   #ifndef/#endif 
10
 
11
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
12
   verwendet wird und dort eine andere, nicht zur Hardware passende 
13
   Taktrate eingestellt ist: Dann wird die folgende Definition 
14
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
15
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
16
   noch nicht definiert: */
17
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
18
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
19
                         // Ohne ergeben sich unten Fehler in der Berechnung
20
#endif
21
22
#define BAUD 9600UL      // Baudrate
23
 
24
// Berechnungen
25
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
26
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
27
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
28
 
29
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
30
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
31
#endif
32
33
int uart_putc(unsigned char c);
34
void uart_puts (char *s);
35
uint16_t ReadChannel(uint8_t mux);
36
int quersumme(int zahl);
37
38
 
39
int main(void)
40
{
41
    UCSRB |= (1<<TXEN);                // UART TX einschalten
42
    UCSRC |= (1<<URSEL)|(3<<UCSZ0);    // Asynchron 8N1 
43
 
44
    UBRRH = UBRR_VAL >> 8;
45
    UBRRL = UBRR_VAL & 0xFF;
46
47
  uint16_t wert;
48
  char buffer[20];
49
50
  while(1)
51
  {
52
    
53
    wert = ReadChannel(0);
54
55
    itoa(wert, buffer, 10);
56
    uart_puts(buffer);
57
58
    uart_puts(" / ");
59
60
    wert = quersumme(wert);
61
62
    itoa(wert, buffer, 10);
63
    uart_puts(buffer);
64
65
    uart_puts("\r\n");
66
67
    _delay_ms(100);
68
  }  
69
}
70
71
72
// bei neueren AVRs andere Bezeichnung fuer die Statusregister, hier ATmega16:
73
int uart_putc(unsigned char c)
74
{
75
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
76
    {
77
    }                             
78
 
79
    UDR = c;                      /* sende Zeichen */
80
    return 0;
81
}
82
 
83
 
84
/* puts ist unabhaengig vom Controllertyp */
85
void uart_puts (char *s)
86
{
87
    while (*s)
88
    {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
89
        uart_putc(*s);
90
        s++;
91
    }
92
}
93
94
95
//
96
// Unter Angabe des Kanals gibt diese Funktion den Analogwert zurück.
97
//
98
uint16_t ReadChannel(uint8_t mux)
99
{
100
  uint8_t i;
101
  uint16_t result;
102
 
103
  ADMUX = mux;                      // Kanal waehlen
104
  ADMUX |= (1<<REFS0); // interne Referenzspannung nutzen
105
  ADMUX &= ~(1<<REFS1);
106
 
107
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
108
                               // setzen auf 8 (1) und ADC aktivieren (1)
109
 
110
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
111
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
112
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
113
  while ( ADCSRA & (1<<ADSC) ) {
114
     ;     // auf Abschluss der Konvertierung warten 
115
  }
116
  result = ADCW;  // ADCW muss einmal gelesen werden,
117
                  // sonst wird Ergebnis der nächsten Wandlung
118
                  // nicht übernommen.
119
 
120
  /* Eigentliche Messung - Mittelwert aus X aufeinanderfolgenden Wandlungen */
121
  result = 0; 
122
  for( i=0; i<5; i++ )
123
  {
124
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
125
    while ( ADCSRA & (1<<ADSC) ) {
126
      ;   // auf Abschluss der Konvertierung warten
127
    }
128
    result += ADCW;        // Wandlungsergebnisse aufaddieren
129
  }
130
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)
131
 
132
  result /= 5;                     // Summe durch X teilen = arithm. Mittelwert
133
 
134
  return result;
135
}
136
137
138
139
int quersumme(int zahl) {
140
    int quersumme=0;
141
    int rest=0;
142
 
143
    do {
144
        rest = zahl%10;
145
        zahl = zahl/10;
146
        quersumme=quersumme+rest;
147
    } while (zahl > 0);
148
 
149
    return quersumme;
150
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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:
1
    wert++;
2
    itoa(wert, buffer, 10);
3
    :

von I. E. (anfaenger69)


Lesenswert?

Was gast den das Oszi auf dem Bus?

von Stefan R. (quark48) Benutzerseite


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

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.