Ads_700x200

tme

poniedziałek, 30 stycznia 2012

AVR - porty - we/wy - dir - PODSTAWY

W związku z dużą ilością pytań oraz w uzupełnieniu do książki "Mikrokontrolery AVR Język C Podstawy programowania" , przedstawiam poglądowy rysunek oraz fragmenty kodów dla mikrokontrolerów AVR. Ma to na celu rozprawić się ostatecznie i wyjaśnić wszystkim początkującym osobom, rozpoczynającym poznawanie mikrokontrolerów AVR jak to jest z tym ustawianiem pinów czy portów na wejścia lub wyjścia. Rysunek przedstawia oczywiście absolutne podstawy w odniesieniu niejako do pojedynczych pinów. Należy sobie jednak zdać sprawę, że każdy mikrokontroler AVR zaopatrzony jest w trzy 8-bitowe rejestry, służące do operacji na portach. Te 3 rejestry istnieją oczywiście dla każdego portu jaki posiada mikrokontroler. Jeśli to będzie np ATmega8 to będzie on posiadał: 3 rejestry kierunku, 3 rejestry wyjściowe oraz 3 rejestry wejściowe:

DDRB    DDRC    DDRD    - rejestry kierunku
PORTB   PORTC   PORTD   - rejestry wyjściowe
PINB    PINC    PIND    - rejestry wejściowe

Analogicznie będzie dla pozostałych mikrokontrolerów. Np. maleńki ATtiny13 będzie posiadał tylko:


DDRB    - rejestr kierunku
PORTB   - rejestr wyjściowy
PINB    - rejestr wejściowy


Spójrzmy więc na rysunek:




Należy jednak pamiętać, że każdy rejestr składa się z 8 bitów. Tak więc na rysunku mamy pokazane jak za pomocą manipulacji na pojedynczych bitach ustawiać poszczególne piny jako Wejścia lub Wyjścia. Tak można to mieszać. Czyli dowolna część pinów jednego portu może być Wejściami a pozostała część Wyjściami. Aby np. jednocześnie ustawić 4 starsze bity portu B jako wyjścia możemy zapisać to krócej, np w ten sposób:

DDRB = 0xF0;      albo  równoważny sposób:    DDRB = 0b11110000;

Po takich zapisach piny PB7, PB6, PB5, PB4 będą wyjściami natomiast PB3, PB2, PB1, PB0 będą wejściami. Jak widać zapis wartości = 0 do odpowiedniego bitu rejestru kierunku DDRx spowoduje że ten bit będzie wejściem. Zapis wartości = 1 spowoduje, że będzie wyjściem.

Na koniec proszę zapamiętaj, że ZAWSZE po resecie mikrokontrolera bezwzględnie wszystkie piny mikrokontrolera są ustawione jako WEJŚCIA co oznacza, że każdy REJESTR DDRx dla danego portu ma wpisane zera w każdym bicie. Jednocześnie PAMIĘTAJ proszę, że każdy rejestr PORTx także posiada wpisane w każdym bicie wartości = 0 po resecie, co powoduje, że wejścia nie są podciągnięte do VCC wewnętrznym rezystorem a to z kolei powoduje, że mamy do czynienia z wejściami tzw "pływającymi" - będącymi w stanie nieustalonym czyli Hi_Z.

Dlatego też wiele osób się zastanawia dlaczego np, jeśli ustawią dany pin jako WEJŚCIE ale nie podciągną go programowo do VCC oraz nie podciągną go do VCC za pomocą zewnętrznego rezystora i na wejściu podłączą przycisk - to mikrokontroler jakby zaczyna żyć własnym życiem ;) .... raz sam widzi że przycisk jest wciśnięty pomimo że faktycznie tak nie jest a innym razem że nie jest wciśnięty. A to dlatego, że napięcie na wejściu "pływa" tzn. zmienia się swobodnie pomiędzy wartością GND a VCC.

Dlatego nigdy nie zapominaj o podciąganiu wejść do VCC - nawet wtedy gdy są nie wykorzystane. Ponieważ mogą działać jako tzw anteny i dotknięcie palcem mikrokontrolera - szczególnie gdy początkująca osoba jeszcze źle zaprojektuje płytkę PCB - to mikrokontroler będzie się resetował.

Ja np zawsze pierwsze co robię w programie to ustawiam wartości wszystkich bitów każdego PORTx na 1, czyli np. dla ATmega8:

PORTB = 0xFF;
PORTC = 0xFF;
PORTD = 0xFF;

a dopiero po tym rozpoczynam właściwe konfiguracje potrzebnych mi pinów. Nawet jeśli wszystkich nie wykorzystam, to te nie używane pozostaną podciągnięte do VCC i nie będzie na nich stanu nieustalonego Hi-Z. Oczywiście, są wyjątki gdy tak się nie robi. Można tu wspomnieć o urządzeniach zasilanych bateryjnie gdzie liczy się każdy nie tylko mA ale także uA !!! .... Wtedy nie ma co na siłę podciągać nie używanych pinów do VCC ponieważ jak wiadomo każdy wewnętrzny rezystor będzie "zjadał" niepotrzebnie troszkę prądu.

