logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C]przerwania attiny2313. Poprawianie kodu.

a2d2a2m 03 Gru 2008 09:33 1508 17
  • #1 5811872
    a2d2a2m
    Poziom 15  
    #include <avr/io.h> 
    #include <stdlib.h> 
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    #include <avr/pgmspace.h> 
    int g=0;
    volatile c=0;
    SIGNAL (SIG_INTERRUPT1)
    {
    if (c==0)
    c=1;
    else
    c=0;
    
    }
    main(void) 
    {
    PORTB=0xf0;
    DDRB=0x0f;
    PORTD=0x0c;
    DDRD=0xf3;
    while(1)
    	{
      	GIMSK = _BV(INT1);
                            //wlacz obsluge przerwan  Int1
      	MCUCR = _BV(ISC11);
    	sei();
    		while(c==0)
    			{		
    				while(g==0)
    				   {
    						{
    						//kod programu
    						}
    						g=1;
    					}
    ////////////////////////////////////////////////////////////////
    				while(g==1)
    				{
    				//kod programu
    				}
    			}
    		while(c==1)
    				{
    				//	kod programu						
    				}
    	}
    }
    

    Dodałem znaczniki [code]
    [zumek]
  • #2 5811884
    snow
    Poziom 31  
    Jakaś dziwna ta deklaracja zmiennej c. Chyba zapomniałeś określić typ tej zmiennej :>
  • #3 5811972
    KowalD
    Poziom 17  
    jezeli dobrze zrozumialem, to chyba bedziesz musial sie pozbyc tych petli "wewnetrznych" i napisac np. while (!c && g), while (c && g), itd. bedzie sprawdzale "zawsze" (w sensie czesciej ;)) warunek c i szybciej reagowal na zmiane c... w obecnym kodzie... albo nie... albo cos zle patrze, albo dziwny ten kod zdecydowanie... porob wciecia... sprawdz, czy klamerki masz na pewno tak jak chcesz, zeby byly... w wstaw w sekcje code i wtedy pomyslimy ;)...
  • #4 5812281
    a2d2a2m
    Poziom 15  
    Zmienną poprawiłem, przy redukcji kodu do umieszczenia na forum usunąłem int. Klamry są ok. ale nawet gdy c==1; kod jest dalej wykonywany w miejscu, gdzie został przerwany przez przerwanie. Oczywiście warunek g mogę całkowicie usunąć ale efekt chyba będzie ten sam. Zmiana zmiennej c w podprogramie przerwania nie wpływa na wykonywany fragment w programie głównym.
    #include <avr/io.h> 
    #include <stdlib.h> 
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    #include <avr/pgmspace.h> 
    int g=0;
    volatile int c=0;
    SIGNAL (SIG_INTERRUPT1)
    {
    if (c==0)
    c=1;
    else
    c=0;
    
    }
    main(void) 
    {
    PORTB=0xf0;
    DDRB=0x0f;
    PORTD=0x0c;
    DDRD=0xf3;
    while(1)
    	{
      	GIMSK = _BV(INT1);
                            //wlacz obsluge przerwan  Int1
      	MCUCR = _BV(ISC11);
    	sei();
    		while(c==0)
    			{		
    				while(g==0)
    				   {
    						{
    						//kod programu
    						}
    						g=1;
    					}
    ////////////////////////////////////////////////////////////////
    				while(g==1)
    				{
    				//kod programu
    				}
    			}
    		while(c==1)
    				{
    				//	kod programu						
    				}
    	}
    }

    Dodałem znaczniki [code]
    [zumek]
  • #5 5812676
    Konto nie istnieje
    Konto nie istnieje  
  • #6 5812899
    a2d2a2m
    Poziom 15  
    Pytanie: dlaczego po zmianie w podprogramie przerwania zmiennej c nie ulega zmianie wykonywanie części kodu w programie głównym. Inaczej mówiąc zmiana w przerwaniu zmiennej c z 0 na 1 nie powoduje wykonanie drugiej części kodu w programie głównym, a tylko powrót do miejsca w którym został przerwany kod główny.
  • #7 5812924
    Freddie Chopin
    Specjalista - Mikrokontrolery
    bo tak dzialaja przerwania? zmienna c jest sprawdzana w okreslonym miejscu w okreslonym czasie - jesli warunek byl kiedys tam spelniony i kod wszedl do jakiejs petli, to mozesz sobie z ta zmienna robic co chcesz - petla sie wykona tak czy siak - do kolejnego sprawdzenia warunku.

    4\/3!!
  • #8 5812947
    a2d2a2m
    Poziom 15  
    Tyle wiem, ale chodzi mi o sprawdzenie zmiennej, która jest zadeklarowana jako globalna. Dodałem na końcu każdej pętli polecenie return; mysląc, że spowoduje to po każdym cyklu wyskoczenie z pętli i sprawdzenie warunku ale brak efektu. Czy jak zamiast while zastosuję polecenie for(warunki) czy wtedy będzie ok. Po wykonaniu jednej pętli nastąpi sprawdzenie warunku?
  • #9 5813027
    skynet_2
    Poziom 26  
    polecenie return przerywa każdą funkcję zwracając wynik w twoim przypadku przerywa główną funkcję main czego rezultatem jest koniec/restart programu.

    pętla while działa do momentu kiedy warunek nie będzie spełniony.

    pętla for to taka rozszerzona pętla while mogąca posiadać własne zmienne .

    Poczytaj Link
  • #11 5815814
    a2d2a2m
    Poziom 15  
    W tym problem, że warunek może jest sprawdzany ale wykonanie przerwania zmienia zmienną c ale nie jest ona brana pod uwagę przy wykonywaniu pętli while. Sam program główny działa prawidłowo, przerwanie przerywa działanie programu głównego ale wykonanie programu przerwania nie wpływa na wyokonywania odpowiedniego fragmentu programu głównego. Chodzi mi o to, żeby po restarcie wykonywwał się program główny od początku, w momencie wykonania się przerwania nastąpiło sprawdzenie zmiennej c i przejście do wykonywania odpowiedniego fragmentu programu głównego. Wygląda tak, że po wykonaniu przerwania program wykonuje swoje działanie bez względu, co wydarzyło się w podprogramie przerwania.
  • #12 5815915
    Freddie Chopin
    Specjalista - Mikrokontrolery
    OMG no przeciez ponoc wiesz ze tak dzialaja przerwania... jesli chcesz aby przerwanie zmienilo ci adres powrotu na inny to nic nie stoi na przeszkodzie zebys sobie go zmienil... niemniej jednak to jest pewna droga do klopotow, bo pare przerwan i nagle okaze sie ze stos zajmuje caly RAM.

    4\/3!!
  • #13 5816156
    a2d2a2m
    Poziom 15  
    OK. może zadam inne pytanie. Program będzie pełnił rolę centralki alarmowej. Pojawienie się stanu niskiego z kodera na INT1 będzie wyzwalało przerwanie, które będzie powodowało czuwanie centralki(1 część prodramu głównego) lub blokowanie centralki(2 część główna programu). Mogę oczywiście umieścić cały program w przerwaniu i będzie ok. Problem tylko, że po restarcie centralka nie będzie przechodziła w stan czuwania. Z założenia umieściłem program centralki w programie głównym, a wykonanie przerwania będzie przełączało centralkę ze stanu w czuwania w stan uśpienia i na odwrót. W moim przypadku program główny działa poprawnie, przerwanie się wykonuje ale brak powiązania.
  • #15 5816359
    skynet_2
    Poziom 26  
    a2d2a2m napisał:
    Problem tylko, że po restarcie centralka nie będzie przechodziła w stan czuwania.

    Czekaj czekaj chcesz żeby centralka zapamiętała stan po wyłączeniu ?
    To musisz użyć pamięci nieulotnej np. eepromu.
  • #16 5816785
    a2d2a2m
    Poziom 15  
    Jeżeli to, co pokazałem jest poprawne, to w reszczcie nic raczej nie namieszałem, ponieważ w pozostałej części jest tylko sprawdzanie czyjników i w momencie wyzwolenia alarmu zmiana stanów na portach i to wszystko działa prawidłowo. Jeżeli zmienię w deklaracjach stan zmiennej c z 0 na 1 to wykonywana jest druga część programu, gdy zrobię odwrotnie wykonywana jest pierwsza część. W momencie wyzwolenia przerwania jest ono wykonywane, ponieważ w każdy wykonywany fragment progrmu jest sygnalizowany inną częstotliwości świecenia diody Led. Po restarcie dioda świeci ciągle, ponieważ jeden z czujników potrzebuje ok. 1 min na klalibrację i w tej części sygały z niego są ignorowane, po tym czasie dioda miga z pewną częstotliwością( centralka uzbrojona- wszystkie czujniki są sprawdzane). Jeżeli nastąpi wyzwolenie alarmu w obu tych stanach nastepuje "alarm" na odpowiednich stanach mikrokontrolera pojawiają się impulsy wyzawalące sygnalizatory alarmu, a częstotliwość migania diody Led się zwiększa. I wszysko działa prawidło. Jeżeli natomiast zmienna c==1; centralka jest wyłączona- dioda led nie świeci. W programie przerwania zawarłem opóżnienie i widzę, po diodzie led, że następuje zatrzymanie programu głównego. Kod, który umieściłem został pozbawiony zawartości, które nie mają wpływu na problem w celu lepszej przejrzystości. Odpowiadając drugiemu koledze; centralka nie ma zapamiętywać stanu. Po restarcie ma automatycznie przechodzić w stan czuwania, za tylko za pośrednictewm przerwania ma przechodzić w stan uśpienia i ponowne jej wybudzenie. Problem w tym, że wykonanie przerwania z zmiana w niej wartości zmiennej c; nie wpływa na program główny. Dzisiaj wieczorem jeszcze raz na sztywno poustawiam wartości c; w celu jednoznaczne określenia problemu.
  • #17 5816849
    Freddie Chopin
    Specjalista - Mikrokontrolery
    zakladasz ze nie namieszales, a ja jestem pewny, ze jednak to zrobiles. masz dwie petle z jakas zmienna g, pierwsza wykona sie tylko raz (bo zaraz po niej zmieniasz wartosc g, wiec po cholere w ogole petla?) a nastepna wyglada jak petla nieskonczona, wiec nie wiem czego oczekujesz...

    
    while(c==1)
    {
    ...
    }
    while(c==0)
    {
    ...
    }
    


    taki kod bedzie robic to co chcesz i innej opcji nie ma. oczywiscie zakladajac, ze wewnatrz nie ma jakichs wielkich delayow albo czegos co moze sie zapetlic na zawsze. wszelkie wewnetrzne petle moga za to powodowac 100 innych problemow...

    4\/3!!
  • #18 5819693
    a2d2a2m
    Poziom 15  
    Dziękuję wszystkim za pomoc. Już wiem na czym polega problem. W pętli spawdzającej warunek c; miałem wewnątrz pętlę z warunkiem g;. Przerwanie zmieniało wartość zmiennej c; ale nie było szans na jej sprawdzenie, ponieważ warunek g; nadal był spełniany i program wykonywał pętlę z warunkiem g;.
REKLAMA