Das habe ich zur Zeit.
Funktioniert auch soweit ganz gut.
[SPOILER]
Code:
/*
* timer_von_null.c
*
* Created: 14.08.2013 17:14:16
* Author: Gerrus
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// eigene Bezeichnungen
#define rot PC0
#define gelb PC1
#define gruen PC2
#define rotf PC4
#define gruenf PC5
#define ein 1
#define aus 0
volatile unsigned char zaehler=0,timer_mit=0,timer_ohne=0,temp=0,temp2=0;
ISR (TIMER0_OVF_vect) // Die Funktion die beim Overflow aufgerufen wird
{
if ((~PIND &(1<<PD3))) //Prüfen ob Taster gedrückt wurde.Taster ist gegen Ground gezogen
{
if ((~PINC&(1<<gruenf)))
{
rotf_schalten(ein); // Fussgänger Rot auf rot stellen.vorher war signal aus.
}
zaehler=1; //Zähler für Tasterzustand auf eins -Taster wurde betätigt.
}
if (timer_ohne < 214) timer_ohne++; else timer_ohne=0; //Variable um auf Sekunden zukommen.Eine Sekunde gleich 15,15 Ticks.beim erreichgen von 213,wieder auf null.
}
void rotf_schalten(unsigned int i) //Fussgänger Rot
{
if (i==ein){PORTC |= (1 << rotf);} // Setzen
else {PORTC &= ~(1 << rotf);} // Rьcksetzen
};
void gruenf_schalten(unsigned int i) //FUssgänger Grün
{
if (i==ein){PORTC |= (1 << gruenf);} // Setzen
else {PORTC &= ~(1 << gruenf);} // Rьcksetzen
};
void rot_schalten(unsigned int i) //Auto Rot
{
if (i==ein){PORTC |= (1 << rot);} // Setzen
else {PORTC &= ~(1 << rot);} // Rьcksetzen
};
void gelb_schalten(unsigned int i) //Auto Gelb
{
if (i==ein){PORTC |= (1 << gelb);} // Setzen
else {PORTC &= ~(1 << gelb);} // Rьcksetzen
};
void gruen_schalten(unsigned int i) //Auto Grün
{
if (i==ein){PORTC |= (1 << gruen);} // Setzen
else {PORTC &= ~(1 << gruen);} // Rьcksetzen
}
void schalten (void) //Hauptfunktion um Ampel zuschalten
{
if (timer_ohne==0) //Sekunde 0
{
rot_schalten(ein);
}
if (timer_ohne==15&&zaehler==1) //Sekunde 1 aber nur wenn Taster gedrückt wurde
{
rotf_schalten(aus);
gruenf_schalten(ein);
}
if (timer_ohne==61&&zaehler==1) //Sekunde 4 aber nur wenn Taster gedrückt wurde
{
gruenf_schalten(aus);
rotf_schalten(ein); //WICHTIG!!!
zaehler=2; //Zähler wird auf Zwei gesetzt damit man nicht durcheinander kommt beim rücksetzen später
}
if (timer_ohne==70&&zaehler==2) //Sekunde 4,6 Schaltet Fussgängerrot aus ,ABER nur wenn schon eine Phase durchgelaufen
{
rotf_schalten(aus);
}
if (timer_ohne==76) // Sekunde 5
{
gelb_schalten(ein);
}
if (timer_ohne==107) //Sekunde 7
{
rot_schalten(aus);
gelb_schalten(aus);
gruen_schalten(ein);
}
if (timer_ohne==183) //Sekunde 12,2
{
gruen_schalten(aus);
gelb_schalten(ein);
//rotf_schalten(aus);
}
if (timer_ohne==213) //Letzter Schaltvorgang Sekunde 14
{
gelb_schalten(aus);
if (zaehler==2)
{
zaehler=0; //Wird nur resetet wenn Fussgängerphase schon durchgelaufen ist
}
}
}
/*void schalten_mit (void)
{
if (timer_mit==0)
{
rot_schalten(ein);
rotf_schalten(ein);
}
if (timer_mit==15)
{
rotf_schalten(aus);
gruenf_schalten(ein);
}
if (timer_mit==61)
{
gruenf_schalten(aus);
rotf_schalten(ein);
}
if (timer_mit==76)
{
gelb_schalten(ein);
}
if (timer_mit==107)
{
rot_schalten(aus);
gelb_schalten(aus);
gruen_schalten(ein);
}
if (timer_mit==183)
{
gruen_schalten(aus);
gelb_schalten(ein);
}
if (timer_mit==213)
{
rotf_schalten(aus);
gelb_schalten(aus);
zaehler=0;
}
}
*/
int main(void)
{
//PORT C als Ausgang
PORTC = 0x00;
DDRC = 0xFF;
//PORT D als Eingang
DDRD = 0<<PD3;
PORTD = 1<<PD3;
TCCR0 |= (1<<CS02)|(1<<CS00); //Einstellen Von Preteiler 1/1024. Datasheet Seite 85
TIMSK |= (1<<TOIE0); //Interrupt auslцsen beim Overflow Datasheet Seite 85
TCNT0 = 0; //den timer selber reseten. Eine Null reinschreiben
sei(); //Interrups aktivieren
while(1)
{
schalten(); //Hauptschleife
}
}
[/SPOILER]
Als nächstes will ich das ganze auf eine Kreuzung portieren.Sprich das ganze noch einmal aber mit verknüpfung zu einander.
Außerdem stelle ich grade fest,dass ich noch eine Sperre für Rot_fuss einbauen muss,sobald gruen_fuss leuchtet.Quasi ein BUG entdeckt.Mein erster!!!!*freu* :-D (siehe EDIT)
In Planung ist auch das ganze in Hardware umzusetzen,mit Batterie Einspeisung.Bin schon am ausschau halten nach ampel gehäuse.vlt einen dicken Kugelschreiber oder ähnliches.
Hier nochmal ein kleiner Plan,falls jemand auf die schnelle ausprobieren möchte.(Widerstände vor den LEDs ,in Höhe von 330 Ohm , fehlen auf der Zeichnung. Diese müssen unbedingt aber in die reele Schaltung rein)
Nicht desto trotz,wenn jemand etwas zu verbessern oder zu optimieren weiss,immer her damit!
Vielen Dank und viel Erfolg!
EDIT: Einfache IF-Anweisung hat den "BUG" behoben.
Code:
if ((~PINC&(1<<gruenf)))
{
rotf_schalten(ein); // Fussgänger Rot auf rot stellen.vorher war signal aus.
}
P.S: Hat evtl. jemand weitere deutsche Foren für Programmieren in C für ATMEL? (ausser microkontroller.net,da sind ja nur "profis"... )
Lesezeichen