Witam!
Napisałem program, który ma liczyć ile czasu trwał impuls i jaki jest odstęp między nimi.
Problem wygląda tak, że mocno przekłamuje, ponad 2x i nie wiem z czego to wynika.
Pomysł był taki, aby za pomocą przerwania od zrównania licznika uzyskiwać czas, czyli jedno przerwanie to u mnie 10µs.
Gdy pojawia się impuls, ogólny czas między impulsami jest wpisywany do jednej zmiennej, liczniki są zerowane i program czeka na zanik impulsu. Gdy to następuje, wpisuje zliczoną wartość do drugiej zmiennej i znowu czeka ale tym razem na pojawienie się impulsu. Gdy od następuje, wpisuje ogólny czas do pierwszej zmiennej, resetuje wszystko i tak w kółko...
Rezonator kwarcowy to 10MHz, układ liczy do 100 czyli przy braku dzielnika zegara wychodzi mi przerwanie co 10µs.
W efekcie tak nie jest...
Wie ktoś dlaczego tak może się dziać? Układ mierzy obroty silnika w samochodzie przez pobieranie informacji z wtryskiwaczy. Czyli odstęp między wtryskami to to czas jednego obrotu (wtrysk grupowy, czyli pierwszy wtrysk na ssaniu, drugi na wydechu).
Pozdrawiam
Napisałem program, który ma liczyć ile czasu trwał impuls i jaki jest odstęp między nimi.
Problem wygląda tak, że mocno przekłamuje, ponad 2x i nie wiem z czego to wynika.
Pomysł był taki, aby za pomocą przerwania od zrównania licznika uzyskiwać czas, czyli jedno przerwanie to u mnie 10µs.
Gdy pojawia się impuls, ogólny czas między impulsami jest wpisywany do jednej zmiennej, liczniki są zerowane i program czeka na zanik impulsu. Gdy to następuje, wpisuje zliczoną wartość do drugiej zmiennej i znowu czeka ale tym razem na pojawienie się impulsu. Gdy od następuje, wpisuje ogólny czas do pierwszej zmiennej, resetuje wszystko i tak w kółko...
Rezonator kwarcowy to 10MHz, układ liczy do 100 czyli przy braku dzielnika zegara wychodzi mi przerwanie co 10µs.
W efekcie tak nie jest...
volatile uint16_t m_czas_wtrysk=0, m_czas_obr=0; //dokładność od 0.01ms do 655.35ms
volatile uint16_t licznik=0;
volatile uint8_t znacznik=1;
ISR(INT1_vect)
{
GIMSK &= ~_BV(INT1); //wyłączenie przerwania od pinu
if( bit_is_set(PIND, PD3) )
{
TCNT1 = 0; //zerowanie licznika
m_czas_obr = licznik; //wpisz czas obrotu wału
licznik = 0; //zerowanie zmiennej licznikowej
znacznik = 0; //zerowanie zmiennej znacznika
}
if( bit_is_clear(PIND, PD3) )
{
m_czas_wtrysk = licznik;
}
EIFR = (1<<INTF1);
GIMSK |= _BV(INT1); //włączenie przerwania od pinu
}
ISR(TIMER1_COMPA_vect){ //przerwanie od zrównania licznika
TCNT1 = 0; // zerowanie licznika
licznik++; //zwiększ zmienną o 1
}
//_______________________________________________________________
uint32_t wynik=0; //wskaźnim na zmienną "wynik"
int main(void){
DDRB = 0xFF;
PORTB = 0x0F;
DDRD = ~_BV(PD3);//0xFF;
PORTD = 0x00;
MCUCR |= _BV(ISC10); //Wszelka zmiana na INT1 powoduje przerwanie
GIMSK |= _BV(INT1);// | _BV(INT0); //Włączenie przerwania od INT1 (PD3)
TIMSK |= _BV(OCIE1A); //Przerwanie od zrównania z OCR1A
TCCR1B |= _BV(CS10); //start timera (przerwanie przez zrównanie)
OCR1A = 100; //Przerwanie gdy wartość licznika równa 100 (co 0.01ms)
sei();
while(1)
{
if(znacznik==0)
{
cli();
write_command(0xC0);
write_to_lcd( '0'+( m_czas_wtrysk/10000) );
write_to_lcd( '0'+((m_czas_wtrysk/1000 )%10) );
write_to_lcd( '0'+((m_czas_wtrysk/100 )%10) );
write_to_lcd(0x2C);
write_to_lcd( '0'+((m_czas_obr/10 )%10) );
write_to_lcd( '0'+( m_czas_obr %10) );
write_to_lcd(' ');
write_to_lcd( '0'+( m_czas_wtrysk/10000) );
write_to_lcd( '0'+((m_czas_wtrysk/1000 )%10) );
write_to_lcd( '0'+((m_czas_wtrysk/100 )%10) );
write_to_lcd(0x2C);
write_to_lcd( '0'+((m_czas_wtrysk/10 )%10) );
write_to_lcd( '0'+( m_czas_wtrysk %10) );
znacznik = 1;
sei();
}
}
}Wie ktoś dlaczego tak może się dziać? Układ mierzy obroty silnika w samochodzie przez pobieranie informacji z wtryskiwaczy. Czyli odstęp między wtryskami to to czas jednego obrotu (wtrysk grupowy, czyli pierwszy wtrysk na ssaniu, drugi na wydechu).
Pozdrawiam
