Hey Hannes,
vielen Dank für den guten Link. Leider werd ich vor Montag nicht dazu kommen es auszutesten :-) Aber dann gehts los :-)
Schaun mer mal :-)
Viele Grüße,
Jimmy
Druckbare Version
Hey Hannes,
vielen Dank für den guten Link. Leider werd ich vor Montag nicht dazu kommen es auszutesten :-) Aber dann gehts los :-)
Schaun mer mal :-)
Viele Grüße,
Jimmy
Hallo Hannes :-)
Also die Sachen die du mir da geschickt hast, passen ziemlich gut zu dem was ich auch machen will. Nur eines ist mir noch unklar...
Mein Timer muss ja irgendwie starten..mache ich das über ne if Anweisung? Oder wie krieg ich den Timer dazu genau dann hochzulaufen wenn der obere Endschalter betätigt ist und dann zu stoppen wenn der untere betätigt ist?
Viele Grüße
Jimmy
Zuerst stellst du den Timer ein (Prescaler,...). Danach gibst du den Timer frei, damit er auf Interrupts des Timers reagiert.
Ich weiß zwar nicht wo du den Taster anschließt, aber hier ein kleines Beispiel.
damit du den Interrupt stoppst musst du sei mit cli austauschen. Den Port und Pin musst du anpassen.Code:if ( PINC & (1<<PINC1) ) sei();
http://www.mikrocontroller.net/artic...R-GCC-Tutorial
MfG Hannes
Also mein erster Taster liegt am Port A Pin 7. Wenn der auf Masse gezogen wird, soll der Timer starten.
Den stelle ich vorher entsprechend dem Datenblatt ein (Prescaler etc.)
In meiner ISR soll nur eine Variable hochgezählt werden...entsprechend dem oberen Link, den du mir geschickt hast.
Heisst das ich muss den Pin so anpassen wie dus da geschrieben hast und wenn er aufhören soll zu zählen einfach ein cli() mit entsprechendem PIN hin ? Und die Stoppuhr läuft dann schon!? Oder kommt in die if-Anweisung sonst noch etwas rein?
Sorry, dass es bei mir so lange dauert:-) Bin manchmal etwas schwer von Begriff :-)
Gruss
Du musst oben das anpassen (Port und Pin). Bei deinem ersten Kontakt wäre das dann
Beim anderen Kontakt ersetzt du "PINA" mit dem Port, den du hast. PIN bleibt immer gleich. der letzte Buchstabe gibt den Port an. PINA wäre Port A, PINB wäre Port B,...Code:if (PINA & (1<<PA7)) sei();
"PA7" musst du mit dem Pin ersetzten. "P" bleibt immer gleich. Das "A" ist der Port und die Ziffer ist der Pin.
Wenn du die Interrupts stoppst musst du "sei();" mit "cli();" austauschen. Die Pins und Ports musst du deinen Bedürfnissen anpassen.
Ich würde den Timer einfach laufen lassen (mittels Kontakt starten). Bei jedem Overflow eine Variable um 1 erhöhen. Wenn der Timer gestoppt wird, ließt du die Variable und das Timerregister mit dem aktuellen Zählerstand. Entweder berechnest du die Zeit direkt und sendest es an den PC oder du sendest die Überläufe und den Zählerstand an den PC und berechnest es am PC.
MfG Hannes
Also ich hab mir da jetzt mal was überlegt...bzw mit deinem Link da zusammengesucht und wollt fragen ob das prinzipiell laufen könnt.
TIMER2_interrupt_init(void)
{
TCCR2 = (1<<WGM21) (0<<WGM20) (1<<CS22) (1<<CS21) (1<<CS20);
TCNT2=0;
OCR2=249;
TIMSK = (1<<OCIE2);
}
int main(void)
{
if(PINA & (1<<PA7))
{sei()
TIMER2_interrupt_init
}
if(PINA & (1<<PA2)
{cli();
}
while(1);
}
ISR(TIMER2_COMP_vect)
{
z++
if(z==125){
sekunde++;
z=0;}
if(sekunde==60){
minute++;
sekunde=0;
if(minute==60){
stunde++;
minute = 0;
}
}
Nun ist es ja so, dass ich mit dem oberen Sensor den Timer starten und den mit dem unteren den Timer stoppen und auslesen will...für die Übertragung an den PC hab ich mir noch wenig gedanken gemacht...zuerst sollte das hier funktionieren!?
wenn ich mein Programm so laufen lass: Was passiert in dem Bereich in dem kein Sensor betätigt wird?Oder kann man das irgendwie machen, dass der nur auf steigende oder fallende Flanken reagiert?
Ist mein Programm prinzipiell richtig?Oder hab ich cli() und sei() falsch eingesetzt?
Vielen Dank und viele Grüße,
Jimmy
Hallo nochmal :-)
also einen fehler hab ich schon gefunden. da wo das while(1) muss ein return(0) hin und vor die if Anweisung in main das while(1). Aber prinzipiell müssts doch dann stimmen ???
Und die Variablen sekunde, minute, stunde müssen doch dann als volatile deklariert werden. Würde mich über jede Antwort freuen.
Viele Grüße,
Jimmy
Bin erst jetzt wieder online. Du hast einige Fehler drinnen.
1.) Das "ISR(Timer2_COMP_vect){...} kommt vor main (wie timer init)
2.) Den Timer nur einmal initialisieren
Als Beispiel:
StattCode:TIMER2_interrupt_init(void)
{
TCCR2 = (1<<WGM21) (0<<WGM20) (1<<CS22) (1<<CS21) (1<<CS20);
TCNT2=0;
OCR2=249;
TIMSK = (1<<OCIE2);
}
ISR(TIMER2_COMP_vect)
{
z++;
if(z==125)
{
sekunde++;
z=0;
}
if(sekunde==60)
{
minute++;
sekunde=0;
}
if(minute==60)
{
stunde++;
minute = 0;
}
int main(void)
{
TIMER2_interrupt_init;
if(PINA & (1<<PA7))
{
sei();
}
if(PINA & (1<<PA2)
{
cli();
}
while(1);
}
kannst du auchCode:if(PINA & (1<<PA2)
{
cli();
}
schreiben.Code:if(PINA & (1<<PA2) cli();
Den Code solltest du kommentieren, damit du später auch noch weißt, warum was geschrieben wurde. (Andere finden sich im Code besser zurecht)
MfG Hannes
Hallo Hannes!
Vielen Dank für die vielen Antworten! Ach so ja stimmt, solange mein Pin gesetzt ist, wird der Timer immer neu initialisiert. Das werd ich so übernehmen und dann weiterprobieren. Und der Timer startet dann immer wenn der obere Pin gesetzt wird bei 0?
Viele Grüße, Jimmy
Habe gerade einige Fehler gesehen, die mir vorher entgangen sind.
1.) Je nachdem was du verwendest musst du if(PINA & (1<<PA2)) cli(); bzw if ( !(PINB & (1<<PINB2))) cli(); schreiben. Das Gleiche gilt für PA7. Wenn du den internen Pullupwiderstand nimmst musst du dieses Ändern.
2.) Die Endschalterabfrage musst du in die While(1) Schleife setzten, sonnst wird das Programm nur einmal ausgeführt.
Das Programm schaut so aus, wenn du den internen (oder externen) Pullupwiderstand nimmst.
Habe nur main geschrieben. die ISR und Timer Init musst du natürlich auch schreiben.Code:int main(void)
{
TIMER2_interrupt_init;
while(1)
{
if(!(PINA & (1<<PA7))) sei();
if(!(PINA & (1<<PA2))) cli();
}
}
Damit du das Programm testen kannst würde ich noch eine Led anschließen. Bei jedem Timerüberlauf (in der ISR) änderst du den Zustand der Led (ein/aus). Bei der Led darfst du den Vorwiderstand nicht vergessen.
Beim Timer init musst du noch die einzelnen Variablen mit | verknüpfen, sonst funktioniert es nicht. Außerdem musst du vor "TIMER2_interrupt_init(void)" noch ein void geben.
Diesen Code habe ich gerade mit einem Atmega8 getestet, deswegen habe ich andere Pins.
Mit Taste1 aktiviert man den Timer, Taste 2 deaktiviert ihn. In der ISR wird eine Led invertiert. Ist der Timer aktiviert, blinkt die Led.Code:void TIMER2_interrupt_init(void)
{
TCCR2 = (1<<WGM21)|(1<<CS22)| (1<<CS21) |(1<<CS20);
TCNT2=0;
OCR2=249;
TIMSK = (1<<OCIE2);
}
ISR(TIMER2_COMP_vect)
{
PORTB ^= (1<<PB0);
}
int main(void)
{
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); //Led und Summer als Ausgang
PORTD |= (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3); //Pullup für Taster ein
PORTB |= (1<<PB2); //Summer ausschalten
TIMER2_interrupt_init();
while(1)
{
if(!(PIND & (1<<PD0))) sei();
if(!(PIND & (1<<PD1))) cli();
}
}
Willst du den Timer jede Sekunde um 1 erhöhen oder soll der Timer so schnell wie möglich laufen und du errechnest dann die Zeit?
MfG Hannes