Skocz do zawartości

Czujnik odleglosci hc sr04 - obsluga w jezyku C Atmega328p


szejkop

Pomocna odpowiedź

Witam

Chciałbym zwrócić się z prośbą o pomoc w obsłudze czujnika odległosci w jezyku C.

W Arduino IDE jest wręcz banalne i zrobiłem to tak jak na kursie:

funkcja odpowiedzialna za to:

int zmierzOdleglosc() 
{
 long czas, dystans;
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);

 czas = pulseIn(echoPin, HIGH);
 dystans = czas / 58;

 return dystans;
}

Ustawienie poszczególnych pinów oraz opóżnień w C jest dosyć łatwe, natomiast chodzi mi o realizacje funkcji pulseIn czyli funkcji odpowiedzialnej za pomiar długości impulsu.

Posiadam: Atmega328p oraz zewnętrzny rezonator 16Mhz - czyli po prostu programuje arduino pisząc program w C.

Ogólnie chciałbym skorzystać z przerwania zewnętrznego, dlatego też echo pin podłączyłem do INT1.

W trakcie kiedy wykryje zbocze narastające, ma zostać uruchomiony timer i ma on mierzyć czas do momentu zmiany wartości syganłu na zero. Następnie przypisać owy czas do pewnej zmiennej,która następnie przetworzymy na odleglość.

#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
//#define trigPin arudino12 pb4
//#define echoPin arudino3 pd3
#include <avr/interrupt.h>
volatile uint16_t czas;

int main(void)
{
 sei();

 Serial.begin (9600);
 DDRB = 0b0000000;//trigg na wejscie
 DDRD = 0b11111111;//echo na wyjscie int

 TCCR0B = (1 << CS02);//256 preskaler

 EIMSK=0b00000010; //aktywowanie przerwania od int1
 EICRA=0b00000011; // reagowanie na narastajace zbocze na int1

 while (1)
 {  
 PORTB &= ~(1 << 4); //przypisanie zera
 delayMicroseconds(2);
 PORTB |= (1 << 4); // przypisanie jedynki
 delayMicroseconds(10);
 PORTB &= ~(1 << 4);
 }
}

ISR( INT1_vect ) //przerwanie
{
 TCNT0 = 0;

 while (PD3); //dopoki echo jest w stanie wysokim zatrzymaj się w tym miejscu
 czas=TCNT0; 
}

Piny przypisałem zgodnie ze zdjęciem,które zostało tutaj załączam.

Link do komentarza
Share on other sites

"...zatrzymaj się w tym miejscu"

To bardzo zły pomysł. Funkcje obsługi przerwań z zasady nigdy na nic nie czekają. Są odpalane zdarzeniami a ich wykonanie powinno trwać jak najkrócej. Jeżeli chcesz zrobić swój pomiar zgodnie z tą ideą, musisz obsługiwać przerwanie raz od zbocza narastającego (kiedy to zerujesz i odpalasz timer i przeprogramowujesz wejście na zbocze opadające) a raz od opadającego (gdy zatrzymujesz i odczytujesz timer, zmieniasz kierunek zbocza i ew. blokujesz dalsze przerwania od wejścia). Samo włączanie przerwania i ustalanie kierunku pierwszego zbocza może odbywać się w funkcji generacji impulsu sondującego. Taka funkcja obsługi jak opisałem będzie wykonywać się kilka mikrosekund, nie będzie zamrażać procesora (zgroza) ale musi rozpoznawać co ma akurat zrobić. Ponieważ stany są tylko dwa (takie zbocze lub takie), może odczytywać rejestr/bit kierunku aktywnego zbocza lub jakiś znacznik (flagę) static boolean.

No dobrze, ale może w ogóle zadaj jakieś pytanie 🙂 W czym potrzebujesz pomocy?

Link do komentarza
Share on other sites

Dziękuje za odpowiedź. Mam problem właśnie z pomiarem długości impulsu. Mój program nie działa i stanąłem w miejscu. Jestem dopiero początkującym w C stąd prosiłbym o kod, który będę mógł przeanalizować , bądź o podpowiedź.

Link do komentarza
Share on other sites

Raczej się nie zdarza by kod programu działał od pierwszego razu. To typowe. Zacznij szukać błędu. Nie musisz "analizować" czyjegoś kodu. Zacznij oglądać i zmieniać swój. Wskazówkę już dostałeś poprzednio. Czego nie zrozumiałeś?

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Ogólnie rzecz biorąc porty były źle ustawione oraz napotkałem inny problem:

