Witam!
Mam taki oto kod:
Program jest dość prosty, ma wyliczać jak długo trwał impuls. Czyli gdy pojawi się opadające zbocze, wyzwala się przerwanie, które uruchamia przerwanie od zrównania licznika, w którym to zmienna jest zwiększana o 1.
Jeśli wyłączę linię while(PIND&0x08); która oblicza czas pomiędzy impulsami, liczy wtedy sam czas impulsów i to działa ok, ale gdy ją włączę, to za pierwszym razem działa program ok, raz zewrę z masą pin to nic się nie stanie, ale za drugim wyświetli się dana. Ale gdy drugi raz chce to zrobić, to już wystarczy że dotknę masy i się cyfry wyświetlają, ale po kilku razach już niema cyfr a są jakieś dziwne znaczki i procek się restartuje
Nie wrzucałem już funkcji od wyświetlacza bo dobrze je przetestowałem i chodzą prawidłowo, niema raczej sensu zaśmiecać tematu zbędnym kodem, coś jest w tym przerwaniu czego nie mogę znaleźć.
Jak dla mnie to powinno działać dobrze, jak raz zewrę pin to program przechodzi w przerwanie gdzie odlicza jak długo jest impuls. Gdy puszczę wpisuje tą daną do zmiennej i liczy dalej sprawdzając jaki jest odstęp między impulsami.
Po ponownym zwarciu powinien przerwać odliczanie, zatrzymać przerwanie, wyświetlić co tam wyliczył, zaczekać aż puszę pin i włączyć przerwanie od zwarcia pinu i utknąć w pętli while w głównej funkcji i czekać na przerwanie, a tak się nie dzieje nie wiem czemu.
Pozdrawiam
Mam taki oto kod:
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 10000000UL
#include <util/delay.h>
char znaki[10]={48, 49, 50, 51, 52, 53, 54, 55, 56, 57};
//znaki ASCII: 0 1 2 3 4 5 6 7 8 9
volatile uint16_t m_sekundy_wtrysk=0, m_sekundy_obr=0, licznik_z, wynik_z; //dokładność od 0.1ms do 200ms
volatile uint16_t *licznik; //wskaźnik na zmienną "licznik"
volatile uint16_t *wynik; //wskaźnim na zmienną "wynik"
volatile ISR(INT1_vect){ //przerwanie od złącza PD3 (INT1)
TCCR1B |= _BV(CS10); //start timera (przerwanie przez zrównanie)
GIMSK &= ~_BV(INT1); //wyłącz przerwania od opadajacego zbocza (wezwanie tego przerwania)
sei(); //uruchomienie przerwań w przerwaniu
while((PIND&0x08)==0); //dopuki jest sygnał... (blokada wyjścia z przerwania)
m_sekundy_wtrysk = licznik_z;
_delay_us(5);
while(PIND&0x08); //obliczanie czasu pomiędzy impulsami
TCCR1B &= ~_BV(CS10); // zatrzymanie timera (przerwanie przez zrównanie)
m_sekundy_obr = licznik_z;
write_command(0xC3); //przejdź do 3 znaku w 2 wierszu
if(m_sekundy_obr >= 0xFFDC){ //jesli zmienna przepełniona
write_text("Nadmiar!");
}else{
write_to_lcd(znaki[m_sekundy_obr/10000]);
write_to_lcd(znaki[(m_sekundy_obr/1000)%10]);
write_to_lcd(znaki[(m_sekundy_obr/100)%10]);//wyświetlanie liczby 5 cyfrowej
write_to_lcd(znaki[(m_sekundy_obr/10)%10]);
write_to_lcd(znaki[m_sekundy_obr%10]);
}
write_command(0x89); //9 kolumna, 0 wiersz na wyswietlaczu
licznik_z = 0; //zerowanie zmiennej licznikowej
TCNT1 = 0; // zerowanie licznika
while((PIND&0x08)==0);//jesli pojawil sie sygnal, zaczekaj az zaniknie
GIMSK |= _BV(INT1); //wlacz przerwania od opadajacego zbocza
}
volatile ISR(TIMER1_COMPA_vect){ //przerwanie od zrównania licznika
TCNT1 = 0; // zerowanie licznika
licznik_z += 0x0001; //zwiększ zmienną o 1
if(licznik_z==0xFFFF){ //jesli licznik sie przepelnil
write_command(0xC9);
write_text("!"); //poinformuj o tym
}
}
int main(void){
DDRB = 0xFF;
PORTB = 0x0F;
DDRD = ~_BV(PD3);//0xFF;
PORTD = _BV(PD3);//0x00;
MCUCR |= _BV(ISC11); //Opadajace zborze wyzwala przerwanie
GIMSK |= _BV(INT1);//Włączenie przerwania od INT1 (PD3)
TIMSK |= _BV(OCIE1A); //Przerwanie od zrównania z OCR1A
TCCR1B = 0x00; //Timer wyłączony przy starcie
OCR1A = 1000; //Przerwanie gdy wartość licznika równa 1000
lcd_init();
write_command(0xC0); //0 kolumna, 1 wiersz
write_text("->");
sei(); //wlacz przerwania
while(1)
{
}
}
Program jest dość prosty, ma wyliczać jak długo trwał impuls. Czyli gdy pojawi się opadające zbocze, wyzwala się przerwanie, które uruchamia przerwanie od zrównania licznika, w którym to zmienna jest zwiększana o 1.
Jeśli wyłączę linię while(PIND&0x08); która oblicza czas pomiędzy impulsami, liczy wtedy sam czas impulsów i to działa ok, ale gdy ją włączę, to za pierwszym razem działa program ok, raz zewrę z masą pin to nic się nie stanie, ale za drugim wyświetli się dana. Ale gdy drugi raz chce to zrobić, to już wystarczy że dotknę masy i się cyfry wyświetlają, ale po kilku razach już niema cyfr a są jakieś dziwne znaczki i procek się restartuje
Nie wrzucałem już funkcji od wyświetlacza bo dobrze je przetestowałem i chodzą prawidłowo, niema raczej sensu zaśmiecać tematu zbędnym kodem, coś jest w tym przerwaniu czego nie mogę znaleźć.
Jak dla mnie to powinno działać dobrze, jak raz zewrę pin to program przechodzi w przerwanie gdzie odlicza jak długo jest impuls. Gdy puszczę wpisuje tą daną do zmiennej i liczy dalej sprawdzając jaki jest odstęp między impulsami.
Po ponownym zwarciu powinien przerwać odliczanie, zatrzymać przerwanie, wyświetlić co tam wyliczył, zaczekać aż puszę pin i włączyć przerwanie od zwarcia pinu i utknąć w pętli while w głównej funkcji i czekać na przerwanie, a tak się nie dzieje nie wiem czemu.
Pozdrawiam