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

Jak zmienić wyjście PWM dla TIMERA2

Piotr Kania 18 Maj 2010 23:54 2642 29
  • #1 8092931
    Piotr Kania
    Poziom 15  
    Witam zrobiłem generator PWM z zmiennym wypełnieniem jego wyjście to PB3 czy istnieje jakiś sposób na zamianę na inne wyjście ?
  • #2 8092961
    mirekk36
    Poziom 42  
    Piotr Kania napisał:
    Witam zrobiłem generator PWM z zmiennym wypełnieniem jego wyjście to PB3 czy istnieje jakiś sposób na zamianę na inne wyjście ?


    Tak - jeśli zrobisz sobie programowy PWM to wtedy możesz go mieć na dowolnym wyjściu, inaczej to byś musiał "pogrzebać" w strukturze scalaka?
  • #3 8092966
    mario06
    Poziom 15  
    A jaki mikrokontroler? Trzeba zmienić timer lub jeśli obsługuje dwa wyjścia to odpowiednio rejestry pozamieniać.
  • #4 8092986
    Piotr Kania
    Poziom 15  
    Atmega32. Pytanie jest konkretne Timer2 z PWM na wyjściu PB3 zamienić na dowolne inne. Chodzi mi o rozwiązanie programowe. Na razie zrobiłem to na TOGGLE i działa ale w wartościach skrajnych pwm przyjmuje 50%.
  • #5 8093048
    GSM
    Poziom 25  
    Witam,

    no to skoro kolega realizuje PWM programowo to jaki problem podmienić w kodzie PB3 na dowolny inny?
    Przy wykorzystaniu hardwereowego generowania nie ma możliwości zmiany wyjścia, tylko PD7 (OC2)

    Pozdrawiam,
    GSM
  • #6 8093101
    Piotr Kania
    Poziom 15  
    Chodzi mi o przekierowanie pwm hardwerowego z pinu PD7 na inny
  • #7 8093105
    GSM
    Poziom 25  
    No to się zdecyduj w końcu... jak już wyżej napisałem nie ma takiej możliwości.

    Pozdrawiam,
    GSM
  • #8 8093117
    Piotr Kania
    Poziom 15  
    Jest jeśli w przerwaniu będziemy zmieniać stan jakiegoś wyjścia
  • #9 8093312
    zerpo
    Poziom 22  
    Jaką chcesz mieć częstotliwość i rozdzielczość PWMa, a jaką taktujesz ATmegę?
  • #10 8093361
    mirekk36
    Poziom 42  
    Piotr Kania napisał:
    Jest jeśli w przerwaniu będziemy zmieniać stan jakiegoś wyjścia


    Albo nie czytasz dokładnie PDF'a albo nie potrafisz porządnie zadać pytania i nie słuchasz odpowiedzi. Toż wyraźnie piszą ci ludzie, że nie zmienisz wyjścia sprzętowego PWM'a. Żadnego wyjścia żadnego timera. Chyba, że jak mówiłem weźmiesz pilnik tarnik i sobie w strukturze pogrzebiesz.

    To co tu wyżej mówisz nie ma nic wspólnego z PWM'em sprzętowym. Jeśli w przerwaniu zmieniasz sobie stan jakiegoś wyjścia to już zaczynamy mówić o PWM'ie programowym właśnie. A wtedy jak też pisałem możesz to zrobić na dowolnym wyjściu procka , powiem więcej można programowo zrobić sobie wiele kanałów PWM a nie tylko jeden i każdy na dowolnym wyjściu.
  • #11 8093836
    Piotr Kania
    Poziom 15  
    Dobrze a jak poprawnie zrobić pwm programowy bazujący na przerwaniu tajmera 2 teraz jest chyba lepiej sformowane pytanie. Chodzi mi o jakiś przykład albo algorytm.
  • #12 8094080
    zerpo
    Poziom 22  
    Jeszcze raz pytam:
    1) jaka częstotliwość PWM,
    2) jaka rozdzielczość,
    3) jaka częstotliwość zegara procesora?
  • #13 8094890
    GSM
    Poziom 25  
    Nie bardzo rozumiem, pierw kolega pisze, że ma już działający PWM programowy potem, że musi go od zera pisać...?

    Zresztą, sam sobie odpowiedziałeś jak to zrobić:
    Piotr Kania napisał:
    Na razie zrobiłem to na TOGGLE i działa ale w wartościach skrajnych pwm przyjmuje 50%.

    Piotr Kania napisał:

    w przerwaniu będziemy zmieniać stan jakiegoś wyjścia


    Pozdrawiam,
    GSM
  • #14 8095099
    Piotr Kania
    Poziom 15  
    Może napisze to bardziej łopatologicznie.

    1)Mam napisany program generujący PWM SPRZĘTOWY na PB3 (atmega8)
    2)Generuje przerwanie w trybie porównania
    3)W uchwycie przerwania robie funkcje TOGGLE na dowolnym wyjściu
    4)Problem pojawia się dla wypełnienia 0 i 255 (wiem dlaczego) pojawia się też po wyjściu z wartości skrajnych (przebieg zmienia polaryzacje)

    Czy ktoś wie jak inaczej to rozwiązać w uchwycie przerwania? Jeśli nie to niech nie pisze!

    p.s.
    1) częstotliwość PWM - obojętna
    2) jaka rozdzielczość - obojętna
    3) jaka częstotliwość - 16 MHz
  • #15 8096232
    GSM
    Poziom 25  
    Wyraźnie plączesz się w zeznaniach! Przed chwilą dyskutowaliśmy o ATmega32...
    Jeśli robisz to w przerwaniu to jest to już software, dla PB3 nie sensu bo PB3 jest wyjściem hardwerowego PWM w mega8 (przyjmując że jeszcze o timerze 2'gim mówimy...). Jeśli chcesz to programowo robić na innym pinie to po prostu TOGGLE'uj inny pin, to też już napisałem wcześniej - odpowiadając tym samym na twoje pytanie.

    Może opisz do czego chcesz go wykorzystać? Może problem da się inaczej rozwiązać?

    Pozdrawiam,
    GSM

    P.S.
    częstotliwość dowolna - 1Hz
    rozdzielczość dowolna - 1bit
    :roll:
  • #16 8096388
    Piotr Kania
    Poziom 15  
    Chce sterować prędkością obrotową wentylatora 12V przez mosfet N. Funkcja TOGGLE niezbyt dobrze działa w zakresie 0 - 255. Problem w tym że pin na którym wisi mosfet jest inny niż sprzętowy pwm
  • #17 8097359
    zerpo
    Poziom 22  
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #define	DOWOLNY_DDR		DDRD
    #define	DOWOLNY_PORT	PORTD
    #define DOWOLNY_PIN		7
    
    volatile uint8_t pwm=0;
    
    int main(void)
    {
    
    	DOWOLNY_DDR |= 1<< DOWOLNY_PIN;	// ustaw jako wyjscie
    	DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN);	// zero
    
    	TCCR2 = 1<<CS22 | 1<<CS20;	// Normalny tryb, preskaler /128
    	TIMSK |= 1<<OCIE2 | 1<<TOIE2; // wlacz przerwania od przepelnienia i prownania
    
    	OCR2 = pwm;		// ustaw wypelnienie	
    
    	sei();
    
    
    	while(1)
    	{
    
    	}
    
    	return 0;
    }
    
    ISR(TIMER2_OVF_vect)
    {
    	if(pwm)	// tylko jesli wypelnienie jest rozne od 0
    		DOWOLNY_PORT |= 1<<DOWOLNY_PIN;
    	OCR2 = pwm;
    }
    
    ISR(TIMER2_COMP_vect)
    {
    	if(pwm!=255)
    	{	// ustaw '0', tylko gdy wypelnienie jest rozne od 255
    		DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN);
    	}
    }
    


    Proszę, prosty i wydajny PWM o częstotliwości równej:
    f_kwarcu / preskaler / rozdzielczosc_PWM = (w naszym przypadku) 16000000 / 128 / 256 = 488 Hz

    Zmieniając preskaler na mniejszy można oczywiście zwiększyć częstotliwość.
    Rozdzielczość PWMa to 8-bitów, więc niemało.
    Wykorzystano 2 tryby pracy Timera2:
    - przepełnienie - w nim ustawiany jest stan PWMa na '1',
    - porównanie - gdy wartość licznika jest równa przepałnieniu - zerowanie wyjścia.

    Wypełnienie zmieniamy poprzez zmianę wartości zmiennej pwm
    Chyba dosyć jasne, ale tłumaczę, żeby uprzedzić dalsze pytania.
    No!
  • #18 8097387
    mirekk36
    Poziom 42  
    zerpo ---> aż dwa przerwania ??????? do takiego czegoś ?? czy to nie przesada ? ;) to znaczy nie przesada ale to można spokojnie zrobić w jednym przerwaniu.

    ISR(TIMER2_COMP_vect) 
    { 
       static uint8_t cnt=0;
       
       if(cnt<my_pwm1) DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN); else DOWOLNY_PORT |= (1<<DOWOLNY_PIN);
    
       if(cnt<my_pwm2) DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN); else DOWOLNY_PORT |= (1<<DOWOLNY_PIN);
    
       cnt++;
    
    } 


    typ zmiennej cnt - stanowi rozdzielczość 8bitów, można ją zrobić uint16_t i jakimś IF'em ograniczać pod koniec przerwania do rozdzielczości 9bit, 10bit - ile chcesz. Tak samo zmienną uint8_t można jeszcze zmniejszać np do 7bit i mniej.

    A przy okazji tworzysz dowolną ilość kanałów PWM na dowolnych pinach

    Oczywiście zmienne: my_pwm1, my_pwm2 itd powinny być globalne i z przydomkiem volatile

    Dodatkowo warunkami w IF'ach albo kolejnością zerowania lub ustawiania dowolnego pinu można sobie zmieniać fazę wg życzenia - co jest odpowiednikiem bitów COMx w sprzętowym PWM'ie
  • #19 8097412
    zerpo
    Poziom 22  
    Wadą Twojego rozwiązania jest niestety znacznie większe obciążenie procesora, bo przerwanie wywoływane musi być co każdy krok PWMa.
    Przewagą mojej propozycji jest fakt, że na cały okres PWMa mamy tylko 2 wywołania przerwania.
    Fakt - trudniej tu o większą rozdzielczość (z mniejszą nie ma problemu, chociaż do sterowania wiatrakiem 8-bitów to chyba aż nadto) i dokładniejsze dostrojenie częstotliwości, ale za to bardzo małe obciążenie procesora, a co za tym idzie większa maksymalna częstotliwość PWMa.

    Niech już kolega Piotr Kania sam zadecyduje co mu jest potrzebne.
  • #20 8097438
    mirekk36
    Poziom 42  
    zerpo --> dlatego dodałem, że to nie przesada - bo każde rozwiązanie , które działa poprawnie jest ok ;) i wcale się nie kłócę które lepsze. Pewnie, że to , które podałeś spokojnie zadziała z tym wentylem.

    Jednak polemizowałbym ostro co do tego, że rozwiązanie podane przez ciebie zmniejsza obciążenie procesora. Być może zapominasz o tym, że każde przerwanie to nie tylko kod w nim zawarty ale także jeszcze prolog i epilog w asemblerze, którego nie widzisz - bo tak zostały stworzone makra przerwań w C, żeby sobie tym głowy nie zawracać (ale trzeba o tym wiedzieć jednak mając na uwadzę potrzebę ostatecznej optymalizacji krótkich czasów jeśli aż takie są potrzebne). Jednak w twoim przypadku dwukrotnie przy wywoływaniu przerwań będą odkładane na stosie rejestry i adres powrotu przy wejściu w przerwanie i dwukrotnie tak samo będą zdejmowane. Tymczasem jeśli chcieć użyć tylko jednego kanału PWM w tym moim rozwiązaniu - to porównaj sobie długość w asemblerze w pliku *.lss po kompilacji - całej procedury przerwania opisanej przeze mnie oraz dwóch procedur w podanym przez ciebie przykładzie.

    Na zakończenie dodam, że poza większą uniwersalnością tego rozwiązania o którym ja wspominam jeszcze dodatkowo fajnie i łatwo dostosowuje się częstotliwość poprzez rejestr OCRx dla przerwania typu CTC tegoż timera.

    Chociaż ? ... jednak z drugiej strony patrząc - teraz dopiero uświadomiłem sobie to co napisałeś, że jednak faktycznie w twoim rozwiązaniu tylko dwa przerwania na cały okres PWM'a . No ok to praktycznie daje jakąś przewagę czasową ;)
  • #21 8097475
    zerpo
    Poziom 22  
    Jestem w pełni świadomy procedury obsługi przerwań "od kuchni" - sam trochę piszę w ASM i często debuguję kod podglądając asemblerową interpretację kodu .

    Jednak pozostanę przy swoim - moje rozwiązanie jest znacznie mniej czasochłonne (dla procka) niż Twoje. U mnie na cały okres PWMa wywoływane są tylko 2 przerwania po raz.
    Nie widzę więc tutaj związku z odkładaniem na stos adresów itp. od dwóch przerwań (zamiast jednego) z pogorszeniem optymalności.

    U Ciebie na jeden okres wywoływane jest co prawda jedno przerwanie, ale w przypadku 8-bitowej rozdzielczości aż 256 razy na okres.

    W moim przypadku jest więc 128 razy mniej obsług stosu na okres niż u Ciebie. Moje przerwania są krótsze przynajmniej o obsługę dodatkowej zmiennej cnt.
    Czy rzeczywiście więc moje rozwiązanie jest tak mało optymalne?

    ----------------

    Dopiero teraz zauważyłem poprawkę w poprzednim poście...
    Cieszę się, że się rozumiemy :-)
  • #22 8097645
    mirekk36
    Poziom 42  
    zerpo napisał:
    Czy rzeczywiście więc moje rozwiązanie jest tak mało optymalne?


    Tak jak zauważyłeś, napisałem na końcu, że jest ok, powiem nawet, że jest dla pewnych rozwiązań bardzo fajne ;)

    Ja wprawdzie zwykle korzystam z tego co przedstawiłem, ale już widzę, że czasem takie rozbicie na dwa przerwania może mieć też wiele zastosowań właśnie szczególnie w przypadkach gdy zależy na odciążeniu procesora ;)

    przynajmniej coś pozytywnego wyniknęło z tej dyskusji i nie tylko dla autora wątku. No bo otrzymał rozwiązanie jak na talerzu - już nie powinien miec najmniejszych problemów z tym.
  • Pomocny post
    #23 8097707
    zerpo
    Poziom 22  
    Cieszę się, że udało mi się pokazać coś nowego ;-)
  • #24 8099609
    Piotr Kania
    Poziom 15  
    Pomysł zerpo jest bardzo fajny i prosty. Dziękuje wszystkim za zainteresowanie
  • #25 8104983
    PO.
    Poziom 20  
    mirekk36 napisał:
    zerpo ---> aż dwa przerwania ??????? do takiego czegoś ?? czy to nie przesada ? ;) to znaczy nie przesada ale to można spokojnie zrobić w jednym przerwaniu.

    ISR(TIMER2_COMP_vect) 
    { 
       static uint8_t cnt=0;
       
       if(cnt<my_pwm1) DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN); else DOWOLNY_PORT |= (1<<DOWOLNY_PIN);
    
       if(cnt<my_pwm2) DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN); else DOWOLNY_PORT |= (1<<DOWOLNY_PIN);
    
       cnt++;
    
    } 




    Pozwolę sobie czepnąć się tego kodu, przynajmniej estetycznie: przekroczenie zakresu zmiennych w c to zdaje się zachowanie niezefiniowane? W związku z tym może się dla cnt bezboleśnie przekręcić licznik (tak jak chcemy tutaj) a może zacząć nadpisywać sąsiedni bajt - zależnie od kompilatora. Czy się mylę?

    Przy okazji offtopnę zapytaniem? Jaka jest różnica w deklaracji globalnej a lokalnej static? Przecież i tak musi być cały czas przechowywana wartość, więc ta sama zajętość pamięci cały czas?
  • #26 8105047
    zerpo
    Poziom 22  
    Static powoduje, że zmienna umieszczana jest w RAMie i sobie tam siedzi i nie ma do niej dostępu z innego miejsca programu, poza tą funkcją.

    Mnie też się nie podoba ten sposób na PWMa.
    cnt będzie się "przekręcał" co 256, jeśli więc chcemy rozdzielczość inną niż 8-bitów, to trzeba wprowadzić dodatkowe IF-y.
    Poza tym taki kod generuje pewne problemy.

    Brak buforowania wart. zadanej pwma "my_pwmx" powoduje, że jeśli gdzieś w programie zmniejszymy wartość żądanego wypełnienia do 0, a akurat będzie stan wysoki, to taki stan zostanie załączony aż do zmiany wypełnienia na != 0.
    Podobnie z ustawianiem my_pwmx na 255 podczas trwania niskiego stanu PWMa.

    Oprócz tego przy zmianie wart my_pwmx mogą pojawiać się dziwne impulsy np. stan wysoki/niski trwający jeden okres.

    Procedura ta wymaga dodania paru if-ów i dodatkowej zmiennej buforującej. Co spowoduje, że obsługa przerwania stanie się dosyć długa, a co za tym idzie spadnie znacznie maksymalna częstotliwość PWMa.
  • #27 8105199
    mirekk36
    Poziom 42  
    PO. napisał:

    Pozwolę sobie czepnąć się tego kodu, przynajmniej estetycznie: przekroczenie zakresu zmiennych w c to zdaje się zachowanie niezefiniowane? W związku z tym może się dla cnt bezboleśnie przekręcić licznik (tak jak chcemy tutaj) a może zacząć nadpisywać sąsiedni bajt - zależnie od kompilatora. Czy się mylę?


    No mylisz się. Jaki sąsiedni bajt? w zależności od jakiego kompilatora? to jest zapis i działanie tylko na jednym bajcie, więc nie ma co tutaj wymyślać.

    PO. napisał:
    Przy okazji offtopnę zapytaniem? Jaka jest różnica w deklaracji globalnej a lokalnej static? Przecież i tak musi być cały czas przechowywana wartość, więc ta sama zajętość pamięci cały czas?

    zerpo napisał:
    Static powoduje, że zmienna umieszczana jest w RAMie i sobie tam siedzi i nie ma do niej dostępu z innego miejsca programu, poza tą funkcją.


    Dla rozjaśnienia tego co napisał zepro dodam, że zarówno zmienna lokalna (automatyczna) jak i globalna są deklarowane w RAMie. Tyle, że słówko static powoduje, że jest ona umieszczona w tej sekcji gdzie znajdują się wszystkie inne zmienne globalne i żyje przez cały czas trwania programu, natomiast bez słówka static zmienna jest tworzona w pamięci RAM ale na stosie w związku z tym, żyje ona tylko tyle czasu ile funkcja w której została zdefiniowana ta zmienna. Po zakończeniu funkcji czyszczony jest stos i ślad po niej nie zostaje.






    zerpo napisał:
    Mnie też się nie podoba ten sposób na PWMa.
    cnt będzie się "przekręcał" co 256, jeśli więc chcemy rozdzielczość inną niż 8-bitów, to trzeba wprowadzić dodatkowe IF-y.


    Jakie IF'y - można jeden IF a nie zaraz miliony ifów ;)

    np dla rozdzielczości 7bit:

    if( ++cnt > 64 ) cnt=0;


    chyba nie muszę pokazywć przykładów IF'a dla innych dowolnych rozdzielczości?

    ale można , jak się dobrze pomyśli panie kolego zepro i bez IF'a a co ciekawe jednocześnie mieć dzięki tej jednej procedurze kilka kanałów PWM o różnej rozdzielczości. np:

    ISR(TIMER2_COMP_vect) 
    { 
       static uint8_t cnt=0; 
        
       // rozdzielczość 7bit 
       if( (cnt & 0b01111111 ) < my_pwm1) DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN); else DOWOLNY_PORT |= (1<<DOWOLNY_PIN); 
    
       // rozdzielczość 6bit
       if( (cnt & 0b00111111) < my_pwm2) DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN); else DOWOLNY_PORT |= (1<<DOWOLNY_PIN); 
    
       // rozdzielczość 8bit
       if( cnt < my_pwm3) DOWOLNY_PORT &= ~(1<<DOWOLNY_PIN); else DOWOLNY_PORT |= (1<<DOWOLNY_PIN); 
    
       cnt++; 
    
    } 


    chyba nie muszę pokazywać przykładu jak zrobić to dla zmiennej cnt typu uint16_t oraz jak uzyskać inne dowolne rozdzielczości, bez żadnych wyimaginowanych przyrostów kodu i IF'ów


    zerpo napisał:
    Poza tym taki kod generuje pewne problemy.

    Brak buforowania wart. zadanej pwma "my_pwmx" powoduje, że jeśli gdzieś w programie zmniejszymy wartość żądanego wypełnienia do 0, a akurat będzie stan wysoki, to taki stan zostanie załączony aż do zmiany wypełnienia na != 0.
    Podobnie z ustawianiem my_pwmx na 255 podczas trwania niskiego stanu PWMa.

    Oprócz tego przy zmianie wart my_pwmx mogą pojawiać się dziwne impulsy np. stan wysoki/niski trwający jeden okres.

    Procedura ta wymaga dodania paru if-ów i dodatkowej zmiennej buforującej. Co spowoduje, że obsługa przerwania stanie się dosyć długa, a co za tym idzie spadnie znacznie maksymalna częstotliwość PWMa.


    No niestety to już bym określił mianem lekkiego braku wyobraźni. Po pierwsze programowy PWM zawsze będzie miał więcej wad niż rozwiązania sprzętowe - więc o co chodzi ???

    po drugie, te problemy o których piszesz wyżej można także w proste sposoby minimalizować i przekonfigurowywać do własnych potrzeb, toż te proste IF'y

    if ( cnt < my_pwm )


    wcale nie MUSZĄ tak wyglądać, czy nie zdajesz sobie sprawy co się stanie jak odwrócisz znak mniejszości/większości albo dodasz jeszcze znak równości ???

    To może jednak warto troszkę pomyśleć o pewnych możliwościach płynnej rekonfiguracji takiej wersji PWM'a programowego??? To, że przyznałem iż twój sposób jest ciekawy nie znaczy , że najlepszy ale nie mam zamiaru bawić się w wytykanie wad czy kłócić się , które rozwiązanie lepsze.

    A problemy o których piszesz, z tym brakiem buforowania itp .... to lekki przerost formy nad treścią ;) bo jak mówiłem z niektórymi sprawami można sobie łatwo poradzić a po drugie one tyle przeszkadzają w zastosowaniach programowego PWM'a co kot napłakał. Szczególnie pojawiania się dłużej czy krócej na cały okres jakiegoś stanu przy przełączaniu - np podczas sterowania silnikiem DC albo choćby jakąś diodą LED. Po prostu sztuczny problem tworzysz.

    Korzystam w wielu projektach z takiej obsługi PWM - bo wg mnie jest właśnie prostsza niż rozbijanie tego na dwa przerwania - nawet kosztem większego obciążenia (co przyznaję) ...... co z tego - jak mogę tak dobrać częstotliwości i rozdzielczości - przy okazji łatwo i dowolnie, że mi to nie przeszkadza w wykonywaniu wielu innych zadań w procku a zwykle realizuję ich wiele w "jednym" czasie.
  • #28 8106001
    PO.
    Poziom 20  
    mirekk36 napisał:
    PO. napisał:

    Pozwolę sobie czepnąć się tego kodu, przynajmniej estetycznie: przekroczenie zakresu zmiennych w c to zdaje się zachowanie niezefiniowane? W związku z tym może się dla cnt bezboleśnie przekręcić licznik (tak jak chcemy tutaj) a może zacząć nadpisywać sąsiedni bajt - zależnie od kompilatora. Czy się mylę?


    No mylisz się. Jaki sąsiedni bajt? w zależności od jakiego kompilatora? to jest zapis i działanie tylko na jednym bajcie, więc nie ma co tutaj wymyślać.

    PO. napisał:
    Przy okazji offtopnę zapytaniem? Jaka jest różnica w deklaracji globalnej a lokalnej static? Przecież i tak musi być cały czas przechowywana wartość, więc ta sama zajętość pamięci cały czas?

    zerpo napisał:
    Static powoduje, że zmienna umieszczana jest w RAMie i sobie tam siedzi i nie ma do niej dostępu z innego miejsca programu, poza tą funkcją.


    Dla rozjaśnienia tego co napisał zepro dodam, że zarówno zmienna lokalna (automatyczna) jak i globalna są deklarowane w RAMie. Tyle, że słówko static powoduje, że jest ona umieszczona w tej sekcji gdzie znajdują się wszystkie inne zmienne globalne i żyje przez cały czas trwania programu, natomiast bez słówka static zmienna jest tworzona w pamięci RAM ale na stosie w związku z tym, żyje ona tylko tyle czasu ile funkcja w której została zdefiniowana ta zmienna. Po zakończeniu funkcji czyszczony jest stos i ślad po niej nie zostaje.


    1. Masz rację, pomyliło mi się z wielkością tablic, z których można wyjechać ;) . To co napisałem wcześniej nie ma sensu.

    2. Wiem jak działa static - pytałem czy z punktu widzenia optymalizacji kodu jest różnica w obciążeniu w stosunku do globalnej deklaracji, w sumie retorycznie chyba :) . Różnice są tylko od strony programisty w ochronie wartości poza blokiem i zwolnieniem nazwy do innych bloków. Coś pominąłem?
  • #29 8106032
    mirekk36
    Poziom 42  
    PO. napisał:

    - pytałem czy z punktu widzenia optymalizacji kodu jest różnica w obciążeniu w stosunku do globalnej deklaracji, w sumie retorycznie chyba :) . Różnice są tylko od strony programisty w ochronie wartości poza blokiem i zwolnieniem nazwy do innych bloków. Coś pominąłem?


    W zasadzie nic ;) ... bo właśnie nie ma żadnych jakichś różnic z punktu widzenia optymalizacji kodu. Dzięki static zmienna zachowuje się dokłanie tak samo jak globalna pod względem dostępu do niej.

    A od strony programisty może nie chodzi tyle chodzi o ochronę poza blokiem funkcji (chociaż też) ile o możliwość przyjemnego uporządkowania kodu. Bo równie dobrze można byłoby ją zdeklarować jako globalną tyle że przydomkiem volatile. A tak? wiadomo jest używana wewnątrz funkcji a dodatkowo ma cechyh zmiennej globalnej.

    Takie rzeczy to tylko w ... C ;) .... w bascomie tego nie uświadczysz.
  • #30 8175647
    PO.
    Poziom 20  
    mirekk36 napisał:
    PO. napisał:

    Pozwolę sobie czepnąć się tego kodu, przynajmniej estetycznie: przekroczenie zakresu zmiennych w c to zdaje się zachowanie niezefiniowane? W związku z tym może się dla cnt bezboleśnie przekręcić licznik (tak jak chcemy tutaj) a może zacząć nadpisywać sąsiedni bajt - zależnie od kompilatora. Czy się mylę?


    No mylisz się. Jaki sąsiedni bajt? w zależności od jakiego kompilatora? to jest zapis i działanie tylko na jednym bajcie, więc nie ma co tutaj wymyślać.


    Jednak odkopuję. Wiedziałem, że skądś mi się to wzięło. Poniżej cytaty i linki, prośba o komentarz:

    Cytat:

    Niezdefiniowane zachowania [edytuj]

    Wiele operacji w C mających niezdefiniowane zachowanie nie jest sprawdzanych w czasie kompilacji. W przypadku C, „niezdefiniowane zachowanie” oznacza, że zachowanie nie jest opisane w standardzie i co dokładnie się stanie nie musi być opisane w dokumentacji danej implementacji C. W praktyce czasami poleganie na niezdefiniowanych zachowaniach może prowadzić do trudnych w rozpoznaniu błędów. Zachowania te mogą różnić się między kompilatorami C. Głównym celem pozostawienia niektórych zachowań jako niezdefiniowane jest pozwolenie kompilatorowi na generowanie bardziej wydajnego kodu dla zdefiniowanych zachowań, co jest ważne dla głównej roli języka C jako języka implementacji systemów; unikanie niezdefiniowanych zachowań jest odpowiedzialnością programisty. Przykłady niezdefiniowanych zachowań:
    Odczyt i zapis poza zasięgiem tablicy.
    Przekroczenie zakresu liczb całkowitych.
    Dotarcie do końca funkcji zwracającej wartość, bez napotkania na wyrażenie return.
    Odczytanie zmiennej przed zapisaniem do niej wartości.
    Kolejność wykonywania wyrażeń przekazanych jako argumenty do funkcji.

    Wszystkie te operacje to błędy programistyczne, które mogą się zdarzyć w wielu językach programowania; C przyciąga krytykę ponieważ jego standard wyraźnie wylicza wiele przypadków niezdefiniowanego zachowania, także tam, gdzie mogłoby ono zostać dobrze zdefiniowane i nie zawiera żadnego mechanizmu obsługi błędów w czasie wykonywania programu.

    za: http://pl.wikipedia.org/wiki/C_(język_programowania)

    oraz
    Cytat:
    Rezultat operacji arytmetycznej może wykroczyć poza dostępny zakres użytego w obliczeniach typu danych. W takiej sytuacji, zwykle dochodzi do utraty najstarszych bitów wyniku (efekt slangowo określany jako przekręcenie się licznika), i ustawienia odpowiedniej flagi (carry flag), która informuje programistę o nieprawidłowości wyniku.

    Niektóre języki nie przewidują automatycznego sprawdzania wspomnianej flagi: w standardzie ISO C99, wynik operacji, dla której zachodzi błąd przekroczenia zakresu liczb całkowitych, jest po prostu niezdefiniowany (a w praktyce, zgodny z wyżej opisanym zachowaniem).

    za: http://pl.wikipedia.org/wiki/Przekroczenie_zakresu_liczb_całkowitych
REKLAMA