PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : For - Schleife (Zeitmessung)



crusico
23.01.2009, 08:55
Hi to @ll,

ich habe folgendes for:

Eine Led (PB1) geht über einen Taster (PB0) an und aus. Wenn ich jetzt aber den Taster (PB0) länger als z.B. 6sec gedrückt halte, soll die Led (PB1) auch aus gehen.

Ich habe schon mal ein Programm geschrieben, aber ich weiß nicht wie ich die Zeitmessung (Zeit_Starten) machen? <.. Über eine For - Schleife?


Hier meine Code:


#include <avr/io.h>
#include <inttypes.h>
#define F_CPU 8000000 // 8 MHz


int Zeit_Starten(void) { //Hier Startet die Zeit, von 0sec bis 1 min
for(i;1<60;i++){

}
}
int main(void) {
DDRB &= (~ (1<<PB0)); /* Pin PB0 als Eingang */
PORTB |= (1<<PB0); /* Pull Up von PIN B0 aktivieren */
DDRB = (1<<DDB1); // PB1 Ausgänge
int Zeit_Abfrage;
int i;

while(1){
if (!( PINB & (1<<PINB0))) { /* mache was wenn PinB0 low ist */

Zeit_Starten(); // Wenn Taste gedrückt wird, dann Anfangen mit der Zeitmessung

if(Zeit_Abfrage > 6){ /* Wenn länger als 6 sec Taster gedrückt, dann Led aus */
PORTB|=(1<<PB1); // high
}
else{
PORTB&= ~(1<<PB1); // low
}
}
}
return 0;
}

thewulf00
23.01.2009, 10:10
Meine erste Idee wäre folgendes:
- Du schaltest den Taster auf einen Interrupt.
- Wird der Interrupt ausgelöst, schaust Du, wie der jetzige Status des PINs ist.
- Ist er HIGH (damit meine ich gedrückt), dann hältst Du die aktuelle Zeit fest, d.h. liest eine Zählervariable aus, die in einem Timer hochgezählt wird.
- Ist er aber LOW, so bildest Du die Differenz aus altem gespeichertem Zeitwert und dem jetzigen und hast die Drückdauer ermittelt.

Nachteil: Das funktioniert erst, wenn man den Taster loslässt.
Interessanter wäre es, wenn er nach 6 Sekunden gedrückthalten autom. anfängt, ohne dass man loslassen muss. Da fällt mir auch schon der passende Code für ein. Aber diese Ausarbeitung überlasse ich dem geneigten Leser.

crusico
23.01.2009, 10:38
Hört sich irgendwie kompliziert an...

Kann ich nicht einfach ein Timer wenn ich den Taster drücke zählen lassen, und wen nich den Taster los lasse Timer auf 0.

Dann könnte ich doch mit der If Abfrage sagen, wenn Timer > 6 dann Led aus.

Oder ist das so nicht machbar?

crusico
23.01.2009, 10:59
Ich dachte so in etwas könnte das aussehen:


#include <avr/io.h>
#include <inttypes.h>
#include <stdint.h>
#define F_CPU 8000000 // 8 MHz



void init_timer(void){
for(;;){ //Endlosschleife
TCCR0 |= (1<<CS00)|(1<<CS02); //Teilung 1024 des Taktes
if(TCNT0==255){ // alle 255 soll i eine Zahl erhöt werden
i=i++;}
}
}
int main(void){
DDRB &= (~ (1<<PB0)); /* Pin PB0 als Eingang */
PORTB |= (1<<PB0); /* Pull Up von PIN B0 aktivieren */
DDRB = (1<<DDB1); // PB1 Ausgänge
int i;
i=0;


while(1){
if (!( PINB & (1<<PINB0))) { /* mache was wenn PinB0 low ist */

init_timer(); // Timer starten

if (i < 6){ /* Wenn länger als ca.6 sec Taster gedrückt, dann aus */
PORTB|=(1<<PB1); // high
}
else{
PORTB&= ~(1<<PB1); // low
TCNT0=0; // Timer zurück setzten
}
}
}
return 0;
}

crusico
23.01.2009, 13:59
Ich nochmals, ich habe mal soweit die hälte geschaft,

