Sygnał PPM

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!
Awatar użytkownika
Artyliusz
Użytkownik
Posty: 305
Rejestracja: 06 sty 2013, 14:10
Lokalizacja: Z Polski
Kontakt:

Post autor: Artyliusz » 18 cze 2013, 17:28

Wydaje mi się, że kolega c4v2 miał na myśli flagi ustawiane jako bity, a nie te, które można sobie programowo zrobić.
Dawid2379 pisze:Gdzieś widziałem że flagę kasuje się tak |=
Tak ustawiasz flagę nie zmieniając wartości wcześniej ustawionych tego rejestru.
Kasuję się ustawiając na logiczne zero "0" chyba, że będzie odwrotnie w dokumentacji, jednak domyśle chodzi ustawić na "0" poprzez kasowanie. Odwrotnie chodzi "ustawić flagę" - a więc ustawić bit na "1".
Kasuję się poprzez
Dawid2379 pisze:Cytat:
INTF0 - Flaga zewnętrznego przerwania 0.
Kiedy zdarzenie na pinie INT0 wywoła przerwanie, flaga INTF0 jest ustawiana na 1. Jeśli ustawiony jest bit I w SREG oraz ustawiony bit INT0 w GICR, mikrokontroler skoczy do odpowiedniego wektora przerwania. Flaga INTF0 jest kasowana kiedy wykonywana jest procedura obsługi przerwania. Możliwe jest „ręczne” jej wykasowanie przez wpisanie do niej 1.


Nawet po Polsku nie łapię tego, zgłoszenie przerwanie - flaga ustawiona na 1, kasowanie w każdym momencie to wpisanie do niej 1? jest kasowana kiedy wykonywana jest obsługa przerwań? jakby kiedy jej się chce?
Może mi ktoś objaśnić łopatologicznie co i jak?
I jak operować tymi flagami
Powyższy cytat przetłumaczonej dokumentacji technicznej mikrokontrolera dotyczy GIFR - General Interrupt Flag Register.
Bit 6 w tym rejestrze to INTF0: External Interrupt Flag.
Przetłumaczę Ci polski na polski:
Rejestr GIFR odpowiedzialny jest za zaznaczanie, że właśnie teraz trwa przerwanie wywołane jakimś stanem na pinie INT. Jeśli owe przerwanie zostanie wywołane pojawieniem się jakiegoś stanu na pinie INT0 to wtedy w tym rejestrze bit 6 INTF0 ustawia się na "1" (domyślnie jest na 0). Jeśli jest ustawiony na "1" oznacza to, że trwa przerwanie - jest ono obsługiwane, czyli wykonuje się to co napisałeś INT0_vect. Kiedy to się wykona automatycznie zmienia się na "0", czyli już nie ma przerwania.

A więc flaga to nic innego jak znacznik. Wyobraź sobie, że ktoś podnosi czerwoną flagę do góry, aby powiadomić kogoś o czymś.
c4v2 pisze:Można ustawiać flagę w przerwaniu INT0 że nadszedł impuls opadający następnie odmierzać czas timerem (inkrementacja jakiejś zmiennej zegarowej) do pojawienia się zbocza narastającego i jeżeli czas jest dłuższy od 2ms ustawić flagę synchronizacji, czy zresetować licznik serw (biorąc pod uwagę poziom logiczny impulsu).
Koledze chodzi, że ustawić Sense Control. Czyli to co ma wywoływać przerwanie na tym pinie. W tym wypadku zbocze opadające. Uruchamia się wtedy obsługa przerwania. I w tym przerwaniu ma być jakaś zmienna inkrementowana (++). Na przykład w pętli for zmienna "i".

Jednak myślę, że z flagą synchronizacji to chodzi o flagę robioną programowo. To znaczy znów jakaś zmienna jest definiowana jest zmienna globalna volatile. Na przykład zmienna Flag. W przerwaniu do tej zmiennej wpisywana jest wartość "1". A w pętli głównej programu zwykłe odpytanie tej zmiennej przez if.
Zobacz też: http://mikrokontrolery.blogspot.com/201 ... wania.html

Wybacz za taki chaos, ale ja też się dopiero co uczę o mikrokontrolerach.
Pozdrawiam.

Awatar użytkownika
c4v2
Użytkownik
Posty: 426
Rejestracja: 22 lis 2005, 15:14
Lokalizacja: z przed monitora

Post autor: c4v2 » 18 cze 2013, 17:50

Przepraszam za nieprecyzyjne wyrażanie się. Przez flagę rozumiem zmienną (najlepiej bit, w przypadku Unsigned Char konkretny bit) może to być również bit w rejestrze roboczym. W języku C ważne aby była odpowiednio "współdzielona" między Main i obsługą przerwania czyli poprzedzona słowem Volatile w deklaracji.

Awatar użytkownika
joon
Użytkownik
Posty: 2076
Rejestracja: 30 cze 2007, 22:56
Lokalizacja: Kraków, Przemyśl, Warszawa
Kontakt:

Post autor: joon » 19 cze 2013, 15:13

Edit: nieistotne, proszę o usunięcie

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 20 cze 2013, 18:42

joon Istotne, zostawić.

