Hallo!
Habe mal ein Frage. Habe michmal mit Interrupts beschäftigt, und es
funktioniert nicht so wie ich das gerne hätte, bzw. gar nicht.
Hab ein Programm geschrieben das einfach per interrupt eine LED
anschalten soll (an PORTB). Macht so keinen Sinn, aber ich will mich da
ja auch nur mal reinarbeiten. Der Interrupt soll durch den überlauf von
counter/timer0 ausgelöst werden.
Vielleicht kann mir ja jemand sagen warum das so nicht funktioniert wie
ich mir das ausgedacht habe.
mfg
Jörg
Ja scho, aber das müsste ich eigentlich mit der Zeile
outp(0x80,SREG); //Global interrupt enable
erschlagen. Oder täusche ich mich da?
Ist übrigens ein Atmega8..
outp/inp outb/inb sind "dperecated"...
Ums mit Jörg Wunsch's Worten zu sagen: Nicht mehr benutzen! Und auch
keine "magic numbers", alle bits sind per Makro definiert...
Gruß,
Patrick...
Daß Du
1.) outp() nicht benutzen sollst, sondern wenn schon,
dann SREG = foobar;
2.) besser SREG |= _BV(SREG_I); schreiben solltest, aber
3.) noch besser einfach sei();
Damit manipulierst Du NUR das Bit "SREG_I" des SREG. _BV steht für
"bit value" und Maskiert das angegebene Bit.
Hier wird eine Oderverknüpfung des Inhalts von SREG mit dem Bit SREG_I
vorgenommen!
Gruß,
Patrick...
Aha, hab ich glaub verstanden.
Also _BV()schreibt mit eine Maske, in dem Fall eben 10000000
, und das ganze wir dann mit dem ganzen Register SREG "verOdert" um
die anderen bits nicht zu verändern.
Richtig?
Aber wieso "|=" und nicht nur "|"
Na ja ich hoffe es stimmt wenigstens so etwa, ich muss mich für heute
abmelden,morgen ist ja auch noch ein Tag.
Danke für eure Hilfe.
Gruß Jörg
Au ja, hätte ich eigentlich wissen können! Danke.
Also ich hab das jetzt mal ein bisschen umgeschrieben, funktioniert
aber immer noch nicht.
Woran liegts?
Und kann ich irgendwie elegant auch mehrere Bits in einem Register,
z.B. hier:
TCCR0 |= _BV(CS00);
TCCR0 |= _BV(CS01);
beide Bits auf einmal setzen? ( TCCR0|= _BV(CS00&CS01)???)
Oder wie macht man das?
Jörg
Letzteres:
TCCR0 |= _BV(CS00) | _BV(CS01);
aber das ist nicht mehr wirklich elegant, da es (zumindest
mit AVR-GCC) dann kein SBI mehr benutzen kann, sondern tatsächlich
read-modify-write Zyklen generiert.
Du solltest Dir halt in solchen Fällen überlegen, ob nicht stattdessen
die Absolutzuweisung
TCCR0 = _BV(CS00) | _BV(CS01);
sinnvoller ist. Die paßt dann wieder in einen OUT Befehl.
Umm, ich gucke mir den Code gerade an... Was geht eigentlich nicht
bzw. was mißt Du wo? Port B klingt mir auch ein bißchen danach, als
könnte es mit dem ISP kollidieren...
Ansonsten: schmeiß die outp()s raus. Hmm, welche Libraryversion hast
Du überhaupt? Ach, wenn das wirklich alles ist, müßtest Du sackweise
Compilerwarnungen bekommen, da Dir mindestens noch 1...2 Headerfiles
fehlen.
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
SIGNAL(SIG_OVERFLOW0)
{
PORTB = 0xff;
}
int
main(void)
{
DDRB = 0xff;
TIMSK |= _BV(TOIE0);
TCCR0 = _BV(CS00) | _BV(CS01);
sei();
for (;;)
;
}
Ist aber langweilig, alle Pins von Port B gehen sofort auf 1 und
bleiben dort. ;-)
Interessanter:
SIGNAL(SIG_OVERFLOW0)
{
static unsigned char c;
c <<= 1;
if (c == 0) c = 1;
PORTB = c;
}
Hallo!
Also es funktioniert nachdem ich den "signal" header eingebaut habe.
komischerweise kamen überhaupt keine Fehlermeldungen, das war ja eben
was mich etwas verwundert hat.
Was deine Interrupt funktion angeht haste natürlich recht, deine ist
schon interessanter. Da hab ich auch gleich die nächste Frage:
if (c == 0) c = 1; warum genau brauch ich diese Zeile.
Also mit c <<= 1; schiebe ich ja praktisch ne 1 durch die 8 Bit von
char c, richtig? Was passiert dann wenn die 1 praktisch "hinten raus"
geschoben wurde? Es fängt nicht automatisch wieder von vorne an,
richtig? Brauch ich dazu die obige Zeile?
Jörg
Eine eigene Frage?
Dieser Thread ist über 22 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.