Mikrokontrolery - Jak zacząć?

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

sobota, 26 marca 2011

Symulator mikrokontrolerów AVR pomaga szybko znaleźć błędy


Autor: Dondu

AVR Atmel Studio - Symulator bardzo pomaga odnaleźć błąd.
Bardzo często początkujący trafiają na sugestie wykorzystania niestandardowych narzędzi programistycznych pozwalających na pisanie programów (np. Eclipse) lub starych narzędzi typu WinAVR.

I choć niektóre z nich jako zwykłe edytory kodu programu są przyzwoite, o tyle nie posiadają dodatkowych funkcji bardzo istotnych w szczególności dla początkującego. Jedną z takich funkcji jest symulator mikrokontrolerów AVR dostępny w oryginalnych narzędziach AVR Studio i Atmel Studio.

Symulator jest bardzo pożytecznym narzędziem ułatwiającym znalezienie błędów w pisanym programie. Ma on olbrzymie możliwości symulowania pracy mikrokontrolera. Niniejszy artykuł jest jedynie zachętą do wykorzystania tego narzędzia, które oszczędza czas i zmniejsza frustrację początkujących, dodatkowo pokazując jak mikrokontroler realizuje powierzone mu zadania.


Przykład problemu

Na forum pojawił się wpis pod tytułem Atmega8 - Czy mam uszkodzony uC?

Program (po usunięciu zbędnych linijek) wyglądał tak (formatowanie widoczne jak w temacie na forum):

#include <avr/io.h>
 
int main(void)
{
DDRD = 0xFF;
DDRC = 0x00;
PORTC = 0x0f;
 
while(1)
      if(!(PINC&(1<<PC4))) PORTD = (1<<PD0);
          if(!(PINC&(1<<PC2))) PORTD = (1<<PD2);
  

     if(!(PINC&(1<<PC3))) PORTD = (1<<PD1);
  }
 

Autor nie mógł znaleźć przyczyny takiego zachowania programu:


polarczn
Wgrywam ten kod i ciągle pali mi się 1 dioda led. Dlaczego?


Podczas kompilacji program nie generował żadnych warningów (ostrzeżeń), ani błędów:


AVR Memory Usage
----------------
Device: atmega8

Program: 80 bytes (1.0% Full)
(.text + .data + .bootloader)

Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)

Build succeeded with 0 Warnings...


W związku z tym autor miał utrudnioną sytuację, by błąd odnaleźć. W takiej sytuacji idealnie pomocnym narzędziem jest właśnie symulator.

Poniżej króciutkie filmy pokazujące wykorzystanie symulatora do określenia przyczyn niepoprawnego działania powyższego programu w środowiskach AVR Studio 4.18 i Atmel Studio.

Program został minimalnie inaczej sformatowany - dodałem Enter po pierwszym warunku, by móc zaobserwować działanie symulatora i być pewnym, kiedy symulator realizuje sprawdzanie warunku, a kiedy wykonuje warunek (gdy jest on spełniony).

Jeżeli bym tego nie zrobił, to podczas pracy symulatora nie byłoby widać co dokładnie w linii z warunkiem symulator wykonuje.

Oddzieliłem także Enterem dwa pozostałe warunki, by łatwiej było obserwować wykonywanie programu.


Program nadal jest oczywiście taki sam, a na potrzeby symulacji wygląda więc następująco:

#include <avr/io.h>
 
int main(void)
{
    DDRD = 0xFF;
    DDRC = 0x00;
    PORTC = 0x0f;
 
    while(1)
        if(!(PINC & (1<<PC4)))    
            PORTD = (1<<PD0);
 
    if(!(PINC & (1<<PC2))) PORTD = (1<<PD2);
    if(!(PINC & (1<<PC3))) PORTD = (1<<PD1);
}
 


AVR Studio 4.18





... i to samo, ale w Atmel Studio 




Jak widzisz bez programowania mikrokontrolera, bardzo szybko można się zorientować jak działa program stwierdzając, że nie wykonuje się znaczna jego część, czyli dwa ostatnie warunki if().

Na filmach zapomniałem pokazać jak stwierdzić, że dioda LED świeci. Wystarczy po prostu podglądać stan odpowiednich pinów portu D (kliknij PORTD), do którego są podłączone diody.


Czy widzisz już na czym polega błąd w programie?