Dzięki za informacje:) Jednak dalej potrzebuje pomocy. Próbowałem różnych opcji, ale cienko, więc zrobiłem tak: jeżeli chodzi o INT0 to jest tak że za pierwszym razem (case1) wchodzi w przerwanie od zbocza narastającego włącza licznik, ustawia bit tak aby w kolejnym przerwaniu wchodziło w nie od zbocza opadającego ( czyli do case2) i tak też się dzieje, wszystko ładnie widać na załączniku, zbocze narastające włącza licznik a zbocze opadające wyłącza i tak w kółko. Mamy wiec przy danej szerokości impulsów dana liczbę impulsów od TIMERA0. No ale nie wiem co dalej?????? Na pewno da się coś z tym zrobic.

Próbowałem z pętlą for oraz zmiennymi i nic mi nie wychodziło:
Miałeś na myśli
for (i=0;i<jakaśliczba;i++)?
czy
for(;;) i++; ?
można w ogóle tego używać w przerwaniu? chyba nie?

Kod: Zaznacz cały

#include <avr/io.h>
#include <avr/interrupt.h>

#define SER1 PD0
#define SER2 PD1 
#define PPM  PD3
#define PPM2 PD2


int main(void)  
{ 
  DDRD  |= (1<<SER1); //wyjście 
  DDRD  |= (1<<SER2); //wyjście 
  DDRB = 0xFF; 
  PORTB = 0xFF; 
  DDRA = 0xFF;    
  PORTA = 0xFF; // nieuzywane porty jako wyjscia     
  GIMSK |= (1<<INT1)|(1<<INT0);
  MCUCR |= (1<<ISC11)|(1<<ISC00)|(1<<ISC01);
  
   sei();  // wl.przerwan 
      
   while(1) 

 { 

	 
 }        
} 
ISR (INT0_vect)
{
static uint8_t i;
i++;
switch (i)
{
case(1):
TCCR0A |= (1<<COM0A0);
TCCR0B |= (1<<CS01);

MCUCR &=~(1<<ISC00);
break;
case(2):

TCCR0A &=~ (1<<COM0A0);
TCCR0B &=~ (1<<CS01);
MCUCR |= (1<<ISC00);
i=0;
break;

}

}

ISR (INT1_vect) 
{  static uint8_t cnt;  // zmienna na potrzeby instrukcji switch 
 
    cnt++;
    switch(cnt) 
   { 
    case(1):           
PORTD |= (1<<PD0);  
    break; 
    case(2): 
PORTD  &=~ (1<<PD0);
PORTD |= (1<<PD1);  
    break; 
 case(3): 
PORTD &=~ (1<<PD1);
    break; 
 cnt=0;
   } 
}
Załączniki
Bez tytułu.png

Awatar użytkownika
Dawid2379
Użytkownik
Posty: 318
Rejestracja: 17 lis 2010, 19:42
Lokalizacja: Kluczbork
Kontakt:

Post autor: Dawid2379 » 21 cze 2013, 18:56

Kombinowałem i kombinowałem aż się udało:). Zrezygnowałem z Timera. Po krotce zrobiłem tak: Przerwanie INT0 - pierwsze wejście w przerwanie następuje od zbocza narastającego, drugie od zbocza opadającego, między zboczami włączany jest licznik w pętli while i osiąga wartość tym większa im dłuższy jest impuls, najdłuższy jest impuls synchronizacji, to i mój licznik ma największą wartość, i jeśli przekroczył 50 to zmienia cnt w INT1 aby synchronizować impulsy wejściowe z wyjściowymi. Sprawdzałem i zawsze było dobrze.

Kod: Zaznacz cały

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define SER1 PD0
#define SER2 PD1 
#define PPM  PD3
#define PPM2 PD2
#define led PD4
volatile uint8_t b;
volatile int licznik;
volatile uint8_t cnt;
int main(void)  
{ 
  DDRD  |= (1<<SER1); //wyjście 
  DDRD  |= (1<<SER2); //wyjście 
  DDRD |= (1<<led); 
  DDRB = 0xFF; 
  PORTB = 0xFF; 
  DDRA = 0xFF;    
  PORTA = 0xFF; // nieuzywane porty jako wyjscia     
  GIMSK |= (1<<INT1)|(1<<INT0);
  MCUCR |= (1<<ISC11)|(1<<ISC00)|(1<<ISC01);
  
   sei();  // wl.przerwan 
    
   while(1) 

 { 



if (b==1)
{  
licznik++;
{
   
   PORTD ^= (1<<PD4); //
   if (licznik>50)
   { b=0;
  
   }
   _delay_us (200);
} 
	 
 }}        
} 
ISR (INT0_vect)
{
static uint8_t cntn; 
cntn++; 
switch (cntn) 
{ 
case(1): 

b=1;
MCUCR &=~(1<<ISC00); 
break; 
case(2): 
if (licznik>50)
   { 
  cnt = 0;
   }
licznik=0;
b=0;
MCUCR |= (1<<ISC00); 
cntn=0; 
break; 

} 
 
	 
}

ISR (INT1_vect) 
{    // zmienna na potrzeby instrukcji switch 
 
    cnt++;
    switch(cnt) 
   { 
    case(1):           
PORTD |= (1<<PD0);  
    break; 
    case(2): 
PORTD  &=~ (1<<PD0);
PORTD |= (1<<PD1);  
    break; 
 case(3): 
PORTD &=~ (1<<PD1);
    break; 
 
   } 
 if(cnt>2) 
    
    cnt=0;
}
Załączniki
Bez tytułu.png

ODPOWIEDZ