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
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
Eine eigene Frage?
Dieser Thread ist über 15 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.