//program testowy//

#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
//#define trigPin arudino12 pb4
//#define echoPin arudino3 pd3
#include <avr/interrupt.h>
volatile uint8_t czas;

int main(void)
{
sei();

Serial.begin (9600);
DDRB = 0b11111111;//trigg na wyjscie
DDRD = 0b00000000;//echo na wejscie int

TCCR0B = (1 << CS02);//256 preskaler

EIMSK=0b00000010; //aktywowanie przerwania od int1
EICRA=0b00000011; // reagowanie na narastajace zbocze na int1

while (1)
{
czas=0;
PORTB &= ~(1 << 4); //przypisanie zera
_delay_us(2);
PORTB |= (1 << 4); // przypisanie jedynki
_delay_us(10);
PORTB &= ~(1 << 4);
Serial.println(czas);
_delay_ms(100);
}
}

Zauważyłem, że istnieje powiązanie pomiędzy globalnym odblokowaniem, a rejestrem EMISK odpowiedzialnym za odblokowanie przerwania zewnętrznego. Kiedy wyrażenie sei(); nie jest zakomentowane program nie działa, dopiero po usunięciu deklaracji globalnego odblokowania program rusza tzn. są przesyłane wartości czasu (0) do monitora szeregowego w przeciwnym wypadku program nie przesyła żadnej wartości. Jak mogę to rozwiązać?

__________

Komentarz dodany przez: Treker

Kody programów należy umieszczać w tag'ach . Tym razem już poprawiłem, pamiętaj na przyszłość 🙂

Link do komentarza
Share on other sites

Udało mi się rozwiązać problem z sei() w arduino, przerwanie reaguje odpowiednio na pojawienie się zbocza narastającego. Teraz chciałbym przejść realizacji zadania zgodnie z podpowiedzią marka1707. Mam problem jak stworzyć drugie przerwanie.

ISR( INT1_vect ) //przerwanie od zbocza narastajacego
{
 TCNT0=0;// start timera
 EICRA=0b00001000;//zmiana na opadajace zbocze
}

Jak wywołać teraz przerwanie od zbocza opadajacego? Nie moge użyc znów ISR( INT1_vect)

Myślałem również, żeby po prostu negować ten bit w rejestrze i sprawdzać jego warość:

ISR( INT1_vect ) //przerwanie
{
 if(EICRA & 0x04) //sprawdzenie ustawionego bitu
 {
TCNT0=0; //przerwanie od zbocza narastajacego czyli start timera
 }
 else
 {
czas=TCNT0; // przerwanie od zbocza opadajcego czyli zczytanie wartosci timera
 }
EICRA^=0x4; // negacja bitu odpowiedzialna za odpowiednia reakcje na zbocze
}

Niestety ta negacja nie działa, patrząc po szeregowym rejstrze,który dalej wskazuje wartosc 12.

Link do komentarza
Share on other sites

Jedno źródło to jeden wektor przerwania. Drugi sposób to dobry trop. Musisz sprawdzać ustawiony kierunek i w zależności od tego wykonywać odpowiednią akcję. Przed startem pomiaru ustaw na spokojnie odpowiedni kierunek zbocza (narastający) a potem w przerwaniu zmień na opadający. Zadziała na pewno.

Wysyłanie przez port szeregowy nie odbywa się w zerowym czasie. Impuls echa jest krótki. Najlepiej nie wysyłaj od razu tego co chcesz, tylko gromadź dane (odczytane zawartości rejestrów, portów, bitów itp) w jakiejś tablicy. Po zakończeniu pomiaru, gdy już nic się nie dzieje wypisz wszystko na raz.

Pamiętaj, że manipulacje w EICRA mogą powodować przerwanie. Nie odblokowuj przerwań INT1 w EIMSK dopóki nie upewnisz się, że odpowiednia flaga w EIFR jest zgaszona. W razie konieczności wyzeruj ją przez zapis jedynki.

"Niestety ta negacja nie działa"

Ojej, pewnie jak zwykle w takich wypadkach trafiłeś na zepsuty procesor.. 😉

Link do komentarza
Share on other sites

Dziękuje za odpowiedź. Tak jak powiedziałeś, ustawiłem na "spokojnie" reakcje na zbocze narastające. W przerwaniu zgaszam flagę(dla pewności) oraz zmieniam reakcje ze zbocza narastającego na opadające.