101 komentarzy:

  1. Czy w poleceniu programowo podciągającym wejście PD0 znak negacji jest potrzebny?

    OdpowiedzUsuń
  2. Oczywiście, że niepotrzebny. Tylda mi się zawieruszyła gdy tworzyłem opis i kopiowałem metodą copy&paste ;)

    Już wszystko poprawione, a kolega jeśli jeszcze nie ma programu MkAvrCalculator a miałby ochotę go mieć, to proszę się zgłosić na maila. Za znalezienie tu błędu mogę zaoferować 50% zniżki na ten program dla kolegi ;)

    OdpowiedzUsuń
  3. Chciałem zapytać czy w książce jest opisane jak można zmienić
    DDRB = 0b11110000 na DDRB = 0xF0 czyli na czym to polega ? Czy trzeba jakieś obliczenia robić ?

    OdpowiedzUsuń
  4. Kolega pyta raczej o sposoby zamiany reprezentacji liczb binarnych na hexadecymalne lub dziesiętne. To niestety nie jest tematem tej książki o którą kolega pyta, ponieważ to są zbyt podstawowe informacje i można na prawdę doczytać to choćby w internecie. Proszę bardzo pierwszy lepszy link koledze w tym pomoże, ale są ich miliony:

    http://pl.wikipedia.org/wiki/Szesnastkowy_system_liczbowy

    Za to w książce jest bardzo dobrze opisane jak odnosić się do poszczególnych bitów lub grup bitów za z wykorzystaniem tzw przesunięć bitowych w języku C i to od podstaw. Czyli precyzyjne wyjaśnienie takich zapisów jak na rysunku w tym artykule.

    OdpowiedzUsuń
  5. Wszystko ładnie wytłumaczone. Czekamy na inne równie tak dobrze opisane tematy :D

    OdpowiedzUsuń
  6. Nie ma sprawy, jak tylko skończę drugą część książki to wezmę się za uzupełnienie takich artykułów ;)

    OdpowiedzUsuń
  7. Bardzo dobry artykułów tych paru słów brakowało w książce

    Dziękuję

    OdpowiedzUsuń
  8. Dlatego właśnie powstał ten artykuł.

    OdpowiedzUsuń
  9. Wczoraj pisałem program i nie podciągnąłem programowo wejść do VCC, układ zaczął fiksować. Jak dobrze, że znalazłem ten artykuł.
    Kolejna sprawa. Mowa tu o stałej konfiguracji pinów, jak jest podłączony przycisk to pin portu będzie wejściem, jak led lub wyświetlacz, tranzystor (itp) to oczywiście pin portu będzie wyjściem. W tych przypadkach nic się nie zmieni. A co jak mamy podpiętą magistralę i dany port ma służyć jednocześnie jako wyjście i wejście. Np. układ DS12887 (RTC) z którym komunikujemy sią za pomoca całej 8-mio bitowej magistrali. Jak wówczas skonfigurować dany port, jak to rozwiązać programowo?

    atek

    OdpowiedzUsuń
    Odpowiedzi
    1. Wszystko zależy jaka magistrala. No jeśli jest to magistrala I2C tak jak w przypadku niektórych RTC to wtedy należy wiedzieć o tej magistrali cokolwiek. Np I2C bezwzględnie wymaga podciągania i to zewnętrznym rezystorem obydwu linii SDA i SCL do VCC o wartości ok 4,7K. Linie SDA i SCL są po prostu typu OC (Open Colector). W przypadku innych magistral zawsze należy przede wszystkim sięgnąć do noty PDF danego scalaka nie mniej jednak najczęściej gdy w grę wchodzą magistrale 8-bitowe lub większe i są one dwukierunkowe to nie wymagają podciągania linii do VCC. Ale jak mówię podstawową informacją zawsze będzie PDF scalaka który chcesz użyć.

      Usuń
    2. Mnie chodzi o konfigurację portów w procesorze, gdyż wyżej jest przedstawione jak porty i/lub poszczególne piny skonfigurować jako konkretnie wyjścia lub wejścia, a co jak ma być port wejściem i wyjściem jednocześnie?
      W moim przypadku jest to magistrala 8-bitowa plus CS, R/W, AS, DS. Powiedzmy, że magistralę AD0-AD7 podpinam do PORTA a piny CS, R/W, AS, DS do pinów z PORTC. Konfiguruję porta na wyjście i wysyłam dane - adres komórki do której chcę dotrzeć, a RTC ma mi wysłać zawartość tejże komórki. Co w tym przypadku? Mam przekonfigurować porta na wejście?

      DDRA=0xFF; //porta jako wyjście
      ...część programu
      DDRA=0x00; //porta jako wejście
      PORTA=0xff; //podciągnięcie do VCC
      ...część programu
      DDRA=0xFF; //porta jako wyjście
      ... itd..

      Czy można zmieniać konfigurację portów w programie?
      Zawsze znajdowałem informację, że należy to robić na początku przed main.

      Usuń
    3. ;) no to złą informację znajdowałeś - a np jak sprawdzać BusyFlag w popularnym LCD opartym o sterownik HD44780 ??? przecież tu masz do czynienia z identyczną sytuacją, że piny procka trzeba raz wachlować jako wyjścia a czasem jako wejścia żeby odczytać coś z LCD ;) No jakże by inaczej to robić ?

      Masz może książkę: "Mikrokontrolery AVR Język C podtstawy programowania" ?

      http://www.sklep.atnel.pl/pl/p/KSIAZKA-I-DVD/1

      ???

      tam masz ładnie to pokazane na przykładzie tworzenia własnej biblioteki do obsługi takich LCD ;)

      oczywiście więc że można a wręcz trzeba często zmieniać kierunki pinów w programie. A jak byś obsłużył czujniki temperatury np DS18B20 ???? na 1wire ??? taka sama sytuacja

      ok - w przypadku jednak takich magistral równoległych gdy piny procka ustawiasz jako wejścia to nie trzeba jak pisałem wyżej podciągać ich do VCC ;) bo przełączasz układ docelowy jako wyjście i on z kolei utrzymuje stabilne stany 0 albo 1 na swoich wtedy wyjściach ;) więc programowo się nie podciąga - inaczej jest w 1wire - a szczególnie gdy czujniki pracują w trybie PARASITE i potrzebują zasilania z linii portu ;) ... no ale jak mówię to zależy od tego co konkretnie robisz. Reasumując przy magistralach równoległych nie rób tego programowo czyli nie podciągaj nic do VCC, nigdy.

      Usuń
  10. // Witam:
    // Ciekawi mnie dlaczego tak się dzieje.
    // Za odpowiedź bardzo dziękuję.
    //>>
    // ATtiny 2313
    // PB0 -> Program: 78 bytes (3.8% Full)
    // PB1 -> Program: 70 bytes (3.4% Full)
    // PB2 -> Program: 70 bytes (3.4% Full)
    // PB3 -> Program: 86 bytes (4.2% Full)
    // PB4 -> Program: 70 bytes (3.4% Full)
    // PB5 -> Program: 86 bytes (4.2% Full)
    // PB6 -> Program: 86 bytes (4.2% Full)
    // PB7 -> Program: 86 bytes (4.2% Full)

    #define DF_CPU 1000000UL
    #include

    #define b1 PB0 // <- w tym miejscu mała zmiana numeru PBx, a tak duża różnica w kodzie max:16 bajtów ???

    void set(void)
    {
    DDRB &= ~b1;
    PORTB |= b1;
    }

    int main(void)
    {
    uint8_t i = 0;

    set();

    while(1)
    {
    if(!(PINB & b1)) i++;
    }
    }

    OdpowiedzUsuń
  11. coś bardzo ale to bardzo mocno kręcisz to po pierwsze :(

    ale żeby móc ci coś pomóc to:

    1. po pierwsze zadaj takie pytanie na naszym forum:

    www.forum.atnel.pl

    bo tam można ładnie sformatować kod - tutaj nic nie widać i miesza się twój opis z kodem

    2. po drugie po co stosujesz w kodzie programu

    #define FCPU xxxxxx

    ?????? po co ??? .... już tym sobie bruździsz na maxa - tego po prostu NIE WOLNO robić w kodzie...

    ale ok dalej pytaj w jakimś wątku na forum, tam będę w stanie (i nie tylko ja) udzielić ci odpowiedzi OK ?

    OdpowiedzUsuń
  12. Ja mam szybkie pytanie. Tym sposobem:
    DDRB = 0b11110000;
    można ustawić funkcję portów czyli wejścia lub wyjścia, a jak tym samym sposobem podciąga się piny do plusa, jak odczytuje stan pinu i jak wystawia odpowiedni stan na pin?

    W Bascomie to proste a w C?

    OdpowiedzUsuń
    Odpowiedzi
    1. Jak się przyjrzeć setkom postów np na forum elektroda na temat właśnie ustawiania kierunków, podciągania czy odczytywania stanu pinów w Bascomie to można prędzej dojść do wniosku, że ludzie włosy tracą z głowy - ponieważ w Bascomie trzeba te sposoby wykuć na pamięć a za to bez zrozumienia działania procesora. Dlatego jest wg mnie trudniej w Bascomie za to o wiele prościej w C. Już tłumaczę.

      Po pierwsze wspomniane DDRB = 0b11110000; nie ustawia funkcji portów a kierunek poszczególnych pinów portu. Wiem może czepiam się słówek ale są tu one ważne. Żeby dobrze to zrozumieć warto przede wszystkim zrozumieć zagadnienia związane z przesunięciami bitowymi w C - które dość przejrzyście opisałem w książce:

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      ale pomijając ten fakt, zobacz - zakładając, że chcesz ustawić PIN powiedzmy PB1 jako wejście, chcesz go podciągnąć do VCC programowo i odczytać stan klawisza - to przecież masz to wyżej na tym rysunku - jednak przypominam:

      DDRB &= ~(1<<PB1); // ustawiam PB1 jako wejście

      PORTB |= (1<<PB1); // podciągam PB1 do VCC


      if( !(PINB & (1<<PB1) ) { // jeśli klawisz wciśnięty
      //... zrób coś
      } else { // jeśli nie wciśnięty
      //... zrób coś innego
      }

      pewnie że może ci się wydać to zagmatwane - ale jak mówię - przeczytanie książki do której link podałem wyżej i wszystko stanie się jasne - bo nie da rady wprost wytłumaczyć tu każdej operacji jeśli się nie pozna PODSTAW C, a książka ładnie to wyjaśnia od początku i po kolei.

      Usuń
  13. [quote name='mirekk36'] w Bascomie trzeba te sposoby wykuć na pamięć a za to bez zrozumienia działania procesora.[/quote]

    Ale działanie procka nie jest mi do niczego potrzebne. Ja chcę skupić się na programowaniu a nie działaniu procesora.

    [quote name='mirekk36']Dlatego jest wg mnie trudniej w Bascomie[/quote]

    Nie żebym zagorzale bronił bascoma, ale właśnie w nim jest latwiej bo jest to intuicyjne.

    [quote name='mirekk36']zakładając, że chcesz ustawić PIN powiedzmy PB1 jako wejście, chcesz go podciągnąć do VCC programowo i odczytać stan klawisza - to przecież masz to wyżej na tym rysunku - jednak przypominam:

    DDRB &= ~(1<<PB1);
    PORTB |= (1<<PB1);
    if( !(PINB & (1<<PB1) )
    [/quote]

    No i właśnie to jest strasznie trudne i to tu trzeba wykuć na pamięć.
    W bascomie napisałbym:

    config PINB.1=input
    set PORTB.1
    if PINB.1=0 then

    A w C jakieś tyldy, wykrzykniki, nawiasy, podwojne ptaszki i to wszystko trzeba znać na pamięć do czego co służy. Dla mnie strasznie trudne i w ogóle nieintuicyjne.

    OdpowiedzUsuń
  14. Jak bardzo mogę upodobnić pisanie w C do pisania w Bascom? ty Mirku powinieneś to wiedzieć bo zdaje się pisałeś w Bascom?

    OdpowiedzUsuń
    Odpowiedzi
    1. Po pierwsze to pozwolisz, że się nie zgodzę z twoim stwierdzeniem, że

      "nie interesuje mnie działanie procka"

      Tak można mówić gdy się programuje na PC pod jakimś systemem operacyjnym. Uwierz mi, że dobrze znam ten ból i przerażenie z tymi (ja też tak to kiedyś nazywałem: "ptaszkami, krzaczkami i daszkami w C" ;) .... może nie uwierzysz ale aż 8 RAZY !!! rozpoczynałem naukę języka C dla AVR a w międzyczasie właśnie poznałem Bascoma i to tak od podszewki. Pewnie że po pierwszym odrzuceniu od C - Bascom wydał mi się również idealny (i tu jestem cię w stanie zrozumieć - bo też to przechodziłem, co więcej znam wielu ludzi, którzy taką samą drogę przechodzą)

      .... ale .... nie mam zamiaru BROŃ BOŻE na siłę ciebie namawiać na C, albo psioczyć na Bascoma. Zatem nie wdam się w dyskusję który język jest lepszy - ponieważ zawsze powtarzam, że każdy język czy procesor jest tylko tak dobry jak programista, który się nim posługuje. A znam programistów Bascoma dużo lepszych od programistów w C jak i odwrotnie ;)

      Jeśli chodzi o twoje ostatnie pytanie - to niestety - tutaj jak widać działa już ten zły niestety nawyk, który wyrabiamy sobie pisaniem programów w Bascomie - i później próbujemy postrzegać programowanie w innym języku tak aby było podobne do Bascoma. BŁĄD :( ... tu jest całkiem inaczej ale na prawdę dużo wygodniej.

      Nie da się bez przeczytania podstaw i ogarnięcia tych "ptaszków" :( ....

      Tyle że trudne to było kiedyś - gdy nie można było znaleźć żadnej książki do tego - a dzisiaj ????

      a dzisiaj - jeszcze raz powtórzę - język C jest prostszy niż Bascom i staram się to udowodnić swoją książką. Ale nic na siłę .... każdy musi ew sam dojść do momentu aby spróbować się przesiąść ... ja mogę w tym co najwyżej pomagać i asystować .... podpowiadać. Także zachęcam .....

      I nie myśl że uważam że Bascom jest zły - bo jeśli robisz w nim absolutnie wszystko czego potrzebujesz i działa ci idealnie to może nawet nie ma sensu myśleć o C ? (nie mówię tego złośliwie - tylko patrzę wstecz na samego siebie i swoje zmagania z C i walkę ze zrozumieniem "ptaszków/krzaczków". Mogę z perspektywy czasu powiedzieć tylko - jedno - KAŻDY , podkreślam - KAŻDY nawet najbardziej zagorzały zwolennik Bascoma, który w końcu zaskoczył tak jak ja kiedyś ten język C - to mówi mi teraz - że to był bardzo dobry krok, nie sądzisz, że coś w tym musi być ?

      Usuń
  15. Wiesz, ja nie neguję tego że na przykład C jest może lepszy, zresztą to jest spieranie się o wyższość świąt jednych nad drugimi.
    Chciałbym nauczyć się C bo nie chcę stać w miejscu, chcę się rozwijać, no i C jest darmowy a za bascom nie crackowany trzeba płacić.
    Ja podchodzę do C już chyba trzeci raz.
    Najpierw czytałem kury online, później przeczytałem Symfonię C++ i nic. Choć przyznaję że po przeczytaniu tej ostatniej pozycji wiele z tego co Ty zapodajesz jest już bardziej zrozumiałe niż kiedy czytałem o C za pierwszym razem.
    W każdym razie chciałbym ogarnąć prócz bascoma również C choćby w takim stopniu jak opanowałem kompilator Marka Albertsa.
    Chcę kupić Twoją najnowszą książkę, ale na razie muszę się wstrzymać.
    Co do mojego pytania o to jak bardzo mogę upodobnić pisanie w C do pisania w bascomie to nie chodzi mi o to że tak się przyzwyczaiłem do bascoma że inaczej nie mogę, tylko o to że jeśli w C będę mógł pisać podobnie jak w bascomie to zrozumienie C przyjdzie o wiele łatwiej.

    OdpowiedzUsuń
    Odpowiedzi
    1. Zgadzam się z tobą w 100% o tym dyskutowaniu który język lepszy więc to zostawmy innym ;)

      Odnośnie zaś języka C dla AVR to hmmm polecam ci jednak tę moją książkę - ale nie tą najnowszą - lecz tą pierwszą , niebieską - dla początkujących

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      ja tyle razy wszędzie piszę, że ciężko jest nauczyć się języka C dla mikrokontrolerów z książek do C czy C++ przeznaczonych dla komputerów PC. Oczywiście są maniacy, którzy na niektórych forach krzyczą że do nauki C dla procków wystarczy sama biblia C jaką jest książka "ANSI C" .... ale to jest tak wg mnie, że owszem jest to SUPER KSIĄŻKA, WARTO I JĄ MIEĆ ... jak najbardziej

      ale ile można się nauczyć z tych książek żeby wystartować nie tylko z C ale jeszcze z C na mikrokontrolery - to sam już sobie odpowiedziałeś wyżej ... bo przerobiłeś kilka z tych książek. Dlatego może skorzystaj z tego co piszą czytelnicy w opiniach na temat tej niebieskiej książki mojej i zajrzyj do niej .... Ja myślę że wtedy twój start z językiem C nabierze przynajmniej o wiele większego tempa ... a jak coś - jakieś pytania wtedy to proszę bardzo .... ja chętnie pomogę.

      Usuń
  16. Rzeczywiście miałem na myśli tą pierwszą książkę Twoją. Przeczytałem fragment gdzieś udostępniony w sieci, który notabene ponoć udostępniony był legalnie. Na sebdspace można go znaleźć.

    http://www.sendspace.pl/file/eb27160a2c02035d2fa8819/mikrokontrolery-avr-jezyk-c-podstawy-programowania

    OdpowiedzUsuń
    Odpowiedzi
    1. No ale przecież w tym linku który podałem wyżej masz PDF do pobrania nie tylko ze spisem treści ale także obszernymi fragmentami książki - więc zapraszam to tego oficjalnego linku

      Usuń
  17. dla usystematyzowania:
    1. Czy jak port robi jako wejście to zwie się pinem czy portem?
    2. czy PIN się definiuje podobnie jak np: "PORTC |= (1<<PC0)" czy to tylko służy do odczytywania stanu 1 lub 0 w kodzie programu?
    3. Czy można diodę podpiąć pod wejście tak aby się zapaliła, czy też prądy są tu tak male ze nie zapalą diody, a może ich wcale nie będzie od strony procesora?
    Przez co jeśli po restarcie procesora wszystkie będą wejściami to rozumiem że nie ma to wpływu żadnego na podłączone peryferia? tzw bezpieczny stan?

    OdpowiedzUsuń
    Odpowiedzi
    1. ad.1) Nie ma takiego pojęcia jak nazywanie portem czy pinem w zależności od tego co robi :( .....

      wyraźnie piszę. Każdy PIN procesora (gdzie PIN oznacza fizyczną nogę procka) .... może być albo WEjściem albo WYjściem. A to czy ty chcesz dokonywać odczytu czy zapisu zależy z jakiego rejestru skorzystasz. Czyżbyś przeoczył na górze informację o trzech rejestrach ???

      DDRx - rej. kierunku
      PORTx - rejestr wyjściowy
      PINx - rejestr wejściowy

      co to ma wspólnego z nazywaniem nóżki procka pinem czy portem ???? chociaż wiem skąd się bierze taki problem w głowach niektórych początkujących - to niestety pozostałość po chorym Bascomie w tym zakresie, gdzie każdy próbuje się nauczyć tamtejszej dziwacznej terminologii. :(

      ad.2) PIN się nie definiuje - weź jednak proszę postaraj się uważnie i powoli przeczytać artykuł od początku, ale jak coś to doprecyzuję tutaj .... PINx (gdzie x zastępuje literkę A,B,C,D itd) .... to FIZYCZNY rejestr procesora i służy do ODCZYTU tego co jest na wejściu każdej z 8 nóg danego portu X procesora gdy jest on ustawiony jako WEJŚCIE. Eeeeh czyli jeśli po resecie masz wyzerowany rejestr kierunku np

      DDRA = 0

      a jednocześnie np wszystkie linie portu A podciągnięte rezystorami do VCC

      to gdy odczytasz zawartość rejestru

      PINA

      dostaniesz wartość = 255 (0xff)

      jeśli natomiast zewrzesz nogę PA7 do GND to po odczycie rejestru PINA

      dostaniesz wartość = 127

      a jak wszystkie zewrzesz do GND to dostaniesz ZERO z rejestru WEJŚCIOWEGO PINA

      A ty się pytasz o operację PORTC |= (1<<PC0) pewnie nie rozumiejąc co to znaczy np |= albo << .... niestety - tu odsyłam cię do książki - bo wszystkiego to nie jestem w stanie wytłumaczyć w 2 zdaniach:

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      ad.3) Można podłączyć diodę LED bezpośrednio do pinu w prockach AVR ponieważ mają sporą wydajność prądową - niech będzie że 20-30mA to z powodzeniem wystarczy do zapalania diod LED..... ale UWAGA! mam nadzieję, że nie przyjdzie ci pomysł do głowy aby diodę LED podłączać bez REZYSTORA broń Boże !!!

      Tak po restarcie wszystkie piny są wejściami w stanie wysokiej impedancji. Tak to bezpieczny stan.

      Usuń
    2. O dzięki za wytłumaczenie, czytając po forach często jestem zmieszany.

      A skąd wiedziałeś że mam diodę bez rezystora podpiętą? :) faktycznie ostatnio tak zrobiłem podłączyłem 2 białe szeregowo co daje ponad 6V, nic się nie spaliło do teraz wszystko działa, muszę dać ten rezystor? są jakieś niebezpieczeństwa?

      operacje bitowe znam ale zastanawiam się czy jak dam np: DDRA=0xff oraz PORTA=0xFF to jaką wartość przyjmie PINA i czy będzie to równe PORTA? czy ten rejestr będzie nieokreślony ponieważ PINY są wyjściami?

      Jeśli chcę oszczędzać energię to do czego mam podpiąć PIN aby nie był HI-Z, powinienem wyprowadzić do masy?

      Usuń
    3. Jak jeszcze raz w rozmowie użyjesz że do dzisiaj ci wszystko działa jakoś tam podłączone czy jest sens to zmieniać - to w ogóle proszę cię nie dyskutujmy ok? to taka moja gorąca prośba. Bo albo chcesz się czegoś nauczyć albo chcesz robić totalne głupoty, które powielasz z innych głupich stron czy niestety o zgrozo z pewnej książki. Więc kończę to raz na zawsze. Jak chcesz się zająć elektroniką - to zapoznaj się z podstawowym prawem ohma i wzorem I=U/R. Poszukaj informacji podstawowych na temat tego prawa i obliczania rezystorów dla diod LED - jest tego pełno - tylko trzeba chcieć. Sorrry ale ja nie mam zamiaru dyskutować i tracić czas na takie (przepraszam) dziwne tematy.

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

      po ustawieniu DDRA=0xff oraz PORTA=0xff nastąpi włączenie podciągania każdego pinu wejściowego - wewnętrznym wbudowanym rezystorem do VCC, dzięki czemu na wejściu już nie będzie panował stan wysokiej impedancji tylko stan wysoki.

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

      Pin do masy ??? ..... zapamiętaj sobie na całe życie - jeśli jakiś pin może pracować jako WYJŚCIE to NIGDY się go nie podłącza do masy albo VCC. A temat oszczędzania energii zostaw sobie na później jak troszkę lepiej zrozumiesz elektronikę. Na razie poćwicz podstawy ok?

      Usuń
    4. Czegoś tutaj mój mały rozumek nie ogarnia. ;)
      Jeśli dobrze pamiętam, to DDRA=0xff ustawia cały port A jako wyjścia a PORTA=0xff wystawia na nim stany wysokie, co powoduje połączenie pinów z VCC poprzez "górny" tranzystor wyjściowy (source). Rezystor podciągający byłby użyty, gdyby port został ustawiony jako wejście poleceniem DDRA=0x00.
      Pozdrawiam
      PS. Świetny blog, chyba się tutaj rozgoszczę. ;)

      Usuń
    5. Zapraszam ale nie rozumiem też problemu? i czy w ogóle jest ? bo oczywiście że podciąganie działa gdy pin jest WEjściem a nie Wyjściem - więc dobrze kolega rozumie. Czy jak gdzieś wyżej w tekście coś źle napisałem ?

      Usuń
    6. Problemu w zasadzie nie ma. W odpowiedzi dla innego Anonimowego kolegi nad moim postem napisane jest:
      " po ustawieniu DDRA=0xff oraz PORTA=0xff nastąpi włączenie podciągania każdego pinu wejściowego - wewnętrznym wbudowanym rezystorem do VCC, dzięki czemu na wejściu już nie będzie panował stan wysokiej impedancji tylko stan wysoki. "
      Pomyślałem, że może to być mylące dla osób, które stawiają pierwsze kroki, dlatego ośmieliłem się zakwestionować. ;)

      Usuń
    7. Aaaa no tak .... oczywiście że się walnąłem tu wyżej, zresztą dalej piszę o wejściach a niechcący napisałem że DDRA = 0xff; .... źle miało być DDRA = 0x00;. Więc ma kolega w 100% rację i dobrze że zwrócił na to uwagę. Dzięki.

      Usuń
  18. Mirku - na wstępie dzięki bardzo za pracę włożoną w tego bloga. Po przeczytaniu tego i zapoznaniu się z datasheet atmega8 wreszcie zrozumiałem (chyba) o co chodzi. W datasheet były 4 zdania które mi bardzo pomogły:
    1. rejestry PORTx i DDRx są read/write; a PINx read only
    2. jeśli dla danego pinu DDRxn ustawisz 0 i PORTxn 0 to dostaniesz stan nieokreślony
    3. jeśli DDRxn=0 i PORTxn=1 (wtedy PINxn=1, a po zwarciu pinu xn do masy PINxn=0)
    4. DDRxn=1 PORTxn=1 i DDRxn=1 PORTxn=0 ustawia odpowiednio 1 i 0 na danym pinie procesora. Pytanie co w tym przypadku znajduje się w rejestrze PINx (logika podpowiada, że to jaki output podaje pin) i czy jest sens to wogóle odczytywać skoro jest podane na sztywno(?)

    Popraw mnie jeśli się mylę, bo zestawu jeszcze nie zamówiłem i nie mam na czym testować.

    OdpowiedzUsuń
    Odpowiedzi
    1. Dobrze myślisz ;) gdy masz kierunek WYJŚCIOWY ustawiony przez DDRx i wystawiasz na zewnątrz 0 lub 1 to oczywiście że jeśli odczytasz PINx to zobaczysz dokładnie to co tam ustawiłeś ;)

      a dlaczego nie miałoby sensu użycia wtedy PINx ? przecież można sobie zawsze coś tam wymyślić ;) Tak na szybko przychodzi mi myśl, że jeśli w jakiś asynchroniczny sposób zmieniam stan jakiegoś wyjścia a później w jakimś momencie chcę sprawdzić co jest na wyjściu bo nie mam tego w jakiejś zmiennej - to czemu nie użyć odczytanej wartości z PINx ? ;)

      Usuń
  19. Panie Mirku na wstępie chciałbym przeprosić, bo czytam i czytam i za chorobę nie mogę zakumać o co w tym chodzi :/ No po porostu nie może to do mnie dotrzeć. Dlatego może jakiś mega banalny przykład, by mi w tym pomógł. Powiedzmy, że mam uC ATmega8. I teraz tak: do PC0 podłączam przycisk a do PC1 podłączam diodę. Chciałbym żeby przycisk zapalał i gasił diodę (przycisk włączony dioda zapalona, przycisk wyłączony dioda zgaszona). W takim razie jak powinienem ustawić rejestry?

    OdpowiedzUsuń
    Odpowiedzi
    1. Nie ma za co przepraszać, to jest w zasadzie MEGA podstawowy poradnik i jest to poradnik do mojej książki:

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      bo w niej zabrakło właśnie akurat tego .... a reszta w zasadzie jest w książce. Tego czego ci brakuje do zrozumienia jak dalej postępować czyli mieszać sobie na jednym porcie WEJŚCIA z WYJŚCIAMI to coś takiego jak np operacje przesunięć bitowych bardzo szeroko i przejrzyście opisane w książce ... polecam, a ciężko byłoby mi tu to wszystko teraz przepisywać tym bardziej, że to nie jest jedna, dwie czy trzy strony w książce a sporo więcej.

      A taki banalny przykład w kodzie o jaki pytasz ? proszę bardzo:

      DDRC |= (1<<PC1); // ustawiamy pin PC1 jako WYjście
      DDRC &= ~(1<<PC0);// ustawiamy pin PC0 jako WEjście

      PORTC |= (1<<PC0);// podciągamy linię klawisza do VCC

      i dalej dokładnie jak w przykładach wyżej

      Usuń
    2. DDRC |=(1<<PC1); //ustawiamy pin PC1 jak wyjście
      DDRC &=~(1<<PC0); //ustawiamy pin PC0 jako wejście
      PORTC|=(1<<PC0); //podciągamy linię klawisza do VCC

      //sprawdzamy stan wejścia PC0
      //narazie jest stan wysoko na PC0, ponieważ jest programowo podciągnięte do VCC

      if ( !(PINC & (1<<PC0)) DDRC |=(1<<PC1);
      else DDRC &=~(1<<PC1);

      //gdy przycisk włączony (PC0 do GND)
      //if spełniony i zapalamy diodę
      //gdy przycisk wyłączony (PC0 do VCC)
      //if nie jest spełniony i gasomy diodę

      Czy dobrze rozumiem?

      Usuń
    3. No ale żartujesz ;) albo jakąś literówkę robisz kosmiczną ;) skąd taki pomysł ?

      if ( !(PINC & (1<<PC0)) DDRC |=(1<<PC1);
      else DDRC &=~(1<<PC1);

      toż rejestr DDRC jest do ustawiania kierunku a nie do wystawiania na pin stanu 0 lub 1 ... więc musi być TAK:

      if ( !(PINC & (1<<PC0)) PORTC |=(1<<PC1);
      else PORTC &=~(1<<PC1);

      ;)

      Usuń
  20. Miało być tak jak Pan napisał. W pewnym momencie już mi się wszystko pomieszało ale właśnie powoli zaczynam kapować co i jak. Dziękuję za pomoc :)

    OdpowiedzUsuń
  21. Hej.
    PINx jest R/O ale można do niego pisać (?!). Cytat z dokumentacji ATmega48/88/168/328: "Writing a logic one to PINxn toggles the value of PORTxn, indenpendent of the value of DDRxn."
    Miłego dnia :-)

    OdpowiedzUsuń
    Odpowiedzi
    1. Hej, to znowu ja.
      Wydawać by się mogło że to mało użyteczne (zapis do PINx) nawet przy ustawieniu portu jako wyjście (przy wejściu to już chyba całkiem bez sensu) bo to samo można uzyskać przez PORTx ^= maska, ale jak właśnie gdzieś doczytałem zapis do PIN jest wykonywany atomowo a XOR nie.

      Usuń
  22. Witam, ostatnio bawiąc się ATmegą8 przez własną głupotę i pośpiech ustawiłem w programie "DDRB = 0", oczywiście w sekcji B znajdują się ważne porty do pogramowanie (MISO, SCK). Po tej operacji programik ISP Programmer przestał rozpoznawać mikrokontroler i nie mogę zaprogramować nowego flasha. Sama atmega działa, gdyż odpala ostatni wgrany program( zaświeca diody). Czy jest coś co mogę zrobić żeby cofnąć proces, lub jakoś to ominąć, czy niestety muszę poszukać innej "zabawki"? Pozdrawiam

    OdpowiedzUsuń
    Odpowiedzi
    1. ;) gdyby przez ustawienie DDRB=0 można było zablokować jakikolwiek procek AVR to byłaby jakaś zbiorowa paranoja ;)

      WSZYSCY mieliby chyba zablokowane procki - ja również ;)

      Panie kolego - już wyjaśniam bo bardzo mocno nie doczytałeś noty PDF procka ale chyba też książka Bluebook nie wpadła ci w ręce co ?

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      Otóż w nocie masz jak BYK napisane że KAŻDY, podkreślam KAŻDY rejestr kierunku i nie ważne czy DDRB czy DDRA czy DDRC itp ... jest ustawiony na 0 ... po prostu po resecie WSZSYTKIE piny są WEJŚCIAMI. ;)

      a ten fakt W NICZYM nie może przeszkadzać temu aby działał interfejs ISP (do programowania) ponieważ w trakcie sygnału RESET i tak te piny są ustawiane automatycznie tak jak trzeba dla programowania) - rozumiesz ? ;)

      więc nie ważne czy są WEjściami czy WYjściami - i tak ZAWSZE ISP zadziała

      Reasumując - w ogóle w programowy sposób nie jesteś w stanie zablokować procka chociażbyś się nie wiem jak starał ;) NIE MA TAKIEJ OPCJI ;)

      a to że programator ci nie widzi procka to błędne połączenia .... i to że akurat przydarzyło ci się to w jednym czasie to widzę że wpłynęło na to iż wysnułeś z zakamarków swojej podświadomości taką oto niecną teorię - że niby z głupoty przez ustawienie DDRB=0 zablokowałeś procka ;) NIC Z TYCH RZECZY - i mam nadzieję, że teraz już jaśniej ci się zrobiło ? hmmm ;)

      Usuń
    2. Dzięki serdeczne :D Jaśniej i cieplej na sercu :P Dziś podłączyłem ATmegę i wszystko działa idealnie. Dzięki za wyczerpującą odpowiedź i serdeczność nawet przy moich brakach :) Idę się kształcić i dalej eksperymentować z AVRką, Pozdrawiam

      Usuń
  23. Witam,
    a czy pisząc:
    PORTB = 0xFF;
    PORTC = 0xFF;
    PORTD = 0xFF;
    Nie ustawimy pinu reset jako podciągnięty do Vcc? I podłączymy przez rezystor port RESET z Vcc to takie podwójne podciągnięcie nie będzie powodować jakiś problemów?
    I moje drugie pytanie a czy ustawienie nieużywanych pinów jako wyjścia i ustawienie 0 na nich nie jest lepszym rozwiązaniem żeby nie zbierać zakłóceń i nie pobierać nadmiernie prądu gdy zasilamy układ z baterii?

    OdpowiedzUsuń
    Odpowiedzi
    1. mozna tak zrobic przy baterii ... a pin reset nie ma nic wspolnego z programowym podciąganiem

      Usuń
  24. Kurde jak zawsze znów zapomniałem się o coś zapytać. A jak zaczynałem pisać to pamiętałem o co chciałem się jeszcze zapytać.
    Czy np. porty RxD oraz TxD automatycznie ustawią się na wejście i wyjście gdy uruchomię funkcję inicjalizacji USART?

    OdpowiedzUsuń
  25. Witam,
    Mam następujący problem. Steruję dwoma silnikami DC za pomocą układu L293D. Wykorzystuję po dwa sygnały sterujące na każdy silnik: A1, B1 oraz A2, B2. Na razie nie używam PWM - podłączone do VCC. Jako uC stosuję ATmegę16. Podłączyłem sygnały A1, B1 (pierwszy silnik) do portów PC7 i PC6. Natomiast sygnały A2, B2 (drugi silnik) do portów PC5 i PC4 tego procesora. Napisałem prosty program na podstawie przykładu Pana Mirka z niebieskiej książki do sterowania silnikiem DC. Zmodyfikowałem go o drugi silnik. Działanie ma polegać na tym, że na zmianę mają załączać się na chwilę oba silniki jeden po drugim. Niestety jest tak, że o ile porty PC7 i PC6 wyzwalają sygnałami pracę jednego silnika, o tyle porty PC5 i PC4 już nie. Podobnie porty PC3 i PC2. Dopiero para portów PC0 i PC1 odpowiednio steruje drugim silnikiem i wszystko działa jak powinno. Wobec tego czy porty PC5...PC2 nie mogą z jakiś powodów pracować jako standardowe porty I/O? Jeżeli mogą to czy dla tych portów ATmegi16 trzeba coś dodatkowo poustawiać?

    OdpowiedzUsuń
  26. Czy porty PC5 do PC2 mogą pracować jako standardowe portywyjściowe w Atmega16?

    OdpowiedzUsuń
  27. OK, problemem był włączony JTAG. Wyłączyłem i porty działają. Zajrzałem do noty atmegi:-)

    OdpowiedzUsuń
  28. Czy można zmieniać stan wyjść w ten sposób np.:

    PORTB = 0b11110000;
    PORTB = 0b11110101;

    zamiast używać operacji bitowych? Czy jest to poprawne?

    OdpowiedzUsuń
    Odpowiedzi
    1. Pewnie że można jeśli akurat od razu chcesz ustawić cały port .... tylko ciężko tak doradzać w oderwaniu od kodu - bo jest wiele sytuacji gdy robi się to wygodniej za pomocą ustawiania odpowiednich grup bitów

      Usuń
    2. Ja jestem początkującym, i widziałem, że w większości tutoriali w Internecie używa się operacji bitowych do zmiany stanu wyjść w jakimś programie np. miganie LEDami, więc stąd moje pytanie czy mogę zrealizować to używając przypisania w którym zmieniam stany odpowiednich bitów? Mianowicie w ten sposób:

      for(;;)
      {
      PORTB = 0b11111111; //zapalam wszystkie podłączone LEDy
      _delay_ms(1000);
      PORTB = 0b00000000; //gaszę wszystkie
      }

      Czy jest to gorszy sposób od operacji bitowych?

      Usuń
    3. Już pisałem wyżej , że jeśli do zabawy i migasz wszystkimi diodami na porcie czy jakieś tam ćwiczenia - to co może być złego w tym sposobie ? nic ;)

      Usuń
    4. Dziękuję za odpowiedź, to jest taka forma zabawy-nauki ;) A jak chce migać tylko jedną?

      for(;;)
      {
      PORTB = 0b11111111; //zapalam wszystkie podłączone LEDy
      _delay_ms(1000);
      PORTB = 0b11111110; //gaszę jedną
      }

      Czy tak jest gorzej niż operacjami bitowymi, bo dla mnie taki kod jest czytelniejszy? Przepraszam za dociekliwość i może głupie pytania, ale dopiero się uczę :)

      Usuń
    5. słuchaj jeśli NIC INNEGO nie robisz tylko bawisz się 8 diodami podłączonymi do całego portu to - na prawdę nie wiem ile razy mam powtórzyć, że nie ma znaczenia jak to robisz ;) ... co za różnica ? Co ma tu być lepszego w przesunięciach bitowych jak piszesz lub gorszego ?

      Nie rozumiesz wciąż jednej rzeczy - później pisanie programów nie będzie się sprowadzało do ciągłego migania diodą lub diodami na całym porcie - chyba sam wiesz że to bez sensu :(

      I wtedy dopiero zaczną być BARDZO ale to BARDZO potrzebne przesunięcia bitowe i to WCALE NIE TYLKO do migania diodami bo ty wciąż sprowadzasz przesunięcia bitowe do migania diodami co niestety też jest totalnie bez sensu :(

      To że teraz sprawia ci to trudność to świadczy tylko o jednym - nie miałeś jeszcze w ręku książki:

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      bo każdy kto ją miał to zrozumiał raz na zawsze przesunięcia bitowe jako podstawowe operacje podczas programowania w C na mikrokontrolerach i dzięki temu nawet do tak durnej rzeczy jak miganie diodą LED każdy woli ich użyć niż bawić się w takie zapisy binarne ....

      Ty niestety nie wiesz nawet co to za sobą niesie, jak ułatwia życie i programowanie - za to wciąż szukasz sposobu jak ominąć tego żeby się nauczyć i zrozumieć przesunięcia bitowe i to jest twój błąd ;)

      zajrzyj proszę na nasze przyjazne forum:

      www.forum.atnel.pl

      więcej zrozumiesz i więcej się nauczysz nawet jeśli jeszcze nie masz tej książki ...

      ale pomyśl o niej ... popytaj ludzi czy warto kupić .... bo to jest prawda że z przesunięciami bitowymi się WSZYSTKO łatwiej robi niż tak jak ty się teraz męczysz - a co więcej przy takim podejściu będzie ci ciężko wiele innych rzeczy zaprogramować - no ale przekonasz się o tym wkrótce sam ;)

      Usuń
    6. A czy przypadkiem przed samym końcem pętli nie brakuje
      opóżnienia - przecież dioda zgaśnie i zapali się natychmiast
      (no po kroku procesora)

      Usuń
    7. masz rację brakuje tu jeszcze jednego delaya - gdyby napisać tak

      PORTB ^= (1<<PB0);

      to wystarczyłby jeden delay ;) ...

      Usuń
  29. Dziękuję, już wzystko rozumiem. Książkę już zamówiłem i na nią czekam ;)

    OdpowiedzUsuń
  30. Witam
    Widzę że diody można podłączać na dwa sposoby, raz do GND a raz do VCC i wtedy programowo do załączania diody ustawiamy PORTx raz na 1 a raz na 0. Czy jeden sposób ma jakąś przewagę nad drugim, tzn czy możemy mieć dodatkowo jakieś korzyści albo uniknąć przykrych niespodzianek wybierając jeden z tych sposobów? Czyli krótko: jak lepiej?:) Pozdrawiam

    OdpowiedzUsuń
    Odpowiedzi
    1. Akurat w prockach AVR - na zasadzie "jak ci wygodnie" ;) ja wprawdzie z przyzwyczajenia z innych procków i scalaków gdzie najczęściej trzeba było sterować prądowo z GND podłączam katodą do pinu ... ale nie zawsze - no jak wygodnie tak robię przy AVR'kach ;) bo czy dioda sterowana ze stanu wysokiego czy niskiego to może taki sam prąd zapodać procek ;)

      Usuń
    2. Co za szybka odpowiedz:) Dzieki wielkie, wszystkiego dobrego w Nowym Roku

      Usuń
  31. Witam, czy poprawny będzie zapis, dla zmiany stanu na wszystkich pinach portu D (toggle):
    PORTD ^= (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0);
    Czy mogę to jakoś uprościć?

    OdpowiedzUsuń
    Odpowiedzi
    1. Ale ja dosyć często nawet tu na blogu, wyżej pisałem - że jeśli chcemy zmieniać stan za jednym razem np na wszystkich pinach albo na jednej połówce to zdecydowanie lepiej użyć jednak zapisu HEX w takich konkretnych wypadkach. Czyli w twoim wypadku:

      PORTD ^= 0xFF;

      gdybym chciał starszą połówką migać to:

      PORTD ^= 0xF0;

      a młodszą:

      PORTD ^= 0x0F;

      rozumiesz ? oczywiście twój zapis zadziała w PEŁNI poprawnie tylko że po prostu nie ma sensu pisać dla KAŻDEGO bitu jeśli używasz akurat WSZYSTKICH naraz.

      Usuń
  32. Wszystko jasne, bardzo dziękuję za odpowiedź.

    OdpowiedzUsuń
  33. Ja mam pytanie odnośnie pliku #include
    Rozumiem ,że to plik uniwersalny ,ale czy programując pod załóżmy Atmege32 mogę wybrać #include ??? ,wydawałoby się to bardziej sensowne ,z racji tego ,że zawartość pliku i konfiguracja pewnie bardzie jest pod Atmege32.

    Pytam bo wydaje mi się to ważne. Z góry dziękuję za odpowiedź i mam nadzieję ,że nie zamieszałem zbytnio :)

    OdpowiedzUsuń
    Odpowiedzi
    1. Nie zamieszałeś ;) pytać warto, a szczególnie gdy nie rozumie się PODSTAW języka C. Dlatego PRZEDE WSZYSTKIM odsyłam kolegę do podstaw czyli do książki:

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      bo tam jest naprawdę wszystko wyjaśnione, a tutaj nadmienię że WCALE nie wydawałoby się sensowne aby dla każdego procka inkludować inny plik konfiguracyjny tak jak sugerujesz (czyli tak jak to jest w Bascomie - a pewnie się z niego przesiadasz co ? ;) i masz taki już nawyk - niezbyt dobry zresztą)...

      pomyśl sobie potem trzeba szukać jak się tam jakiś plik nazywa itp itd

      tymczasem w C wystarczy i nawet WAŻNE jest aby inkludować UWAGA! TYLKO I WYŁĄCZNIE

      plik

      pomyśl sobie jaka to wygoda - oderwij się na chwilę od myślenia bascomowego ... widzisz ? nie muszę myśleć jaki procek - daję tylko tak i wszystko DZIAŁA - bo procka panie - to ja ustawiam we właściwościach projektu - więc sam teraz się zastanów - po co jeszcze raz w kodzie ?

      A są tacy co i tak robią to w kodzie bo twierdzą nawet że inaczej się nie da - tylko że potem mają coraz większe MEGA problemy

      więc zapamiętaj - jeśli C ... to ZAWSZE WYSTARCZY i TRZEBA wręcz TYLKO:

      #include

      i NIC INNEGO ok ? ;)

      Usuń
  34. ok dzięki ,przyłapałeś mnie z tym bascomem ( faktycznie nawyk) ,dobrze że nie zapytałem jeszcze jak ustawiać kwarc w programie ,choć byłoby to przydatne.

    W ramach ,ćwiczeń i tak spróbuję kompilacji na obu includach ,bo męczy mnie ciekawość :)

    OdpowiedzUsuń
    Odpowiedzi
    1. hehehe w programie nie ustawiamy kwarcu tzn częstotliwości taktowania - chociaż często spotkasz się w dzisiejszych czasach z dyrektywą

      #define F_CPU xxxxxx

      w kodach źródłowych programów w C ... tylko że niestety są to MEGA BZDURY z którymi walczę jak ogniem i mieczem i pomimo to że w poradnikach wideo i na forum pokazuję i tłumaczę DLACZEGO tego wręcz nie można robić w kodzie - to co z tego - jak wiele blogów w Polsce, wiele kursów internetowych - właśnie uczy początkujących takich BZDUR (nie obawiam się tego powiedzieć) ... A jak chcesz wiedzieć dlaczego to BZDURY i dlaczego prowadzą do błędów to sam też oglądaj sukcesywnie wszystkie moje poradniki wideo .... szczególnie tu:

      http://www.youtube.com/watch?feature=player_detailpage&v=UhcyBpM57vo#t=2911

      obejrzyj koniecznie od tego momentu - ten poradnik.

      Odnośnie zaś twoich własnych ćwiczeń z podłączaniem plików specyficznych dla procka - to niestety - idziesz też taką złą drogą i zobaczysz że będziesz miał więcej problemów niż pożytku z inkludowania plików specyficznych dla procków bo to jest tak naprawdę JESZCZE GORSZA BZDURA niż z tym #define F_CPU

      no ale jak wolisz się dłużej uczyć ;) zamiast nauczyć się na cudzych błędach to powodzenia ;) to już twoja wola

      Usuń
  35. Ok ,dzięki już rozumiem o co chodzi, tylko że ja po prostu lubię wiedzieć szczegółowo jak co działa, chyba sam rozumiesz.
    Jak zaczynałem w bascomie to podobnie nie uczyłem się na "pałę" jak ktoś robi ,ale tak długo grzebałem ,aż zrozumiałem dlaczego tak powinno być. Spędziłem sporo czasu na tzw. "porażki" i to że nic nie działało. Ale dużo się przy tym nauczyłem.
    Także nie zrozum mnie źle, nie robię sobie specjalnie pod górkę. Ale staram się jak najlepiej zrozumieć i spróbować wszystkiego. A jak nie działa to dojść dlaczego nie działa ,a nie "pokażcie mi rozwiązanie" .


    P.S. pewnego dnia też może dojdę do tego jak wkleiłeś linka z filmikiem zaczynającym się od odpowiedniego momentu. :)

    OdpowiedzUsuń
    Odpowiedzi
    1. To nie o to chodzi - każdy lubi sobie popróbować - tylko że niektórzy lubią jeszcze tracić czas na zbędne rzeczy zamiast przeznaczyć go na naukę od podstaw. Dlaczego tak mówię ?

      Dlatego - że jakbyś przeczytał w książce i poćwiczył jak się stosuje inkludowanie plików w C to nie za bardzo by nawet przychodził pomysł do głowy - żeby inkludować pliki specyficzne dla procka. Jednym słowem mówiąc wolisz się uczyć od tyłu ;) i to o to mi chodziło - ale twoja wola ;)

      A co do wklejania linku do filmu na YT od konkretnego momentu (czasu) to pewnie nigdy dotąd nie kliknąłeś prawym klawiszem mychy na filmie i nigdy przez to nie zobaczyłeś opcji "Kopiuj adres URL od bieżącego momentu" ... to wszystko ;) ... kliknij i sprawdź - zobaczysz że działa i jak działa

      Usuń
  36. Wielkie dzięki jeszcze raz za poświęcony czas. Po obejrzeniu filmiku z (odnajdywaniem nazw wektorów przerwań) oraz z zapoznaniem się z #define i preprocesorem (niebieska książka) już zaczynam kapować dlaczego plik ,bo resztę wybierze kompilator automatycznie po wybraniu odpowiedniego procka w Target Hardware. Teraz już rozumiem dlaczego tak ma być i będę się tego trzymał przy pisaniu kodu.

    Jeszcze raz wielkie dzięki!!! :) ,myślę że ten czas nie poszedł na marne.

    OdpowiedzUsuń
  37. Ja potrzebowałbym zdefiniować typ zmiennej ,która będzie przyjmować tylko wartości 0 lub 1.
    W tabelce na stronie 73 (bluebook) ,najmniejsza to uint8_t ,zakres 0-255 (ale to za dużo w moim przypadku)
    Pisze też coś o bool ,ale że żadko stosowane z konieczności załączania oddzielnej biblioteki.

    Mógłby ktoś coś poradzić ,z góry dziękuję i pozdrawiam.

    OdpowiedzUsuń
    Odpowiedzi
    1. No i właśnie uint8_t w takim przypadku

      Usuń
  38. Aha czyli 1 bajt to minimum. Myślałem raczej o pojedynczym bicie ,bo to zwykła flaga programowa ,która i tak przyjmie tylko 0 lub 1 ,no nic jak się inaczej nie da to trudno. Dzieki.

    OdpowiedzUsuń
    Odpowiedzi
    1. W prockach AVR nie ma sprzętowych pól bitowych jak np w 8051. Możesz wprawdzie zrobić sobie strukturę pól bitowych w C ale i tak aby mieć jedno pole bitowe to w pamięci RAM zostanie zajęty 1 bajt. Dopiero gdybyś zrobił 8 pól bitowych w strukturze to byłaby oszczędność miejsca. Ale nie koniecznie zawsze jest to optymalne czasowo. Więc spokojnie można używać 1-go bajtu,

      Usuń
  39. Bardzo dawno temu w zamierzchłych czasach, napisałem że bluebook nie wyjaśnia jak ustawiać porty.
    Teraz po jego dokładniejszym przeczytaniu i zaprzyjaźnieniu się z notą aplikacyjną ,chciałbym to
    sprostować ,jest dokładny opis przy przesunięciach bitowych ,którego ja na samym początku nie
    rozumiałem. Mam nadzieję ,że wybaczysz :)

    A teraz trochę na poważnie do szczęścia pozostał mi jeszcze jeden krok ,powiedz czy dobrze rozumiem
    ,że za pomocą #define LED (1<<PC7) ,mogę sobie w ten sposób dowolnie nazwać wyprowadzenie portu w tym przypadku PC.7
    i używać wygodniejszej nazwy w programie. (w tym przypadku LED bo podłączam akurat diodę ,ale sama nazwa nie ma znaczenia)

    Możnaby śmiało powiedzieć ,że to taki "Bascomowy" alias ,dobrze rozumiem?

    OdpowiedzUsuń
    Odpowiedzi
    1. Nie wiem tzn nie pamiętam już bascomowych aliasów ale dokładnie tak jest można sobie zdefiniować dowolne makra o dowolnych nazwach ;)

      Usuń
  40. Witam, mógłby mi ktoś wyjaśnić ,dlaczego w nocie katalogowej Atmela,
    sekcja I/O ports configuration ,w przykładowym pliku C mamy:

    DDRB = (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);

    natomiast w książce zawsze jest:


    DDRB |= (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);


    ,różni się |= ,ustawianiem bitu ,ale skąd ta różnica w nocie i książce???

    Wybacz Mirku ,że tak Ci truję ale

    w programowaniu ,tak jak w życiu ,najtrudniej znaleźć odpowiedź na najprostsze pytania :)

    OdpowiedzUsuń
    Odpowiedzi
    1. To nie jest trucie ;)

      Pomyśl sobie jeśli np miałeś już wcześniej w kodzie ustawiony rejestr DDRB tak:

      0b10000001

      czyli już najmłodszy i najstarszy bit są WYjściami, a teraz chciałbyś ustawić jeszcze drugi bit jako wyjście, więc co się stanie jak myślisz, gdy napiszesz TAK (przypadek I-szy)

      DDRB = (1<<DDB1);

      hmmm? .... ano ustawisz owszem drugi bit jako wyjście ale SKASUJESZ panie kochany te wcześniejsze bity i będą one wyzerowane.

      0b00000010

      Dlaczego ? zapraszam do poczytania rozdziału o przesunięciach bitowych - fajnie wyjaśnione w Bluebooku:

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      a teraz pomyśl sobie co się stanie gdy ten sam drugi bit ustawisz TAK (przypadek II-gi)

      DDRB |= (1<<DDB1);

      ;) tym razem panie kochany ustawisz bit drugi a inne bity pozostaną ustawione tak jak były wcześniej czyli otrzymasz

      0b10000011

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

      Spróbuj sobie to przeanalizować i odpowiedzieć dlaczego. Uwaga - to nie jest tak że w książce jest ŹLE a w PDF jest DOBRZE albo odwrotnie!.....

      Wszystko po prostu zależy kiedy i jak chcemy danej operacji użyć, a ja akurat stosuję częściej |= bo pomimo że to nadmiarowa operacja to pozwala unikać wielu błędów. I w tym jest rzecz.

      Usuń
  41. Używam do testów procesora Atiny2313 ,bo nie ma aż tak wielu rejestrów i jest w miarę przejrzysty na start.
    Migam sobie diodą na PB.0 ,ale nie o to chodzi.

    Mam pytanie ,podciągam cały portD (są to nie używane wejścia)

    PORTD |= 0b1111111;

    ,jednak po wpisaniu

    PORTD |= 0b11111111;

    lub PORTD = 0xFF

    kompilator nie woła o błąd ,a przecież poprawne powinno być

    PORTD |= 0b1111111;

    lub

    PORTD = 0x7F

    ,dlatego ,że PORTD7 (najstarszy bit jest zastrzeżony) reserved !!!

    ,czemu więc kompilator zezwala na wpisywanie do niego???

    OdpowiedzUsuń
    Odpowiedzi
    1. A czemu ma nie pozwalać? kolega wymyśla sobie problemy na wyrost niestety. Identyczna sytuacja jest w wielu innych prockach np w ATtiny13 nie ma całego PORTB, w ATmega8 nie ma całego PORTC

      a można spokojnie wpisywać wartości do rejestrów tych portów, a co to za problem ? Rejestry są a to że nie wszystkie bity mają bezpośrednie powiązanie z pinami (np pinami których nie ma) to już całkiem inna kwestia i na poziomie sprzętu a nie na poziomie programowego dostępu do rejestrów.
      Teraz jaśniej ?

      Usuń
  42. Dzień dobry, a ja mam takie pytanko. W jaki sposób na wejściu uC wykryć stan wysoki z wyjścia jakiegoś innego układu? Tzn jak zrobić żeby uC wykrywał nie zwarcie do masy, a pojawienie się sygnału 5V? Jeżeli podciągnę pull-up'a to stan wejścia mi się nie zmieni, jak nie podciągnę to wejście będzie "pływało". Jest na to jakaś rada? Pozdrawiam

    OdpowiedzUsuń
    Odpowiedzi
    1. Aleś pan teraz przekombinował ;) ZASTANÓW się sam chwileczkę ;) pomyśl

      co to w ogóle znaczy żeby uC wykrywał nie zwarcie do masy ?!

      toż to nonsens ... Prockiem możesz wykrywać każdy stan albo zero albo jeden z jakiegoś tam wyjścia. Dalej piszesz jeszcze gorsze rzeczy, że

      Jeśli podciągnę pull'upa to stan wejścia mi się nie zmieni. Panie kochany ... panie kochany - na prawdę przemyśl co piszesz. Co to znaczy wykrywać stan wysoki? Jeśli masz wysoki to wykryjesz wysoki a jeśli niski to NISKI

      po co podciągasz pullupa ? robisz to nie po to żeby wykrywać tylko po to jeśli wyjście jest np OC (czyli Open Collector) ... więc totalnie mieszasz pojęcia.

      Podobnie z klawiszem - możesz go podłączać i zwierać albo do VCC albo do GND ... a wtedy pullupa robisz albo do GND albo do VCC. A ty w głowie sobie jakby ustawiłeś że puulup jest do wykrywania stanu.

      Usuń
    2. Pull -up ustawiamy żeby nadać wejściu określony stan, żeby nie znajdowało się w stanie wysokiej impedancji, dobrze rozumiem? Tak jakby nadajemy mu stan wysoki. I mając przycisk który zwiera nam do masy, przy wciśniętym mamy 0, przy nie wciśniętym 1.
      A załóżmy że chcę mieć przycisk zwierający do VCC a nie do masy. Jak wtedy będzie wyglądał kod obsługi takiego przycisku? Może jest to oczywiste, ale ja nie wiem dlatego pytam. Pozdrawiam.

      Usuń
    3. Jak się uprzesz na klawisz zwierający wejście do VCC to robisz pullup do GND rozumiesz ?

      Usuń
    4. Już rozumiem. Właśnie tego nie wiedziałem. Dzięki.

      Usuń
  43. Witam czy istnieje jakiś sposób aby zapisywać konfiguracje bitów w systemie decymalnym.
    Wiem że istnieje sposób zapisu np.
    DDRD = 0b11000000 czy DDRD = 0xC0
    i czy da się to samo uzyskać pisząc DDRD = 192
    Może trzeba wgrać jakieś pliki nagłówkowe z pomocą #include
    Wcześniej pisałem programy w Bascomie i jestem przyzwyczajony do systemu decymalnego.

    OdpowiedzUsuń
    Odpowiedzi
    1. oczywiście że mozna zapisywać albo binarnie albo szesnastkowo albo decymalnie. Po choineczkę coś inkludować ? ;) wystarczy napisać DDRD = 192; w czym problem.

      Ja natomiast SZCZERZ ODRADZAM i to absolutnie w ogóle konfigurowanie pojedynczych bitów na takie sposoby, nie ważne czy decymalne, szesnastkowe czy binarne - bo to jest KOMPLETNE ABSOLUTNE MEGA NIEPOROZUMIENIE W C niestety :( .... w ten sposób będziesz długą ciągnął za sobą paskudne nawyki programowania z Bascoma i w końcu programowanie w C cię wkurzy - zobaczysz .... a później jak zrozumiesz dlaczego stosuje się przesunięcia bitowe - to to dojdziesz do wniosku że straciłeś KUPĘ CZASU ...

      Piszę o tym w swojej książce:
      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      nie wiem czy ją posiadasz - jeśli nie to gorąco polecam.

      Co do zaś zapisu dziesiętnego przy ustawianiu bitów to już jest ABSOLUTNE MEGA NIESZCZĘŚCIE, i aż się dziwię jak można sobie taką krzywdę samemu robić .... Pomyśl - jak ci powiem nagle - ustaw na JEDEN bit 6, 5, 2 i bit 1, to jaka to będzie liczba dziesiętnie ? powiesz to od razu ? bez przeliczania ? ;) wątpię

      To już 100000x razy lepiej zapisywać to szesnastkowo czy binarnie na początku jak się zaprzesz rękami i nogami

      jeśli mi na to odpowiesz, że trudno ci przeliczać te HEXy czy binrane wartości to panie kochany - widać że jeszcze nie oglądałeś TEGO PORADNIKA ;)

      https://www.youtube.com/watch?v=zVjjbQiEXxs

      i tego

      https://www.youtube.com/watch?v=kZ32DsDWzDg

      mówię ci KONIECZNIE obejrzyj - skorzystaj z TEJ METODY DLA KAŻDEGO a obiecuję ci - że będziesz w głowie (BEZ KARTKI PAPIERU, BEZ KALKULATORA) posługiwał się HEX'ami i binarkami ;)

      Usuń
  44. Witajcie,
    Nie wiem czy tutaj dostanę odpowiedź... Ale jak wygenerować dźwięk z buzzera (z generatorem) jak ma się go podpiętego pod port PD5? (dopisze jeszcze że na portach 6,7 mam przyciski)
    Próbowałem różnych sposób i nic

    OdpowiedzUsuń
    Odpowiedzi
    1. Na podstawie tego bloga można bez problemu to rozwiązać. Wystarczy dokładnie przeczytać (ze zrozumieniem) tekst i znać podstawy C.
      LED zamieniam na buzzer.
      Zakładam, że przyciski PD6 i PD7 zwierają do GND, buzzer do GND:

      #include
      #include

      main()
      {
      DDRD &= ~((1<<PD6) | (1<<PD7)); //ustalenie wejścia
      PORTD |= (1<<PD6) | (1<<PD7); //podciagnięcie do VCC

      DDRD |= (1<<PD5); // ustawienie wyjścia
      PORTD &= ~(1<<PD5);//ustawienie na wyjściu stanu 0

      while(1)
      {
      if (!(PIND & PD6 || PIND & PD7)) // jeśli wciśniesz przycisk
      {
      PORTD |= (1<<PD5); //buzzer da dźwięk
      _delay_ms(1000); // przez 1 sek
      PORTD &= ~(1<<PD5); // i ucichnie
      }
      }
      }

      Usuń
  45. Witam mam pewien problem z portami, napisałem sam prosty program,
    ale nie funkcjonuje tak jak trzeba, gdyż nie wyświetla mi się
    cyfra 2.
    /*
    * main.c
    *
    * Created on: 16 lis 2015
    * Author: oczek
    */
    #include
    #include
    int main(void)
    {
    DDRD = 0xFF; //binarnie 1111 1111 kiedrunek > wyjście




    while(1) //pętla nieskończona
    {



    PORTD = 0xCF; // Cyfra 1
    _delay_ms(500); // opóźnienie 500m
    PORTD = 0xC0; //Cyfra 2




    }

    }
    Bardzo proszę o pomoc.

    OdpowiedzUsuń
    Odpowiedzi
    1. Panie kolego do tego typu pytań (to tak na przyszłość) jest forum:

      www.forum.atnel.pl

      a tutaj zastanów się co się dzieje w twoim kodzie w pętli głównej:

      while(1) {

      ... ustaw stan X
      ... czekaj X ms
      ... ustaw stan Y

      }

      i co? jak to ma działać wg ciebie ? .... gdy ustawi się stan Y to co dalej się stanie ? jak myślisz ? widzisz już babola ?

      Usuń
    2. Czyli muszę zmienić stan X ?

      Usuń
    3. Panie jeszcze raz, Ustawiasz sobie stan X .... dajesz oczekiwanie np 1 sekundę - dzięki temu co widzisz swoimi oczami ? że te diody LED w stanie X świecą przez czas 1 sekundy tak ???

      No to gdy ten czas oczekiwania się skończy - ustawiasz nagle stan Y ... i co ???? zdążysz swoimi oczami zobaczyć że diody w stanie Y będą świecić ? ile czasu one będą ci świecić w tym stanie Y ???

      na to odpowiedz - zamiast pisać co musisz zmienić

      Usuń
  46. Okkk mam już błąd, dziękuje za pomoc. ;)

    OdpowiedzUsuń
  47. Ja stary asemblerowiec ale nie tej rodziny...
    Załóżmy, ze na PD0 i PD1 są RXD i TXD. Uruchomiony USART.
    Rozumiem, że o ustawienie kierunku 2 pinów już się nie martwię.
    Wpisany znak do wysłania, procek wysyła. Chcę inne bity
    tego portu (np. starszą czwórkę) natychmiast wykorzystać jako
    wyjścia. Co się stanie, gdy wyslę coś do portu np.
    PORTD = zmienna & 0xF0 ? Czy USART całkowicie "zabezpieczy"
    sobie oba piny czy się jednak pogryzą tzn. zakłócę transmisję?
    Podobnie gdy pomacham bitami np. PORTD |= 0x08 ?

    OdpowiedzUsuń
    Odpowiedzi
    1. Oczywiście, że moduł UART przejmie nad nimi pełną kontrolę i nic nie przeszkodzi w działaniu UARTA jeśli będzie się wystawiać jakieś stany logiczne na te piny

      Usuń
  48. Panie Mirku, Ja mam natomiast innego rodzaju problem.
    Od razu mówię, że to z moje GŁUPOTY i sam sobie jestem winien, ale może coś Pan zaradzi.
    Pracuję na Attiny2313 - przy okazji gratki za mkAVR, bo bardzo się przydaje :)

    Przejdę do problemu. Przegapiłem fakt, że wyjścia procka pracują tylko jako wyjścia/wejścia. Zrobiłem "projekt" na LED tak, aby do jednej nóżki były podpięte 2 diody. Czyli jestli wyjście, pali się jedna dioda jak wejście pali się druga - logiczne. Niestety zapomniałem, że będę kiedyś potrzebował wygasić wszystkie diody i tu jest problem.
    Teraz jest tak, że zawsze jakaś się zapali, a to z katodą a to anodą przy nóżce.

    Ma może Pan jakieś rozwiązanie? Od razu mówię, że wszystkie nóżki są zajęte i ne mam jeden luźnej {a raczej dwóch dla pinów B i pinów D}, aby tam ustawiać stany i ominąć inne diody tak, aby mogły być zgaszone.

    I proszę nie krzyczeć, bo się muszę przyznać że podłączyłem diody bezpośrednio pod MISO i MOSI - już wiem, że tak nie wolno i postaram się o jakiś bufor.

    OdpowiedzUsuń
    Odpowiedzi
    1. To zadanie dla hardorowca ;) ale fajnie że stawiasz sobie takie zadania ... to znaczy, że myślisz, że kombinujesz (jak każdy prawdziwy POLAK!) ... że się nie poddajesz i drążysz temat...

      Spróbuj zatem zrozumieć co to znaczy stan Hi-Z czyli tzw stan trzeci, stan nieustalony ... czyli ? ...

      czyli gdy ustawisz pin jako WEjście ale bez podciągnięcia do VCC. Wtedy nie ważne jaki będzie ten stan nieustalony ale nie będzie w stanie płynąć prąd, a więc żadna z diod nie będzie w stanie świecić ;)

      czujesz to ? ;)

      Usuń