Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.

wtorek, 1 marca 2011

Pierwszy program :-)

Autor: drzasiek
Redakcja: dondu

Drzaśkowy pamiętnik: Spis treści

Na końcu poprzedniej części artykułu pisałem o szybko zmontowanym i zaprogramowanym układzie. Zanim jednak to zrobiłem, zasięgnąłem nieco teorii, żeby nie zrobić jakiegoś głupiego błędu przy podłączeniu.

Korzystając z tej specjalistycznej wyszukiwarki, wpisując nazwę mikrokontrolera ATmega8 znalazłem jego dokumentację czyli datasheet (j.ang).

Nie miałem wcześniej „przyjemności” czytać tego typu dokumentacji, więc zanim połapałem gdzie, co szukać, to minęło trochę czasu. Pierwszą rzeczą jaką uważałem za konieczną do prawidłowego podłączenia było znalezienie rozmieszczenia pinów mikrokontrolera.

To akurat poszło szybko ponieważ stosowny rysunek znajduje się na samym początku :-)




No dobrze. Wiem już gdzie co jest, ale jak i co tutaj podłączyć? 

Skorzystanie z gotowego schematu przedstawionego w kursie jest proste, ale trzeba jeszcze zrozumieć co gdzie i dlaczego? W dokumentacji znalazłem więc odpowiedni rozdział, gdzie można znaleźć interesujące mnie wartości napięć i prądów, itd., a więc Electrical Characteristics:




Najbardziej istotna okazała się pierwsza tabelka w tym rozdziale, wraz z adnotacja obok. Zawiera ona maksymalne możliwe parametry zasilania, obciążenia prądowego oraz temperatury, jakie może wytrzymać ten mikrokontroler. Ich przekroczenie może doprowadzić do jego uszkodzenia.


Rys. Atmega8 - Najważniejsze parametry.



Wiedząc na czym stoję i korzystając nieco z dokumentacji stabilizatora 7805 wykonałem zasilacz 5V:




Teraz to wszystko można znaleźć też tutaj: Zasilanie mikrokontrolera



Zegar taktujący

Z dokumentacji mikrokontrolera dowiedziałem się, że fabrycznie jest on ustawiony za pomocą bitów konfiguracyjnych (j.ang: fuse bits) tak, że jest taktowany przez wewnętrzny zegar RC o częstotliwości 1MHz. Nie musiałem więc stosować zewnętrznego kwarcu.
Bity konfiguracyjne opisałem na mojej stronie: Fuse Bits




Projektuję schemat

Pozostało już tylko prawidłowo podłączyć zasilanie, programator, diody oraz przycisk a więc standardowy układ do ćwiczeń dla początkującego:




Pobierz schemat Eagle: schemat_uc.rar

Jak policzyłem rezystor przy diodach LED? Użyłem kalkulatora: Kalkulatory elektronika

Skąd te dodatkowe elementy (kondensatory i rezystory) po lewej stronie schematu?
Wszystkiego możesz dowiedzieć się tutaj: Minimalne podłączanie pinów


Pierwszy program

Przyszedł więc czas na napisanie programu. Przykładowy program z kursu niewiele mi mówił, napisałem więc bardzo prosty program mrugający naprzemiennie dwoma diodami.

//częstotliwość zegara
#define F_CPU 1000000L 

#include <avr/io.h>
#include <util/delay.h>

//definicja LED1 (do którego pinu podłączony LED1)
#define LED1 PB0 

//definicja LED2 (do którego pinu podłączony LED2) 
#define LED2 PB1 


// Pętla główna
void main(void)
{
    //########### I/O ###########
    DDRB  |= (1<<LED1) | (1<<LED2); //Ustawienie pinów sterujących diodami
                                         //jako wyjścia

    PORTB |= (1<<LED1);    //Ustawienie stanu wysokiego na wyjściu 
                                 //sterującym LED1 (stan początkowy)
     //##########################
    
   while (1) //Pętla główna
   {

        PORTB ^=(1<<LED1); //suma modulo 2 (XOR) stanu poprzedniego na porcie 
                             //pinu LED1 (zmiana stanu na przeciwny)

        PORTB ^=(1<<LED2); //suma modulo 2 (XOR) stanu poprzedniego na porcie 
                             //pinu LED2 (zmiana stanu na przeciwny)
        
        _delay_ms(1000); //opóźnienie 1000ms czyli 1s
    }
}
Pobierz projekt w AVR Studio: main1.rar

