www.mikrocontroller.net

Forum: Compiler & IDEs atmega 8, timer, interrupt, gcc


Autor: Jochen Kunz (joku)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Jochen Kunz (joku)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>#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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.