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

Zliczanie zmiennej w przerwaniu w C - zmienna nie wpływa na podprogramy

Buliilub 26 Wrz 2007 00:27 1829 12
REKLAMA
  • #1 4320108
    Buliilub
    Poziom 11  
    Posty: 49
    Ocena: 1
    Kod programu poniżej. Mam nadziej ze ktoś mi doradzi jak go poprawić problem jest miaowicie taki ze zmienna jest zliczana w przerwaniu i w zależności od zmienne jest uruchamiany odpowiedni „program”. Jak na początku programu zadeklaruję zmienna o jakiejś wartości to wchodzi w odpowiednia dla te wartości pętlę jeśli natomiast za pomocą przerwania zmienię tą zmienna to już nie uruchamia się odpowiedni podprogram zupełnie tak jak by przerwanie nie miało wpływu na zmienna, a w podglądzie widać ze się zmienia.

    
    #include <avr\io.h>
    #include <inttypes.h>
    #include <avr\signal.h>
    #include <avr\interrupt.h>
    #include <avr\pgmspace.h>
    #include <avr\delay.h>
    // Definicje wyprowadzeń
    #define LED_A 0
    #define LED_B 2
    #define int_0 1
    #define LEDPORT PORTB
    #define LEDDDR DDRB
    
    //Deklaracje zmiennych
    uint8_t g_prog = 0;
    
    
    
    int main(void)
    {
    	/////////////////////////////
    	// inicjacja
    	LEDDDR = 1<<LED_A | 1<<LED_B | 0<<int_0;
    	//ustawienie jednynki na wejsciu int0
    	LEDPORT = 1<<int_0;
    	//przerwanie zboczem lub stanem
    		//  0      1
    	MCUCR = 0<<0 | 1<<1;
    	//odblokowani wybur przerwania pcinto
    	GIMSK = 1<<6 | 0<<5;
    	//wybur zrudla pcint
    		//PCMSK = 1;
    	
    	
    	// Globalne zezwolenie na przerwania
    	sei(); 
    	// koniec inicjacji
    	/////////////////////////////
    	
    	
    	for(;;)
    	{
    		if(g_prog==0)
    			{
    			LEDPORT = 1<<LED_A | 0<<LED_B;
    			//_delay_loop_2(0xffff);
    			LEDPORT = 0<<LED_A | 1<<LED_B;	
    			//_delay_loop_2(0xffff);
    			}
    		if(g_prog==1)
    			{
    			LEDPORT = 1<<LED_A | 1<<LED_B;
    			//_delay_loop_2(0xffff);
    			LEDPORT = 0<<LED_A | 0<<LED_B;	
    			//_delay_loop_2(0xffff);
    			}	
    	}
    	return 0; 
    }
    
    //___________________________
    //SIG_INTERRUPT0
    //SIG_PIN_CHANGE0
    SIGNAL(SIG_INTERRUPT0)
    {
        
    	g_prog++;
    	_delay_loop_2(0xffff);
        _delay_loop_2(0xffff);
    	_delay_loop_2(0xffff);
    	_delay_loop_2(0xffff);
    	if(g_prog>2)
    		g_prog = 0;	
    	GIFR = 1<<6;
    			
    }
    
    
    	
    
    
    
    	
    
  • REKLAMA
  • #2 4320129
    snow
    Poziom 31  
    Posty: 1825
    Pomógł: 178
    Ocena: 201
    Jak dla mnie to tu brak ustawienia rejestrow TIMSK i TCCR0
  • #3 4320167
    autoservice
    Poziom 20  
    Posty: 516
    Pomógł: 7
    Ocena: 16
    ...zgadzam się z przedmówcą... a najlepszy to jest koniec inicjacji ;) :D
    Pzdr.
  • REKLAMA
  • #4 4320270
    Caladan
    Poziom 19  
    Posty: 242
    Pomógł: 33
    Ocena: 3
    I funkcje opóźniające w przerwaniu to trochę głupia rzecz. Prócz tego poczytaj może o słowie kluczowym volatile.Oczywiście jak już poprawisz te wcześniej wspomniane rejestry...
  • #5 4320349
    Buliilub
    Poziom 11  
    Posty: 49
    Ocena: 1
    Kiepsko znam angielski ale z tego co widzę to wydaje mi się ze rejestry TIMSK i TCCR0 odpowiedzialne sa za ustawienia licznika a ja nie używam licznika.

    Opóźnienie w przerwaniu służy likwidacji drgania styków gdy go nie ma to przerwanie wywołuje sie w momencie wciskania przycisku i w momencie jego puszczania.

    volatile - pomogło i jest teraz ok dzieki za pomoc
  • #6 4322274
    Caladan
    Poziom 19  
    Posty: 242
    Pomógł: 33
    Ocena: 3
    Hmm, ale licznik i timer to jest jeden i ten sam podzespół. I te rejestry właśnie włączają tę część sprzętu.
  • #7 4732499
    jachok
    Poziom 12  
    Posty: 19
    Ocena: 4
    cze czy moglbys umiescic ten dzialajacy programik bo mi jest potrzebny taki tylko jeszcze jak bys mi pomogl i opisal ten program troche z gory dzieeki
  • REKLAMA
  • #8 4734386
    megao
    Poziom 25  
    Posty: 690
    Pomógł: 66
    Ocena: 90
    Buliilub napisał:
    // inicjacja
    /.../
    // koniec inicjacji
    Proponuję sprawdzić w słowniku co oznacza inicjacja ;)
    Buliilub napisał:
    //odblokowani wybur przerwania pcinto

    Buliilub napisał:
    //wybur zrudla pcint

    Co za styl :!: Nic dziwnego, że program nie chce działać :!:
  • REKLAMA
  • #9 4734598
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    dokladnie - ja na miejscu kompilatora bym sie powiesil [;

    ciekawe kiedy pojawi sie pierwszy kompilator z podwojnym modulem sprawdzania skladni (jezyk programowania + jezyk programu) oraz z modulem ortografii i stylistyki [; dyslexia friendly <:

    0x41 0x56 0x45!!
  • #11 4886748
    wisnio
    Poziom 11  
    Posty: 6
    Witam, temat trochę stary ale nie chcę tworzyć nowego.
    Pierwsza sprawa to inicjowanie globalnych zmiennych używanych w przerwaniu jako volatile, tak aby przy optymalizacji kompilator nie nabałaganił (skoki adresów ect). Tak więc romario4 ma rację :)

    Pójdę o krok dalej - mam problem odczytywania zmiennej, inkrementowanej w przerwaniu. Muszę sprawdzać tę wartość w pętli while(coś) i tu jest zonk. Naczytałem się, że podczas while() zmienne nie są 'odświeżane' i taki też mam objaw. Program przerwania i działania pętli jest w porządku, jednak nie mogę np. wysłać zmiennej aktualnej podczas, gdy jestem w pętli.
    Czy warto próbować zapisywać jako register? a może zastąpić czymś pętlę while?

    ------ fragmenty kodu------

    volatile uint8_t hal1=0;
    ...
    SIGNAL(SIG_INTERRUPT1) // przychodzi przerwanie od hallotronu silnika
    {
    hal1--;
    if (hal1<5) tryb=1;
    }
    ...

    void motorB_FW(uint16_t impulsy1, uint8_t vel) // motor B FW
    {
    hal1=impulsy1;
    sbi(PORTD,5); // wlacz obroty przod dla silnika B

    while (tryb==0)
    {
    //asm("nop");
    USART_TRANSMIT(hal1); // powiedzmy ze chce wyslac
    }
    cbi(PORTD,5); // wylacz obroty przod dla silnika B
    tryb=0;
    }
    ...

    w main():

    motorB_FW(300,255); // impulsy,pwm
  • #12 4888415
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    jesli zmienna jest deklarowana jako volatile, to nie ma opcji, aby program wzial jej zla wartosc, wiec na twoim miejscu szukalbym bledu gdzie indziej... zerknij w wynik assemblacji, czy program sciaga sobie ta zmienna z pamieci to sie przekonasz...

    0x41 0x56 0x45!!
  • #13 4890243
    maly_elektronik
    Poziom 23  
    Posty: 777
    Pomógł: 35
    Ocena: 5
    Po pierwsze w tym twoim kodzie brakuje miejsca w którum ustawiasz starszy bit i młodszy bit przerwania i oczywiście początkowego stanu liczniki(od jakiej liczby na zliczaś, zlicza od 0 do 255- sutomatycznia ale możesz ustawić że ma zliczaś od 200 do 255) i wtedy przerwanie będzie wygenerowana albo co 255 us albo co 155us

Podsumowanie tematu

✨ Dyskusja dotyczy problemu zliczania zmiennej w przerwaniu w języku C na mikrokontrolerze AVR, gdzie zmienna modyfikowana w przerwaniu nie wpływa na działanie głównego programu mimo widocznej zmiany jej wartości w debugerze. Główną przyczyną problemu jest brak deklaracji zmiennej jako volatile, co powoduje, że kompilator optymalizuje dostęp do niej, nie odświeżając wartości w pętli głównej. Użytkownicy zwrócili także uwagę na konieczność poprawnego ustawienia rejestrów TIMSK i TCCR0, które odpowiadają za konfigurację timera/licznika i generowanie przerwań. Wskazano, że funkcje opóźniające w przerwaniu są niezalecane, a do eliminacji drgań styków lepiej stosować inne metody. W dalszej części dyskusji poruszono problem odczytu zmiennych inkrementowanych w przerwaniu podczas działania pętli while, podkreślając, że zmienne te muszą być volatile, aby zapewnić poprawne odświeżanie wartości. Zwrócono uwagę, że timer i licznik to ten sam podzespół sprzętowy, a rejestry TIMSK i TCCR0 służą do jego konfiguracji. Wskazano również, że warto sprawdzić kod asemblerowy, aby upewnić się, że zmienna jest pobierana z pamięci, a nie z rejestru. Podsumowując, kluczowe jest użycie słowa kluczowego volatile dla zmiennych modyfikowanych w przerwaniach oraz poprawna konfiguracja rejestrów timera/licznika, aby przerwania działały zgodnie z oczekiwaniami.
Wygenerowane przez model językowy.
REKLAMA