#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
//#define trigPin arudino12 pb4
//#define echoPin arudino3 pd3
#include <avr/interrupt.h>
volatile uint8_t czas;

int main(void)
{

EIMSK=0b00000010; //aktywowanie przerwania od int1
EICRA=0b00001100; // reagowanie na narastajace zbocze na int1

Serial.begin (9600);
DDRB = 0b11111111;//trigg na wyjscie
DDRD = 0b00000000;//echo na wejscie int

TCCR0B = (1 << CS00);//256 preskaler

sei();
while (1)
{
PORTB &= ~(1 << 4); //przypisanie zera
_delay_us(2);
PORTB |= (1 << 4); // przypisanie jedynki
_delay_us(10);
PORTB &= ~(1 << 4);
_delay_ms(200);
Serial.println(EICRA);

}
}

ISR( INT1_vect ) //przerwanie
{
TCNT0=0; /start timera
EIFR=0b00000010; //gaszenie flagi
EICRA=0b0001000; // opadajace
}

W jaki sposób teraz powrócić do przerwania(realizowanego przez zbocze opadające) i zapisac wartość timera do zmiennej,a potem znowu zmienić reakcje na zbocze narastające.

Link do komentarza
Share on other sites

Przede wszystkim zacznij od pisania funkcji. Stwórz jakąś która będzie robiła pomiar. To w niej powinno być przygotowanie systemu przerwań, generacja impulsu sondującego i ew. oczekiwanie na koniec. Jeśli nie chcesz, by funkcja "utykała" czekając na wynik (inaczej pewnie nie robiłbyś tej całej zabawy z przerwaniami), niech po wystartowaniu pomiaru kończy się. Kolejna funkcja może czekać. Wymyśl jakiś mechanizm (zmienna volatile?) informowania jej o zakończeniu pomiaru i gotowości wyniku. Będziesz ją wołał gdy już procesorowi znudzi się robienie czegoś innego i będzie potrzebował wyniku. Możesz też użyć mechanizmu callbacku.

Dopiero wtedy zajmij się funkcją obsługi przerwania. Twój pomysł był dobry. Test kierunku przerwania wg zawartości EICRA i odpowiednia akcja.

Acha i jeszcze jedno. Jeśli piszę:

"Pamiętaj, że manipulacje w EICRA mogą powodować przerwanie. Nie odblokowuj przerwań INT1 w EIMSK dopóki nie upewnisz się, że odpowiednia flaga w EIFR jest zgaszona. W razie konieczności wyzeruj ją przez zapis jedynki" to znaczy, że niespodziewane przerwanie może być zgłoszone już podczas ustawiania systemu przerwań. A Ty najpierw odblokowujesz INT1 przez zapis do EIMSK, potem dopiero ustawiasz jego tryb nigdzie nie sprawdzając czy właśnie sam sobie nie zgłosiłeś przerwania. I czytaj dokumentację procesora zamiast zgadywać lub robić coś na czuja:

"The flag is cleared when the interrupt routine is executed"

Link do komentarza
Share on other sites

Stworzyłem funkcje, program stał się bardziej przejrzysty. Niestety warunki w przerwaniu oraz negacja nie działa prawidłowo.

Jestem dopiero początkującym i callback oraz flagi nie są aż tak mi znane, dlatego też zwracam się z prośbą.

#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
//#define trigPin arudino12 pb4
//#define echoPin arudino3 pd3
#include <avr/interrupt.h>
volatile uint8_t czas;

int main(void)
{
DDRB = 0b11111111;//trigg na wyjscie
DDRD = 0b00000000;//echo na wejscie int
TCCR0B = (1 << CS00);//256 preskalera
Serial.begin (9600);

void sonda();
void initprzerwanie();
initprzerwanie();

 while (1)
 {
 sonda();
 Serial.println(czas);
 _delay_ms(200);
 }  
}
//////////Inicjalizacja przerwania///////////////

void initprzerwanie(void)
{
EIMSK=0b00000010; //aktywowanie przerwania od int1
EICRA=0b00001100; // reagowanie na narastajace zbocze na int1
sei();
}

//////////Sygnal sondujacy///////////////

void sonda(void)
{
PORTB &= ~(1 << 4); //przypisanie zera
_delay_us(2);
PORTB |= (1 << 4); // przypisanie jedynki
_delay_us(10);
PORTB &= ~(1 << 4);
}

