• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Timery Atmega8 nie działają poprawnie

Cloud VPS
0 głosów
536 wizyt
pytanie zadane 4 października 2016 w Mikrokontrolery przez Mavimix Dyskutant (8,420 p.)

Napisałem taki kod:

#define F_CPU 1000000UL

#include <cstdlib>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.c"

int main(void)
{
	LCD_Ini();

	sei();

	TIMSK |= (1<<TOIE0);
	TCCR0 |= (1<<CS01);

	_delay_ms(5000);

	TCCR0 &= ~(1<<CS01);

	char Temp[8];
						sprintf(Temp,"%i", TCNT0);

	LCD_ZapiszText(Temp);
}

ISR(TIMER0_OVF_vect)
{
	TCNT0 = 0;
}

Według moich obliczeń (reszta z dzielenia 5.000.000 przez 256) wynika, że TCNT0 powinno być równe 64, a na wyświetlaczu pokazuje że jest równe 231. Zauważyłem, że timer nie działa poprawnie. Czemu tak jest?

1 odpowiedź

+1 głos
odpowiedź 4 października 2016 przez jeremus Maniak (59,720 p.)

Bardzo karkołomny kod. Nie wiem za bardzo co chcesz udowodnić.Ustawiłeś preskaler na 8. Przerwania powinny być 125 000 razy na sekundę . Procedura obsługi przerwania , mimo że prosta zajmuje trochę czasu i ten delay(5000) będzie trwał nieco dłużej niź 5 sekund. W liczniku może więc pojawić się dziwna przypadkowa ( acz powtarzalna ) . Użyj prawidłowego sposobu obsługi Timerów i wszystko się zgodzi. http://www.robotyka.net.pl/mikrokontrolery-avr-czesc-6-timer0/

komentarz 5 października 2016 przez Mavimix Dyskutant (8,420 p.)

Faktycznie nie zauważyłem, że ustawiłem preskaler na 8 a nie na 1. Poprawiłem to, ale cały czas ten sam błąd. Co zrobić żeby dokładnie odmierzyć 10us? Czy ten program będzie działał?


#define F_CPU 1000000UL
 
#include <cstdlib>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.c"
 
int main(void)
{
    LCD_Ini();
 
    sei();
 
    TIMSK |= (1<<TOIE0);
    TCNT0 = 246;
    TCCR0 |= (1<<CS00);
 
    while(1)
    {
    }

}
 
ISR(TIMER0_OVF_vect)
{
    TCCR0 &= ~(1<<CS00);
    TCNT0 = 0;

    char Temp[8];
                        sprintf(Temp,"%i", TCNT0);
 
    LCD_ZapiszText(Temp);
    LCD_XY(0,1);
    LCD_ZapiszText("Minelo 10 us");

     _Delay_ms(100000);
}

 

komentarz 5 października 2016 przez jeremus Maniak (59,720 p.)

ale co właściwie ten program ma robić ?

funkcja obsługi przerwania powinna być jak najkrótsza

np.

zwiększ jakiś licznik;

ustaw jakiś wskaźnik

i

TCNT0=246; // aby powtórzyć kolejny cykl

nie należy używać w tej funkcji żadnych instrukcji delay, obługa wyświetlacza tez zajmuje trochę czasu

10 us to raptem 10  taktów zegara przy tym taktowaniu  procesora - niewiele więc można zrobić  w procedurze przerwania

poza tym :

 dlaczego wyłączasz obsługę przerwań ?  TCCR0 &= ~(1<<CS00);

 

 ma się tylko raz wykonać przerwanie  po 10 us ?

ale to trochę bez sensu -

i na koniec

sei() wykonujemy po ustawieniu rejestrów a nie przed - to powinna być ostatnia instrukcja przed pętlą główną programu

 

komentarz 5 października 2016 przez Mavimix Dyskutant (8,420 p.)
Docelowo chcę zaprogramować czujnik odległości - ustawiam na jeden pin stan wysoki przez 10us, potem do mikrokontrolera wysyłany jest sygnał wysoki, który trzeba zmierzyć też w mikrosekundach i w zależności od tego czasu przelicza się na odległość. Za każdym razem jak napiszę program sprawny w 99% to mam wrażenie, że timery nie działają poprawnie.

Podobne pytania

–1 głos
2 odpowiedzi 889 wizyt
pytanie zadane 9 lipca 2016 w Mikrokontrolery przez Mavimix Dyskutant (8,420 p.)
0 głosów
1 odpowiedź 214 wizyt
pytanie zadane 5 marca 2017 w Mikrokontrolery przez Mavimix Dyskutant (8,420 p.)
0 głosów
1 odpowiedź 517 wizyt
pytanie zadane 9 lipca 2016 w Mikrokontrolery przez Mavimix Dyskutant (8,420 p.)

93,460 zapytań

142,454 odpowiedzi

322,724 komentarzy

62,837 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...