Konfiguracja Timera w Atmega8

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Konfiguracja Timera w Atmega8

Post autor: maxxxior » 10 gru 2013, 23:42

Witam, posiadam program migający diodą. Chciałbym aby dioda gasła i świeciłąna zmianę co 1s. Oto poniższy program.

Kod: Zaznacz cały

#include <avr/io.h>		// dołączenie głównego systemowego  pliku nagłówkowego
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>

#define F_CPU 1000000

int main(void)
{
DDRB = 0xFF;
PORTB = 0x00;

TCCR1B |= (1<<WGM12);				// tryb CTC
TCCR1A = (1<<COM1A1);				// dioda podpieta do OC1A
TCCR1B |= (1<<CS12)|(1<<CS10);		// preskaler = 1024
OCR1A = 31250;						// dodatkowy podział przez  (rej. przepełnienia)
TIMSK |= (1<<OCIE1A);				// zezwolenie na  przerwanie od porownania

sei();

while(1);

}

SIGNAL(SIG_OUTPUT_COMPARE1A)
{
	PORTB ^=(1<<PB1);
}
wiem że wartość wpisana do OCR1A jest zła dla 1s, ale teraz nawet dioda mi nie świeci ani nic...

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 11 gru 2013, 1:49

Witaj.

Z jednej strony ustawiasz generowanie sygnału przez timer na pinie OC1A, a z drugiej w przerwaniu chcesz zmieniać stan pinu PB1 na przeciwny. Problem w tym, że to ten sam pin :), a wtedy:
If one or both of the COM1A1:0 bits are written to one, the OC1A output
overrides the normal port functionality of the I/O pin it is connected to
.

Dodatkowo policzmy nieco:

1MHz (F_CPU) / 1024 (preskaler) ≈ 976 cykli timera na 1 sekundę.
Skoro ustawiłeś OCR1A na 31250, to przerwanie otrzymasz co:

31250 / 976 ≈ 32 sekundy

Wiem, że wiesz, iż to zła wartość OCR1A, ale czy odczekałeś tyle czasu? :)

Jak masz podłączoną diodę? Anodą, czy katodą do pinu?


BTW.
Używaj funkcji przerwań ISR() i nowych wektorów: http://www.nongnu.org/avr-libc/user-man ... rupts.html

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 11 gru 2013, 16:01

czyli tak jest dobrze:

Kod: Zaznacz cały

#include <avr/io.h>		// dołączenie głównego systemowego  pliku nagłówkowego
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>

#define F_CPU 1000000

int main(void)
{
DDRB = 0xFF;
PORTB = 0x00;

TCCR1B |= (1<<WGM12);				// tryb CTC
TCCR1B |= (1<<CS12)|(1<<CS10);		// preskaler = 1024
OCR1A = 488;						// dodatkowy podział przez  (rej. przepełnienia) czyli 1000 000Hz/1024=976 więc czestotliwosc migania diody=488/976=0,5s
TIMSK |= (1<<OCIE1A);				// zezwolenie na  przerwanie od porownania

sei();

while(1);

}

SIGNAL(SIG_OUTPUT_COMPARE1A)
{
	PORTB ^=(1<<PB1);
}
?? Dioda miga co ok 1s, ale nie jestem w stanie sprawdzić czy na pewno co równą 1s.

Awatar użytkownika
Artyliusz
Użytkownik
Posty: 306
Rejestracja: 06 sty 2013, 14:10
Lokalizacja: Z Polski
Kontakt:

Post autor: Artyliusz » 12 gru 2013, 7:00

Na wewnętrznym zegarze nie da się uzyskać równo 1s. Można trochę dokładniej używając przepełnień jak Drzesiek w tym linku http://mikrokontrolery.blogspot.com/201 ... timer.html

Dzieląc zegar przez preskalery nie dostaniesz równej sekundy, bo tak się nie da podzielić. Aby uzyskać równo 1s to musisz zastosować kwarc zegarowy 32.768kHz, który podłącza się do timera co dzieląc przez preskalery daje możliwość otrzymanie dokładniejszego czasu 1s. Możesz ostatecznie zastosować RTC, ale to przerost. :)
Sprawdź sobie tutaj: http://mikrokontrolery.blogspot.com/201 ... timer.html

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 12 gru 2013, 14:45