//////////Obsluga przerwania///////////////

ISR( INT1_vect ) //przerwanie
{
 if(EICRA & 0x04) //sprawdzenie ustawionego bitu
 {
TCNT0=0; //przerwanie od zbocza narastajacego czyli start timera
 }
 else
 {
czas=TCNT0; // przerwanie od zbocza opadajcego czyli zczytanie wartosci timera
 }
EICRA^=0x4; // negacja bitu odpowiedzialna za odpowiednia reakcje na zbocze

}
Link do komentarza
Share on other sites

To może temat jest po prostu dla Ciebie za trudny? Nie napiszę Ci gotowca. Może spróbuj czegoś prostszego? Może zwykłego liczenia czasu w pętli aktywnego oczekiwania? Wiesz dlaczego tak myślę? Bo Twój prościutki program jest napisany bez sensu. Nawet przez chwilę nie spojrzałeś na niego na spokojnie i nie zastanowiłeś się jak to będzie działać. Np. dlaczego uważasz, że zaraz po wywołaniu funkcji sonda() będzie dostępny jakiś wynik w czas? Dlaczego nie przeniosłeś inicjalizacji przerwań od czujnika do funkcji, która musi to robić za każdym razem gdy wysyła impuls? Dlaczego nie ma żadnej synchronizacji między pomiarem w przerwaniu a programem głównym wypisującym wynik? itd, itd.. Tu problem nie leży w przerwaniach tylko w tym, że nie ogarniasz podstawowych technik programowania. Ja Cię tego nie nauczę. Musisz pisać, pisać, pisać.. a tymczasem zacznij od prostszych rzeczy. Przykro mi 🙁

Link do komentarza
Share on other sites

Stosunkowo uzupełniłem swoją wiedzę i stworzyłem program wykorzystujący przerwania od timera2.

Pierwsza funkcja: void InitInterrupt(void)

Funkcja inicjalizująca dane wstępne,parametry portów oraz timera2 (ustawienie preskalera oraz tryb jego pracy CTC). Posiadam rezonator o f=16MHz i ustawiłem podział przez 1 oraz rejestr OCR2A = 0x10,aby uzyskać przerwania równe co 1us. Następnie zadeklarowałem przerwanie od Timera2 w momencie zrównania się rejestrów, licznik powinien zwiększyć się o 1. (cały czas przy założeniu, że przerwania występują co 1us.) Następnie jest proces deklaracji przerwania zewnętrznego w którym sprawdzane są warunki. Jeśli nie było flagi to ustawiamy rejestr odpowiedzialny na obsługę przerwania (zrównanie się rejestrów) czyli jest to związane z włączeniem timera,następnie przestawiamy rejestr EICRA na zbocze opadające i ustawiamy flage na 1 czyli,wystawienie informacji, że wystapiło zbocze narastające. Teraz oczekujemy na zbocze opadające, stąd przerwanie, w którym jest to sprawdzane. Zachodzi reakcja na zbocze opadające i sprawdzamy wcześniej ustawiona flage. Następuje wyłączenie przerwania od timera2(stop timera), zmiana rejestru EICRA na zbocze narastające (proces zaczyna sie powtarzać), ustawienie flagi. Ostatnia faza to przypisanie zliczonych przerwań, które występowały co 1us. Ostatecznie przeskalowuje owy czas na dystans i przesyłam wartość do monitora szeregowego. W funkcji pomiar wysłam sygnał sondujący, który tworzy echo.

#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
//#define trigPin arudino12 pb4
//#define echoPin arudino3 pd3
#include <avr/interrupt.h>
volatile uint8_t czas;
volatile double licznik;
volatile uint8_t flaga;
volatile double odl1;