die Led geht nach 6 sec aus, wenn ich den Taster dauert gedrückt halte.
Aber wenn ich jetzt nur kurz den Taster betätige, leuchtet die Led dauern :-(

Hier der Code:


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

ISR(TIMER0_OVF_vect)
{
static int a = 0;
a++; // Breakpoint #1 im Simulator



if (!( PINB & (1<<PINB0))) /* mache was wenn PinB0 low ist */
{


if (a > 6)
{
PORTB|=(1<<PB1); // high
}
else
{
PORTB&= ~(1<<PB1); // low
a = 0;
}
}

}

void InitTimer(void)
{
TCCR0 = TCCR0 | (1<<CS00); // Prescaler CK/8
TCNT0 = 0;
TIMSK = TIMSK | (1<<TOIE0);
}

int main(void)
{

InitTimer();
sei();


DDRB &= (~ (1<<PB0)); /* Pin PB0 als Eingang */
PORTB |= (1<<PB0); /* Pull Up von PIN B0 aktivieren */
DDRB = (1<<DDB1); // PB1 Ausgänge


while(1)
{
}
}

Hubert.G
23.01.2009, 17:09
Wenn die Taste nicht mehr gedrückt ist, springt das Programm nicht mehr in die if-Schleife. Ein else anfügen zum Led löschen.
Die gesamte if-Schleife aber in die Endlosschleife einfügen, den Code in der ISR so kurz wie möglich halten.

crusico
26.01.2009, 09:32
Hi Hubert.G,

wenn ich die gesamte if-Schleife aber in die Endlosschleife einfügen, habe ich Problem mit der Variable A. Muss ich die wieder in der Endlosaschleife deklarieren? Ich weiß jetzt nicht genau wie du es meinst... Könntest du mir es erklären?

Wo muss ich das genau einbienden, hier der Code:


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


ISR(TIMER0_OVF_vect)
{
static int a = 0;
a++; // ca. 1 sec zahlt die Variable a
}

void InitTimer(void)
{
TCCR0 = TCCR0 | (1<<CS00); // Prescaler CK/8
TCNT0 = 0;
TIMSK = TIMSK | (1<<TOIE0);
}


int main(void)
{

InitTimer();
sei();


DDRB &= (~ (1<<PB0)); /* Pin PB0 als Eingang */
PORTB |= (1<<PB0); /* Pull Up von PIN B0 aktivieren */
DDRB = (1<<DDB1); // PB1 Ausgänge


while(1)
{
if (!( PINB & (1<<PINB0))) /* mache was wenn PinB0 low ist */
{
// Hier muss Variable a abgefragt werden
PORTB|=(1<<PB1); // high
}
else
{
PORTB&= ~(1<<PB1); // low
}

}
}

Hubert.G
26.01.2009, 12:19
So sollte es funktionieren, die Timerzeit stimmt nicht und wenn die Taste länger als 65535 gedrückt ist dann leuchtet die LED wieder, da es zu einem Zählerüberlauf kommt.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

volatile unsigned int a = 0;

ISR(TIMER0_OVF_vect)
{

a++; // ca. 1 sec zahlt die Variable a
}

void InitTimer(void)
{
TCCR0 = TCCR0 | (1<<CS00); // Prescaler CK/8
TCNT0 = 0;
TIMSK = TIMSK | (1<<TOIE0);
}


int main(void)
{

InitTimer();
sei();


DDRB &= (~ (1<<PB0)); /* Pin PB0 als Eingang */
PORTB |= (1<<PB0); /* Pull Up von PIN B0 aktivieren */
DDRB = (1<<DDB1); // PB1 Ausgänge


while(1)
{
if (!( PINB & (1<<PINB0))) { /* mache was wenn PinB0 low ist */
if (a < 6){ /* Wenn länger als ca.6 sec Taster gedrückt, dann aus */
PORTB|=(1<<PB1); // high
}
else {PORTB&= ~(1<<PB1); // low
}
}
else
{
PORTB&= ~(1<<PB1); // low
a=0;
}
}
}

crusico
26.01.2009, 13:05
Danke für dein Code, aber so leutet die lampe sehr sehr schwach und nicht normal! Da ist irgendwo noch ein Denkfehler!

jetzt gehts besser ich habe den Wert a>6 geändert und es klappt!

Danke nochmals.