2 LEDs im Gegentakt toggeln lassen? + Zeitproblem

#3513628
Lesenswert?

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_t ir_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
void ir_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...
Gast #3513646
Lesenswert?

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.
#3513654
Lesenswert?

@ 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
#3513663
Lesenswert?

... 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.
#3513746
Lesenswert?

> 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?
Gast #3513773
Lesenswert?

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.
Gast #3513774
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren