Geimel
20.08.2007, 17:27
Hallo,
ich will für eine CarreraBahn eine Zeitmessanlage bauen. Dazu habe ich 2 Auslöser an der Bahn die an einen Mega8 als externer Interrupteingang angschlossen sind. Nun will ich jeweils nur die Rundenzeit und die Rundenanzahl anzeigen. Da der Kontakt jedoch für einige ms besteht, wird der Interrupt ja quasi mehrmals ausgelöst. Mein frage ist nun, kann ich wenn jeweils der entsprechende Interrupt 1 oder 2 ausgelöst wurde den für zB. 250ms sperren, mit nem Timer oder so? Die Zeit soll aber weiterzählen.
Hier ein einfacher Code der bis dahin funkioniert, jedoch mehrmals auslöst: (soll noch weiterentwickelt werden, wenn dieses Problem gelöst ist)
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#define F_CPU 4000000UL // 4 MHz
#include <util/delay.h>
#include "lcd.c"
#include "lcd_hw.h"
#include <string.h>
uint16_t time,time1,time2;
int rd1,rd2;//Rundenanzahl
char zeichen,output[20+1];
void delay_ms(unsigned int ms)
/* delay for a minimum of <ms> */
{ while(ms){ _delay_ms(0.96);ms--;}}
static void int_to_ascii(uint16_t inum,char *outbuf,signed char decimalpoint_pos,signed char spacepadd){
signed char i,j;
char chbuf[8];
j=0;
while(inum>9 && j<7){
// zero is ascii 48:
chbuf[j]=(char)48+ inum-((inum/10)*10);
inum=inum/10;
j++;
if(decimalpoint_pos==j){
chbuf[j]='.';
j++;}
}
chbuf[j]=(char)48+inum; // most significant digit
decimalpoint_pos--;
while(j<decimalpoint_pos){
j++;
chbuf[j]='0';}
if (spacepadd && j > (decimalpoint_pos+2)){
spacepadd=0;
}
if(decimalpoint_pos==j){
j++;
chbuf[j]='.';
j++;
chbuf[j]='0'; // leading zero
}
if (spacepadd){
j++;
chbuf[j]=' '; // leading space padding: "9.50" becomes " 9.50"
}
// now reverse the order
i=0;
while(j>=0){
outbuf[i]=chbuf[j];
j--;
i++; }
outbuf[i]='\0';
}
ISR(INT0_vect) {lcd_gotoxy(0,0);lcd_puts("P1: ");// in Zeile 1 P1: schreiben
int_to_ascii(rd1,output,0,1);lcd_puts(output);//in Zeile 1 Rundenanzahl1 schreiben
int_to_ascii(time1,output,3,1);lcd_puts(output);ti me1=0;//im Zeile 1 Rundenzeit1 schreiben
rd1++;//Rundenanzahl erhöhen
}
ISR(INT1_vect) {lcd_gotoxy(0,1);lcd_puts("P2: ");
int_to_ascii(rd2,output,0,1);lcd_puts(output);
int_to_ascii(time2,output,3,1);lcd_puts(output);ti me2=0;
rd2++;
}
int main(void)
{ DDRD |= (1<<PD2); //Register D für PD2 (auf 1) als Ausgang geschaltet
DDRD |= (1<<PD3);
PORTD |= (1 << PD2);
PORTD |= (1 << PD3);
GICR |= (1<<6)|(1<<7); //INT0 als Interrupt aktivieren
lcd_init(LCD_DISP_ON);
lcd_puts(" Los gehts ");delay_ms(2750);lcd_clrscr();
time=0;time1=0;time2=0;rd1=0;rd2=0;
sei(); //Interups Global an
while (1) {
_delay_us(980);time1++;time2++;
//time++ //Gesamtzeit
//int_to_ascii(integer wert,output char,kommastelleverschieben wert,leerzeichen vor dem wert)
/*lcd_puts("out_buf");
lcd_puts("V ");
lcd_putc('[');
lcd_puts("lool");
lcd_gotoxy(0,1);*/
}
return(0);
}
ich will für eine CarreraBahn eine Zeitmessanlage bauen. Dazu habe ich 2 Auslöser an der Bahn die an einen Mega8 als externer Interrupteingang angschlossen sind. Nun will ich jeweils nur die Rundenzeit und die Rundenanzahl anzeigen. Da der Kontakt jedoch für einige ms besteht, wird der Interrupt ja quasi mehrmals ausgelöst. Mein frage ist nun, kann ich wenn jeweils der entsprechende Interrupt 1 oder 2 ausgelöst wurde den für zB. 250ms sperren, mit nem Timer oder so? Die Zeit soll aber weiterzählen.
Hier ein einfacher Code der bis dahin funkioniert, jedoch mehrmals auslöst: (soll noch weiterentwickelt werden, wenn dieses Problem gelöst ist)
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#define F_CPU 4000000UL // 4 MHz
#include <util/delay.h>
#include "lcd.c"
#include "lcd_hw.h"
#include <string.h>
uint16_t time,time1,time2;
int rd1,rd2;//Rundenanzahl
char zeichen,output[20+1];
void delay_ms(unsigned int ms)
/* delay for a minimum of <ms> */
{ while(ms){ _delay_ms(0.96);ms--;}}
static void int_to_ascii(uint16_t inum,char *outbuf,signed char decimalpoint_pos,signed char spacepadd){
signed char i,j;
char chbuf[8];
j=0;
while(inum>9 && j<7){
// zero is ascii 48:
chbuf[j]=(char)48+ inum-((inum/10)*10);
inum=inum/10;
j++;
if(decimalpoint_pos==j){
chbuf[j]='.';
j++;}
}
chbuf[j]=(char)48+inum; // most significant digit
decimalpoint_pos--;
while(j<decimalpoint_pos){
j++;
chbuf[j]='0';}
if (spacepadd && j > (decimalpoint_pos+2)){
spacepadd=0;
}
if(decimalpoint_pos==j){
j++;
chbuf[j]='.';
j++;
chbuf[j]='0'; // leading zero
}
if (spacepadd){
j++;
chbuf[j]=' '; // leading space padding: "9.50" becomes " 9.50"
}
// now reverse the order
i=0;
while(j>=0){
outbuf[i]=chbuf[j];
j--;
i++; }
outbuf[i]='\0';
}
ISR(INT0_vect) {lcd_gotoxy(0,0);lcd_puts("P1: ");// in Zeile 1 P1: schreiben
int_to_ascii(rd1,output,0,1);lcd_puts(output);//in Zeile 1 Rundenanzahl1 schreiben
int_to_ascii(time1,output,3,1);lcd_puts(output);ti me1=0;//im Zeile 1 Rundenzeit1 schreiben
rd1++;//Rundenanzahl erhöhen
}
ISR(INT1_vect) {lcd_gotoxy(0,1);lcd_puts("P2: ");
int_to_ascii(rd2,output,0,1);lcd_puts(output);
int_to_ascii(time2,output,3,1);lcd_puts(output);ti me2=0;
rd2++;
}
int main(void)
{ DDRD |= (1<<PD2); //Register D für PD2 (auf 1) als Ausgang geschaltet
DDRD |= (1<<PD3);
PORTD |= (1 << PD2);
PORTD |= (1 << PD3);
GICR |= (1<<6)|(1<<7); //INT0 als Interrupt aktivieren
lcd_init(LCD_DISP_ON);
lcd_puts(" Los gehts ");delay_ms(2750);lcd_clrscr();
time=0;time1=0;time2=0;rd1=0;rd2=0;
sei(); //Interups Global an
while (1) {
_delay_us(980);time1++;time2++;
//time++ //Gesamtzeit
//int_to_ascii(integer wert,output char,kommastelleverschieben wert,leerzeichen vor dem wert)
/*lcd_puts("out_buf");
lcd_puts("V ");
lcd_putc('[');
lcd_puts("lool");
lcd_gotoxy(0,1);*/
}
return(0);
}