///////////////////////////////////////////////////////////
void InitInterrupt(void)                   
{
DDRB = 0b11111111;//trigg na wyjscie
DDRD = 0b00000000;//echo na wejscie int
EICRA=0b00001100;
//
TCNT2 = 0x00;                            //Zerowanie rejestru TCNT2 (Rejestr jednostki zegara)

   TCCR2A = (1<<WGM21);            //Ustawia timer2 w tryb CTC bez preskalera
          TCCR2B=(1<<CS20);                                //Czestotliwość 16Mhz/1=16MHz

   OCR2A = 0x10;                            //Górna wartość licznika wynosi 16
                                           //Przerwania będą następować co 1us 
sei();
}
///////////////////////////////////////////////////////////
   //F-cja przerwania od Timera2
   ISR(TIMER2_COMP_vect)                       
   {
       licznik=licznik+1;
   }

    ISR(INT1_vect)   
   {
       if(flaga=0)
       {
       TIMSK2 = (1<<OCIE2A);                //włącza Timer2 w trybie dopasowania (START)

       EIMSK=0b00000000;
       EICRA = 0x00;                        //Przerwanie zostanie wywołane zboczem opadającym
       EICRA = (1<<ISC11);                //na wejściu INT1

       EIMSK=0b00000010;
       flaga=1;
       }

       else if(flaga=1)
       {
       TIMSK2 &=~(1<<OCIE2A);                //zatrzymuje Timer2 (STOP)
       EIMSK=0b00000000;
       EICRA = 0x00;                        //Przerwanie zostanie wywołane zboczem rosnącym
       EICRA = (1<<ISC11)|(1<<ISC10);        //na wejściu INT1
       EIMSK=0b00000010;
       odl1=licznik;                        //Zapisuje wartość licznika do zmiennej "odl"
       odl1/=20;                            //oraz skaluje go
       licznik=0;                            //Zerowanie licznika
       flaga=0;
       }
   }
double s_pomiar(void)           
   {
    EIMSK=0b00000010;
    PORTB |= (1 << 4); // przypisanie jedynki
    _delay_us(10);
    PORTB &= ~(1 << 4);
    _delay_us(2);
    EIMSK=0b00000000;
    return odl1;
   }


int main(void)
{

void InitInterrupt(void);
double s_pomiar(void);
while(1)
{
 Serial.begin (9600);

InitInterrupt();
s_pomiar();
Serial.println(odl1);
_delay_ms(200);
}
}


Myslę, że idea programu jest prawidłowa 🙂 Jednak jest tutaj jakieś niedociągnięcie. Program wysyła impulsy prawidło do czujnika i odpowiada odpowiednią długością impulsu, ale jednak nie otrzymuje wartości licznika. Proszę o pomoc

Link do komentarza
Share on other sites

"Myslę, że idea programu jest prawidłowa"

Muszę Cię zmartwić. Wyszedł absolutny brak wyczucia tego na czym pracujesz. To nic złego, na pewno z biegiem czasu to się zmieni a widzę, że szybko się nie zniechęcasz. Popatrz: masz procesor RISC taktowany zegarem 16MHz, to znaczy, że w czasie 1 sekundy wykonuje jakieś 10-12 milionów instrukcji. W warunkach idealnych: 16 milionów. A Ty każesz mu obsługiwać przerwania co 1us. Litości. Już okres 100us (czyli przerwania 10kHz) są dla niego bardzo częste. Do liczenia takich małych kwantów czasu są sprzętowe timery. Obsługa najkrótszego przerwania zajmuje kilka-kilkanaście instrukcji a jeśli używasz jakiejś zmiennej i arytmetyki (gdzie trzeba zachować i odtworzyć stan procesora) - jeszcze dłużej.

Nadal nic się nie zmieniło w podstawowej koncepcji: wołasz funkcję s_pomiar która wykonuje się tyle czasu ile trwa wygenerowanie impulsu sondującego i wraca, a następnie od razu wypisujesz jakiś wynik. Skąd on się ma wziąć??? Przecież dopiero co ultradźwiękowy PING wyruszył w swoją drogę do przeszkody i wciąż leci. Nadal program główny, korzystający z wyników nie ma żadnej synchronizacji z pomiarem. Co więcej, funkcja s_pomiar zaraz po wysłaniu pinga blokuje przerwania od sygnału echa wpisując 0 do EIMSK. Absurd goni absurd. Czy ty w ogóle rozumiesz jak ten czujnik działa?

I jeszcze jedno: wciąż nie czytasz dokumentacji lub robisz to bardzo pobieżnie. Piszesz program na sprzęt tak, jak Ci się wydaje że on działa. Akurat w tych procesorach (bo nie jest to regułą) po wpisaniu do rejestru okresu wartości 16 timer będzie autozerowany i zgłaszał przerwania co 17 swoich "cyknięć".

Czy możemy uznać to za pomoc?

Link do komentarza
Share on other sites

Tak 🙂 Bardzo dziękuję za odpowiedź. Program przeszedł kolejne modyfikacje.

Tutaj zastosowałem dodatkową zmienna impuls, która przedstawia "proces impulsu"

