Skocz do zawartości

Pomocna odpowiedź

Nie dołączaj tylko wstaw kod. Ale najpierw go uporządkuj i wywal zbędne rzeczy by był dla nas łatwy do analizy.

Tak na szybko używasz nowego ISR(), ale starego wektora SIG_OVERFLOW0.

ISR(SIG_OVERFLOW0) 

Tak być nie powinno. Nie oznacza to że to jest przyczyną problemów.


#include <avr/io.h>
#include <avr/interrupt.h> 
#include <util/delay.h> 
#include <stdio.h>
#include <math.h> 
#include <inttypes.h>
#include <avr/wdt.h>    //watchdog

#define F_CPU 8000000UL /* 8 MHz */

//czestotliwosc kwarca i czas trwania 1 cyklu
#define clk_freq 		8000000UL
#define clk_period_us 	1*200*1000000UL/clk_freq

volatile int	licznik;
volatile double	czas;
volatile double	distance;
volatile int	zwrot;
volatile char 	triggered;
volatile int	rejestr;

//--------------------------------------------------------------------------------//


//--------------------------------------------------------------------------------//
//przerwanie 
ISR(INT2_vect) 
{
zwrot++;
TCCR0 |= (0<<CS02) | (0<<CS01) | (0<<CS00) | (0<<WGM01) | (0<<WGM00);
TIMSK |= (0<<TOIE0);
rejestr = TCNT0;

czas = ((int)rejestr + 255 * ((int)licznik));
distance =(((double)czas)/(29)*clk_period_us)/2;

licznik = 0;
TCNT0 = 0;
czas = 0;
triggered = 0;
}

//--------------------------------------------------------------------------------//


//--------------------------------------------------------------------------------//
ISR(SIG_OVERFLOW0) //początek funkcji obsługi przerwania
{
licznik++;
}
//--------------------------------------------------------------------------------//


//--------------------------------------------------------------------------------//
//ustawienia portów
void init_ports(void)
{	
DDRD 	|= _BV(PD7) | _BV(PD5) | _BV(PD4);		 //ustawienie pinów jako wyjść 
PORTD 	|= _BV(PD5) | _BV(PD4);				//stan wysoki
DDRD 	|= _BV(PD0);		//input 1 wyjście
DDRC 	|= _BV(PC1);		//input 3 wyjście
DDRD 	|= _BV(PD1);		//input 2 wyjście
DDRC 	|= _BV(PC0);		//input 4 wyjście
DDRB 	&= ~_BV(PB2);	 	//ustawienie pinu jako wejścia
PORTB 	|= _BV(PB2);	  	//załączenie rezystora podciągającego
}
//--------------------------------------------------------------------------------//


//--------------------------------------------------------------------------------//
void trigger(void)
{
PORTD = _BV(PD7);		//
_delay_us(10);          //czas trwania impulsu TRIG 10us
PORTD = ~_BV(PD7);		//
triggered = 1; 
}
//--------------------------------------------------------------------------------//


//--------------------------------------------------------------------------------//
void pomiar(void)
{
trigger ();
TCCR0 |= (0<<CS02) | (0<<CS01) | (1<<CS00) | (0<<WGM01) | (0<<WGM00);
TIMSK |= (1<<TOIE0);
}
//--------------------------------------------------------------------------------//

//program główny
int main (void)
{ 
init_ports();

MCUCSR |= _BV(ISC2); 
GICR   |= _BV(INT2);	 


sei ();


while (1)
{
	PORTD |= _BV(PD1);		//input 1 stan wysoki do przodu prawa strona 
	PORTD &= ~_BV(PD0);		//input 2 stan niski do przodu prawa strona
	PORTC |= _BV(PC0);		//input 1 stan wysoki do przodu prawa strona 
	PORTC &= ~_BV(PC1);		//input 2 stan niski do przodu prawa strona

	pomiar ();

	if (triggered == 0)
	{
	if (distance <= 50)
	{ 
		PORTD &= ~_BV(PD1);		//input 2 stan niski do przodu prawa strona
		PORTC &= ~_BV(PC0);		//input 2 stan niski do przodu prawa strona
		_delay_ms(1000);
	}
	}
}
return (0);
}

A oto i kod 🙂

0. Jaki to mikrokontroler?

1. Nie wyskakuje Ci taki warning:

c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:85:3: warning: #warning "F_CPU not defined for "

../PROBY.c:11:1: warning: "F_CPU" redefined

Jeżeli definiujesz F_CPU w kodzie, to MUSISZ to zrobić przed inkludowaniem delay.h. Nie wiem w czym piszesz, ale jeżeli w AVR Studio to zegar zdefiniuj w opcjach projektu a nie w kodzie.

2. Nie definiuj dodatkowej etykiety:

#define clk_freq  8000000UL 

Wykorzystaj F_CPU - nie masz wtedy problemu ewentualnej pomyłki przy zmianach częstotliwości zegara.

3. Już pisałem ale napiszę jeszcze raz bo w załączonym kodzie nie poprawiłeś:

używasz nowego ISR(), ale starego wektora SIG_OVERFLOW0 patrz: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

4. mało istotny drobiazg - to jest zbędne:

return (0); 

5. inne warningi?

6. Wprowadź zmiany i sprawdź, a gdyby nadal nie działał to opisz dokładniej co stwierdzasz i jakie są problemy.

Jedyny warning to:

 przerwania.c:100: warning: large integer implicitly truncated to unsigned type 

.

Program piszę w WinAVR, problem polega na tym, że gdy zadam mu jakąś odległość, i porównam ją do otrzymanej z obliczeń to gdzie bym nie ruszył ręką, atmega i tak zareaguje zmieniając stan na wyjściu. Wydaje mi się, że procedura odmierzania czasu jest poprawna oraz obliczanie odległości także, ale warunek ze sprawdzaniem odległości nie działa poprawnie. Jedyną różnicą w jakiej odległości ustawię przedmiot jest czas odpowiedzi mikrokontrolera, im bliżej tym szybsza odpowiedź, ale to wydaje się być logiczne.

Odpowiadając nie napisałeś, czy naniosłeś poprawki które opisałem powyżej?

Teraz nie wiemy, czy ten opis jest po poprawkach czy przed.

Jedyny warning to:
 przerwania.c:100: warning: large integer implicitly truncated to unsigned type 

.

czyli która linia kodu, bo po numeracji nie znajdę?

PORTD = _BV(PD7);        //
_delay_us(10);          //czas trwania impulsu TRIG 10us
PORTD = ~_BV(PD7);        //
triggered = 1; 

Jeśli chcesz ustawić stan na odpowiednim pinie, to chyba powinno być:

PORTD |= _BV(PD7);        //
_delay_us(10);          //czas trwania impulsu TRIG 10us
PORTD &=~ _BV(PD7);        //
triggered = 1; 

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...