Skocz do zawartości

Kurs STM32L4 – #17 – termometry DS18B20 (1-wire, UART)


Pomocna odpowiedź

Dnia 14.12.2021 o 21:14, roz napisał:

Czemu w kodzie pojawia się często delay_us? O ile w przykładzie to nie ma większego znaczenia o tyle w większym projekcie już może sprawiać problemy. To tak, jak z delay...

Z artykułu dość jasno wynika, że delay_us nie jest dobrym podejściem i nie powinno być używane w większych projektach. Autorzy używają tego podejścia żeby zilustrować działanie protokołu 1-wire, co byłoby trudne używając rozwiązania docelowego, czyli UART. Wersja pro, czyli ta z UART, nie wymaga żadnego delay_us.

Edytowano przez adamnar
literówka
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Odnośnie DS18B20, czy tam nie wkradło się parę błędów? Przykładowo sprawdzanie poprawności wywołania RESET przez USART - funkcja sprawdza, czy odczytana wartość jest różna od 0xf0 - to za bardzo nie ma sensu. Jeśli nie ma połączenia - odczytaną wartością będzie 0x00, czyli funkcja zwróci HAL_OK, co jest moim zdaniem błędem. Nie wykryjemy niepodłączonego czujnika. W rzeczywistości DS zwraca 0xe0, czyli 0b1110000 przy poprawnej inicjacji. W razie braku pewności, można sprawdzić, czy chociażby jest to wartość różna od 0x00, albo 0x00 i 0xff, co zdarzy się kiedy na tej linii jest stały stan wysoki lub niski.

Innym błędem jest brak sprawdzania wyniku funkcji set_baudrate() (która w dodatku nic nie zwraca, a powinna zwracać status), oraz HAL_UART_Transmit() i HAL_UART_Receive(), które zwracają status, ale jest on pomijany. Jeśli USART został skonfigurowany nieprawidłowo, lub niezainicjowany, już tu może być wykryty błąd i zwrócony wcześnie, bez próby wykonania odczytu, który, jak sprawdzałem - może zwyczajnie się zawiesić czekając na timeout.

Kosztowało mnie to troszkę kombinowania w sytuacji, kiedy mój konkretny discovery board nie widział pina od TX. Reset przechodził, a nie powinien. Ba - odłączyłem mu druta od TX-a i nadal reset przechodził. Potem read i write przechodziły, chociaż też nie powinny bez podłączonego kabla.

Może nie jest błędem, ale lekkim "code smell" ten "if" w funkcji write_bit(). Nie prościej napisać "uint8_t data_out = value ? 0xff : 0x00"?

No i tak na marginesie, na koniec funkcję ds18B20_init() można usunąć, nasz timer jest już niepotrzebny jak używamy USART-a. A że reset i tak trzeba zawsze wysłać do odczytu DS-a, więc jedyny "init" jaki się wtedy robi to ustawienie taktowania USART-a, ale znów - tu też większość kodu jest niepotrzebna. Jedynie linia ustawiająca baudrate i linia wywołująca init. Przecież pozostałe parametry zostały już wcześniej ustawione i nie zmieniają one swoich wartości (co z resztą przetestowałem na kilku różnych STM-ach i USART-ach).

Tan na marginesie, wersja poprawiona: https://gist.github.com/HTD/07f8ecd36f533382cddf814d2b44b219

Edytowano przez HTD
  • Lubię! 2
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

@HTD, witam na forum i dziękuję za merytoryczny komentarz.

W związku z tym, że ta część kursu była już bardzo długa to musieliśmy tutaj pójść na pewne ustępstwa, aby jeszcze bardziej nie rozciągać przykładów. Stąd akurat w tych przykładach celowo pominęliśmy np. sprawdzanie błędów, na które zwracaliśmy uwagę w innych częściach tego kursu. To nie jest kod produkcyjny, głównym celem było tutaj pokazanie "nietypowego" wykorzystania peryferiów sprzętów. Masz jednak oczywiście rację, że należałoby ten kod rozbudować. Analogicznie, w przypadku warunku wewnątrz write_bit() - taki zapis był celowy, ponieważ z naszych materiałów korzystają często mało doświadczeni programiści, a taki zapis jest dla nich zwyczajnie łatwiejszy w zrozumieniu.

Jeśli chodzi testowanie wartości 0xF0: jeśli nie będzie czujnika to właśnie taką wartość powinien zobaczyć odbiornik. W tym przypadku RX jest spięty z TX, neutralną wartością jest logiczne "1", natomiast STM32 i DS18B20 są podłączone jako AND "po-drucie", czyli którykolwiek nie wystawi "0", stan będzie "0". W związku z tym, jeśli nie ma DS18B20, a na TX jest 0xFF to na RX też będzie 0xFF. A jeśli na TX jest 0xF0 to na RX będzie 0xF0 - i to właśnie jest sprawdzane. Bity przesyłane są od najniższego, czyli dla 0xf0 najpierw są 4 bity o wartości "0". Więc na RX zawsze będą odczytane jako "0". Natomiast wartość wyższych bitów zależy od tego, czy DS18B20 "odpowie". Jeśli nic nie zrobi, to odczytamy same "1", co daje wartość 0xF0. Program w tej postaci jak w przykładzie wykryje poprawnie brak DS18B20. Natomiast nie wykryje "zwarcia" - to zostanie wykryte później, podczas odczytu z czujnika. Nie jest to błąd, po prostu decyzja, żeby nie wnikać w czasy odpowiedzi DS18B20. Brak układu zostanie wykryty podczas resetu, ale jeśli jest zwarcie to i tak nic dalej nie zadziała.

  • Lubię! 2
Link do komentarza
Share on other sites

@Elvis

"Read Rom [33h]

This command can only be used when there is one slave on the bus. It allows the bus master to read the slave’s 64-bit ROM code without using the Search ROM procedure. If this command is used when there is more than one slave present on the bus, a data collision will occur when all the slaves attempt to respond at the same time."

Edytowano przez matsobdev
Link do komentarza
Share on other sites

Cześć,

Niestety jak na złość mam problem z ostatnią częścią kursu. Jestem przekonany, że do kodu nie wkradł się żaden błąd oraz podłączenie jest prawidłowe. Wszystko przebiegało sprawnie do momentu w którym trzeba było sprawdzić adres dwóch czujników po utworzeniu bibliotek. Załączam plik z kodem, z góry bardzo dziękuję za pomoc.

DS18B20.zip

Link do komentarza
Share on other sites

Z frustracji zapomniałem podać tak ważnych informacji, wybaczcie.

Podpinam tylko jeden czujnik jednocześnie. Gdy odpalałem program przez debugger to zawsze wpadał w Error_Handler w momencie sprawdzenia poprawności inicjalizacji czujnika.

  if (ds18b20_init() != HAL_OK) {
    Error_Handler();
  }

Natomiast udało mi się rozwiązać problem, wygląda na to że mógł zaginąć jakiś fragment kodu generowanego przez IDE, ponowne skonfigurowanie pinu DS rozwiązało problem. Dziękuję wszystkim za odzew.

  • Lubię! 2
Link do komentarza
Share on other sites

@P-- fajnie że się udało 🙂 Cube potrafi zaskoczyć. Możesz edukacyjnie skorzystać z Gita i sprawdzać co zmienia się w plikach przy generacji kodu. Przed wygenerowaniem konfiguracji robisz commit, a później sprawdzasz różnice.

  • Lubię! 1
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.