Strony

środa, 28 listopada 2012

AVR-EEPROM Struktury - poradnik do książek


Witam,

Tym razem postanowiłem nakręcić bardzo nietypowy jak dla mnie poradnik video. Jest on w zasadzie odpowiedzią na ankietę i jej wyniki przedstawioną na www.forum.atnel.pl. Zgodnie z tytułem artykułu będzie on dotyczył zagadnień związanych z prawidłowym podejściem do korzystania z pamięci EEPROM w mikrokontrolerach AVR, przy okazji omówię wykorzystanie w tym zakresie struktur ale także wskaźników oraz sposoby wykorzystania zdarzeń (EVENT's) oraz callbacków i timerów programowych, które prezentowałem na łamach książek wydawnictwa Atnel. Nietypowe w tym poradniku jest to, że jest bardzo długi 2 godziny i 10 minut. Uprzedzam o tym osoby, które narzekają na zbyt długie poradniki, lepiej tego nie oglądać ;). Ponieważ jednak jest sporo materiału do omówienia, którego nie poruszałem w książkach a uznałem, że prezentowany tu praktyczny przykład może się przydać wielu osobom, to postanowiłem najpierw przeprowadzić coś w rodzaju wykładu przy tablicy ;) .... a następnie pokazać przebieg tworzenia całego projektu od A do Z. Bez żadnych skrótów, po to aby każdy mógł zobaczyć co po kolei robię zabierając się za pisanie projektów, jak dzielić projekt na pliki, jak radzić sobie z różnymi błędami podczas kompilacji itp. Na koniec pokażę już na żywo działanie prototypowego urządzenia, które zbuduję w trakcie poradnika. Jak widać, w jednym choć długim poradniku zawartych będzie wiele korzyści, a szczególnie dla osób początkujących, które chciałyby poznać jak pisze i tworzy program, ktoś, kto już jest może troszkę dalej jeśli chodzi o znajomość języka C i programowania ....



Z uwagi na długi materiał filmowy został on podzielony na dwa fragmenty, czyli 1 godzinne odcinki. To pierwsze moje takie kompleksowe podejście do stworzenia większego poradnika. Proszę zatem wybaczyć mi wszelkie błędy i jeśli będą jakieś pytania to skupmy się na merytorycznym przekazie, a nie na uwagach odnośnie dykcji, wymowy angielskich wyrazów itp. Poniżej filmów, będzie można znaleźć link, z którego możesz pobrać pełny kod źródłowy tworzony przeze mnie w trakcie poradnika aby dokonywać na nim własnych modyfikacji i ćwiczeń. Myślę, że zaprezentowany tu sposób, sposoby odpowiedzą na wiele różnych pytań jakie czasem pojawiają się czy to na www.forum.atnel.pl, czy na blogu lub w mailach przesyłanych bezpośrednio do mnie.

Poniżej dwa filmy, które można obejrzeć w jakości HD (1280x720) na youtube.

część I


część II



Jeśli chcesz pobrać cały projekt w ECLIPSE omawiany w poradniku:


*** kliknij w ten LINK ***

A teraz UWAGA! ;)

Dzisiaj tj. 3 grudnia 2012r wpadł do mnie do firmy taki fajny człowiek, czytelnik i doniósł mi, że kod który można pobrać wyżej niezbyt dobrze działa tzn daje się skompilować, gdy próbujemy to robić za pomocą najnowszego toolchaina. Co ciekawe nie chodziło mu o najnowszy toolchain atmelowski bo on działa na linuxie ale też ma jakiś najnowszy toolchain ;) .... OK, sprawdziłem i okazało się, że pod windowsem na toolchainie atmelowskim też jest problem, tzn są problemy. Kilka z nich łatwo sobie naprawić na podstawie mojego poprzedniego artykułu na tym blogu:


Eclipse - kłopot z PSTR() ? - przeczytaj ;)



http://mirekk36.blogspot.com/2012/08/eclipse-kopot-z-pstr-przeczytaj.html