Jeśli impuls=0, to znaczy, że jeszcze nie wystąpił impuls.

Jeśli impuls=1, to znaczy, że wystąpiło zbocze narastające, czyli impuls trwa dalej i się jeszcze nie zakończył.

Jeśli impuls=2, to znaczy, że wystąpiło zbocze opadające i impuls zakończył się.

Od owej zmiennej uwarunkowałem funkcję sondująca odpowiedzialna za sygnał sondujący, oraz funkcję pomiar, która wysyła informacje tylko w odpowiednich momentach, czyli w momencie kiedy wystąpiło już zbocze opadające echa i sygnał się zakończył.

Zmniejszyłem również okres występowania przerwań od Timera 2, fclk=16Mhz, ftimera=10kHz i wartość OCR2=200; stąd okres 100us.

Owy program poniżej:

#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
//#define trigPin arudino12 pb4
//#define echoPin arudino3 pd3
#include <avr/interrupt.h>
volatile uint8_t czas;
volatile double licznik;
volatile uint8_t flaga=0;
volatile double odl1=0;
volatile double impuls=0;

///////////////////////////////////////////////////////////
//INICJALIZACJA

void InitInterrupt(void)                   
{
DDRB = 0b11111111;//trigg na wyjscie
DDRD = 0b00000000;//echo na wejscie int
EIMSK=0b00000010;
EICRA=0b00001100;

//
TCNT2 = 0x00;                            //Zerowanie rejestru TCNT2 (Rejestr jednostki zegara)

   TCCR2A = (1<<WGM21);            //Ustawia timer2 w tryb CTC bez preskalera
          TCCR2B=(1<<CS21);                                //Czestotliwość 16Mhz/8=2MHz

   OCR2A = 200;                            //Górna wartość licznika wynosi 200
                                           //Przerwania będą następować co 100us 
sei();
}
///////////////////////////////////////////////////////////
//PRZERWANIE OD TIMERA

   //F-cja przerwania od Timera2
   ISR(TIMER2_COMP_vect)                       
   {
       licznik=licznik+1; // co 100us dodawana jest jedynka
   }
///////////////////////////////////////////////////////////
//PRZERWANIE OD INT1

    ISR(INT1_vect)   
   {
       if(flaga=0)
       {
       TIMSK2 = (1<<OCIE2A);                //włącza Timer2 w trybie dopasowania (START)

       EIMSK=0b00000000;
       EICRA = 0x00;                        //Przerwanie zostanie wywołane zboczem opadającym
       EICRA = (1<<ISC11);                //na wejściu INT1  
       EIMSK=0b00000010;
       flaga=1;
       }
       else if(flaga=1)
       {
       TIMSK2 &=~(1<<OCIE2A);                //zatrzymuje Timer2 (STOP)
       EIMSK=0b00000000;
       EICRA = 0x00;                        //Przerwanie zostanie wywołane zboczem rosnącym
       EICRA = (1<<ISC11)|(1<<ISC10);        //na wejściu INT1
       EIMSK=0b00000010;
       flaga=0;
       odl1=licznik;                      
       odl1/=20; 
       licznik=0; 
       }
       impuls=impuls+1;
   }
///////////////////////////////////////////////////////////    
//SYGNAL SONDUJACY

   void sonda(void)           
   { 
    PORTB &= ~(1 << 4);
    _delay_us(2);
    PORTB |= (1 << 4); // przypisanie jedynki
    _delay_us(10);
    PORTB &= ~(1 << 4);
   }
///////////////////////////////////////////////////////////
//POMIAR WIELKOSCI

   void pomiar(void)           
   {  
    Serial.println(odl1);
    impuls=0;                         
   }
///////////////////////////////////////////////////////////
//FUNKCJA GLOWNA     

int main(void)
{
Serial.begin (9600);

void InitInterrupt(void); //deklaracja
InitInterrupt(); //wywolanie

void sonda(void); //deklracja
void pomiar(void); //deklaracja

while(1)
{
if(impuls=0)
{
sonda(); //wywolanie
}
if(impuls=2)
{
pomiar(); //wywolanie
}
_delay_ms(200);
}
}

Mam nadzieję, że jestem coraz bliżej 🙂

[ Dodano: 28-12-2015, 13:05 ]

Zauważyłem, że zamiast wykonania instrukcji warunkowej, program podstawia za impuls wartość 2, niestety to nie jedyny problem.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.