Witam
Poniższy program mierzy długość trwania impulsu / stanu niskiego podanego na INT1.
Pomiar jest wyzwalany przerwaniem, zboczem opadającym, następnie następuje włączenie timera i przestawienie przerwania na zbocze narastające. Gdy ono nastąpi jest wyzwalane kolejne przerwanie, które zeruje zatrzymuje timer. Odczyt timera (rejestr TCNT1) następuje z godnie z dokumentacją przy wyłączonych przerwaniach. Za pomocą rejestru TCCR1B ustawiam preskaler na 1024. I teraz moje obliczenia
Atmega pracuje z wewnętrzym kwarcem 1Mhz
1Mhz = 1/1000000 = 1us
czyli 1 takt procesora co 1us
prescaler jest ustawiony na 1024 czyli licznik jest zwiększany o 1 po 1024 taktach procesora
1 takt licznika trwa 1us * 1024 = 1024us = 1,024ms
Żeby otrzymać wynik w ms mnożę wartość licznika przez 1,024.
Czy moje obliczenia są poprawne?
Oraz jeszcze jedna wątpliwość, czemu przed każdą zmianą rejestru MCUCR muszę go zerować:
Jeśli tego nie zrobię program/procesor nie reaguje na inne ustawienie tego rejestru.
z góry dziękuję za odpowiedzi i konstruktywną krytykę
--
pozdrawiam
demeus
Poniższy program mierzy długość trwania impulsu / stanu niskiego podanego na INT1.
Pomiar jest wyzwalany przerwaniem, zboczem opadającym, następnie następuje włączenie timera i przestawienie przerwania na zbocze narastające. Gdy ono nastąpi jest wyzwalane kolejne przerwanie, które zeruje zatrzymuje timer. Odczyt timera (rejestr TCNT1) następuje z godnie z dokumentacją przy wyłączonych przerwaniach. Za pomocą rejestru TCCR1B ustawiam preskaler na 1024. I teraz moje obliczenia
Atmega pracuje z wewnętrzym kwarcem 1Mhz
1Mhz = 1/1000000 = 1us
czyli 1 takt procesora co 1us
prescaler jest ustawiony na 1024 czyli licznik jest zwiększany o 1 po 1024 taktach procesora
1 takt licznika trwa 1us * 1024 = 1024us = 1,024ms
Żeby otrzymać wynik w ms mnożę wartość licznika przez 1,024.
Czy moje obliczenia są poprawne?
volatile unsigned char pomiar = 0;
unsigned char sreg;
float i;
char czas[8];
void Inicjalizacja(void)
{
LCD_init(); // Inicjalizacja wyświetlacza
sei(); // Włączenie obsługi przewań
MCUCR = 0; // Zerowanie rejestru MCUCR
MCUCR |= (1<<ISC11)|(0<<ISC10); // Wyzwolenie przerwania zboczem opadającym
GICR |= 1<<INT1; // Załączenie przerwania na INT1
TCCR1A = 0; // T/C1 w trybie czasomierza
}
SIGNAL (SIG_INTERRUPT1)
{
if (pomiar==0)
{
TCNT1 = 0; // Zerowanie czasomierza T/C1
TCCR1B |= (1<<CS10)|(1<<CS12); // Zalaczenie timera1 - preskaler ck/1024
MCUCR = 0; // Zerowanie rejestru MCUCR
MCUCR |= (1<<ISC11)|(1<<ISC10); // Przestawienie przerwania na zbocze narastajace
pomiar = 1;
}
else
{
TCCR1B &= ~((1<<CS10)|(1<<CS12)); // Wylaczenie timera1
MCUCR = 0; // Zerowanie rejestru MCUCR
MCUCR |= (1<<ISC11)|(0<<ISC10); // Przestawienie przerwania na zbocze opadajace
pomiar = 0;
}
}
int main( void )
{
Inicjalizacja();
while(1)
{
LCD_xy(0,0);
sreg = SREG; // Zapis ustawień rejestru SREG
cli(); // Wyłączenie obsługi przerwań
i = TCNT1; // Zapis rejestru TCNT1 do zmiennej i
SREG = sreg; // Ustawienie rejestru SREG
dtostrf(i*1.024,8,2,czas); // Konwersja float do ascii
LCD_putstr_P(PSTR("TCNT1: "));
LCD_putstr(czas);
}
}Oraz jeszcze jedna wątpliwość, czemu przed każdą zmianą rejestru MCUCR muszę go zerować:
MCUCR = 0; // Zerowanie rejestru MCUCR
MCUCR |= (1<<ISC11)|(0<<ISC10); // Przestawienie przerwania na zbocze opadajaceJeśli tego nie zrobię program/procesor nie reaguje na inne ustawienie tego rejestru.
z góry dziękuję za odpowiedzi i konstruktywną krytykę
--
pozdrawiam
demeus