Forum: Compiler & IDEs 2 LEDs im Gegentakt toggeln lassen? + Zeitproblem


von Robert D. (cluricaun80)


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...

: Bearbeitet durch User
von Haro (Gast)


Lesenswert?

1
(0<<PC1)

Eine Null kannst du soweit shiften wie du willst, sie bleibt eine Null.

von Rolf Magnus (Gast)


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.

von Falk B. (falk)


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

von Robert D. (cluricaun80)


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.

von Robert D. (cluricaun80)


Lesenswert?

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...

von Jonas K. (jonas_k)


Lesenswert?

durch eine initialisierung mit einsprechend entgegengesetzten Werten

von Falk B. (falk)


Lesenswert?

@ 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.

von Verwirrter (Gast)


Lesenswert?

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 ?

von Robert D. (cluricaun80)


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?

von Bitklauber (Gast)


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.

von Benji (Gast)


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

von Benji (Gast)


Lesenswert?

PORTC = (1 <<PC0); //PC1 an, der Rest ist aus.

Muss natürlich heißen: //PC0 an, der Rest ist aus!

von Robert D. (cluricaun80)


Lesenswert?

Das Initialisieren war wirklich das Problem...jetzt funkitonierts!
Gar nicht so schwer. Aber kam einfach nicht drauf!

VIELEN DANK!!!

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.