PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer?



Mr Bean
09.05.2007, 20:29
Hallo

Ich wollte mir ein kleines Programm schreiben um mit einem Timer einen Schalter zu entprellen. Ich hab eine Mega8 mit 4 MHz systemtakt. Leider weiß ich gar nicht wie ich da am besten anfange und habe auch nach suchen auf diesen Seiten hier nichts gefunden was mir wirklich auf die Sprünge hilft. Wäre schön wenn mir einer von euch da weiter helfen könnte.

Vielen Dank!

MFG

Bean

Mr Bean
09.05.2007, 21:35
So, hab nun mal etwas Code geschrieben. Funktioniert aber leider noch nicht so ganz. Will damit ein Schalter an Port C3 entprellen. Und dann die 8 LED`s die ich an Port D hab einschalten (Werden mit logisch 0 eingeschalten).


#include <avr/io.h>
#include <avr/interrupt.h>

void main(void)
{
DDRD = 0xff; //LED PortB als Ausgang definieren
DDRC &= ~(1<<DDC3); //Port C3 als Eingang definieren.
PORTC |= (1<<PC3); //internen Pull Up von Port C3 aktivieren

TCCR0 |= (1<<CS00)|(1<<CS02); //Timer0 mit Vorteiler 1024 starten

sei(); //Interrupts global freigeben



}

ISR(TIMER0_OVF_vect)
{
if(! (PINC & (1<<PINC3)))
{
PORTD = 0x00;
}
}

Die LED`s sind nach dem Programmieren aber immer sofort an ohne daß der Schalter irgend einen Einfluss auf die LED`s hat.
Könnt ihr mir da weiter helfen?

MFG

Bean

izaseba
09.05.2007, 21:47
Damit die Led beim start nicht angeht, mußt Du sie wohl am Anfang ausschalten :wink:
PORTD = 0xFF;
Für den Timer mußt Du den Interrupt noch einschalten, guck mal im Register TIMSK nach, ich meine TOIE0 ?

Gruß Sebastian

P.S. irgendwie fehlt da noch die Endlosschleife Dein Controller läuft Amok

Micro5
09.05.2007, 21:53
Hallo

also ich kenne mich mit Interrupts auch nicht so gut aus, aber ich glaube, dass dein Programm sich zu früh beendet. Es werden kurz die Befehle der main- Funktion durchgegangen, danach ist dein Programm fertig. Die Interrupts kommen gar nicht zum Zug. Zum Testen kannst du z.B. eine while(1)- Schleife hinter die Funktion sei() setzen.
Außerdem können die LEDs dann nur einmal eingeschaltet werden, ausgeschaltet können sie mit diesem Programmcode nicht mehr. Da du das aber so wolltest, macht das ja nichts.

Gruß micro5

Mr Bean
09.05.2007, 22:07
Hallo

Danke für die Antworten. Ich hab jetzt noch den TIMSK freigegeben. Und eine While Schleife eingefügt, weiß aber nicht ob die so richtig ist. AUßerdem hab ich in der ISR noch was eingefügt mit dem ich eigentlich die LED`s wieder ausschalten möchte. Das funktioniert nun aber auch nicht, die LED`s sind immer aus.

#include <avr/io.h>
#include <avr/interrupt.h>

#define FCPU_4000000UL


ISR(TIMER0_OVF_vect)
{

if(PINC & (1<<PINC3)) //Hier zum ausschalten
{
PORTD = 0xff;
}

if(! (PINC & (1<<PINC3))) //Hier zum einschalten
{

PORTD = 0x00;
}


}

void main(void)

{
while(1);
{
DDRD = 0xff; //LED PortB als Ausgang definieren
DDRC &= ~(1<<DDC3); //Port C3 als Eingang definieren.
PORTC |= (1<<PC3); //internen Pull Up von Port C3 aktivieren

TCCR0 |= (1<<CS00)|(1<<CS02); //Timer0 mit Vorteiler 1024 starten

PORTD = 0xff; //alle LED`s ausschalten ???WARUM???

sei(); //Interrupts global freigeben
TIMSK |= (1<<TOIE0); //interrupt von Timer 0 freigeben
}

}
Vielleicht könnt ihr da noch einmal drüber schauen.

Vielen Dank!

MFG

Bean

Micro5
09.05.2007, 22:29
Hallo

hinter die while(1)- Schleife darf kein Semikolon, sonst bleibt das Programm immer an dieser Stelle hängen.
Man schaltet die LED am Amfang aus, um sie auf einen definierten Zustand zu bringen, du könntest sie genausogut am Anfang alle einschalten, nur meistens schaltet man sie anfangs aus.

Gruß micro5

Mr Bean
09.05.2007, 22:54
OK, Das mit dem Semikolon hab ich geändert. Aber daran lag es auch nicht. Ich werde jetzt erstmal ne Nacht drüber schlafen.

Trotzdem nochmal Danke an der Stelle!

MFG

Bean

izaseba
10.05.2007, 17:38
Das Problem bei Dir ist, daß Du auf Flankenänderung reagieren mußt, und nicht auf Taste gedrückt, Taste los.
Ich schicke Dir ein kleines Programm, guck mal ob Du es verstehst, wenn nicht frag einfach mal. An PORT B hängen die LEDs , PD0 der Taster


#include<avr/io.h>
#include<avr/interrupt.h>

ISR (TIMER0_OVF_vect) {
static uint8_t flanke = (1<<PD1);
/*flanke 1 Pin 1 -> keine Aenderung 0
flanke 1 Pin 0 -> Tasten druck 1
flanke 0 PIN 0 -> keine Aenderung 0
flanke 0 PIN 1 -> Taste losgelassen 1
*/
if (flanke ^ (PIND&(1<<PD1))){
if (flanke)
PORTB =~PORTB;
flanke ^= (1<<PD1);
}
}

int main(void) {
TIMSK = (1<<TOIE0);
TCCR0= (1<<CS02)|(1<<CS00);
DDRD = 0x00;
PORTD = 0xFF;
DDRB = 0xFF;
PORTB = 0xFF;
sei();
while(1);
return 0;
}


Gruß Sebastian

Mr Bean
13.05.2007, 23:30
Hallo

Danke für die Antwort und das Programm! Hat mir sehr geholfen. Hab es nach einiger Zeit auch verstanden. Funktioniert ja über ein XOR zwischen der Flanke und dem Wert der an dem Pin anliegt. Damit werden die LED`s aber mit jeder steigenden Flanke ein und auch wieder aus geschalten. Ich hab dann mal die zweite if Abfrage weggelassen, damit schaltet man die LED`s dann einfach wie mit einem schalter ein und aus.

Hab aber doch noch ein, zwei fragen. Warum legst Du die Variable flanke gerade als uint8_t an? Und was genau bewirkt das static?

Vielen Dank nochmal!

Grüße!!

Dominik