ich hab die Tage eine Experimental-Schaltung zusammengebastelt, um zunächst die Anbindung Atmega <--> PC für sich zu testen, in Vorbereitung für ein eigenes, komplexeres Projekt. Ich teste immer gern alle Aspekte zunächst separat. Die Schaltung besteht im wesentlichen aus einem mit 18,432 MHz getakteten Atmega 644P und einem Pegelwandler MAX3232, letzterer entsprechend Datenblatt mit 100nF Kondensatoren beschaltet. Verbindung zum Terminal ohne Hardwarehandshake als Drei-Leiter-Verbindung TxD, RxD über Kreuz, sowie Ground mit Ground. Konfiguration an beiden Enden 9600,8N1, am Terminal ohne Software-Flow-Control eingestellt. Ich verwende die C Bibliothek von Peter Fleury. Soweit ich bisher recherchiert habe ist das die meist-verwendete Bibliothek für diesen Zweck(?) Bisher sind meine Tests ausschliesslich auf dem Beispielcode von Peter Fleury für das Hauptprogramm basiert. Die Übertragungsrichtung Atmega --> Terminal klappt von Anfang an problemlos, also sowas wie uart_puts("bla bla"\r\n); geht. Solange die interrupt-basierte Abfrage des UART-Ports im Hintergrund vor sich hinwerkelt, läuft auch alles stabil. Aber sobald in der Hautpschleife des Peter-Fleury Beispiel main Programms uart_getc() mit hoher Frequenz ausgeführt wird führt der Atmega nach paar Tastendrücken am Terminal ein Reboot aus. Hab in jene Schleife mal ein _delay_ms(5) eingebaut - und sofort läuft alles stabil. Ich hab mich die letzten Tage fast zu Tode gegoogelt auf der Suche nach Hinweisen zu diesem Problem. Kann es sein dass die Funktion uart_getc() aus der Peter-Fleury irgendwas unsauberes mit den Ringpuffer-Pointern macht wenn sie (schnell getakteter Atmega und langsame Baud-Rate) viel öfter in Aktion tritt als der UART-Recieve-Interrupt?
An sich ist alles möglich. Aber der Code von Peter ist schon relativ oft verwendet worden und falls das öfter passiert, wäre es hier im Forum zu finden. Such doch mal. Um aber konkret auf Dein Problem einzugehen, wäre es gut zu wissen, welchen Code Du genau verwendet hast. Es gibt nämlich verschiedene Versionen davon und ein paar Leute haben den Code noch variiert. Poste bitte mal einen Link genau auf den Beitrag wo Du den Code her hast.
Es wäre auch wichtig Deinen Code dazu zu sehen. Ich kann mir aber auf Anhieb nicht vorstellen, das ein wildgewordener Zeiger in den UART Funktionen von Peter das Problem ist.
na von dorten: http://homepage.hispeed.ch/peterfleury/avr-software.html Im code des test-Hauptprogramms, im unteren Teil, in der Endlosschleife for(;;) { ... } crasht das Programm nach paar Tastendrücken am Terminal, wenn ich es so lasse wie es ist. Wenn ich entweder das uart_getc() auskommentiere oder einen Delay einfüge läuft alles stabil - im ersten Fall natürlich funktionslos ohne Eingabe. Mein persönlicher Verdacht: da spielen 2 Faktoren eine Rolle: 1. verwenden die meisten Anwender sowieso nur die Datenrichtung Atmega --> PC 2. verwenden die meisten wahrscheinlich höhere Datenraten als 9600. Ich vermute das Problem besteht wenn uart_getc() häufiger auftritt als die ISR, die Daten in den Ringpuffer tut...
Micha schrieb: > na von dorten: > http://homepage.hispeed.ch/peterfleury/avr-software.html Welcher Code genau? Poste ihn doch einfach, statt irgendwelcher Verweise. Micha schrieb: > Ich vermute das Problem besteht wenn uart_getc() häufiger auftritt als > die ISR, die Daten in den Ringpuffer tut... Dass das uart_getc der Fleury-Lib nicht blockierend arbeitet, und also auch so was wie "kein Zeichen verfügbar" zurück geben kann, hast du aber bedacht, oder?
Micha schrieb: > Im code des test-Hauptprogramms, im unteren Teil, in der Endlosschleife > > for(;;) > { > > ... > > } > > crasht das Programm nach paar Tastendrücken am Terminal, Du verwendest den Code ohne irgendwelche Änderungen? Richtig? > Mein persönlicher Verdacht: da spielen 2 Faktoren eine Rolle: > 1. verwenden die meisten Anwender sowieso nur die Datenrichtung Atmega > --> PC > 2. verwenden die meisten wahrscheinlich höhere Datenraten als 9600. Antwort auf beide Vermutungen: Spielt alles keine Rolle. Deswegen darf der Code nicht crashen. Solange du händisch am Terminal tippst, kannst du tun was du willst, diesen Code darfst du nicht zum Crashen bringen. So schnell kannst du nicht tippen.
>na von dorten:
Was heisst "na"? Nur weil Du eine Quelle gefunden hast, heisst, das ja
nicht, das es die einzige ist. ;-) Ich z.B. hab meine Variante hier
aus dem Forum. Such mal hier im Forum nach Peter Fleury. Da findest Du
noch weitere Varianten.
Ich habe mal nachgeguckt, aber in der getc routine kann aus meiner Sicht
nichts crashen, egal wie häufig man die aufruft. Wenn kein Zeichen da
ist, ist halt keins da und wenn doch wird der Index UART_RxTail nur in
getc verändert.
Deine Vermutung muss deswegen nicht falsch sein, aber hat es doch nötig
durch Informationen erhärtet zu werden.
ja ich weiss, so ein Problem ist immer irgendwie ne komplexe Mischung aus möglichen Hard- und Software- Ursachen. Ich hab leider vorläufig nicht das Equipment (Speicher-Oszi, Logik-Analyzer) um Hardware-Probleme zuverlässig einzukreisen. Ich hänge mal unten den aktuellen Stand meines Experimental-Codes an. Startpunkt für das Hauptprogramm war test_uart.c aus dem Archiv direkt von Peter Fleury's Webpage. Strings vom Atmega zum Terminal hat von Anfang an gut geklappt. Hab zunächst mal die PROGMEM Sachen rausgetan um eine mögliche Ursache zu eliminieren. Ohne Erfolg. Dann hab ich verschiedenes ausprobiert. Mit dem Code wie angehängt resettet der Atmega jeweils nach ca. 2 bis 10 Tastaturanschlägen auf dem Terminal. Wenn ich die Zeile mit *uart_getc()* auskommentiere läuft der Atmega stabil durch. Wenn ich ein *_delay_ms(5)* in die Hauptschleife einfüge läuft es ebenfalls stabil, dann bekomme ich sogar die Zeichen wieder aufs Terminal ge-echot. Läuft stundenlang, ohne Zeichen-Verlust. Ich hab die Zeile mit dem delay mit >>> <<< markiert, das ist selbstverständlich nicht Teil des eigentlich verwendeten Quelltexts:
1 | /************************************************************************* |
2 | |
3 | Title: example program for the Interrupt controlled UART library |
4 | |
5 | Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury |
6 | |
7 | File: $Id: test_uart.c,v 1.4 2005/07/10 11:46:30 Peter Exp $ |
8 | |
9 | Software: AVR-GCC 3.3 |
10 | |
11 | Hardware: any AVR with built-in UART, tested on AT90S8515 at 4 Mhz |
12 | |
13 | |
14 | |
15 | DESCRIPTION: |
16 | |
17 | This example shows how to use the UART library uart.c |
18 | |
19 | |
20 | |
21 | *************************************************************************/ |
22 | |
23 | |
24 | |
25 | /* define CPU frequency in Mhz here if not defined in Makefile */ |
26 | |
27 | #ifndef F_CPU |
28 | |
29 | #define F_CPU 18432000 // do NOT append UL to this number |
30 | |
31 | #endif |
32 | |
33 | |
34 | |
35 | #include <stdlib.h> |
36 | |
37 | #include <avr/io.h> |
38 | |
39 | #include <avr/interrupt.h> |
40 | |
41 | // #include <avr/signal.h> |
42 | |
43 | #include <avr/pgmspace.h> |
44 | |
45 | #include <util/delay.h> |
46 | |
47 | |
48 | |
49 | #include "uart.h" |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | /* 9600 baud */ |
58 | |
59 | #define UART_BAUD_RATE 9600 |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | int main(void) |
66 | |
67 | { |
68 | |
69 | // set unused ports to OUTPUT mode |
70 | |
71 | DDRA = 0b11111111; |
72 | |
73 | DDRC = 0b11111111; |
74 | |
75 | DDRD |= 0b11111100; |
76 | |
77 | DDRB = 0b11111111; |
78 | |
79 | unsigned int c; |
80 | |
81 | char buffer[7]; |
82 | |
83 | int num; |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | /* |
90 | |
91 | * Initialize UART library, pass baudrate and AVR cpu clock |
92 | |
93 | * with the macro |
94 | |
95 | * UART_BAUD_SELECT() (normal speed mode ) |
96 | |
97 | * or |
98 | |
99 | * UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode) |
100 | |
101 | */ |
102 | |
103 | uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); |
104 | |
105 | |
106 | |
107 | /* |
108 | |
109 | * now enable interrupt, since UART library is interrupt controlled |
110 | |
111 | */ |
112 | |
113 | sei(); |
114 | |
115 | |
116 | |
117 | /* |
118 | |
119 | * Transmit string to UART |
120 | |
121 | * The string is buffered by the uart library in a circular buffer |
122 | |
123 | * and one character at a time is transmitted to the UART using interrupts. |
124 | |
125 | * uart_puts() blocks if it can not write the whole string to the circular |
126 | |
127 | * buffer |
128 | |
129 | */ |
130 | |
131 | uart_puts("COMMODORE BASIC V2\r\n"); |
132 | |
133 | |
134 | |
135 | /* |
136 | |
137 | * Transmit string from program memory to UART |
138 | |
139 | */ |
140 | |
141 | uart_puts("39387 BASIC BYTES FREE.\r\n"); |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | /* |
148 | |
149 | * Use standard avr-libc functions to convert numbers into string |
150 | |
151 | * before transmitting via UART |
152 | |
153 | */ |
154 | |
155 | for (num=0;num<=1000;num++) { |
156 | |
157 | itoa( num, buffer, 10); // convert integer into string (decimal format) |
158 | |
159 | uart_puts("next number is "); |
160 | |
161 | uart_puts(buffer); // and transmit string to UART |
162 | |
163 | uart_puts("\r\n"); |
164 | |
165 | } |
166 | |
167 | |
168 | |
169 | /* |
170 | |
171 | * Transmit single character to UART |
172 | |
173 | */ |
174 | |
175 | // uart_putc('\r'); |
176 | |
177 | uart_puts("\r\n"); |
178 | |
179 | for(;;) |
180 | |
181 | { |
182 | |
183 | /* |
184 | |
185 | * Get received character from ringbuffer |
186 | |
187 | * uart_getc() returns in the lower byte the received character and |
188 | |
189 | * in the higher byte (bitmask) the last receive error |
190 | |
191 | * UART_NO_DATA is returned when no data is available. |
192 | |
193 | * |
194 | |
195 | */ |
196 | |
197 | >>> _delay_ms(10); <<< |
198 | |
199 | c = uart_getc(); |
200 | |
201 | if ( c & UART_NO_DATA ) |
202 | |
203 | { |
204 | |
205 | /* |
206 | |
207 | * no data available from UART |
208 | |
209 | */ |
210 | |
211 | } |
212 | |
213 | else |
214 | |
215 | { |
216 | |
217 | /* |
218 | |
219 | * new data available from UART |
220 | |
221 | * check for Frame or Overrun error |
222 | |
223 | */ |
224 | |
225 | if ( c & UART_FRAME_ERROR ) |
226 | |
227 | { |
228 | |
229 | /* Framing Error detected, i.e no stop bit detected */ |
230 | |
231 | uart_puts("UART Frame Error: "); |
232 | |
233 | } |
234 | |
235 | else if ( c & UART_OVERRUN_ERROR ) |
236 | |
237 | { |
238 | |
239 | /* |
240 | |
241 | * Overrun, a character already present in the UART UDR register was |
242 | |
243 | * not read by the interrupt handler before the next character arrived, |
244 | |
245 | * one or more received characters have been dropped |
246 | |
247 | */ |
248 | |
249 | uart_puts("UART Overrun Error: "); |
250 | |
251 | } |
252 | |
253 | else if ( c & UART_BUFFER_OVERFLOW ) |
254 | |
255 | { |
256 | |
257 | /* |
258 | |
259 | * We are not reading the receive buffer fast enough, |
260 | |
261 | * one or more received character have been dropped |
262 | |
263 | */ |
264 | |
265 | uart_puts("Buffer overflow error: "); |
266 | |
267 | } |
268 | |
269 | else uart_putc( (unsigned char)c ); |
270 | |
271 | } |
272 | |
273 | } |
274 | |
275 | } |
Ich denke, das es sich um eine Hardwareproblem handelt? Bei welcher Spannung läuft Dein Prozessor und der Max? Hast Du Abblockkkondensatoren am Prozessor?
Wie versorgst Du die Schaltung? Strombegrenzung mal hochgedreht?
mag ich überhaupt nicht ausschliessen dass es ein Hardware-Problem ist. Ich hab zwei Varianten ausprobiert: 1) Mit 4,5V (Pack aus drei AA Batterien). 2) Mit einem käuflich erworbenen 5V Netzteil, in dem Fall hab ich einen 100uF Elko zwischen Netzteil und Schaltung. Ohne den Elko geht garnichts, da gibts jede Menge Fehler bzw Resets, mit dem Elko geht Senden stabil, und empfangen mit _delay auch. Aus praktischer Sicht hab ich das Problem ja inzwischen gelöst, ein 5us Delay reicht (im Listing waren es 10 us), würde mich aber trotzdem interessieren wo das Problem liegt. Der Maxim MAX3232 den ich verwende braucht laut Datenblatt "nur" 100nF Kondensatoren um die Pegelwandlung von 0..5V auf -12..+12V hinzuzaubern. Ist das womöglich fauler Zauber? Sollte ich mir doch dringend einen Speicheroszi bzw. einen Logikananlyzer besorgen? Fragen über Fragen...
Also bei dem MAX3232 habe ich im Datenblatt andere Angaben zu den Kondensatoren gefunden. Nicht alles 100nf sondern 47nF und 330nF resp. 100nF und 470nF. Siehe Seite 7, Bild 4. Das >Ohne den Elko geht >garnichts, da gibts jede Menge Fehler bzw Resets, mit dem Elko geht >Senden stabil, und empfangen mit _delay auch. deutet auch darauf hin, das Du Probleme mit der Stromversorgung hast. Nachdem Du die Kondensatoren am Max korrigiert hast, könntest Du da auch mal mit anderen Kondensatoren spielen. Was ist das für ein Netzteil? Schaltregler, Linearregler oder nur Trafo mit Gleichrichter?
so messgeräte sind auf jeden fall nicht verkehrt.. neben dem 100µF elko hast du natürlich auch noch die obligatorischen 100nF kerkos zum abblocken an den vcc/gnd pins des µC?
>Aus praktischer Sicht hab ich das Problem ja inzwischen gelöst...
ist jedenfalls ein Irrtum. Die Software ist OK und wird durch ein Delay
in keiner Weise verbessert. Du beseitigst nicht die Ursache sondern die
Symptome.
Das Delay deutet übrigens auch auf Probleme mit der Stromversorgung und
zwar in Bezug auf den Max. Denn das Delay bedeutet das der Wandler mehr
Zeit hat, nach einer Belastung auf Sollausgangsspannung zu kommen.
>neben dem 100µF elko hast du natürlich auch noch die obligatorischen >100nF kerkos zum abblocken an den vcc/gnd pins des µC? Ja. Genau. Das habe ich Dich ja auch gefragt, aber Du hast darauf nicht geantwortet.
war nicht böse gemeint, ist nur verwirrend wenn alle "Noname" heissen. Ja, ich hab nen 100nF am Prozessor. Aber ich muss mir wohl wirklich dringend entsprechende Messtechnik zulegen. Ideal sind ja immer alles Rechteck-Impulse. Aber was ich inzwischen so auf diversen Websiten zum Thema Digitaltechnik und Signale gesehen hab macht mich schon nachdenklich... Ich war seit langen ein "Softie" der sich nur mit Programmierung beschäftigt hat, in der Hardware Welt der Atmels bin ich erst seit rel. kurzer Zeit unterwegs.
da es ja wirklich nen HW problem zu sein scheint, poste doch mal nen schaltplan/layout?
>war nicht böse gemeint, ist nur verwirrend wenn alle "Noname" heissen.
Verstehe ich nicht. Worauf beziehst Du Dich?
Ich bin immer derselbe Noname. Alle anderen sind billige Kopien. :-)
Was ist jetzt mit dem Max und den Kondensatoren? Was mit dem Netzteil?
Hallo Micha, bitte mache auch noch ein paar Bilder. Ist auch Port A == AVCC, AGND nach Datenblatt, AP beschaltet ? Siehe: www.atmel.com/dyn/resources/prod_documents/doc8011.pdf 2.3.10
das Datenblatt des Herstellers MAXIM das mir bisher vorlag gibt für die Beschaltung des MAX3232 durchgängig 100nF an. Das oben zitierte Datenblatt ist von Texas Instruments, gibt tatsächlich teils andere Werte vor. Ich glaub inzwischen die Chip-Hersteller sind teils noch viel schlampiger als Du und Ich...
Mein Fehler. Hab ich nicht daran gedacht. Hast Du den wirklich von MAXIM-Dallas? Schau mal auf den Chip welches Logo zu sehen ist. Die Hersteller sind aber durchaus nicht schlampig. Obwohl die Chips gleich heissen, brauchen sie, je nach Hersteller unterschiedliche Kondensatoren. Das ist schon ok so. Trotzdem hast Du meiner Ansicht nach ein Problem mit der Stromversorgung. Also auf jeden Fall noch 100nF parallel zu dem Elko am Netzteil. Falls es nicht geht, anderes Netzteil probieren. Was für ein Netzteil ist das denn jetzt? Hast immer noch nicht geantwortet und ich werde nicht nochmal fragen.
der MAX3232 den ich verwende (bei reichelt gekauft) trägt tatsächlich das Logo von Maxim. Die Stromversorgung hab ich bei komputer.de gekauft, ist so ein Teil: http://www.komputer.de/zen/index.php?main_page=product_info&cPath=22&products_id=127 Wie schon gesagt, geht nur stabil mit einem 100uF Kondensator dahinter.
>der MAX3232 den ich verwende (bei reichelt gekauft) trägt tatsächlich >das Logo von Maxim. OK. Hm. Das "Netzteil". Wie versorgst Du es? Über USB oder über die Hohlsteckerbuchse? Falls USB, dann könnte es sein, das sich Dein Host streng an die USB-Spec. hält und Dich nur wenig Strom ziehen lässt, vor allem wenn es auf enumerationsanforderungen nicht reagiert. Offen gesagt ist das Ding aus meiner Sicht sowieso Murks. Es gibt weder ein Datenblatt noch funktioniert die auf der Platine angegebene Website. Da sind noch so Halbleiter zu sehen, die sicher auch nicht für umsonst arbeiten (soll heissen ohne Spannungsabfall). Nimm lieber was richtiges. Das Ganze zeigt mit jedem bekannt werdenden Detail immer weiter in Richtung Probleme mit der Stromversorgung. Was hast Du für Messgeräte und alternative Stromversorgungen (ausser Batterie).
>Wie schon gesagt, geht nur stabil mit einem 100uF Kondensator dahinter.
Nein. Es geht nicht stabil, da die UART-Kommunikation abbricht.
Denke Dir das nicht so zurecht, das es "fast" passt und nur noch das
Delay fehlt.
ich hab hier ehrlich gesagt ein massives Verständnisproblem: Die Kommunikation zwischen RS232 und Atmel wird über Interrupt-Routinen abgewickelt, die die ganze Zeit aktiv sind. Wenn ich uart_getc() garnicht einbinde (oder mittels delay) in größeren Zeitabständen, dann kann ich wie verrückt auf der Tastatur des angeschlossenen Terminals herumtippen - ohne dass der Atmel in ein Reset gerät. Kann auch beliebig Strings zur RS232 ausgeben mittels uart_puts() zu Kontrollzwecken. Erst wenn ich uart_getc() in schneller Folge ausführen lasse gibt es nach paar Tastendrücken ein Reset. Aber uart_getc() macht doch nichts mit der Hardware direkt sondern guckt nur in den Ringpuffer ob Zeichen da sind. Hab ich einen Denkfehler? Nach meinem Verständnis deutet das auf einen Konflikt zwischen Interrupt-Routine und uart_getc() hin? Was Stromversorgung angeht hab ich bisher nichts "ordentliches". Über Tips wär ich dankbar. Ist ein sog. "Labornetzteil" sinnvoll für solche Versuche auf Breadboard-Basis?
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.