Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

zamiennik sprintf - Odchudzenie pamięci programu Atmega8

mirek1968 06 Sty 2013 11:44 3849 30
  • #1 06 Sty 2013 11:44
    mirek1968
    Poziom 13  

    Mam prośbę o pomoc w sprawie zamiany funkcji sprintf na inną w celu odchudzenia pamięci kodu programu w c.
    Dal przykładu mam taki program dla odczytu czasu z DS1307 i aby wyświetlić aktualny czas do przkształceń używam funkcji sprintf,ale jest pamięciożerna i chcę ją czymś zastąpić.To jest w pętli ciągłej while.


    Kod: c
    Zaloguj się, aby zobaczyć kod




    Natomiast w głównej pętli mam zdefiniowane zmienne typu uint_t i nie wiem w jaki sposób wyświetlić czas(czyli godz min i sek )inną funkcją od sprintf.
    Spróbowałem użyć wcześniej funkcji itoa w taki sposób itoa (s,czas,10); ale wtedy sekundy gdy przekroczyły wartość 9 sekund to zamiast w części dziesiątek sekund zamiast 0 pojawiało się 9 czego nie rozumiem dlaczego.


    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 29
  • #2 06 Sty 2013 13:00
    daniel11
    Poziom 13  

    Jeśli jest to C++ to można użyć strumieni.. C używa sprintf() oraz itoa()

    0
  • #3 06 Sty 2013 13:10
    Freddie Chopin
    Specjalista - Mikrokontrolery

    daniel11 napisał:
    Jeśli jest to C++ to można użyć strumieni..

    Z pewnością będą mniej zajmować niż sprintf()...

    4\/3!!

    0
  • #5 06 Sty 2013 13:16
    daniel11
    Poziom 13  

    [quote="Freddie Chopin"][quote="daniel11"]Jeśli jest to C++ to można użyć strumieni..[/quote]
    Z pewnością będą mniej zajmować niż sprintf()...

    4\/3!![/quote]

    Mój błąd... człowiek jak wstanie to się może pomylić..

    0
  • #6 06 Sty 2013 13:34
    tmf
    Moderator Mikrokontrolery Projektowanie

    Są też odchudzone wersje sprintf, wystarczy je dołączyć do projektu (printf_min). Z drugiej strony brakuje ci pamięci, że muszisz odchudzać, czy dążysz do tego, żeby np. 3 kB leżało odłogiem ?:)

    0
  • #7 06 Sty 2013 14:39
    mirek1968
    Poziom 13  

    Zastosowałem już funkcję itoa ale pokazuje mi np. sekundy raz liczy mi do 10 sekundy potem przechodzi na część dziesiątek sekund i tam liczy znów do 10 zamiast 0 mam 9 nie wiem co robię nie tak.
    proszę o sprawdzenie ,ewentualną poprawę kodu.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #8 06 Sty 2013 20:47
    BlueDraco
    Specjalista - Mikrokontrolery

    To licz każdą cyfrę czasu oddzielnie. Wtedy do wyświetlenia wystarczy dodać do wartości cyfry kod zera, czyli '0'.

    Moderowany przez zumek:


    To, czy "licz każdą cyfrę oddzielnie" oznacza to samo, czy coś zupełnie innego niż "rozbijaj na cyfry", niech zdecyduje autor tematu.

    0
  • #9 06 Sty 2013 23:25
    mirek1968
    Poziom 13  

    No tak ale w jaki sposób mam każdą cyfrę z sekund liczyć oddzielnie przecież w zmiennej uint8_t s są zdeklarowane dwie cyfry tak samo jak w pozostałych zmiennych odczytu czasu.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Proszę o modyfikację mojego wcześniejszego kodu o ile to nie sprawi trudności.

    0
  • #10 06 Sty 2013 23:41
    tmf
    Moderator Mikrokontrolery Projektowanie

    Masz w tej zmiennej liczbę zapisaną w formacie binarnym, czy BCD? Jeśli w BCD to itoa nie zadziała, ale wtedy po prostu maskujesz tetrady i dodajesz '0'.

    0
  • Pomocny post
    #11 07 Sty 2013 09:16
    BlueDraco
    Specjalista - Mikrokontrolery

    Tak liczyć:
    (W tym kodzie czas jest trzymany w tablicy - pozycja 0 to jednostki sekund, 5 - dziesiątki godzin.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #12 07 Sty 2013 12:07
    mirek1968
    Poziom 13  

    Ten kod który podałeś ma być użyty w programie głównym int main(void)? czy też w innym.(np ds1307.c)
    Czy tablica char o nazwie time ma zdeklarowane 6 elementów i co to jest za funkcja updtime.

    0
  • #13 07 Sty 2013 12:11
    BlueDraco
    Specjalista - Mikrokontrolery

    U mnie ten kod był w obsłudze przerwania timera. Na pewno nie powinien on być umieszczony w programie głównym. updtime to zmienna, u Ciebie zapewne niepotrzebna. tablica ma tyle bajtów, ile cyfr ma czas - u mnie było 6, bo to był zwykły (no niezupełnie) zegarek z wyświetlaczem 6- cyfrowym.

    0
  • #14 08 Sty 2013 14:17
    mirek1968
    Poziom 13  

    Cofnę się do początku mojego pytania.
    Obecnie mam działający program który poprawnie wyświetla mi czas (godziny,minuty i sekundy we właściwym ułożeniu na LCD).
    Problemem jest pamięciożerna funkcja przekształcająca sprintf.(zajętość około 85% pamięci programu mojego na Atmega8), a bez tego sprintf o 22 % mniejsza.
    Z tego co widzę czas jest zapisany u mnie w zmiennych uint8_t h,m,s,d,mm,y,D; czyli jest to liczba rzeczywista od 0 do 255 (wartości sukund zawierają się w 8 bitach ,minuty 8 bitach tak samo i godziny też.
    Ustawiam czas wstępnie funkcją "ds1307_setTime(23,59,40);" i w efekcie tego na wyświetlaczu wyświetli się 23:59:40 i jest OK.
    Jeśli nikomu z szanownych kolegów znających temat nie sprawi to problemu proszę dopisać do mojego wyżej wypisanego kodu w c kilka linijek programu które zastąpią mi tą niechcianą funkcję sprintf.Proszę o zrozumienie i wyrozumiałość bo uczę się c_avr z dobrej książki i sieci ale nie wszystko jeszcze w dostatecznym stopniu rozumiem i dlatego wolę jako pomoc dopisane kilka linijek poprawnego kodu niż teorię na temat ego co zrobić z tym problemem.

    0
  • #15 08 Sty 2013 14:31
    Samuraj
    Poziom 35  

    Nie mam teraz pod ręką programu ale napisze jak to ja robię.
    Pobierasz liczbę (godzin, minut czy sekund co tam chcesz od 0 do 99).
    Dzielisz przez 10 i dodajesz 0x30. 0x30 to cyfra 0, 0x35 to 5 i odpowiednio do 9. Taką otrzymaną wartość wysyłasz do wyświetlacza.
    Tak samo robisz z resztą z dzielenia (%). W efekcie otrzymujesz dwie cyfry na wyświetlaczu.
    Sprawdź w jakim systemie masz zapisane zmienne do DS1307.
    To co podałeś w poście #9 "ds1307_setTime(23,59,40);" to wygląda na zapis w systemie dziesiętnym.

    0
  • #16 08 Sty 2013 14:52
    BlueDraco
    Specjalista - Mikrokontrolery

    lcdchar(h / 10 + '0');
    lcdchar(h % 10 + '0');
    lcdchar(':');

    itd. - to samo dla minut i sekund.

    0
  • #17 08 Sty 2013 16:01
    mirek1968
    Poziom 13  

    Zastosowałem Twój przykład BlueDraco zadziałało super i odchudziło mi pamięć o 22% to mi wystarczy w 100%.
    Bardzo dziękuję wszystkim szanownym kolegom za zainteresowanie moim problemem i cierpliwość,cieszę się bo mój cel został osiągnięty i program jest odchudzony.
    Mam jeszcze jedno pytanko dotyczące troszkę czegoś innego.Chodzi mi w jaki sposób korygować programowo mój zegar który mi spieszy około 5 sekund na dobę.
    Czy powodem spieszenia może być to że jak go zostawię na podtrzymaniu bateryjnym i w tym czasie żadna pętla nie działa ma na to wpływ?.
    Jeśli tak to załóżmy że stale będę zasilał moją płytkę i program będzie stale działał jaka wtedy jest prosta metoda na korektę sekund(odjęcie tych 5sekund na przykład raz na dobę lu jakaś inna kalibracja okresowa.
    Proszę jeszcze o pomoc w tej sprawie.

    0
  • #18 08 Sty 2013 16:39
    BlueDraco
    Specjalista - Mikrokontrolery

    Działanie DS1307 nie zależy od żadnych pętli w programie. Ogólnie prostą kalibrację można zrobić na zasadzie "co ileś sekund odejmij/dodaj jedną sekundę". Trochę to nieelegancko wygląda na wyświetlaczu, ale od biedy ujdzie. lepiej oczywiście korygować odpwoiednio częściej o np. 1/100 sekundy, w przypadku RTC można to zrobić przez załadowanie nowego czasu do RTC, łatwiej oczywiście się to robi dla czasu utrzymywanego przez uC.

    0
  • #20 08 Sty 2013 17:58
    BlueDraco
    Specjalista - Mikrokontrolery

    Eee, "jak się patrzy" to jest bez trymera, tylko programowo. ;)

    0
  • #21 08 Sty 2013 18:05
    Samuraj
    Poziom 35  

    o 00:00:05 odczytaj sekundy i wpisz nową wartość 00:00:00

    0
  • #22 08 Sty 2013 19:00
    mirek1968
    Poziom 13  

    Trymerem już się bawiłem ale nie potrafiłem poradzić sobie z dokładnym dostrojeniem.Wolę korektę programową.

    Próbowałem już tak zrobić w warunkiem ifelse ,ale nie potrafię wyjść z tego dalej aby był realizowany program ,nie wiem co robię źle.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #24 08 Sty 2013 19:23
    BlueDraco
    Specjalista - Mikrokontrolery

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #26 08 Sty 2013 19:58
    BlueDraco
    Specjalista - Mikrokontrolery

    Na to też są sposoby - w rejestrach RTC zapisuje się informacje o ostatniej korekcie. Cofanie jednorazowe o 5 sekund też nie jest dobrym pomysłem, ale początkujący Kolega od czegoś musi zacząć.

    0
  • #28 09 Sty 2013 15:53
    mirek1968
    Poziom 13  

    Korekta działa dobrze,wywala tylko błąd kompilacji w linijce

    Kod: c
    Zaloguj się, aby zobaczyć kod


    o treści:
    Location Type suggest explicit braces to avoid ambiguous 'else'

    Muszę jeszcze pomierzyć jaki prąd pobiera mój zegarek tak aby można było go stale zasilać aby program mógł być ciągle realizowany bo tylko wtedy korekta sekund zadziała.Dziękuję za pomoc:-)

    0
  • #29 09 Sty 2013 16:00
    BlueDraco
    Specjalista - Mikrokontrolery

    To nie jest błąd, tylko ostrzeżenie nadgorliwego kompilatora, któremu wydaje się, że ostani else być może miał być do pierwszego if, a nie drugiego (a nie miał). Wstaw klamrę po pierwszym if i po klamrze kończącej ostatni else if, to przestanie pyskować.

    0