Oczywiście wyżej pokazany program jest to już wersja po kilkukrotnym poprawianiu, jak na początek przystało :-) , aż do otrzymania komunikatu:



Programowanie wg instrukcji z kursu, podłączenie prawidłowe a więc wszystko przebiegło pomyślnie, a dwie mrugające diody chyba nigdy wcześniej nie dawały mi tyle satysfakcji :-)

Następnie postanowiłem wykorzystać podłączony do atmegi przycisk do sterowania w jakiś sposób diodami. I tak na przykład powstał programik, który reagując na wciśnięty przycisk zatrzymywał mrugające diody:

//częstotliwość zegara
#define F_CPU 1000000L

#include <avr/io.h>
#include <util/delay.h>

//definicja LED1 (do którego pinu podłączony LED1)
#define LED1 PB0

//definicja LED2 (do którego pinu podłączony LED2)
#define LED2 PB1

//definicja KLAWISZ (do którego pinu podłączony KLAWISZ)  
#define KLAWISZ PC0              

void main(void)
{
    //########### I/O ###########
    DDRB  |= (1<<LED1) | (1<<LED2); //Ustawienie pinów sterujących diodami
                                               // jako wyjścia
    PORTB |= (1<<LED1); //Ustawienie stanu wysokiego na wyjściu sterującym LED1 
                               //(stan początkowy)
    
    DDRC  &=~ (1<<KLAWISZ); //Ustawienie pinu klawisza jako wejście 
    PORTC |=  (1<<KLAWISZ); //włączenie rezystora podciągającego tzw. Pull_up
    //##########################
    
   while (1) //Pętla główna
   {
      if(PINC & (1<<KLAWISZ))//jeśli klawisz nie wciśniety
      {
        PORTB ^=(1<<LED1); //suma modulo 2 (XOR) stanu poprzedniego 
                           //na porcie i pinu LED1 (zmiana stanu na przeciwny)

        PORTB ^=(1<<LED2); //suma modulo 2 (XOR) stanu poprzedniego na porcie 
                          //pinu LED2 (zmiana stanu na przeciwny)

        _delay_ms(1000); //opóźnienie 1 s
      }
        
    }
}

Pobierz projekt w AVR Studio: main2.rar

Takich programików powstało kilka, trudno je wszystkie tutaj przytaczać. Ale trzeba się rozwijać, więc poszedłem dalej, wykorzystując Timer do mrugania diodami. Ale o tym w kolejnej części mojego pamiętnika.

Drzaśkowy pamiętnik: Spis treści

Autor: drzasiek
Redakcja: dondu

Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

