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

MikroC - PIC16F628A - formowanie wyniku z DS18B20 do wysłania po UART

30 Cze 2016 07:58 3600 15
  • Poziom 18  
    Witam,

    czy ktoś mógłby mnie nakierować co muszę zmienić w poniższym kodzie aby otrzymać po UART poprawny wynik temperatury odczytanej z DS18B20 ?

    Kod (MikroC, PIC16F628A)
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wyświetlany wynik po UART:
    MikroC - PIC16F628A - formowanie wyniku z DS18B20 do wysłania po UART

    gdzie w pomieszczeniu mam ok 25C (wg wskazań innego termometru).

    Kombinowałem też z poniższym kodem i też wysyła niepoprawne wyniki:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    poniżej wyświetlane wyniki (niepoprawne):
    MikroC - PIC16F628A - formowanie wyniku z DS18B20 do wysłania po UART
  • PCBway
  • Pomocny post
    Poziom 37  
    ze szczegółów to użycie zmiennej text masz nieprawidłowe, piszesz po stałych.
    Wskaźnik na jakiś string (sekwencję literek) a bufor na literki, choć w kodzie C pisze się to formalnie prawie tak samo, są głębokie różnice.

    To jest sławny w C Undefined Behaviour.

    Po drugie wite(13) lepiej wygląda write('\r')
    a coś+48 to nie lepiej temu będzie coś+'0' jeśli zgaduję dobrze zamiar kodu?

    EDIT: a takie coś
    Kod: c
    Zaloguj się, aby zobaczyć kod
    to proszenie się o strzał w stopę (dokładniej to w dwie z dwóch powodów). Sam wiem, że również w notach kontrolerów są straszne przykładu kodu, powinni za nie kołem łamać

    Zależnie od wersji standardu C bezpiecznie jest coś takiego
    Kod: c
    Zaloguj się, aby zobaczyć kod


    ew mniej straszne #define
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Nie pomogłem ci z tematem ściśle uP ale to moje oczy wychwytują
  • Pomocny post
    Poziom 2  
    Z opisu DS18B20 rozumiem, że on zawsze zwraca część ułamkową w najmłodszych 4 bitach LSB - niezależnie od rozdzielczości.

    Tak więc wystarczy zmienić w Display_Temperature() pierwszą linię na

    unsigned short RES_SHIFT = 4;

    Wynik będzie o 3 bity (8 razy) mniejszy - więc zamiast 207.5 uzyskasz 25.9
  • Specjalista - Mikrokontrolery
    A temat wraz z odpowiedziami powaraca na forum co miesiąc - wystarczy poszukać.
  • PCBway
  • Poziom 18  
    JacekCz napisał:
    ze szczegółów to użycie zmiennej text masz nieprawidłowe, piszesz po stałych.
    Wskaźnik na jakiś string (sekwencję literek) a bufor na literki, choć w kodzie C pisze się to formalnie prawie tak samo, są głębokie różnice.


    Zamiast:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zrobiłem tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Niestety kompilator wywalił błąd, że wskaźnik niezadeklarowany (coś w ten deseń)

    pierzogad napisał:
    Z opisu DS18B20 rozumiem, że on zawsze zwraca część ułamkową w najmłodszych 4 bitach LSB - niezależnie od rozdzielczości.

    Tak więc wystarczy zmienić w Display_Temperature() pierwszą linię na

    unsigned short RES_SHIFT = 4;

    Wynik będzie o 3 bity (8 razy) mniejszy - więc zamiast 207.5 uzyskasz 25.9


    Dzięki Twojej poradzie udało się wyświetlić poprawny wynik :)

    Kod prezentuje się teraz następująco [MikroC, PIC16F628A]:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    a wysyłane po UART wyniki tak:
    MikroC - PIC16F628A - formowanie wyniku z DS18B20 do wysłania po UART
    widać temperaturę 27C, która pokrywa się z temperaturą w pomieszczeniu, dalej złapałem palcami za czujnik :D

    PS. Pierwszy wysłany wynik to 85 - ale zauważyłem go kiedyś zarówno na Arduino jak i na ESP8266 przy odczytywaniu temperatury z DS18B20 - więc ten błąd przyjmuję za "normalkę".
  • Pomocny post
    Poziom 33  
    Nie zmienia to faktu, że to:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    jest źle. Twój program działa całkiem przypadkiem.
  • Pomocny post
    Poziom 37  
    mariomario napisał:
    JacekCz napisał:
    ze szczegółów to użycie zmiennej text masz nieprawidłowe, piszesz po stałych.
    Wskaźnik na jakiś string (sekwencję literek) a bufor na literki, choć w kodzie C pisze się to formalnie prawie tak samo, są głębokie różnice.


    Zamiast:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zrobiłem tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Niestety kompilator wywalił błąd, że wskaźnik niezadeklarowany (coś w ten deseń)


    Zdziwiony jestem, że rozmawiamy na tematy z pierwszych kartek podręcznika C (oraz zupełnie na chłopski rozum projektowania).

    Kod: c
    Zaloguj się, aby zobaczyć kod
    lub
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Już by kompilator nie krzyczał.

    Deklaruje to bufor (o długości inicjatora+1) za pierwszym razem zainicjowany wartością, ale dostępny do zapisu.

    Ale, myśląc "projektowo", czy kiedykolwiek chcemy użyć tych zer? Nigdy. Więc prawidłowy zapis by był - przy okazji mamy oszczędności - jak poniżej.
    Kod: c
    Zaloguj się, aby zobaczyć kod


    EDIT: zapis z char * = "stała" jakbym był twórcą kompilatora na uP bym przemieszczał do ROM/flasha. Ciągły problem gdzie ubywa RAM itd by się skończył

    Drobny "szczegół" miliony linii kodu nie trzymającego standardu by przestały działać, więc w realnym świecie pewnie taka decyzja producentów kompilatorów nie powstanie.
  • Specjalista - Mikrokontrolery
    JacekCz napisał:

    EDIT: zapis z char * = "stała" jakbym był twórcą kompilatora na uP bym przemieszczał do ROM/flasha. Ciągły problem gdzie ubywa RAM itd by się skończył

    Drobny "szczegół" miliony linii kodu nie trzymającego standardu by przestały działać, więc w realnym świecie pewnie taka decyzja producentów kompilatorów nie powstanie.


    I dokładnie tak robi to większość przyzwoitych kompilatorów dla przyzwoitych procesorów (np. ARM), natomiast nie da się tego zrobić bez dodatkowych zaklęć typu PROGMEM dla architektur z rozdzielonymi pamięciami danych i kodu (AVR, PIC), dlatego na AVR taki kod jak powyżej (z modyfikacją "stałego" łańcucha wskazywanego przrz wskaźnik) zadziała, chociaż zgodnie ze standardem C nie powinien.
  • Poziom 37  
    BlueDraco napisał:

    I dokładnie tak robi to większość przyzwoitych kompilatorów dla przyzwoitych procesorów (np. ARM), natomiast nie da się tego zrobić bez dodatkowych zaklęć typu PROGMEM dla architektur z rozdzielonymi pamięciami danych i kodu (AVR, PIC), dlatego na AVR taki kod jak powyżej (z modyfikacją "stałego" łańcucha wskazywanego przrz wskaźnik) zadziała, chociaż zgodnie ze standardem C nie powinien.


    Tak. Żeby się wyżyć "naukowo" to rozdzielone przestrzenie zwykle krótko nazywa się Harvard, a wspólną przestrzeń adresową jako architektura von Neumanna

    W nieco innej dziedzinie blisko obserwuję jak trudno producentowi oprogramowania na liczny rynek (tzn nie dedykowany 1-2 egzemplarze) wyjść z "drobnych błędów" polegających na akceptowaniu sytuacji której akceptować nie powinien. Jeśli nowa wersja zareaguje "prawidłowo" zgodnie ze standardami, kanonami itd i bardziej rygorystycznie, to może wysadzić w powietrze wiele kodu o którym producent przecież nawet nie ma pojęcia.
  • Poziom 33  
    Cytat:

    ...chociaż zgodnie ze standardem C nie powinien

    Zgodnie ze standardem to jest UB. Więc może działać albo nie działać. Przyzwoite kompilatory pozwalają umieścić .rodata gdzie się użytkownikowi podoba ;)

    Szkoda, że w C literały nie są typu const char *. Wtedy autor uniknąłby tego błędu.
  • Specjalista - Mikrokontrolery
    Naukowo to współczesne maszyny "Harvard" spełniają z grubsza postulaty von Neumanna i wcale nie przypominają tego, co skonstruowano na Harvardzie. Za to współczesne "vonNeumannowskie" wykazują dość istotne różnice koncepcyjne w stosunku do komputera von Neumanna, który jawnie rozróżniał dane od kodu. ;)

    Stąd moim skromnym zdaniem różnicowanie "Harvard - von Neumann" w odniesieniu do współczesnych komputerów małych ani dużych nie ma sensu.

    literały są typu const char *, tylko przypadku, o ktrym mowa, kompilator nie ma jak wygzekwować, bo modyfikujemy nominalnie stałą umieszczoną w pamięci RAM wskazywaną przez wskaźnik na zmienną.
  • Poziom 33  
    Cytat:

    literały są typu const char *, tylko przypadku, o ktrym mowa, kompilator nie ma jak wygzekwować, bo modyfikujemy nominalnie stałą umieszczoną w pamięci RAM wskazywaną przez wskaźnik na zmienną.


    To, że coś jest w pamięci FLASH nie znaczy, że jest typu const. W języku C literały nie są typu const char * w żadnym wypadku. Dlatego to:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    nie generuje warninga niezależnie od tego czy literał jest w RAM, FLASH czy gdziekolwiek.
  • Poziom 18  
    Dziękuję Wam za pomoc :) . Poniżej wstawiam już działający kod, wiem że nie jest on idealny, ale zajmuje bardzo mało pamięci RAM i Flash (50 bajtów RAM, 627 bajtów Flash, czyli mniej jak 1/3 pamięci i tak bardzo starego i słabego PIC16F628A ;) ).

    Kod:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    A wysyłane wyniki po UART:
    Kod: html
    Zaloguj się, aby zobaczyć kod
  • Specjalista - Mikrokontrolery
    int x = 5;

    też nie generuje ostrzeżenia, z tego samego powodu. :)
    A "5" jest stałą.

    Ciekawe, jak zadziała coś takiego:

    "abc"[1] = 'x';
  • Pomocny post
    Poziom 23  
    JacekCz napisał:


    Kod: c
    Zaloguj się, aby zobaczyć kod
    lub
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Już by kompilator nie krzyczał.


    Te zapisy nie są równowazne. Skąd ci się ten drugi wziął? Sprawdziłem na ideone i się nie kompiluje. To nie C#...

    https://ideone.com/yqng7Y
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 37  
    p.kaczmarek2 napisał:
    JacekCz napisał:


    ... lub
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Już by kompilator nie krzyczał.


    Te zapisy nie są równowazne. Skąd ci się ten drugi wziął? Sprawdziłem na ideone i się nie kompiluje. To nie C#...

    https://ideone.com/yqng7Y


    W sumie racja. Mam przekonanie, to było legalne w jakiś wersjach na poziomie Kerrigan&Ritchie.
    Używam (w C/C++) wyłącznie pierwszej.