Hallo zusammen,
bin programmiertechnisch noch Anfänger und habe ein (vermutlich) kleines
Problem, komme aber einfach nicht auf die Lösung. Hoffe es hilft mir
jemand.
Habe 8 IR-LEDs an meinen ATMEGA 644 (20MHz) angeschlossen und möchte
jeweils 4 im Gegentakt zu den anderen Toggeln lassen.
Jedoch schaffe ich es nur, dass 4 Toggeln, die anderen bleiben dauerhaft
aus.
Prinzipiell versuch ichs mit CTC Timer und Compare Match Interrupt:
(nachfolgend nur Auszug aus dem Programm; Bib-Einbindung, u.ä ist
natürlich erfolgt...)
1
TCCR0A=(1<<WGM01);// CTC
2
TCCR0B=(1<<CS02)|(1<<CS00);// Prescaler 1024
3
OCR0A=194;//20MHz/1024/194 ~ 100Hz
4
TIMSK0=(1<<OCIE0A);
5
sei();
6
7
uinit8_tir_zaehler;
8
9
ISR(TIMER0_COMPA_vect)
10
{
11
if(ir_zaehler)ir_zaehler--;
12
}
Und aus der Main-Programm rufe ich dann folgende Funktion auf:(hier nur
mit 2 verschiedenen LEDs am PORTC)
1
voidir_blink(void)
2
{
3
if(ir_zaehler==0)
4
{
5
PORTC^=(1<<PC0)|(0<<PC1);
6
ir_zaehler=1;
7
}
8
9
}
Nunja... LED1 am PC0 toggelt wunderbar vor sich hin. LED2 am PC1 bleibt
jedoch dunkel.
Hätte jemand bitte ne Erklärung dafür und evtl. noch nen
Lösungsvorschlag?
Ach und nebenbei: Aus irgendeinem Grund stimmt die Zeit auch nicht. D.h.
laut den Berechnungen wird der Timer alle 10ms aufgerufen. Das heißt
aufgrund dessen dass der ir_zaehler nur auf 1 gesetzt wird, müssten die
LEDs im 10ms Rhythmus blinken...jedoch sind es schon eher 0,5s (250ms
aus/ 250ms an). Wenn mir auch hierbei jemand helfen könnte wär ich sehr
dankbar...
Robert D. schrieb:> Nunja... LED1 am PC0 toggelt wunderbar vor sich hin. LED2 am PC1 bleibt> jedoch dunkel.>> Hätte jemand bitte ne Erklärung dafür und evtl. noch nen> Lösungsvorschlag?
Das da ergibt nicht viel Sinn:
> PORTC ^= (1<<PC0) | (0<<PC1);
0<<PC1 ist 0, also kann man das auch einfacher schreiben:
1
PORTC^=(1<<PC0);
Das erklärt dann, warum, die LED an PC1 nicht binkt. Du toggelst nur
PC0.
> Ach und nebenbei: Aus irgendeinem Grund stimmt die Zeit auch nicht.
Bist du denn sicher, daß dein µC mit 20 Mhz läuft? Wenn der nicht über
die Fuses passend eingestellt wird, läuft er nämlich mit den
werksseitigen 1 Mhz.
@ Robert D. (cluricaun80)
>Habe 8 IR-LEDs an meinen ATMEGA 644 (20MHz)
Volle Kraft vorraus!
> angeschlossen und möchte>jeweils 4 im Gegentakt zu den anderen Toggeln lassen.>Jedoch schaffe ich es nur, dass 4 Toggeln, die anderen bleiben dauerhaft>aus.
An welchen Pins sind die angeschlossen? JTAG Fuse deaktiviert?
http://www.mikrocontroller.net/articles/AVR_Fuses#Kompatibilit.C3.A4tsfuses_und_manchmal_l.C3.A4stige_Defaults>Prinzipiell versuch ichs mit CTC Timer und Compare Match Interrupt:>(nachfolgend nur Auszug aus dem Programm; Bib-Einbindung, u.ä ist>natürlich erfolgt...)
Warum postet du keinen VOLLSTÄNDIGEN Quelltext als Anhang? Als Anfänger
kann der nicht so groß sein.
>Ach und nebenbei: Aus irgendeinem Grund stimmt die Zeit auch nicht. D.h.>laut den Berechnungen wird der Timer alle 10ms aufgerufen. Das heißt>aufgrund dessen dass der ir_zaehler nur auf 1 gesetzt wird, müssten die>LEDs im 10ms Rhythmus blinken...jedoch sind es schon eher 0,5s (250ms>aus/ 250ms an). Wenn mir auch hierbei jemand helfen könnte wär ich sehr>dankbar...
Taktquelle nicht per Fuses richtig ausgewählt bzw. F_CPU define falsch.
http://www.mikrocontroller.net/articles/AVR_Fuses#Taktquellen_Fuse_Einstellung
... und somit wäre das Zeiträtsel gelöst. Danke dir! Ging davon aus,
dass der ATMEGA 644 standartmäßig mit 20MHz läuft und deswegen auch so
definiert.
> PORTC ^= (1<<PC0) | (0<<PC1);
Dass ich die 0 in PC1 nicht toggeln kann habe ich schon vermutet. Aber
ich habe keinen Plan, wie ich dem µC sagen soll, dass wenn LED1 aus ist
er die LED2 anschalten soll und umgekehrt.
IR-LEDs hängen an PORT C und JTAG Fuse ist deaktiviert.
Habe keinen VOLLSTÄNDIGEN Quelltext gepostet, da das Programm ja noch
mehr macht und ich nur das wesentliche Problem hervorheben wollte...
@ Robert D. (cluricaun80)
>ich habe keinen Plan, wie ich dem µC sagen soll, dass wenn LED1 aus ist>er die LED2 anschalten soll und umgekehrt.
Mit Bitmanipulation.
Stehe gerade ein wenig neben mir, sind aber schließlich noch genügend
andere hier um mich zu berichtigen :
Robert D. schrieb:> OCR0A = 194; //20MHz/1024/194 ~ 100Hz
Das ist doch ein 8 Bit Timer, der zählt doch nur bis 256 ?
Robert D. schrieb:> uinit8_t ir_zaehler;
Wird in der ISR verwendet und sollte eigentlich volatile sein wenn ich
mich nicht irre ?
> OCR0A = 194; //20MHz/1024/194 ~ 100Hz
Das ist doch ein 8 Bit Timer, der zählt doch nur bis 256 ?
Ja maximal. Und hier im CTC-Mode eben nur bis 194...oder seh ich das
falsch? Aber der Timer an sich und das Toggeln im Allgemeinen von einer
LED funktioniert ja, aber Ich möchte Dauerhaft, dass die LEDs im
Gegentakt ihren Zustand ändern.
-> 1s LED1 an, dann LED1 aus und LED2 an, dann LED2 aus und LED1 an, ...
Bezüglich dem Link zur "Bitmanipulation" werde ich leider auch nicht
schlauer. Entweder ich kapiers nicht oder es gibt dort nichts was mir
weiterhilft. Trotzdem danke...
Wäre es vllt möglich, dass mir jemand kurz ein konkretes Beispiel für
die richtige Befehlszeile zeigt?
Das Problem ist die Startbedingung für PORTC. Bestimmt ist das auf 0x00
initialisiert. Für PC0 ergibt sich ein toggeln, weil 0 ^ 1 = 1 bzw. 1 ^
1 = 0 wird. Für PC1 bleibt die Rechnung immer bei 0 ^ 0 = 0 hängen.
Besser wäre es, PORTC einmalig so zu beschreiben:
PORTC = (1<<PC0) | (0<<PC1);
und in der Folge so zu toggeln:
PORTC ^= (1<<PC0) | (1<<PC1);
Das gibt dann die gewünschte Folge.
Naja, du bist ja fast am Ziel.
Ändere die Zeile so, dass beide Pins Toggeln:
PORTC ^= (1<<PC0) | (1<<PC1);
Jetzt ändern sich beide, leider gleichzeitig! Also musst du bevor du in
den Togglemodus umschaltest, die LEDs noch "gegenläufig" initialisieren:
PORTC = (1 <<PC0); //PC1 an, der Rest ist aus. (nicht schön: also vorher
PORTC einlesen, PC1 auf null zwingen und PC0 auf 1!
PORTC = (PORTC & ~(1 << PC1)) | 1 << PC0; //nur schnell hingeschmiert,
könnte passen :)
Grüße