Hallo,
ich habe vor, ein Positionslicht für ein Modell zu bauen.
Dieses soll drei unterschiedliche Modi bisitzen:
Mode 0: 50ms an, 1450ms aus;
Mode 1: 50ms an, 50ms aus, 50ms an, 1350ms aus;
Mode 2: 50ms an, 50ms aus.
Sinn dahinter:
0 steht für "Modell im Standby, soweit alles roger";
1 ist normaler Betrieb (Doppelblitz);
2 ist das Signal für einen Fehler.
Das ganze hab ich mir mit Delayschleifen schnell hinprogrammiert. Aber
das ist ja nicht so das Gelbe...
Ich würde das gerne mit einem Timer im Hintergrund machen. Da ich aber
doch noch sehr neu in der ganzen Sach bin, würde ich mich über einen
Denkanstoß freuen... Keine komplette Lsg.
Ich hab jetzt schon rausgefunden, dass es Timervectoren gibt, in denen
ich Code ausführen lassen kann, wenn ein Timer überläuft. Aber so recht
bringt mich das noch nicht weiter...
Hier ist erstmal der Code mit Trödelschleifen:
Stell dir einen Timer auf 50ms Periodendauer (CTC-Mode) ein.
In der ISR zählst du dann eine Variable herunter, die dir den
Umschaltzeitpunkt signalisiert.
Wurde umgeschaltet, lädt man die Variable mit dem nächsten
Countdownwert...
Die Werte schreibt man vorher in ein Array und muss dann nur noch den
Wert, der duch den Index beschrieben wird in die Zähövariable laden.
Gut, dass schonmal etwas läuft.
* Du hast immer noch im Hauptprogramm eine Schleife, die sich um alles
kümmern muss.
Ausgehend von obiger Lösung verlegst Du jetzt noch einen Teil in die
Interrupt-Routine. Vorschlag: Die Kommunikation erfolgt über Variablen:
status wird von main geschrieben und vom Interrupt gelesen, phase
wird alleine vom Interrupt benutzt, ebenso counter.
Damit ist main völlig unabhängig und braucht außer dem Schreiben von
status bei einem Statuswechsel sich überhaupt nicht mehr mit dem Blinken
zu befassen.
* Du setzt COM20 und das sorgt dafür, dass am IO-Port "OC2" ein Signal
ausgegeben wird (falls dieser Pin auch als Ausgang geschaltet ist). Das
ist für Debugzwecke oder in anderen Zusammenhängen nützlich, hat aber
mit Deinem Blinken nichts zu tun und ist daher überflüssig.
Hi, danke für den Tipp, hört sich sehr sinnig an!
Aber da komm ich an meine C-Grenze...
Ich habe das jetzt so gemacht:
blinker.c:
1
volatileuint8_tstatus;
2
3
intmain(void){
4
DDRD=0b11100011;
5
TCCR2|=(1<<WGM21)|(1<<CS20)|(1<<CS22);
6
TIMSK|=(1<<OCIE2);
7
OCR2=255;
8
9
sei();
10
PORTD|=(1<<PD5);
11
while(1){
12
if(Taster.t1)
13
status=1;
14
else
15
status=0;
16
17
}
interruptVectors.c:
1
uint8_tcounter=0;
2
uint8_tphase=0;
3
volatileuint8_tstatus;
4
constuint16_tleuchtzeiten[3][4]={
5
{30,860,0,0},
6
{30,30,30,800},
7
{30,30,0,0}};
8
9
10
ISR(TIMER2_COMP_vect)
11
{counter++;
12
13
if(counter>=leuchtzeiten[status][phase]){
14
counter=0;
15
if(phase<3)
16
phase++;
17
else
18
phase=0;
19
PORTD^=(1<<PD5);
20
}
21
}
Aber es tut sich nichts... Bei einem TAstendruck leuchtet die LED
einmal, beim Loslassen ein weiteres mal...
Ist der Fehler für jemanden von euch ersichtlich?
Viele Grüße,
Matthias
So, Problem gelößt. Falscher Datentyp. uint8 kann schwer die gewünschte
Pausenzeit von 860 erreichen O_o
Jetzt aber mal ne andere Frage:
Warum funktioniert das Programm auch, wenn ich vor keine der Variabeln
extern, volatile oder ähnliches schreibe. Es compiliert und läuft in
dieser Form:
intteruptVectors.c:
hast du die Codeoptimierung an??
Wenn nicht, dann liegt es daran. volatile saget dem Compiler nur, dass
er diese Variable nicht irgendwie optimieren darf, da sich diese während
der Programmabarbeitung ändern kann (z. B. durch eine ISR)
Hallo,
ich habe mit OPT={s|0|3} probiert. Der Code ist immer gleich groß und
verhält sich immer gleich.
Naja, ich mach erstmal an anderen Baustellen weiter.
Danke jedenfalls allen Helfern :-)
Viele Grüße,
Matthias