Pepisoft was du doch willst ist mit einem Timer mehrer Zeiten messen. Also Ultraschall, rc5 und PWM von deinem Kompass. Der Timer1 hat hat nur einen Input Capture Pin (für srf04). Du kannst aber die Externen Interrupt Pins benutzen.
Ich hab hier mal Code:
Code:
// geändert auf 8MHZ
#include <io.h>
#include <avr/delay.h>
#define US_PORT PORTD
#define US_PORT_RICHTUNG DDRD
#define US_PIN PD7 // Der Pin kommt zum Trigger-Puls Eingang
volatile unsigned int us_zeit=0;
volatile unsigned int zeit_int0=0,zeit_int1=0; // geändert
SIGNAL(SIG_INTERRUPT0)
{
zeit_int0=TCNT1; // geändert
TCCR1B= ~(1<<CS12) & ~(1<<CS11) & ~(1<<CS10); // Timer wieder aus
TCNT1=0;
}
SIGNAL(SIG_INTERRUPT1)
{
zeit_int1=TCNT1; // geändert
TCCR1B= ~(1<<CS12) & ~(1<<CS11) & ~(1<<CS10); // Timer wieder aus
TCNT1=0;
}
SIGNAL(SIG_INPUT_CAPTURE1) // Interrupt für US Zeitmessung
{
us_zeit=ICR1;
TCCR1B= ~(1<<CS12) & ~(1<<CS11) & ~(1<<CS10); // Timer wieder aus
TCNT1=0;
}
unsigned char start_us_messung(void) // Ultraschallmessung
{
unsigned char wert,wert_in_cm;
// PD6 ist Input Capture Pin beim ATMega8, hier kommt der Echo-Pulse Ausgang hin
TIMSK|= (1<<TICIE1); // Input Capture Interrupt enable
TCCR1B&=~(1<<ICES1); // Fallende Flanke für Input Capture
US_PORT|=(1<<US_PIN); // Trigger-Puls Eingang high
_delay_us(15); // Laut Datenblatt Trigger-Puls min 10us auf high
_delay_us(15); // Laut Simulator ist wartet _delay_us() nur die
// hälfte der Zeit
US_PORT&=~(1<<US_PIN); // Trigger-Puls Eingang wieder auf low
_delay_us(185); // Erst wird ein 200us langer 40kHz Burst vom srf04 gesendet
_delay_us(185);
TCCR1B|=(1<<CS11); // Prescaler 8, startet Timer
while(us_zeit==0); // Warten bis Ergebnis
if(us_zeit>19000) // Dann kein Objekt vor den Sensor
{
wert=0;
us_zeit=0;
return wert;
}
else
{
wert=172*us_zeit/10000; // wert ist nun in cm
us_zeit=0;
return wert;
}
}
// Zeitmessung mithilfe von Externem Interrupt 0 und Timer1
unsigned long long star_zeitmessung_int0(unsigned char flag) // flag = 1 fallende Flanke generiert Interrup
{ // flag = 2 gegenteil
unsigned long long wert;
if(flag==1)
MCUCR|=(1<<ISC01);
if(flag==2)
MCUCR=(1<<ISC01|(1<<ISC00);
GICR |=(1<<INT0); // Externer Interrupt an
TCCR1B|= (1<<CS11); // Timer an, Prescaler 8 damit Zeitäuflösung genau 1 micro sekunde !!! geändert
while(zeit_int0==0); // Warten bis Ergebnis
wert=zeit_int0; // Wert in micro sekunden
zeit_int0=0; // Wieder auf 0 setzen für nächste Messung
return wert;
}
// Zeitmessung mit Externem Interrupt1 und Timer1
unsigned long long start_zeitmessung_int1(unsigned char flag)
{
unsigned long long wert;
if(flag==1)
MCUCR|=(1<<ISC11);
if(flag==2)
MCUCR=(1<<ISC11) | (1<<ISC10);
GICR|=(1<<INT1);
TCCR1B|= (1<<CS11); // Timer an, Prescaler 8 geändert
while(zeit_int1==0);
wert=zeit_int1;
zeit_int1=0;
return wert;
}
void main (void)
{
unsigned char wert;
unsigned long long wert1,wert2;
US_PORT_RICHTUNG|=(1<<US_PIN); // US_PIN auf Ausgang
wert=start_messung();
wert1=start_zeitmessung_int0();
wert2=start_zeitmessung_int1();
}
Damit kann man mit einem Timer alle deine drei Ereignisse messen. Die Funktionen start_zeitmessung_intX() geben dir nur die Zeit in micro sekunden zurück. Was du damit machst (umrechnen in Grad bei Kompass, rc5 usw.) ist dir überlassen. In deinem Fall muss halt z.B. den Out Pin von deim TSOP auf einen der Externen Interrupt Pins von deinem ATMega. Allerdings weis ich immer noch nicht was passiert wenn der Timer mehr als 1mal durchläuft, also nach 262,144 millisekunden. Um den sozusagen Höchsmesswert zu erhöhen kann man den Prescaler in den Funktionen start_zeitmessung_intX() verändern und in den Interrupts in den Zeilen zeit_intX=TCNT1*4; das *4 dementsprechend ändern. Hoffe man hats verstanden.
Gruß Muraad
EDIT: nochmal geändert, das mit TCCRB1 und TICIE1
EDIT: Code funktioniert nicht richtig. Bitte in den Thread schauen:
https://www.roboternetz.de/phpBB2/vi...?p=67114#67114
Lesezeichen