Hallo zusammen, ich hab hier schon gesucht aber nix gefunden was zu meinem Problem passt. Nachdem ich schon eine Weile herumexperimentiert hab, hab ich mein Problem auf das wesentlichste reduziert. Ich habe einen einfachen Testaufbau gemacht. ATMega32 mit 16Mhz Quartz, dessen UART Eingang (RX) über einen MAX232 an meinem PC hängt. Dann zu Testzwecken eine LED mit Widerstand an einen Pin von Port C. Ich habe ein kleines Testprogramm geschrieben das im Hauptteil PORTC auf Ausgang schaltet, den UART initialisiert (9600Baud) und in einer Endlosschleife nachfragt ob ein Byte angekommen ist, es evtl. ausliest und dann PORT C auf 0xff setzt und nach kurzer Zeit wieder auf 0x00. Mein Oszi sagt mir: PORTC ist für ca 12us auf high und dann kurz (ca. 2.5us) auf low. Da am PORTC eine LED hängt leuchtet diese auch wie erwartet (konstant Hell). Iss halt ne Art PWM. Jetzt sendet ein Programm auf meinem PC irgendwelche Daten an den ATMega. Mein Oszi sagt mir das der Spannugsverlauf auf PORTC ziemlich unregelmäßig wird. Es kommt tatsächlich vor das die LED für kurze Zeit (1/4 sec) ausgeht. Das irritiert mich. Der UART scheint sich massiv auf das Timing des Programmablauf auszuwirken. Folgendes hab ich probiert: UART komplett gar nicht initialisiert und nur PORTC an/aus in einer main while Schleife. PORTC an/aus in einer Interruptroutine, UART empfang in main. Ist dem ATMega völlig egal. Sobald der UART irgendwas empfängt, flackert die LED = die PWM auf PORTC kommt völlig durcheinander. Anbei mein auf das wesentlichste reduzierter code. Ich hoffe es hat jemand ne Idee? Tausend Dank Volker #include <avr/io.h> #define F_CPU 16000000UL // 16MHz #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 volatile unsigned char received ; void uart_init(void) { UBRRH = UBRR_VAL >> 8; // Wie oben berechnet UBRRL = UBRR_VAL & 0xFF;// Wie oben berechnet UCSRB = (1<<RXEN) | (1<<TXEN) ; // UART RX einschalten UCSRC = (1<<UCSZ1)|(1<<UCSZ0) |(1<<URSEL); // Asynchron 8N1 } void indicateAction(void) { int wait ; PORTC = 0b11111111 ; // just to wait a bit for (wait = 0 ; wait < 10 ; ++wait) ; PORTC = 0b00000000 ; } int main() { DDRC = 0xFF; // PORTC Ausgang uart_init(); while (1) { if (!(UCSRA & (1<<RXC))) { // no character } else { received = UDR ; } indicateAction() ; } }
Als Nachtrag vielleicht noch: Warum das Ganze? Plan ist in einer ISR eine LED Matrix per PWM zu steuern. Die Daten dafür kommen per RS232 vom PC und werden in der main methode in einer Schleife aus dem UART gelsen und für die ISR zur Anzeige aufbereitet. Leider wird die ISR duch die UART Empfangsaktivitäten derart gestört das die Anzeige inakzeptabel flackert.
> Es kommt tatsächlich vor das die LED für kurze Zeit (1/4 sec) ausgeht. > Das irritiert mich. Der UART scheint sich massiv auf das Timing des > Programmablauf auszuwirken. 1/4 Sekunde? Mit dem Code? Das ist zu viel. Viel zu viel. Ich denke du hast ein Hardwareproblem. Wie sieht deine Schaltung aus? Abblockkondensatoren an der Versorgungsspannung? Mega32 und PORTC: JTAG ist abgeschaltet?
Danke für die Tipps. JTAG ist aus. 100uF und 100nF an Vcc, GND direkt vor'm ATMega. MAX232 mit 5x1uF wie es "alle" machen. Analog AGND, AVCC hatte ich nicht angeschlossen. Jetzt schon. Hilft auch nix. ISP Steckplatz am ATMega angeschlossen, aber kein ISP dran. Was ich natürlich frech verschwiegen habe... Ich habe hier einen Testaufbau auf einer Experimentier-Steckplatine, aber nachdem das mit der PWM LED ohne UART so schon ausgesehen hat, frage ich mich ob das mit UART das Problem sein kann? Evtl. muß ich in den sauren Apfel beißen und doch mal ne Testlochrasterplatine löten. Falls Du noch sachdienliche Hinweise zum Ergreifen des Täters hast... wäre ich dankbar. Gruß Volker
Ach ja, habe auch schon 2 ATMega ausprobiert. Identischer Effekt.
Volker schrieb: > Was ich natürlich frech verschwiegen habe... > Ich habe hier einen Testaufbau auf einer Experimentier-Steckplatine, > aber nachdem das mit der PWM LED ohne UART so schon ausgesehen hat, > frage ich mich ob das mit UART das Problem sein kann? Glaub ich nicht. Kannst ja mal folgendes probieren: am Anfang in main() schaltest du eine LED in einem bestimmten Muster ein/aus. Das Muster an sich ist egal, du musst es nur eindeutig wiedererkennen können. Wenn meine Hypothese stimmt, dann hast du sporadische Resets, die den Controller resetten. Sprich: dein Programm läuft immer wieder von vorne an. Das ausgegebene Muster auf der LED am Programmanfang würde dir das zeigen.
Hallo Volker, Dein Code oben pollt nur. Habe ich das richtig verstanden, dass Dein Timing nur bei der RX-ISR aus dem Tritt kommt? Benutzt Du eine ISR für das asynchrone Empfangen eines Zeichnens über die UART? Wenn ja, solltest Du Dir angewöhnen nach dem Eintreten in eine Interrupt-Service-Routine das allgemeine Interruptflag wieder zu setzen. Solange eine Interrupt bearbeitet wird, sperrt der AVR jedes weitere Interruptereignis. Er hat keine Priorisierung. Man kann das aber mit ISR bla bla bla { sei(); // läßt die Unterbrechung dieses Interruptes zu. mache was schlaues } umgehen. Dann wird kann dieser aktuelle Interupt wieder von einem anderen unterbrochen werden. Ich treibe ein Grafikdisplay über UART, einen CAN-Controler, ein Modem und einen Schedulerinterrupt parallel auf einem ATmega1280 bei 16Mhz und es kommt zu keinen bemerkenswerten Aussetzern. Deshalb würde ich in den ISRs suchen. Die sollten natürlich kurz und knapp programmiert sein. Vielleicht helfen meine Anregungen. Viel Glück
cskulkw schrieb: > Hallo Volker, > > Dein Code oben pollt nur. Habe ich das richtig verstanden, dass Dein > Timing nur bei der RX-ISR aus dem Tritt kommt? Habe keine RX ISR. Hatte ich auch nicht vor. Ich wollte eine ISR auf Timer Basis haben, die alle x ms ein paar LEDs ansteuert. Das ganze als ISR damit mir da nix dazwischenfunkt und die LEDs flackern. Den Empfang der Daten vom RS232 wollte ich weiterhin gepollt machen und das Ergebnis dann per volatile Übergabearray für die ISR bereitstellen. > > Benutzt Du eine ISR für das asynchrone Empfangen eines Zeichnens über > die UART? Nein. Siehe oben. > > Wenn ja, solltest Du Dir angewöhnen nach dem Eintreten in eine > Interrupt-Service-Routine das allgemeine Interruptflag wieder zu setzen. > > Solange eine Interrupt bearbeitet wird, sperrt der AVR jedes weitere > Interruptereignis. Er hat keine Priorisierung. > > Man kann das aber mit > > ISR bla bla bla > { > sei(); // läßt die Unterbrechung dieses Interruptes zu. > mache was schlaues > > } > > umgehen. Dann wird kann dieser aktuelle Interupt wieder von einem > anderen unterbrochen werden. > > Ich treibe ein Grafikdisplay über UART, einen CAN-Controler, ein Modem > und einen Schedulerinterrupt parallel auf einem ATmega1280 bei 16Mhz und > es kommt zu keinen bemerkenswerten Aussetzern. > > Deshalb würde ich in den ISRs suchen. Die sollten natürlich kurz und > knapp programmiert sein. > > Vielleicht helfen meine Anregungen. Viel Glück Danke für Deine Anregungen. Ich hatte wir wie gesagt überlegt: LED per PWM in einer ISR ansteuern, die per timer ausgelöst wird. Da das zeitkritisch ist möchte ich das nicht unterbrechen lassen. Daher RS232 Empfang in der Main Loop.
@Karl Heinz Deine Idee mit dem Reset des ATMega ist goldrichtig. Hab jetzt mal als erstes im main() PORT A an und aus gehen lassen. Ohne RS232 Empfang => nix passiert. Sobald RS232 Zeichen empfangen werden => Ich sehe am Oszi Resets auftauchen (PORTA hat Spitzen). Ich schätze ich habe soetwas ähnliches ... => Beitrag "UART verursacht Reset(?)" Weil der MAX232 auf meinem Steckboard nicht sooooo weit weg ist von meinem Quartz habe ich jetzt mal CKOPT gefused und siehe da: Aktuell sehe ich keine Spitzen mehr => keine Resets mehr. Die eigentliche Test LED leuchtet konstant hell und flackert nicht mehr. Ich denke also der CKOPT hat geholfen. Danke für Eueren Support Gruß Volker
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.