Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega8A - [C/Eclipse] Zapis i odczyt zmiennych z EEPROM

iwi1 13 Nov 2013 00:53 3153 11
  • #1
    iwi1
    Level 17  
    Witajcie.
    Napisałem programik zliczający energię w kWh.
    Super działa do czasu wyłaczenia z prądu - wtedy się resetuje i od nowa prawidłowo nalicza.
    Są wbudowane funkcje w eeprom.h które próbuję zmusić do działania i nic z tego nie wychodzi - ciągle kompilator wywala błędy.
    Zapisywanie do EEprom chcę zrobić funkcją eeprom_write_float
    Code: c
    Log in, to see the code

    i w kompilatorze otrzymuje taki błąd: ../main.c:387:5: warning: passing argument 1 of '__eewr_float_m8' makes pointer from integer without a cast [enabled by default]
    zmienna

    Odczytywanie pamięci eeprom mam taką funkcją zrobione, ale nie wiem czy działa bo ciągle nie mogę nic zapisać
    Code: c
    Log in, to see the code
  • #2
    mickpr
    Level 39  
    iwi1 wrote:
    passing argument 1 of '__eewr_float_m8' makes pointer from integer without a cast
    Pierwszy parametr powinien być wskaźnikiem do zmiennej (możesz podać &uiAddress).
  • #3
    iwi1
    Level 17  
    Nie bardzo rozumiem.
    na pierwszym miejscu mamy zadeklarować gdzie ma być zapisana czyli adres, a na drugim zmienna.
    zmienna w RAM to kWh_stan
    zmienna do eeprom to kWh_stan_ee - ewentualnie jak to się nie pomiesza to może być jedna zmienna kWh_stan do eeproma i do Ramu.

    uiAddress jest zadeklarowana na samym poczatku jako float
    uint16_t uiAddress = 0 ;
    i nie ma znaczenia czy podam zero na końcu czy 1 czy inną liczbę - ciągle się nie kompiluje

    czy może ktoś poać jakiś przykład zapisania zmiennej np kWh_stan do pamięci eeprom
    a jeszcze dokładniej

    1. uC uruchamiamy.
    2. odczytujemy zmienną kWh_stan - jeśli nie istnieje w eepromie to dajemy jej wartość 0
    3. Po wykonaniu warunku IF (jeżeli inna zmienna (Ws_stan) osiągnie wartość 1 kWh=3600000Ws) zwiększamy tą zmienną o 1 i zapisujemy kWh_stan do eeprom już z nową wartością w tym samym adresie.
    W którym adresie ją zapiszemy - jest mi obojętne.
    Wielkość może być uint16_t - nie musi być float.
    Ja już się poddaje - niby takie proste, a nie do końca proste.
  • #4
    Carmixus
    Level 15  
    Quote:
    uiAddress jest zadeklarowana na samym poczatku jako float
    uint16_t uiAddress = 0 ;
    i nie ma znaczenia czy podam zero na końcu czy 1 czy inną liczbę - ciągle się nie kompiluje


    To w końcu float, czy uint16_t? To są różne rzeczy.

    Pierwszym argumentem powinien być adres zmiennej w pamięci EEPROM - czyli zmienna typu wskaźnik na float. Spróbuj:

    Code: c
    Log in, to see the code


    Gwiazdka oznacza zmienną typu wskaźnikowego.
  • #5
    mickpr
    Level 39  
    iwi1 wrote:
    Nie bardzo rozumiem. na pierwszym miejscu mamy zadeklarować gdzie ma być zapisana czyli adres, a na drugim zmienna.
    Zacznij od pokazania nam definicji/deklaracji funkcji eeprom_write_float.
    Bez tego - to sobie tylko gdybamy.
  • #6
    inmo
    Level 9  
    Dzięki koledzy. Wygląda na to że już będzie działało, ale jeszcze chciałbym uściślić parę wątpliwości
    Quote:
    To w końcu float, czy uint16_t? To są różne rzeczy.

    jest mi obojętne czy to będzie float czy integer byleby działało. Ogólnie będą liczby całkowite więc wystarczy uint16_t, ale próbowałem już różnych sposobów.
    Nie działała funkcja eeprom_write_byte bo tam było w deklaracji uint8_t a ja cały czas dawałem uint16_t dlatego przeszedłem na float.

    Quote:
    float* uiAddress = 0;

    po takiej zmianie ładnie się kompiluje, ale albo nie zapisuje, albo nie odczytuje bo po resecie jest zero w dalszym ciągu.
    Jeszcze raz spróbuję przejrzeć cały kod co może być nie tak.

    Czy jest znaczenie między takim zapisem - zamieniam na uint16_t oczywiście?
    uint16_t kWh_stan_ee; a
    uint16_t EEMEM kWh_stan_ee;

    bo wyczytałem że EEMEM to jakieś makro zapisujące do eeprom.
    Ale potem inni piszą, że skoro używa się funkcji eeprom_write_ to nie potrzeba tego makra EEMEM, a to makro służy tylko do wygenerowania pliku, który potem można ręcznie wgrać do eeproma. Jak to jest naprawdę?

    jeszcze takie pytanie. Jak zapisuje cały czas ten sam blok pamięci to korzystać z funkcji write czy update? Jest jakaś różnica?
    przecież jak w komórce 0 siedzi np 0xFF to robiąc write zapisuje w tym miejscu wartość np 0XEE. Zapisując ponownie znowu zamienia z 0xEE na 0xDD itd.
    czym się różnią te funkcje między sobą.

    i czy w uiAddress podajemy dziesiętnie czy szesnastkowo adres pamięci?
    i ewentualnie bo człowiek się gubi w tym. Atmega8A ma 512 bajtów pamięci. Czyli 4096 bitów Czyli zapisując to szesnastkowo to 0x000 do 0xFFF.
    Czyli zapisując zmienną uint16_t zapisuje ją w 16 bitach - czyli ustawiając uint16_t na 0 (0x000) to pierwsze szesnaście bitów jest zajęte i teraz jak będę adresował inną zmienną to muszę pamiętać o tym?
    Ewentualnie nie podając żadnego adresu przy deklarowaniu uiAddress to czy kompilator sam sobie rozmieści zmienną gdzie chce?.


    w pliku eeprom.h jest taki zapis
    Code: c
    Log in, to see the code
  • #7
    tmf
    Moderator of Microcontroller designs
    Ja na twoim miejscu zacząłbym od nauki podstaw C, a potem ogarnięcia tego języka na AVR. To po pierwsze, a po kolejne:
    - do zliczania nie używaj float, wbrew pozorom to nie jest obojętne, czy będzie float, czy int. Poczytaj o tym jak float jest reprezentowany w pamięci, bo możesz się zdziwić, kiedy np. x+1 będzie ciągle równe x.
    - EEMEM nic nie zapisuje do EEPROM, to kwantyfikator określający lokalizację zmiennej w przestrzeni adresowej procesora (wymagany ze względu na różne przestrzenie w AVR). Musisz go określić dla zmiennej, która ma być w EEPROM.
    - zapis float* uiAddress = 0; powoduje utworzenie wskaźnika na float, który wskazuje na zmienną tego typu umieszczoną w pamięci pod adresem 0. Ponieważ pod tym adresem znajdują się rejestry R0-R3 AVR, odwołanie się do tego adresu jest błędem. Jeśli używasz wskaźnika, to przed użyciem musi on wskazywać na poprawny adres, zamiast tego prościej użyć operatora & z nazwą zmiennej w EEPROM.
    - makra write od update różnią się tym, że to drugie zanim coś zapisze najpierw sprawdza czy znajdująca się w EEPROM wartość nie jest czasem równa nowozapisywanej i jeśli tak to odstępuje od zapisu. Przede wszystkim ma to za zadanie wydłużyć żywotność EEPROM przez eliminację niepotrzebnych zapisów. Swoją drogą, to też musisz przemyśleć - czyli zastosować jakieś techniki wear leveling, lub zapisywać tylko wtedy kiedy jest to niezbędne, inaczej wykończysz EEPROM.
    - co do zapisu dziesiętnego lub szesnastkowego. Czy procesor rozróżnia te zapisy? Raczej nie, prawda?
    - co do adresowania EEPROM - przyjrzyj się rejestrowi adresowemu EEPROM, a wyjaśni się sprawa niewykorzystanych bitów. Stosując EEMEM + operator & kompilator wygeneruje taki adres jaki jest potrzebny.
  • #8
    inmo
    Level 9  
    Witajcie.
    Sprawa okazała się prostsza niż myślałem. Problem byłw ustawieniach Eclipse.
    Domyślnie ustawia się, żeby nie wgrywać EEPROMa.
    Po zmianie na taki w właściwościach AVRDUDE działa ładnie.
    Atmega8A - [C/Eclipse] Zapis i odczyt zmiennych z EEPROM
    a domyślnie jest ustawiona na "do not upgrade eeprom image"

    a już żeby zamknąć temat to kod który działa wygląda tak:

    Code: c
    Log in, to see the code
  • #10
    tmf
    Moderator of Microcontroller designs
    inmo wrote:

    a już żeby zamknąć temat to kod który działa wygląda tak:

    Code: c
    Log in, to see the code


    Ten kod jest błędny i działa tylko przypadkowo. uiAddress używasz niezainicjowany - nie masz żadnych ostrzeżeń kompilatora? Wywal go.
    Powinno być:
    Code: c
    Log in, to see the code
    [/quote]
  • #11
    inmo
    Level 9  
    Code:
    if (!kWh_stan) { kWh_stan = 0; }

    ten if jest po to, żeby na starcie wpisywał do zmiennej kWh_stan wartość 0 a nie domyślnie 0XFFFF;

    co do ostrzeżeń kompilatora to nie było żadnych błędów i kod działał.
    Ale dzięki za info - zastosuje Twoje uwagi.
  • #12
    tmf
    Moderator of Microcontroller designs
    ! jest operacją logiczną. Inaczej to wygląda tak - jeżeli kWh_stan jest równy zero to go wyzeruj. O to ci chodziło? To nie to samo co:
    Code: c
    Log in, to see the code


    BTW, zmienne w EEPROM są zainicjowane, przynajmniej mogą być, więc taki kod jest niepotrzebny, wystarczy napisać:
    Code: c
    Log in, to see the code