Ok, chciałem tylko sięowiedzieć czy dobrze rozumuje to działanie Timera w trybie CTC, tzn czy program jest dobry.
I teraz drugie pytanie: Chciałbym aby program wchodził w przerwanie z częstotliwością 75Hz, i aby to przerwanie trwało/wywoływało się przez okres 10s. Chodzi mi np o to, aby dioda migała z częstotliwością 75Hz przez 10s. Jak uzyskać to 10s?

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 12 gru 2013, 15:16

Zwiększać wartość zmiennej w przerwaniu do określonej wartości. Gdy zostanie osiągnięta ta wartość zostanie odmierzony czas i po np. 10sek zatrzymać przerwanie.

Jeżeli przerwanie występuje co 1/75s (przy 75Hz) to zliczyć np. zmienną x do 750 i zatrzymać przerwanie.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 06 sty 2014, 16:18

ok, zrobiłem to aby przerwanie wystepowalo z zadaną częstotliwością, przez określony czas, lecz teraz chciałbym zmodyfikować program o przycisk. Miało by to działać tak, że po wciśnięciu przycisku, na pinie PB0 pojawia się sygnał o częstotliwości np 2Hz, i przez 10s(to już zrobiłem). I tutaj utknąłem, ponieważ nie wiem jak to rozwiązać. Miganie diodą jest w jednym przerwaniu, a przycisk też muszę jakoś zrobić z przerwaniem co nie? Chodzi mi o takie coś: Jeśli wciśnięto przycisk, to wejdź w przerwanie migania diodą.

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 07 sty 2014, 12:11

Pokaż aktualną wersję programu i schemat.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 07 sty 2014, 17:44

na razie mam tylko miganie diodą z częstotliwością ok 160Hz, oraz konfiguracja przerwania zewnętrznego. Dioda podłączona do PB1, a przycisk do PD2. Oto kod:

Kod: Zaznacz cały

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>
volatile int czas;

int main(void)
{
DDRD = 0x00;
PORTD=0xFF;
DDRB = 0xFF;
PORTB = 0x00;

TCCR1B |= (1<<WGM12);				// tryb CTC
TCCR1B |= (1<<CS12)|(1<<CS10);		// preskaler = 1024
OCR1A = 6;			//OCR1A=488 dla migania dioda co 1s			// dodatkowy podział przez  (rej. przepełnienia) czyli 1000 000Hz/1024=976 więc czestotliwosc migania diody=488/976=0,5s
TIMSK |= (1<<OCIE1A);				// zezwolenie na  przerwanie od porownania

     MCUCR |= 1<<ISC01; //konfiguracja przerwania INT0
     GICR |= 1<<INT0; //włączenie przerwania INT0

sei();
_delay_ms(50);
	while(1)
	{
	}

}

SIGNAL(SIG_OUTPUT_COMPARE1A)
{

	czas++;

		if(czas<=1600)
		{

			PORTB ^=(1<<PB1);
		}
		else
		{
			PORTB =0x00;
		}

}

ISR(INT0_vect)     //obsługa przerwania zewnętrznego
{
	// co tutaj pisac?
}
Tylko nie wiem, jak wywołanie tego przerwania w którym migam diodą, uzależnić od wciśnięcia przycisku.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 09 sty 2014, 20:07

Halo, pomoże ktoś?

keruseykaryu

Post autor: keruseykaryu » 12 sty 2014, 17:48

Dżizas. Z której to choinki się kolega urwał z tym przestarzałym SIGNAL?
Tylko nie wiem, jak wywołanie tego przerwania w którym migam diodą, uzależnić od wciśnięcia przycisku.
Wie kolega jak wyłączać i włączać źródła przerwań przez rejestry? Wie kolega jak postawić zmienną i ją zmieniać w przerwaniu? Jak wie to sprawa jest banalnie prosta.

maxxxior
Użytkownik
Posty: 210
Rejestracja: 19 mar 2010, 21:27
Lokalizacja: Skierniewice

Post autor: maxxxior » 13 sty 2014, 19:25

czyli co, włączam przerwanie od prczycisku, i w tym przerwaniu dopiero ustawiam rejestry konfigurujące przerwanie migające diodą?

Awatar użytkownika
dondu
Użytkownik
Posty: 211
Rejestracja: 24 maja 2005, 9:47
Lokalizacja: Śląskie
Kontakt:

Post autor: dondu » 16 sty 2014, 17:38

Tak, tak możesz zrobić.

ODPOWIEDZ