HomeMade

Pełna wersja: Programowanie w języku C w środowisku AVR Studio4
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
OK, tłumaczę. [attachment=4715] Jak widzisz wartości sa przypadkowe/przykładowe widzialem gdzies ten przykład w necie i go poprostu skopiowałem. Zasade działania tłumacze słupkami. Rozdzieliłem i ponumerowałem 4 słupki i tylko 4 wjaśnię.
Pierwszy słupek można zapisać tak : 0 ^ 0 = 0
Zasada jest taka że jesli na miejscu czerwonym jest jedynka to wymikiem będzie zmiana zielonego argumentu ( z 0 na 1 lub z 1 na 0 ).
Jesli na miejscu czerwonym jest 0 argument zostaje niezmienony i zostaje przepisany do wyniku.
Drugi słupek można zapisać 1 ^ 0 = 1
Trzeci słupek zapiszę 0 ^ 1 = 1 ( tu nastapiła zamiana 0 na 1 bo czerwona jest jedynka.
Czwarty słupek - to zamiana jedynki na zero. Jasne ??

Kod:
Kod sie wkleja między znaczniki  [code] jakis kod [ / code ]
(musiałem zrobić odstęp pomiędzy / a code)
Ja nie jestem specem od C ani AVRów. Jak wspomniałem kiedyś, uczyłem się zaledwie kilka miesięcy od zera. zarówno Języka jak i AVRów. Poprostu wiem że wielu pragnie samemu coś poprogramować lecz nie wie jak sie za to zabrać - i to głównie do nich jest kierowany kurs.
Jest z nami człowiek który chce trochę naprostować moje poczynania - gdyż ja zdaję sobie sprawę, że robie jakieś błedy - i ja jemu przekażę teraz głos ...
Pawle SQ6OXK ... "go-ahead" Smile
Witam! No a jak działa ta linijka w pętli?
Witaj SP9LAP, pytasz jak to coś działa - o tak:

Po pierwsze jest pętla:
Kod:
while(1)
        {
    /*zrób cośtam*/
        }

Program sprawdza wyrażenie wewnątrz nawiasów () i oblicza jego wartość logiczną - czy jest to prawdz, czy fałsz.
W języku C przyjęta jest konwencja, że "fałsz" oznaczany jest wartością 0 (zero), "prawda"to wartość niezerowa.
Jeśli wartość wyrażenia logicznego wewnątrz nawiasów jest niezerowa (prawdziwa) to wykonuje polecenia wewnątrz nawiasów {}. Po wykonaniu kodu w {} ponownie obliczana jest wartość wyrażenia logicznego. Jeśli zostanie stwierdzona wartość 0 - program pominie kod pomiędzy nawiasami {} i zacznie wykonywać kolejne polecenia poniżej, jeśli wyliczy w () wartość niezerową - ponownie wykona kod w {}. I tak dalej w pętli.

W tym konkretnym wypadku mamy while(1), czyli "zawsze prawda" - więc polecenia wewnątrz {} będą wykonywane w nieskończonej pętli - aż do zaniku zasilania procesora.
Oznacza to, że efektywnie będą wykonywały się instrukcje

Kod:
if(bit_is_clear(PINB, 0))
            {
            PORTA=PORTA^0b00000001;
            _delay_ms(160);
            } //if  
//tu sprawdzi sobie warunek logiczny pętli - while(1) - prawda - więc wykona ponownie:
        if(bit_is_clear(PINB, 0))
            {
            PORTA=PORTA^0b00000001;
            _delay_ms(160);
            } //if  
//tu sprawdzi sobie warunek logiczny pętli - while(1) - prawda - więc wykona ponownie:
        if(bit_is_clear(PINB, 0))
            {
            PORTA=PORTA^0b00000001;
            _delay_ms(160);
            } //if  
//tu sprawdzi sobie warunek logiczny pętli - while(1) - prawda - więc wykona ponownie:
... itd. aż nam się znudzi i wyciągniemy wtyczkę.
Teraz przyjrzyjmy się co to oznacza.
Kod:
if(bit_is_clear(PINB, 0)) - sprawdza stan pinu - czy wciśnięty klawisz - jeśli tak, to wykonuje to co w {}
            {
            PORTA=PORTA^0b00000001;
            _delay_ms(160);
            } //if


Cała zabawa tkwi w linijce PORTA=PORTA^0b00000001;. Oznacza ona: do portu PORTA wstaw to, co masz w chwili obecnej na porcie PORTA bitowo XORowane z 0b00000001. Operatory bitowe wykonują operacje na odpowiadających sobie bitach operandów wejściowych - bit 0 pierwszego z bitem 0 drugiego, bit 1 z bitem 1, itd - jak w wyjaśnieniu Marcina SP4EJT pod kodem programu. Zauważmy jedną bardzo ciekawą właściwość. 1^0 daje 1, 0^0 daje 0. Wniosek - XORowanie "czegokolwiek" z zerem daje taką samą wartość jak to "cokolwiek". 1^1 daje 0, 0^1 daje 1. Wniosek kolejny - XORowanie "czegokolwiek" z jedynką zmienia wartość na przeciwną.
Tutaj robimy PORTA=PORTA^0b00000001;. Jako drugi operand mamy liczbę 0b00000001 - 7 najstarszych bitów to zera i jedna jedynka. Na PORTA mamy jakąś wartość. XORujemy odpowiadające sobie bity. Chcemy zamrugać wylącznie jednym wyprowadzeniem. Na 7 najstarszych bitach XORujemy z zerem - co nie zmienia wartości tych bitów (nie robimy krzywdy wystawionemu tam stanowi logicznemu), na najmłodszym bicie robimy XOR z jedynką. Jeśli była tam jednynka, to 1^1=0, jeśli było zero, to 0^1=1 - czyli zmieniamy stan ostatniego bitu na przeciwny. Tak właściwie ta linijka robi jedną rzecz - zmienia najmłodszy - ostatni bit PORTA na przeciwny. Wartość po zmianie jest z powrotem wpisywana do rejestru PORTA.
Po tej operacji odczekujemy chwilkę poleceniem _delay_ms - żeby wszystko nie działo się tak szybko.
I... właśnie doszliśmy do końca kodu w pętli while(1) - więc wykonamy te operacje od nowa, i od nowa, i od nowa itd...W kolejnych wejściach procedura zmieni stan ostatniego bitu 1-0-1-0-1-0-itd. - czyli po prostu będzie mrugać.

Pojaśniłem trochę czy zamotałem jeszcze bardziej?
73 de SQ8MHI
Tomek
SQ8MHI... i wszystko jasne!! Smile

No i jeszcze żebym miał pełny pogląd na sytuację: Jaki stan ustala się na na A0 i pozostałych pinach portu A po pierwszej linijce programu czyli po:

DDRA = 0b00000001;

bo wygląda że przypadkowy. Pasowałaby zaraz po niej instrukcja np.:

PORTA= 0b00000000;

I jeszcze jedno. Instrukcja

if(bit_is_clear(PINB, 0)) sprawdza 0 na B0, a
if(bit_is_clear(PINB, 2)) sprawdza 0 na B2...itd.. ??Smile

Zaraz to sprawdzę empirycznie Smile

Tnx, Jarek sp9lap
Dzięki, Tomku SQ8MHI, że mnie wspomogłeś - ja dopiero mam czas na siedzenie przed kompem, córka mi żyć dzis nie dała i nie miałem czasu wyjaśniać Jarkowi.
(11-02-2012 23:11)SP9LAP napisał(a): [ -> ]No i jeszcze żebym miał pełny pogląd na sytuację: Jaki stan ustala się na na A0 i pozostałych pinach portu A po pierwszej linijce programu czyli po:

DDRA = 0b00000001;

bo wygląda że przypadkowy. Pasowałaby zaraz po niej instrukcja np.:

PORTA= 0b00000000;
Musiałbyś poczytac trochę o Atmedze. Istnieje takie zjawisko jak wartość domyślna ( początkowa ? ) rejestru(ów). Jeżeli nie ustawisz inaczej to wszystkie rejestry:
- DDRA, DDRB, C, D - nazwijmy je DDRx oraz rejestry PORTx mają wartoć 0 ( lub jak wolisz 0b00000000 ).
Zatem nie pisząc nic co dotyczy tych portów powodujesz że maja wpisane w rejestry zera ( bo nie zmieniasz tych zer na inne wartości ).
Ale jeżeli to ułatwi ci zrozumienie kodu lub czytelność dodawaj linijkę PORTA= ....
Ja poprostu już pamiętam że domyślnie są zera
SP9LAP napisał(a):I jeszcze jedno. Instrukcja

if(bit_is_clear(PINB, 0)) sprawdza 0 na B0, a
if(bit_is_clear(PINB, 2)) sprawdza 0 na B2...itd.. ??Smile

Zaraz to sprawdzę empirycznie Smile

Tnx, Jarek sp9lap
Tak, if(bit_is_clear(PINB, 2)) sprawdza czy jest 0 na B2, bo wyrażenie bit_is_clear(PINB, 2) przyjmuje wartość 1 jesli na B2 jest stan niski.
Jeszcze jakieś pytania ?
U mnie po resecie lub włożeniu wtyku USB do gniazda, zdarza się że dioda świeci, czyli stan na A0 jest wysoki... ??
Jeżeli to dioda podłączona do A0 to tak - stan jest zapewne wysoki.
Ale to jest po uplywie tych 8 sekund bootloadera czy w trakcie pierwszych 8 sekund po załaczeniu zasilania/resecie ?
Po 8 sekundach dla bootloadera.
W takim razie dodaj PORTA= 0b00000000; i zobacz czy to przyniesie zmiany.
Oki...

Dziękuje Marcinie, za pozwolenie, chciałbym pomóc Wam w nauce programowania w C.

Nie mam oczywiście zamiaru krytykować pracy jaką wykonał i wykonuje kolega Marcin SP4EJT, chciałbym uzupełnić jego teksty i przykłady, o doświadzczenie jakie ja już mam na tym polu.

Będzie to materiał dla wnikliwych, dla osób które zamierzają pisać większe i bardziej skomplikowane programy.
Będe zamieszczał uzupelnienia, propozycję napisanie tego programu w inny sposób itp.

Da to kolegą, większy obraz na to jak można rozwiązać ten sam problem w innym sposób, ewentualnie jak można napisac go w sposób przyspieszający jego działanie lub uzyskac dzięki temu mniejszy kod.

Na pierwszy rzut pójdzie lekcja 8. Zostala w niej zaprezentowany sposób dołanczania plików nagłówkowych i dzielenie programu na części które ułatwiają jego analizę i pisanie oraz pozwalają w przyszłości skorzystać z takich "gotowców" przy innych programach.

Choć przykład Macina działa, posiada pewne błedy które choć teraz nie są widoczne moga w przyłości utrudnić lub nawet uniemożliwic kompilacje.

Muszę odejść teraz od komputera. Skończe ten post pózniej.....
Stron: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Przekierowanie