Hallo, im Anhang habe ich ein kleines Testprogramm (mit vielen angelehnten Codefragmenten); vielleicht kann mir jemand die Ursache erklären.... Hardware ist ein Atmega 8, das Board ist von myavr, an die Steckerleiste habe ich eine Lochrasterplatine mit Mäuseklavier, einigen LEDs sowie Widerständen verbaut. PORTD ist der Digitaleingang, PORTB sind die LEDs zur Anzeige, der USART dient zur Kommunikation mit einem Rechner (Schaltzustände weiterleiten). Nun zu meinem Problem: ich möchte im Sekundentakt eine LED blinken lassen (von diesem sekundentakt dann zuätzlich ableiten, dass zB ein Ausgang für 10 Sekunden high bleibt) PIND2 auf 1 schaltet PORTB0 auf 1, PORTB1 soll blinken. Ist in main innerhalb der while-Schleife die Abfrage nicht auskommentiert, so blinkt die LED ca im Sekundentakt, jedoch kommt es zu längeren Pausen, also aussetzern bzw längerer HIGH oder LOW-Phase. Vermuten tu ich zur Zeit, dass PORTD sich mit der seriellen Schnittstelle in die Quere kommt.... Worin liegt das Problem in meinem Programm bzw wie kann ich sowas "besser" angehen? gruss jochen
> ISR (USART_RXC_vect) > { > unsigned char ucSign = 0x00; > > ucSign = UARTGetChar(); > //... Das ist imho nicht wirklich sinnvoll. Wenn der RXC-Interrupt auslöst, bedeutet das, dass bereits ein Zeichen empfangen wurde. Man braucht dann nur noch UDR auszulesen. Wozu also der Aufruf von UARTGetChar()? Außerdem rufst Du in der UART-RXC-ISR die Funktion puthelp() auf, die sicher eine ganze Weile braucht, um den String auszugeben. Während der Zeit kann kein Timer-Interrupt bearbeitet werden. Vermutlich ist genau dieser Funktionsaufruf für die Abweichungen verantwortlich. BTW: > if (PORTB & (1 << PB1)) { > PORTB &= ~(1 << PB1); > } else { > PORTB |= (1 << PB1); > } Warum so umständlich? Schreibs doch einfach mit nem Exklusiv-ODER: PORTB ^= 1 << PB1; Macht das gleiche, ist aber nur eine Zeile...
Nach nochmaligem drüberschauen ist mir nix anderes mehr aufgefallen, außer, dass die Funktion putvers() noch übler ist, als puthelp(). MERKE: Funktionsaufrufe, insbesondere solche, die viel Zeit brauchen, also Ausgaben über die serielle Schnittstelle (Stringausgaben...), die mit Wartezeiten verbunden sind, haben in einer ISR nichts zu suchen, da während ihrer Ausführung die Bearbeitung aller anderen Interrupts blockiert ist!
Hallo, zuerst einmal vielen Dank für die Auffrischung des Toggles über das XOR, ist nicht mehr alles so frisch wie früher. Meine gestrigen Experimente und Versuche haben ergeben, dass auch wenn ich den UART mit dem wenig performanten Code/Interrupt aktiviert habe, die Blinkerei (wenigstens nach Auge) im constanten Puls-/Pausenverhältnis in den Griff bekomme: Im der Signalroutine für den Timer setzte ich mir eine globale Variable, von 0 bis 7 auf 0 und von 8 bis 14 auf 1; in der main-loop setzte ich abhängig von dieser Variablen den Blink-Ausgang auf HIGH oder LOW. Jetzt kann ich am Eingang PIND2 Pegel nach belieben wechseln, ohne dass die Hell/Dunkelphase des Blinklichts verändert wird. Ich denke, mir einen Sekundentakt zu erzeugen und dadurch gesteuert unterschiedliche Ausgänge für unterschiedliche Zeiten zu altivieren. Noch eine Kochbuch-Frage zum UART: wenn ich ohne Interrupt arbeite, für eine kleine Steuerungsaufgabe sollte das reichen, denke ich, in der main-loop UDR auszulesen und dann bei Bedarf auf Empfang gehen, indem ich die Empfangsroutine anstosse. Also pollen. bei RS485 wird die Adresse durch ein gesetztes 9tes Bit erreicht, diese Möglichkeit habe ich beim Atmel noch nicht entdeckt. Ich hoffe, nach knapp 10 Jahren Pause wieder etwas mehr in die Reglungs-/Steuerungstechnik einzusteigen. gruss jochen PS: Übung macht den Meister, aber ich möchte Fallen und Sackgassen vermeiden
Das 9. Datenbit kannst Du selbstverständlich beliebig setzen. Musst nur drauf achten, dass es vor dem Schreiben von UDR gesetzt wird (bzw. beim Lesen des empfangenen Zeichens vor UDR gelesen wird).
>#define UART_UBRR_CALC(BAUD_,FREQ_) ((FREQ_)/((BAUD_)*16L)-1)
Istd as 'L' hinter der 16 richtig und stimmt die kontante 'FREQ'?
Sollte die in der Berechnung nicht 'F_CPU ' sein?
Versuch mal die Baudrate als Kontante (Wert) anzugeben und nicht zu
berechnen. Hatte damit auch mal Probleme.
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.