Znamy już skutki i teraz należy ustalić, co w programie powoduje działanie inne niż autor się spodziewał, a przyczyna jest prosta: Brak nawiasów klamrowych określających, która część programu ma być realizowana w pętli głównej while().

Ponieważ autor chciał wykonać w pętli wszystkie trzy warunki, powinien był dodać nawiasy klamrowe w następujący sposób:

Przykład 3 (w kompilatorze)
#include <avr/io.h>
 
int main(void)
{
   DDRD = 0xFF;
   DDRC = 0x00;
   PORTC = 0x0f;
 
   while(1)
   {
       if(!(PINC&(1<<PC4))) PORTD = (1<<PD0);
       if(!(PINC&(1<<PC2))) PORTD = (1<<PD2);
       if(!(PINC&(1<<PC3))) PORTD = (1<<PD1);
   }
}
 

Zauważ jak poprawnie, a przez to czytelnie jest sformatowany powyższy kod programu. Takie poprawne formatowanie znacznie ułatwia szybkie wzrokowe odnalezienie błędu.

Tematy związane z nawiasami klamrowymi dot. tego przypadku:


Prawdopodobny drugi błąd

Czytelnik ukrywający się pod Anonimowy, w pierwszym komentarzu do tego artykułu słusznie zauważył, że program włącza rezystory pull-up tylko dla przycisków na pinach od PC0 do PC3, ale pin PC4 pozostawia bez włączonego pull-up.

Jeżeli więc autor tematu nie podłączył zewnętrznego rezystora, to przycisk na pinie wejściowym PC4 nie będzie pracować prawidłowo, ponieważ nic nie wymusi na nim stanu wysokiego podczas puszczenia przycisku. Jeżeli tego nie zrobił to symulator nie jest w stanie tego przewidzieć, a my na filmiku symulowaliśmy za pomocą PC4 prawidłowe działanie przycisku.

Ale problem ten można było stwierdzić już na etapie wykonywania instrukcji:

PORTC = 0x0f;

zaznaczonej czerwoną strzałką:


AVR Studio - Symulator - stan symulacji podczas wykonywania programu.
Stan po wykonaniu ustawienia portu C.


Powyższy ekran przedstawia stan po wykonaniu powyższej instrukcji, kiedy to symulator zatrzymał się na pierwszym warunku (żółta strzałka). Możemy przyglądnąć się stanowi rejestrów odpowiedzialnych za piny portu C.

AVR Studio - Symulator - rejestry portu C.
Rejestry portu C.


Rejestr DDRC odpowiedzialny na kierunki pinów portu C ustawiony jest na zera (jasne kwadraty), czyli wszystkie piny są wejściami.

W przypadku rejestru PORTC odpowiedzialnego (dla pinów wejściowych) za włączenie rezystorów pull-up możemy zauważyć, że jeżeli autor planował włączyć rezystor pull-up na pinie PC4, to pin ten w rejestrze PORTC powinien być ustawiony na jedynkę (ciemny kwadrat) tak ja piny PC0-PC3. Jak widać tak się nie stało, co od razu powinno zostać przez autora wychwycone, a program poprawiony, czyli:

PORTC = 0x1f;

Powyższy błąd nie zmienia podstawowego problemu opisanego w niniejszym artykule i na filmach dot. pozostałych przycisków PC2 i PC3.



Inne funkcjonalności symulatora

Oprócz prostego sprawdzania stanu rejestrów oraz dokonywania zmian stanu pinów wejściowych i wyjściowych, symulator ma olbrzymie możliwości. Dlatego warto przyglądnąć się jego okienku I/O View:


AVR Studio 4.18 - Okienko z możliwościami symulacji pracy mikrokontrolera.
AVR Studio 4.18 

... i analogicznie w przypadku Atmel Studio.


Wykorzystujcie oryginalne narzędzia producentów mikrokontrolerów tym bardziej, gdy są darmowe. Naprawdę warto!!!




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