31 komentarzy:

  1. Mam pytanie. Czemu za diodą led jest rezystor 1k omowy? Po pierwsze, to chciałbym zaznaczyć, że nie ogarniam tak 99% ; q. Patrzę w data sheety atmegi8, napięcie wychodzące - 5V, natężenie - 20mA. Liczę, liczę, prawo Ohma, Kirchhoffa - no wychodzi rezystor 100 omowy jak ulał. A proponujecie tysiąc. Wrzucam dane w circuit simulator - no 1k nie pasuje, dioda (3V) się nie świeci. Pomocy ; ).

    OdpowiedzUsuń
  2. Zanim Drzasiek odpowie zaglądnij do menu KALKULATORY ELEKTRONIKA. Znajdziesz tam kalkulator LEDów.

    Być może Drzasiek wykorzystywał LEDy o wysokiej jasności świecenia, które przy znacznie mniejszych prądach świecą bardzo jasno.

    OdpowiedzUsuń
  3. Szanowny Anonimowy
    To, co policzyłeś zależy przede wszystkim od tego co i jak liczyłeś :) Rezystor w szeregu z diodą daje się po to, by ograniczyć prąd diody. Jednak dioda w szeregu z rezystorem to nie to samo co sam rezystor, więc nie możesz liczyć rezystora do diody podstawiając do wzoru z prawa Ohma jedynie napięcie zasilania oraz oczekiwany prąd. Ważnym parametrem jest spadek napięcia na diodzie oraz maksymalny prąd diody. Parametry te musisz odnaleźć w dokumentacji do diody, lub jeśli jej nie masz to przyjąć jakieś bezpieczne wartości. Spadek napięcia zależy od materiału, a więc od koloru świecenia diody. Można to sprawdzić nieco googlując, jaki kolor to jaki spadek napięcia. Przyjmuje się, że 20 mA jest prądem bezpiecznym dla większości diod, nie znaczy to jednak, że należy na siłę starać się aby płynął prąd 20 mA, gdyż większość LEDów świeci się już przy kilku mA. Wszystko zależy od wymagań projektu, do testów nie ma sensu jechać na maksymalnych obrotach.

    A więc znając spadek napięcia na diodzie, odejmujesz go od napięcia zasilania.
    Np:

    U = Ucc - Ud
    U = 5 V - 2.3V
    U = 2.7V

    Następnie otrzymaną wartość dzielisz przez oczekiwany prąd który ma popłynąć przez diodę (do obliczenia podajemy w amperach) i otrzymujesz wartość rezystancji, którą należy wpiąć w szereg z diodą LED.
    Np:

    R = U / Id
    R = 2.7 V / 0.005 A
    R = 540 [Omów]

    OdpowiedzUsuń
  4. Aaaa! Teraz już wszystko jasne i zupełnie inne liczenie ; ). Dzięki wielkie za pomoc!

    OdpowiedzUsuń
  5. Witam! Jako początkujący mam parę pytań, wiem może ,,gópie'', ale chciałbym się dowiedzieć:
    1. Zamiast Atmegi8 mam pod ręką Atmege8A - dobrze widzę, że w Dokumentacji pobór prądu wynosi 3.6mA? Myślałem, że taki procek pobiera więcej.
    2. Czy zasilacz od starego Siemensa ok 7,75V i 150mA starczy bezproblemu na zasilenie tego układu, a w przyszłości trochę bardziej rozbudowanych? Wiem, że LED pobiera ok 20mA co daje nam 40mA + procek, czy się mylę?
    3. Czy Programując płytkę odłączyć zasilacz, mam programator USBasp?

    OdpowiedzUsuń
  6. Witaj!

    Ad. 1
    Nie podałeś dla jakiego napięcia zasilania, częstotliwości zegara i trybu pracy tę wartość odczytałeś, więc trudno odpowiedzieć jednoznacznie, ale prawdopodobnie nie pomyliłeś się.

    Ad.2
    Kombinujesz prawidłowo, czyli wystarczy. Dodam tylko, że LED wcale nie musi być zasilany 20mA. Przy 10mA może świecić niewiele gorzej niż przy 20mA. Wszystko zależy od zastosowanego LED. Są takie, które mają bardzo dużą jasność przy prądzie rzędu 2mA.

    Ad. 3
    Jeżeli masz osobne zasilanie i nie wykorzystujesz zasilania z USBasp, to nie musisz odłączać. Ważne jest, by masy były połączone. Innymi słowy nie powinno się łączyć równolegle dwóch źródeł zasilania.

    OdpowiedzUsuń
  7. Witam

    Mam pytanie o 2 miejsca w kodzie:

    1. DDRB |= (1<<LED1) | (1<<LED2)

    DDRB to rejestr 8 bitowy w którym się ustawia czy porty PB0 do PB7 mają być wyjściami czy wejściami, natomiast LED1 i LED2 wskazująna konkretne wyprowadzenia PB0 i PB1 czyli przedstawiają raczej po 1 bicie. W związku z tym zastanawiam się czy w trakcie funkcji OR nie jest LED1 i LED2 przedstawiane jako 8 bitów z ustawianymi wartościami tylko na pozycjach odpowiadającymi wyprowadzeniom PB0 i PB1.

    2. if(PINC & (1<<KLAWISZ))

    Jest to warunek na klawisz nie wciśnięty, jak ma wyglądać warunek na wciśnięty przycisk??

    OdpowiedzUsuń
  8. 1. Nie wiem, czy jest już późno i nie rozumiem pytania, albo po prostu je mało sprecyzowałeś.
    Ale spróbuje zgadnąć o co mogło Ci chodzić. Rejestr DDRB jest 8 bitowy, każdy bit odpowiada za kierunek pracy danego pinu w porcie. Jeśli chcesz, aby rejestr/zmienna została załadowana tylko nową wartością, dajesz po jej nazwie znak = , np:

    DDRB = 4;
    lub analogiczny zapis:
    DDRB = (1<<2);

    Ale jeśli chcesz, aby wartość, która była w rejestrze/zmiennej zapisana nie uległa skasowaniu, a jedynie chcesz ustawić/skasować dany bit to możesz zapisać to w takiej postaci:

    DDRB = DDRB | (1<<2);

    Wtedy wartość rejestru będzie równa DDRB "lub" 00000100.
    Język C umożliwia skrócony zapis takiego typu, czyli np. zapis w postaci:

    DDRB = DDRB | 1;

    można zapisać tak:

    DDRB |= 1;

    Podobnie z innymi operacjami, np jeśli do zmiennej licznik chcemy dodać wartość 2, możemy napisać to w taki sposób:

    liczkik = licznik + 2;

    lub w sposób skrócony:

    licznik += 2;

    2. Zaprzeczenie tego, co jest w nawiasie, czyli:

    if(!(PINC & (1<<KLAWISZ)))

    lub sposób bardziej jasny:

    if((PINC & (1<<KLAWISZ))==0)

    OdpowiedzUsuń
  9. Ten komentarz został usunięty przez autora.

    OdpowiedzUsuń
  10. Witam, jaka wersja AVR studio jest wykorzystywana do kompilowania programów ? Jak należy zmodyfikować program by ruszył pod attiny13 ? Czy problem może leżeć w rejestrze i/o ? Błąd jaki mi wyrzuca to ../Asd.c:15:10: warning: return type of 'main' is not 'int'
    To moje pierwsze kroki w tym języku, dziękuję za wyrozumiałość.

    OdpowiedzUsuń
  11. To nie jest błąd tylko ostrzeżenie. main ma prototyp int main(), nie void main(). Często, tak jak w powyższych przykładach pisze się void, bo main w AVR nigdy się nie kończy, więc zwracanie wyniku nie ma sensu. To ostrzeżenie można zignorować, lub napisać dla spokoju int main. Powyższe przykłądy skompilujesz w czymkolwiek, musisz tylko dostosować nazwy rejestrów do tych, które są dostępne w użytym procku.

    OdpowiedzUsuń
  12. Witam
    Na początek przedstawię swój fragment:
    #define LED1 0x02
    #define LED2 0x04
    #define PRZ2 0x08

    int main(void)
    {
    // Ustawianie wyjść
    DDRB |= LED1;
    DDRB |= LED2;

    // Włączanie wyjść
    PORTB |= LED1;

    //Rezystory podciągające
    PORTB |= PRZ2;

    while (1) {
    if ((PINB&PRZ2)) PORTB^=LED1|LED2;
    }
    Jako, że dopiero raczkuję z AVR (m.in. dzięki Wam idzie to całkiem przyjemnie) mam kilka pytań:
    1) DDRB |= (1<<LED1) | (1<<LED2);
    podzieliłem to na dwie instrukcje, wynik: objętość kodu wynikowego zmniejszona o 2 bajty (1 rozkaz?) - jakie są tego konsekwencje? Chodzi mi o to, czy zmniejszając kod nie dałem procesorowi więcej obliczeń (dwa polecenia), gdzie wg. poradnika jest to w jednym poleceniu - a dokładnie: jaka jest różnica w ASM pomiędzy tymi dwoma sposobami?
    2) if(PINC & (1<<KLAWISZ))
    zmieniłem to ze względu na stosowanie liczb hex - jednak aby to działało musiałem zastosować podwójny nawias - dlaczego? Czyżby operacja AND zwracała jakiś wynik (który jest brany pod uwagę przy pojedynczym nawiasie)?
    Stosuję AtmelStudio + wbudowany symulator na ATTiny 13. Ze względu właśnie na wbudowany symulator nie zastosowałem delay.

    Dzięki za poradniki - nie tylko ja, ale pewnie wiele osób z tego skorzysta :)

    Pozdrawiam
    codedigger

    OdpowiedzUsuń
  13. Witaj,

    Cieszymy się, że artykuły są przydatne :-)


    PYTANIE 1
    ----------
    W Atmel Studio możesz podglądać kod assemblera generowany przez kompilator stąd możesz samemu sprawdzić, różnicę w wygenerowanym kodzie.

    W pierwszym przypadku:

    // Ustawianie wyjść
    DDRB |= LED1;
    DDRB |= LED2;

    realizujesz osobno dwie operacje ustawiania bitów dlatego wygenerowany kod wygląda dla tego fragmentu tak:

    SBI 0x17,1 Set bit in I/O register
    SBI 0x17,2 Set bit in I/O register

    W drugim przypadku w jednym rozkazie ustawiasz oba piny na raz:

    DDRB |= (1<<LED1) | (1<<LED2);

    dlatego kod wygląda tak:

    IN R24,0x17 In from I/O location
    ORI R24,0x14 Logical OR with immediate
    OUT 0x17,R24 Out to I/O location

    Za to działanie odpowiadają preprocesor i kompilator. Najpierw preprocesor na etapie przed kompilacją oblicza wartość wyrażenia:

    (1<<LED1) | (1<<LED2)

    i otrzymuje wynik:

    0x14

    a następnie kompilator realizuje algorytm dodania logicznego tej wartości do rejestru DDRB (kod wynikowy podałem wyżej).

    Teraz widzisz skąd różnica w ilości kodu, a w konsekwencji czasu jego realizacji.
    Czy w tym zakresie wszystko jasne?

    Pytanie drugie wyjaśnię w następnym komentarzu.

    OdpowiedzUsuń
  14. PYTANIE 2


    Na początek dobra rada - nie stosuj liczb hex, tylko definicje pinów. To kolosalna zaleta, z kilku powodów:
    - nie pomylisz bitów,
    - kod łatwiej analizować po czasie, gdy się do niego wraca,
    - osoba sprawdzająca ma ułatwione zadanie.


    W Twoim przypadku podwójne nawiasy nie mają znaczenia. kod wygenerowany dla

    if ((PINB&PRZ2)) PORTB^=LED1|LED2;

    jest taki

    LDI R25,0x06 Load immediate
    SBIS 0x16,3 Skip if bit in I/O register set
    RJMP PC-0x0001 Relative jump
    IN R24,0x18 In from I/O location
    EOR R24,R25 Exclusive OR
    OUT 0x18,R24 Out to I/O location
    RJMP PC-0x0005 Relative jump

    a dla:

    if (PINB&PRZ2) PORTB^=LED1|LED2;

    jest dokładnie taki sam:

    LDI R25,0x06 Load immediate
    SBIS 0x16,3 Skip if bit in I/O register set
    RJMP PC-0x0001 Relative jump
    IN R24,0x18 In from I/O location
    EOR R24,R25 Exclusive OR
    OUT 0x18,R24 Out to I/O location
    RJMP PC-0x0005 Relative jump


    Proponuję potestować w kompilatorze CManiak na następującym kodzie:

    #include <stdio.h>

    int main(void){

    #define PB3 3
    #define KLAWISZ PB3

    //symulujemy, że pin PB3 ma stan wysoki
    unsigned char PINB = 0x08;

    printf( "PINB = %d \n", PINB);
    printf( "KLAWISZ = %d \n", KLAWISZ);
    printf( "(PINB & KLAWISZ) = %d \n", (PINB & KLAWISZ));
    printf( "(1<<KLAWISZ) = %d \n", (1<<KLAWISZ));
    printf( "(PINB & (1<<KLAWISZ)) = %d \n\n", (PINB & (1<<KLAWISZ)));

    if(PINB & KLAWISZ) printf("Warunek 1 spełniony. \n");

    if(PINB & (1<<KLAWISZ)) printf("Warunek 2 spełniony. \n");


    return 0;
    }


    Podsumowując oba pytania:
    1. Poczytaj o preprocesorze.
    2. Warto poczytać manual kompilatora GCC, chociażby pobieżnie, ale po to by mieć pojęcie, co w nim można znaleźć.

    OdpowiedzUsuń
  15. Mam pytanie odnośnie tego zapisu:

    1. DDRB |= (1<<LED1) | (1<<LED2)

    Jak mam rozumieć "<<" bo to raczej nie jest przesunięcie w lewo. Gdzie znajdę przystępne informacje na temat definicji pinów? Na razie rozumiem ustawianie pinów za pomocą liczb hex. Z góry dziękuje za odpowiedź.

    OdpowiedzUsuń
  16. << to przesunięcie w lewo: Przesuwanie bitow w lewo

    Definicje znajdziesz w datasheet, ponieważ odpowiadają one nazwom pinów, rejestrów i ich bitów. Możesz także szukać w plikach kompilatora np. pliku iom8.h który zawiera definicja dla ATmega8.

    OdpowiedzUsuń
  17. Witam!
    Skoro << to przesunięcie w lewo to czemu (1<>LED1) daje wartość logiczną zero? Mógłbym prosić o dokładniejsze napisanie jak to działa?

    OdpowiedzUsuń
  18. Witam,
    Potrzebuję pomocy odnośnie ustawianie portów:
    DDRB |= (1<<LED1)
    Wcześniej używałem przypisanie heksadecymalnie DDRB = 0x03
    Rozumiem przesuniecie bitowe jak i dodawanie OR | ale razem
    kompletnie nie rozumiem. Zmienna LED1 jest konkretnym portem,
    załóżmy że np PD0 czyli przesuwamy PD0 o 1 bit w lewo?.?.?.
    I co tam robi dodawanie bitowe | ?
    Donu Why? ;]
    Pozdrawiam

    OdpowiedzUsuń
    Odpowiedzi
    1. Witaj,

      Brakuje Ci wiedzy co kryje się pod zdefiniowanym PD0. Aby to sprawdzić sięgasz do pliku nagłówkowego z definicjami dla Twojego mikrokontrolera. W przypadku ATmega8 jest to plik iom8.h.

      Znajdujesz w nim:

      /* PORTD */
      #define PD7 7
      #define PD6 6
      #define PD5 5
      #define PD4 4
      #define PD3 3
      #define PD2 2
      #define PD1 1
      #define PD0 0

      czyli w czasie kompilacji pod PD0 podstawiane jest zero, czyli de facto otrzymujesz:

      DDRB |= (1<<0)

      a to oznacza, że przesuniemy jedynkę o zero pozycji w lewo, czyli nadal otrzymamy jedynkę, a w zapisie binarnym 0b00000001

      Spróbuj teraz pokazać jak to będzie w przypadku PD5.

      Gdy odpowiesz, to ja dodam program do wypróbowania w CManiaku i obserwowania wyniku.

      Usuń
    2. Czyli tak,
      Mamy 8 bitowy rejestr DDRD 0b00000000
      z całej siły chcę ustawić kierunek wyjściowy na PD5

      DDRB |= (1<<5) czyli tak 0b00010000 lub 0b00100000 ???

      wiem że przesuwam ...... o 5 bitów w lewo
      lecz problem polega na tym że nie wiem co.
      Są 2 opcje :

      1. to po prosty bit '1'.
      2. Jest to 8 bitowy PD1 0b00000010

      no i nie wiem po co to dodawanie |

      Musisz mi wybaczyć mój brak wiedzy ale wybrałem złą książkę
      "AVR & ARM7..." z góry dziękuję za Zainteresowanie i bezinteresowną Pomoc ;]
      Pozdrawiam

      Usuń
    3. Czytaj wolniej lub kilka razy ponieważ napisałem cyt.
      "DDRB |= (1<<0)
      a to oznacza, że przesuniemy jedynkę o zero pozycji w lewo ..."

      Czyli w Twoim przypadku:
      (1<<5) daje wynik 0b00100000


      Poniżej obiecany program do sprawdzenia i próbowania w CManiaku:

      unsigned char DDRD; //symulujemy rejestr DDRD

      /* PORTD */
      #define PD7 7
      #define PD6 6
      #define PD5 5
      #define PD4 4
      #define PD3 3
      #define PD2 2
      #define PD1 1
      #define PD0 0

      //funkcja konwersji liczby na ciąg znaków reprezentacji binarnej
      const char *byte_to_binary(int x){
      //wykorzystuje nagłówek string.h
      int z; static char b[9]; b[0] = '\0'; for (z = 128; z > 0; z >>= 1){strcat(b, ((x & z) == z) ? "1" : "0");}; return b;
      }


      int main(void) {

      //ustaw w DDRD bit PD0
      DDRD |= (1<<PD0);
      printf("%s\n", byte_to_binary(DDRD)); //pokaż DDRD

      //ustaw dodatkowo bit PD5
      DDRD |= (1<<PD5);
      printf("%s\n", byte_to_binary(DDRD)); //pokaż DDRD


      //podmień nową zawartość DDRD ustawiając od razu bity PD3, PD4 i PD7
      DDRD = (1<<PD7) | (1<<PD4) | (1<<PD3);
      printf("%s\n", byte_to_binary(DDRD)); //pokaż DDRD

      return 0;
      }

      Usuń
    4. Dzięki Dondu!!!
      Teraz ogarnąłem... takie banalne a zepsuło mi parę dobrych litrów krwi ;)
      Jeszcze raz Dziękuję!

      Usuń
  19. Hej,
    na schemacie z układem do podłączenia przy pinie 1, PC6(/RESET), widoczne kółko to oznaczenie negacji sygnału? Trzeba jakis dodatkowy układ negujący zastosować czy połączenie VCC przez R10k jest jakby negacją sygnału? a moze to oznaceznie czegos zupelnie innego?
    Nie wiem jak to rozumieć, z góry dzięki
    Przemek

    OdpowiedzUsuń
    Odpowiedzi
    1. Witaj.

      Tak, kółko oznacza negację. Pin RESET jest wejściem. Jeżeli nie byłoby negacji, oznaczało by to, że podanie jedynki (stan wysoki, zwarcie do Vcc, np. 5V) na ten pin spowodowałoby zresetowanie mikrokontrolera.

      Ponieważ jednak jest negacja na tym pinie oznacza to, że zresetowanie mikrokontrolera następuje przy podaniu zera (stan niski, czyli zwarcie do masy).

      Dlatego też normalnie pin ten jest podłączony przez rezystor do Vcc, by nie nastąpiło przypadkowe zresetowanie mikrokontrolera.

      Usuń
  20. u mnie w Atmel Studio 6 (ver.: 6.1.2730)
    trzeba było zamienić void main(void)
    na int main(void)
    i dodać na końcu return 0; bo inaczej program się nie budował.

    OdpowiedzUsuń
  21. Witam, gdybym chciał aby 3 LED mrugały jedna po drugiej? Męczę się z tym dłuższy czas i już nie mam pomysłów.Zadeklarowałem 3 diodę na PB2 dodałem instrukcję do pętli i mrugają raz jedna raz dwie... Pozdrawiam



    #define F_CPU 1000000L

    #include
    #include


    #define LED1 PB0
    #define LED2 PB1
    #define LED3 PB2




    void main(void)
    {
    //########### I/O ###########
    DDRB |= (1<<LED1) | (1<<LED2) (1<<LED3);

    PORTB |= (1<<LED1);
    //##########################

    while (1)
    {

    PORTB ^=(1<<LED1);
    PORTB ^=(1<<LED2);
    PORTB ^=(1<<LED3);
    _delay_ms(1000);
    }
    }

    OdpowiedzUsuń
    Odpowiedzi
    1. Musimy jednak przejść na forum, bo system ucina znaki i kod staje się nieczytelny. Utwórz proszę więc nowy temat w dziale: Mikrokontrolery AVR

      i wklej tutaj link do tematu na forum, gdy już go utworzysz.

      Usuń
    2. http://www.elektroda.pl/rtvforum/viewtopic.php?p=13219331#13219331
      Pozdrawiam

      Usuń
    3. Dodam tylko klikalny link, gdzie rozwiązaliśmy Twój problem: Atmega8 - Mruganie 3 LED

      Usuń
  22. Siemka dlaczego pobrany od cb program "main2" po wgraniu na atmega8 zajmuje tylko 112 bajtów a po skopiowaniu tego co napisałeś i kompilacji w programie Code Blocks to samo zajmuje 3218 bajtów

    OdpowiedzUsuń
    Odpowiedzi
    1. CodeBlocks - to już prehistoria :D

      Może w programie używasz liczb zmiennoprzecinkowydh (typy Double lub float)?

      Poza tym musisz mieć włączoną optymalizację - masz?

      Usuń

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.