Hallo zusammen, ich bin gerade mit der AVR Programmierung angefangen und versuche ein Markisen Steuerung zu programmieren. Quelltext: // Port Definition // PC0 -> Eingang -> rein / raus umschalter & motor bewegen // PC1 -> Eingang -> Wind blockieren // PC2 -> Eingang -> blockieren nicht möglich // PC3 -> Ausgang -> durch Winde blockiert // PC4 -> Ausgang -> rein / raus // PC5 -> Ausgang -> Motor ein #define F_CPU 1000000UL #include <util/delay.h> #include <avr/io.h> #include <avr/interrupt.h> struct { unsigned wind:1; // 1 Bit für bStatus_1 unsigned manuellbetrieb:1; // 1 Bit für bStatus_2 unsigned motor_bewegung:1; // Und hier noch mal ein Bit unsigned richtung_raus:1; // Dieses Feld ist 2 Bits breit // All das hat in einer einzigen Byte-Variable Platz. // die 3 verbleibenden Bits bleiben ungenutzt } status; int motor_ein() { status.motor_bewegung = 1; PORTC |= (1<<PC5); return 0; }; int motor_aus(void) { PORTC &= ~(1<<PC5); status.motor_bewegung = 0; return 0; }; volatile unsigned int Counter; ISR( TIMER0_OVF_vect ) { Counter++; if(Counter == 2) { Counter = 0; TCCR0 &= ~((1<<CS00)|(1<<CS01)|(1<<CS02)); //Timer deaktivieren cli(); motor_aus(); } }; int bewegungsrichtung_change() { //Richtung invertieren PORTC = PINC ^ ( 1 << PC4 ); return 0; }; int markise_fahren() { bewegungsrichtung_change(); motor_ein(); TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); // Teiler: 1024 TIMSK = ( 1 << TOIE0 ); // Overflow Interrupt einschalten sei(); // Interrupt generell zulassen return 0; }; int markise_ein_fahren() { //Bewegungsrichtung rein PORTC &= ~(1<<PC4); motor_ein(); TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); // Teiler: 1024 TIMSK = ( 1 << TOIE0 ); // Overflow Interrupt einschalten return 0; }; int init() { //Datenrichtung bestimmen DDRC = 0b00111000; //Ausgänge & Eingänge setzen status.wind = 0; status.manuellbetrieb = 1; status.motor_bewegung = 0; status.richtung_raus = 1; //Markiese einfahren markise_ein_fahren(); return 0; }; int main (void) { init(); //markise_fahren(); while(1) { if ( PINC & (1<<PINC0) ) { markise_fahren(); } } return 0; }; Mein Problem ist, dass das Programm erst in die main() springt, dann in die init(). Soweit ist auch alles ok. Aber in der init() ruft er markise_ein_fahren(). Von dort führt er auch alles aus aber springt dann irgendwann in bewegungsrichtung_change() und anschließend in markise_fahren(). Aber warum? Gruß, Tobi
Springt er nicht vielleicht von markise_fahren() nach bewegungsrichtung_change() und führt anschließend den restlichen code von markise_fahren() aus? Es ist wohl deine if-abfrage "if ( PINC & (1<<PINC0) )" falsch, dass er immer reinspringt?
Da fehen wohl ein paar volatiles. Ausserdem kannst du nicht im Programm die IRQs aktivieren und in einer ISR deaktivieren. Beim Beenden der ISR wird der vorherige Programmstatus -- also auch das I-Flag -- wieder hergestellt. Johann
Hallo, was schlägst du vor, wie ich den Timer starte und anschließend wieder stoppe? Oder soll der Timer einfach die ganze Zeit laufen? Gruß, Tobi
Hi, ibot, "TIMSK = ( 1 << TOIE0 ); // Overflow Interrupt einschalten sei(); // Interrupt generell zulassen" Hier gibt Du Interrupts frei. Bei jedem Überlauf springt der Programmzähler auf die Adresse, wo er den Sprungvektor für die Interrupt-Routine ISR(SIG_OVERFLOW0) (oder so ähnlich) erwartet - und dort rastet er aus. Schau in das Datenblatt, welche ISR genau benötigt wird, füge sie hinzu, und schon ist dieser Fehler behoben - und der nächste taucht auf....;-( Ciao Wolfgang Horn
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.