20 komentarzy:

  1. Hm ciekawostka. Nigdy tego nie uzywalem. Ale i tak na tym etapie nie zostal wykryty jeszcze jeden maly blad programowy. Chodzi o pin PC4-nie ma on podciagania do plusa zasilania i program moglby troche wariowac przez ten jeden przycisk;)

    OdpowiedzUsuń
    Odpowiedzi
    1. Słuszna uwaga, ponieważ autor nie dodawał zewnętrznych rezystorów pull-up. Tego niestety nawet symulator nie wykryje. :-)

      Usuń
    2. Dopisałem Twoją uwagę na forum: tutaj

      Usuń
    3. Dodałem opis tego potencjalnego błędu - dziękuję za jego wychwycenie :-)

      Usuń
  2. Jacku dziękuję ci bardzo za ten artykuł wskazówkę. Nawet nie zauważyłem, że taki symulator istnieje. Zerknąłem na okienko, którego screen dałeś na końcu i jestem w szoku! Tam można nawet przerwania symulować - REWELACJA!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    OdpowiedzUsuń
    Odpowiedzi
    1. Owszem można i to z każdego wewnętrznego układu danego mikrokontrolera.
      A to nie wszystko - warto tam pogrzebać nieco :-)

      Usuń
  3. Ten komentarz został usunięty przez administratora bloga.

    OdpowiedzUsuń
    Odpowiedzi
    1. Bartek. Czytałeś co napisałem czerwonym tekstem poniżej?

      Usuń
  4. Tym artykułem Dondu zachęciłeś mnie do przetestowania Atmel Studio (dotychczas używałem tylko Eclipse)

    OdpowiedzUsuń
  5. Jak się śledzi zmienne?

    OdpowiedzUsuń
    Odpowiedzi
    1. Menu View > Watch. Otworzy się okienko Watch, gdzie w kolumnie Name wpisujesz nazwę zmiennej i przyciskasz Enter.

      Usuń
  6. Używam symulatora od paru lat odkąd zacząłem z AVR. Najpierw AVR Studio, a teraz Atmel Studio. Muszę powiedzieć, że o ile teraz rzadko wykorzystuję (poziom już jakiś mam), to na początku symulator był podstawą mojej nauki. Wielokrotnie już miałem zadawać pytanie na Elce, ale gdy odpaliłem symulator, to z reguły szybko dochodziłem do rozwiązania problemu. Symulator oszczędził mi masę czasu. Tak swoją drogą, to szkoda, że dopiero teraz o tym piszesz, gdy już niestandardowe narzędzia rozpleniły się na dobre. Ale lepiej późno niż wcale :) Pozdrawiam ekipę!

    OdpowiedzUsuń
    Odpowiedzi
    1. Tak powinien był się pojawić wcześniej. Ale z drugiej strony, to ciekawość grzebania w menu programu który się używa powinna była od razu doprowadzić każdego, do odnalezienia symulatora, stąd nie było ciśnienia w zakresie pisania artykułu na ten temat.

      Argument z rozplenieniem się nieoryginalnych środowisk jest trafiony :)

      Również pozdrawiamy.
      Ekipa

      Usuń
  7. A ja się kiedyś męczyłem i ręcznie liczyłem ilość taktów funkcji przerwania, a wystarczy ją odpalić w symulatorze.

    OdpowiedzUsuń
  8. powinniście załączyć jeszcze link do tego filmiku atmela:
    http://www.youtube.com/watch?v=9QlDSNeuAdY

    OdpowiedzUsuń
  9. Wykorzystywałbym ten program, gdyby nie był on tak cholernie zasobożerny... :/

    OdpowiedzUsuń
    Odpowiedzi
    1. Sprawdziłem - całe Atmel Studio w trakcie symulacji programu (który dla ATmega32 zawiera się w parwie 10kB FLASH) zajmuje w systemie Windows niecałe 500MB RAM. Co do ewentualnego przyspieszenia Atmel Studio przeczytaj: Atmel Studio: Jak przyśpieszyć?

      Symulator działa szybko, a wcale nie mam jakiegoś super komputera na biurku :-)

      W ostateczności możesz korzystać z wcześniejszej wersji środowiska, która także zawiera symulator: AVR Studio

      Usuń
  10. Atmel Studio używam od początku zainteresowania się AVRami , aktualnie mam wersję 7 i piszę w asemblerze na xmega128a1u, udało mi się podłączyć zewnętrzną pamięć, razem 128K, oczywiście pojawiły się problemy i skorzystałem z symulatora. Niestety za żadne skarby symulator nie chce obsłużyć pamięci ram powyżej 4000h, nie można zapisać ani odczytać, na podglądzie komórki wypełnione są znakami zapytania. Jak to odblokować ?

    OdpowiedzUsuń

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.