ale jeden a w zasadzie dwa babole pozostają, aż pozwolę sobie je tutaj pokazać i za chwilę rozprawić z nimi na amen ;)



O dziwo w przypadku gdy stworzymy własny typ strukturalny i chcemy utworzyć w oparciu o niego zmienną w pamięci EEPROM albo zmienną/stałą w pamięci PROGMEM to Eclipse wyświetla nam o zgrozo "Syntax Error", pomimo że cała kompilacja w konsoli przebiega bez najmniejszych problemów. Oczywiście tak jest w rzeczywistości - kompilacja jest i musi być prawidłowa i mamy prawidłowy wsad. Jednak - chyba rozumiesz - że ja zawsze tłumaczę, że nie cierpię mieć jakichś tam szlaczków, podkreśleń itp ... muszę to wyplenić do samego końca ;) .... Tutaj też się zacietrzewiłem po wyjściu kolegi czytelnika, który przyniósł mi ten orzech do zgryzienia i dawaj do rozwiązywania problemu ...

no i jest ;) ... okazuje się bowiem, że powodem tego jest tak jakby źle się w samym Eclipse rozprzestrzeniały że tak brzydko powiem, niektóre systemowe definicje preprocesora z plików nagłówkowych

eeprom.h
pgmspace.h

a przecież one tam są! ... kombinowałem jak koń pod górkę i postanowiłem po nitce do kłębka dojść, do miejsc definicji np PROGMEM czy też EEMEM. I proszę bardzo pierwsza z nich w pliku progmem.h , jak każdy z was może to sam podejrzeć, wygląda tak:

#define PROGMEM __ATTR_PROGMEM__

ok, no dobrze ale teraz co to jest __ATTR_PROGMEM__ ??? ;) ... na szczęście będąc w kochanym Eclipse wystarcza tylko przytrzymać klawisz CTRL i klikać lewym klawiszem mychy i jesteśmy od razu teleportowani do kolejnego właściwego miejsca czyli kolejnej definicji i tak na końcu docieramy co to jest to wyżej:

#define __ATTR_PROGMEM__ __attribute__((__progmem__))

ooo proszę bardzo - mamy tu po prostu ubrany pod płaszczykiem PROGMEM czysty żywy atrybut progmem. Więc pomyślałem - a jakby tak to nim się posłużyć a nie słówkiem PROGMEM ? no to próbujemy, i eureka! to działa ;)



To znaczy jest lepiej bo nie działa jeszcze zmienna z EEMEM, ale tu już pewnie się domyślasz, robię IDENTYCZNIE czyli:



Jak widać od tej pory wszyscy są szczęśliwi czyli, kompilator, Eclipse no i uśmiechnięty programista ;)



.


.

