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
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?
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 | }
|
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 | :
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.