30 komentarzy:

  1. Mirku, bardzo dziekuję za każdą chwilę, którą poświęcasz ludziom na forum, ludziom, którzy zakupili biblie ;) Materiał video jest obszerny i w wysokiej jakości, więc w domu tego nie obejrze, by nie zarzynać sobie miesięcznego limitu transferu. Szczęśliwym trafem wymieniam komputer w pracy na KOMPUTER i nareszcie bedę mógł w pełni korzystac z dobrodziejstw internetu (filmy). Wciąz kuleje u mnie tworzenie struktur i obsługa eepromu i ogromnie się ciesze, że stworzyłes kolejne źródło wiedzy, którą będe mógł przyswoić. Po prostu dziekuję :)

    OdpowiedzUsuń
  2. Proste rozwiązania są najlepsze, aż prosi się żeby struktura była klasą. Bardzo mi się podoba takie podejście do eepromu :)

    OdpowiedzUsuń
    Odpowiedzi
    1. Dlatego ja bodajże w drugiej książce piszę o tym, że struktury w C to protoplaści klas w C++ ;)

      Usuń
    2. Klasa i struktura to to samo. Jedyna różnica to klasa jest domyślnie private a struktura jest public.

      Usuń
    3. Porównywać to może i troszkę można, jednak nie oszukujmy się C nie jest zorientowane obiektowo i nigdy nie było. W dodatku struktury nie mają metod, a to już spora różnica.

      Usuń
    4. No dokładnie ;) dlatego ja zawsze mówię, że struktury to protoplaści ;) hmm przodkowie klas ;) .... ale nie mają nic wspólnego z klasami jeśli chodzi oczywiście o porównanie struktur z C z klasami w C++ (bo naturalnie w C nie ma klas)

      Usuń
  3. Mirku wszystko można podsumować jednym zdaniem: Jesteś WIELKI! Mam nadzieję że to nie wypadek przy pracy i takich lekcji będzie więcej.
    Już nie chodzi i same wykorzystanie tej techniki ale o chęć przekazania wiedzy i sposób jej przekazania.
    Jak w ten sposób wyglądają Twoje szkolenia, to zazdroszczę Twoim uczniom nauczyciela.
    I osobiście będę z nadzieją wypatrywał, czy nie pokaże się dalszy ciąg lekcji.
    Ot takie małe życzenia do Mikołaja pod choinką :)

    Pozdrawiam
    MarCiu

    OdpowiedzUsuń
  4. wiem, że to Twój pierwszy raz, ale w drugim uśmiechnij się trochę, bo masz naprawdę powód do radości, Świetna Robota !!!

    ... ale idealnie nie jest, bo drugi mazak słabo jest widoczny wg. mnie

    wireless

    OdpowiedzUsuń
    Odpowiedzi
    1. hmmm wiesz, że masz rację ;) i to w dwóch przypadkach ... jak sam to oglądałem to się zdziwiłem że nie doszło do żadnego uśmiechu - ale chyba byłem zbyt zestresowany - i obiecuję poprawę, także poprawę z pisakami ;)

      dziękuję za te uwagi

      Usuń
  5. Super zawsze lubię video poradniki twojej produkcji do których często wracam świetne rozwiązania tu przedstawiasz oby więcej takich filmów.Mirek dzięki tobie potrafię dziś tworzyć PCB w eagle i to właśnie dzięki takim poradnikom jak ten łatwo do nich wracać gdy się coś zapomni a nie zawsze wszystko z książki da się zrozumieć.Video poradnik+książki świetnie się uzupełniają to jest to czego mi brakowało i pewno wielu innym forumowiczom.

    OdpowiedzUsuń
  6. Tablica to świetna rzecz, sam choruję na suchościeralną..... Powinieneś częściej robić takie poradniki :).

    OdpowiedzUsuń
  7. Pozostaje tylko napisać:
    ŚWIETNA ROBOTA !!!
    oby tak dalej !

    OdpowiedzUsuń
  8. Może dla doświadczonych moje pytanie wyda się niedorzeczne, ale zastanawia mnie czym różnią się deklaracje:

    unsigned char x;
    uint8_t x;

    chodzi mi o to, czy jest jakaś wyższość tej drugiej, że jest powszechnie stosowana, czy chodzi tylko o mniej pisania. Wywodzę się z epoki pascala i C i dla mnie czytelniejsza i zrozumiała na pierwszy rzut oka jest pierwsza wersja.

    OdpowiedzUsuń
    Odpowiedzi
    1. Mniej pisania ? hmm to chyba najsłabszy powód istnienia uint8_t.

      Przede wszystkim jest on rzeczywiście odpowiednikiem unsigned char. Nie mniej jednak twórcy AVR GCC bo o tym konkretnie kompilatorze mówimy, i tylko w nim to występuje wprowadzili to jeszcze z innych i bardzo zacnych powodów. W ogóle nie rozpatruj tego w kategoriach wyższości czy niższości. Zasady korzystania z uint8_t ale też uint16_t czy uint32_t - hmmm również int8_t czt int32_t - są proste:

      1. zwyczajowo gdy definiuję zmienne w których będę przechowywał liczby - to zgodnie z zaleceniem AVR GCC warto nadawać im typy jak wyżej, np uint8_t

      2. jeśli zaś definiuję zmienne czy tablice w których będę przechowywał (UWAGA! ważne) ... znaki ASCII to korzystam z typu char. Widzisz ? nie napisałem unsigned char tylko samo "char" o tym dlaczego tak - za chwilę

      Dzięki tej prostej i skutecznej zasadzie, jak analizuję swój czy też cudzy program to od razu i na pierwszy rzut oka domyślam się do czego są jakie zmienne. I na pewno w programach pisanych zgodnie z zaleceniami AVR GCC nikt nie stosuje takich np dziwolągów:

      unsigned char i;
      for( i=0; i<10; i++ ) .....

      tylko

      uint8_t i;
      for( i=0; i<10; i++ ) .....

      oczywiście odnosi się to nie tylko do zmiennych iteracyjnych. A wracając do zagadnienia dlaczego piszę char a nie unsigned char - ano dlatego że domyślnie w opcjach kompilacji typ unsigned char jest zamieniany na char. Oczywiście można to wyłączyć jak ktoś się uprze. Można stosować typy jak z czystego C, tylko później proszę się nie dziwić, gdy korzystając z niektórych funkcji wbudowanych trzeba za dużo jawnego rzutowania robić - szczególnie przy wskaśnikach ... ale to już inny i dłuższy temat.

      Usuń
    2. Właśnie zamówiłem książeczkę, mam nadzieje że dotrze przed świętami i nie zaginie na poczcie jak ostatnia przesyłka.

      Myśląc o młodszych "programatorach" w tym o sobie, zastanawia mnie, czy nie dałoby się sprzedawać "mikro-licencji" dla programu mkarvcalculator, np. 5 pln - 2 wybrane procesory. Nie każdego bez stałych dochodów stać aby wydać większą kwotę i sam wolę poświęcić chwile na przeczytanie noty katalogowej niż zakupić pełną wersję programu.

      Usuń
    3. Dziękuję za zakup, mam nadzieję, że książka się przyda. Jeśli chodzi o program MkAvrCalculator to zauważ że on bez żadnej opłaty - obsługuje w pełni aż 4 i to w sumie bardzo popularne mikrokontrolery:

      ATmega8
      ATtiny2313
      ATmega128
      ATmega162

      Proponuję może najpierw na tym podziałać troszkę i zobaczyć w ogóle co to jest i jak się sprawuje. A poza tym warto odwiedzać nasz nowy profil na Facebooku bo niedługo zacznie się tam spora akcja promocyjna, konkursowa itp .... będą m.in rozlosowywane właśnie licencje na te programy ale i wiele innych bardzo ciekawych rzeczy, serdecznie zapraszam na:

      http://www.facebook.com/pages/Atnel-Mikrokontrolery-J%C4%99zyk-C/229870243781242

      Usuń
    4. Zaraziłem się AVR-ami od kolegi który używał atmegi16 i chcąc być z nim kompatybilny, zrobiłem sobie płytkę testową również z 16-ką. Ale mam też atmege8, więc w wolnej chwili również ją jakoś w płytkę wkomponuje.

      Usuń
  9. witam gratuluje tutka i pytanie czy na starym toolchanie będzie ten program działał

    OdpowiedzUsuń
    Odpowiedzi
    1. Programy pisane na nowym toolchainie na pewno będą działać od razu poprawnie na starym ;) ale odwrotnie to już niekoniecznie. Nowy toolchain wprowadza bowiem dodatkowe obostrzenia w kodzie (i słusznie zresztą) ;)

      Usuń
  10. Witam. Dlaczego w funkcji "copy_ram_to_eem();" zastosowałeś: "eeprom_write_block" a nie "eeprom_update_block"?

    Z tego co gdzieś się dowiedziałem lepiej jest "updatować" niż zawsze wgrywać nie raz te same dane. Podobno ma to wydłużyć życie EEPROM (zmniejszyć ilość zapisów), update najpierw porównuje a następnie gdy uzna różne wartości wgrywa świeże (dłuższy czas wykonywania przy wgrywaniu nowych wartości, lecz krótszy gdy wartości są takie same) - dobrze rozumie?

    OdpowiedzUsuń
    Odpowiedzi
    1. Dobrze rozumiesz ;) i oczywiście można stosować update, tyle że to nie ma na celu wydłużenia żywotności ;) a jedynie powiedzmy zmniejszenie czasu operacji, bo jeśli nie było zmian to operacja nie zostanie wykonana.

      Zapis do EEPROM wartości takich samych jakie już tam są nie powoduje straty cyklu zapisu. Dopiero przeprogramowywanie bitów 0 na 1 lub 1 na 0 powoduje że tracimy cykl zapisu bo rzeczywiście przeprogramowujemy komórkę

      Usuń
  11. Bo drugim obejrzeniu, dopiero moge napisac- ROZUMIEM!

    OdpowiedzUsuń
    Odpowiedzi
    1. No to i tak jesteś dobry ;) bo ja nieraz muszę o wiele więcej razy obejrzeć jakiś poradnik zanim wszystko załapię....

      Usuń
  12. Witam

    Jak zapisać jeden parametr z struktury w pamięci RAM do struktury EEPROM

    np.
    struktura_ram[0].dana >> zapisać do >> struktura_ee[1].dana

    struktura RAM i EEPROM są identyczne.

    OdpowiedzUsuń
    Odpowiedzi
    1. No przecież w poradniku pokazuję sposoby i tłumaczę, że najlepszym wyjściem jest

      eeprom_write_block()

      a jak się uprzesz to możesz i pojedynczo się bawić - choć nie wiem po co

      eeprom_write_byte()

      albo

      eeprom_write_word()

      .... a najlepiej to jednak może obejrzyj dokładnie ten poradnik - taka moja propozycja ....

      Usuń
    2. Ja właśnie korzystam z eeprom_write_block(), ale udaje mi się zapisać poprawnie tylko całą strukturę, a gdy próbuję zapisać na krzyż
      struktura_ram[0].dana >> zapisać do >> struktura_ee[1].dana
      a następnie
      struktura_ram[1].dana >> zapisać do >> struktura_ee[0].dana

      Funkcja do zapisu w EEPROM z jakie korzystam
      eeprom_write_block(&sens_ram[si1].id_sens, &sens_ee[si2].id_sens, sizeof(T_SENS));

      to jedna wartość zapisuje się poprawnie a druga jest pusta (same zera).

      Korzystam z twoich porad i oglądałem poradnik z 2 lub 3 razy, dlatego korzystam z struktur i zapisu blokowego. A nie robienia "sieczki", jak gdzieś było to wspomniane.

      Usuń
    3. Z takimi pytaniami to dawaj pan na nasze forum:

      www.forum.atnel.pl

      a nie tutaj, bo z tego pytania twojego to nic nie wiadomo no i tu się źle kod czyta ... a na forum przede wszystkim pokaż w kodzie to co próbujesz robić

      Usuń
  13. Witam
    Bardzo dobry film. Świetnie przekazane informacje.

    OdpowiedzUsuń
  14. Super poradnik, rzeczowy i jasny.
    Mam jednak jedno pytanie, patrzę w te kody i się zastanawiam, w którym miejscu jest realizowany zapis tych ustawień zmienianych podczas zabawy z płytką. Czyli zapis z RAM do EEPROM. Bo widzę wyraźnie i to było omówione w poradniku - gdzie jest zapis z Flash do EEPROM podczas włączenia z przytrzymanym przyciskiem. To jest jasne. Ale gdzie zapisywane są dane, dzięki którym po normalnym ponownym uruchomieniu mamy konfigurację, która była podczas wyłączenia płytki - tego nie widzę.

    OdpowiedzUsuń