Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 12 kwi 2026, o 13:21


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 7 ] 
Autor Wiadomość
PostNapisane: 17 sie 2014, o 19:06 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 17 sie 2014
Posty: 8
Pomógł: 0

To mój pierwszy post na Forum więc:
Witam wszystkich serdecznie
Jestem szczęśliwym posiadaczem BlueBooka i zestawu firmy Gotronik na ATmegę16/32 ver2
Mój problem dotyczy transmisji danych przez SPI ale kod ten może bez problemu zostać zaadoptowany do innych interfejsów.
Opis stanowiska:
mikrokontrolery ATmega32 (w układzie 1 Master wiele Slave)
Sprzętowe SPI
Dane dla zaoszczędzenia wysyłanych bajtów wysyłane będą w postaci szesnastkowej (uint8_t w postaci dziesiętnej potrzebuje do 3 bajtów, w postaci hex do dwóch bajtów analogicznie uint16_t 5 bajtów w dec, a 4 w hex). Jest to mój pomysł na to jak "zmniejszyć" troszkę wysyłane zmienne, jeżeli sposób ten jest nieoptymalny/ niepotrzebny nie będę się go trzymał :)
Ramka danych tworzona jest przy pomocy funckji sprintf a oto przykładowa ramka:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Następnie wysyłamy ramkę "str" i gotowe ... po stronie nadawcy, ale problem pojawił się po stronie odbiorcy :(
Oczywiście w BlueBook-u w Rozdziale z UDP jest super wyjaśnione jak sobie poradzić z podziałem ramki.
Pozwala na to (w przykładzie z książki) funkcja np. prase_set_led(); której działanie opiera się na funkcji strtok_r()
Jednak problem mam z przejścia z np. ciągu znaków A4C1 uzyskanych przy pomocy strtok_r() na wartość uint16_t = 42177
Jakiego narzędzia/ funkcji użyć ? Gdzie szukać odpowiedzi ? :)
Jeżeli ktoś ogólnie ma inny lepszy sposób na transmisję danych po SPI proszę o pomoc :)
i z góry dziękuję za wszelkie uwagi :)


ROZWIĄZANIE:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


A oto otrzymany rezultat:

Obrazek
x
Obrazek

Przebiegi otrzymałem przy pomocy analizatora stanów logicznych Saleae logic , który polecam początkującym takim jak ja, aby na własne oczy zobaczyć "co w trawie piszczy" (oczywiście zdaję sobie sprawę, że to nie oscyloskop i należy o tym pamiętać).

_________________
sig off ;(



Ostatnio edytowano 3 wrz 2014, o 12:49 przez Unter, łącznie edytowano 2 razy

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sie 2014, o 22:18 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Najlepszym rozwiązaniem jest oczywiście transmisja danych w sposób bezpośredni (bez użycia niepotrzebnych konwersji). Lepiej wysyłać bajty tzn. zamiast '%X' dać '%c' i w razie typów większych od 1B stosować przesunięcia bitowe.

Parsowanie otrzymanych danych można dokonywać na wiele różnych sposobów, począwszy od FSM (skończonej maszyny stanów) aż po analityczną analizę łańcuchów znakowych.

Pierwszej metody opisywał nie będę, mimo iż jest ona podstawą wszystkich protokołów komunikacyjnych, ponieważ jest tego mnóstwo wszędzie. Natomiast odnośnie drugiej, można użyć funkcji "strchr" do wyszukania separatora (znaku '|'), który defacto nie ma sensu w przypadku transmisji "bajtowej". Następnie wyszukany fragment można skonwertować przy użyciu funkcji "strtol".

Parsowanie kolejnych danych może wyglądać w ten sposób (dodatkowo niezbędna pętla):

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Jednak zdecydowanie lepiej nie dokonywać żadnych konwersji, jeżeli urządzenie odbiorcze tego nie wymaga.



Ostatnio edytowano 17 sie 2014, o 22:40 przez atmel, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sie 2014, o 22:31 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 17 sie 2014
Posty: 8
Pomógł: 0

Rozumiem ale wydawało mi się, że jeżeli tak zrobię przy wysłaniu wartości zmiennej typu uint8_t równej 124
funkcja odpowiedzialna za dzielenie odebranego z SPI ciągu znaków odczyta go jako separator "|" (kod ASCII) [ponieważ jakiś ten separator musi być :) ]... to samo wydaje mi się że tyczy się wysyłania zera ... która odpowiada według ASCII NULL i może być błędnie odczytane jako koniec ciągu znaków ??
Jeżeli mylę się to proszę o wyprowadzenie mnie z błędu (na dokładnie tą chwilę nie posiadam drugiego mikrokontrolera aby wykonać test)

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sie 2014, o 22:49 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Zgadza się, jednak nie do końca się do tego tak podchodzi. Separatory zdecydowanie zmniejszają prędkość transmisji i nie ma sensu ich implementować. Jeśli znane są typy oraz ilość wysyłanych danych to zarówno nadawca jak i odbiorca utrzyma prawidłową łączność. Ważne są jedynie nagłówki i ewentualnie znaki terminatora (prefix, suffix) np.: [d1d2d3...].
Jeśli ilość/długość danych jest nieznana to tutaj w grę wchodzi jakiś własny "protokół", który powiedzmy w pierwszym swoim bajcie przechowuje taką informacje.

Identycznie sprawa się ma odnośnie wysyłania 0. Po prostu nie analizujemy danych jako ciągi znakowe, a jako sekwencje danych do których 0 się również zalicza. W takim wypadku odpadają oczywiście wszystkie metody analizy tekstu, a w grę wchodzi właśnie automat lub pętla odbiorcza, która jest niejako jego prostszą wersją (zmienna licznikowa jest informacją o aktualnym stanie automatu).



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sie 2014, o 23:37 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 17 sie 2014
Posty: 8
Pomógł: 0

Ilość zmiennych jak i ich kolejność w moim przypadku będzie znana po obu stronach więc przychylę się do rezygnacji z separatorów. Funkcja którą próbuję stworzyć będzie miała za zadanie odebrane dane wysłane w jednym ciągu przypisać do odpowiednich zmiennych.
Gdy powstanie swego rodzaju "ramka danych" będzie ona uniwersalna bo jej obróbka dla różnych interfejsów będzie taka sama, dlatego własnie mi na tym zależy.
Oczywiście dziękuję za dotychczasową pomoc atmel :)


Edit:
W temacie "Odbieranie danych z RS232 i dekodowanie" chyba znalazłem sposób o który chodziło
Cytuj:
Wysyłaj komunikaty o stałej długości, czyli (preambuła, cyfra1, cyfra2, ...cyfraN).
Po stronie odbiornika czekasz na bajt o wartości preambuły.
Jeżeli przyjdzie, to wiesz że jest to początek komunikatu i zaraz nadejdzie znana liczba bajtów.
Czyli (w pseudokodzie):

przerwanie_od_zdarzenia_rx_complete:
Rx_data = Udr0
select case stan_odbioru
case czekam_na_preambule
if rx_data=preambula then stan_odbioru=poczatek_komunikatu; licznik=0

case poczatek_komunikatu
bufor(licznik)=rx_data
incr licznik
if licznik=dlugosc_komunikatu then stan_odbioru=koniec

end select

W petli glownej sprawdzasz czy stan_odbioru=koniec i robisz z wynikiem co tam chcesz, potem ustawiasz stan_odbioru=czekam_na_preambule
Można obudować to potem jakąś sumą kontrolną, timeoutem, etc...

Teraz jeszcze ubrać to w kod ... dzisiaj już nie dam rady ale jak tylko mi się uda postaram się to wrzucić
Nie mam jeszcze koncepcji jak napisać funkcję do wysyłania danych w ten sposób by pasowała do różnych interfejsów (UART, SPI, Ethernet(UDP))

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 18 sie 2014, o 00:49 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Dokładnie o to chodziło. Mamy tutaj przykład typowej maszyny stanów (dwóch :) ).
Takie rozwiązanie doskonale ujednolica kod i w prosty sposób umożliwia dowolne modyfikowanie ramki.

Rozwiązaniem uniwersalnej funkcji do wysyłki/odbioru danych są oczywiście "callback'i" tzn. wskaźniki na funkcje (dedykowane dla każdego z interfejsów). Prościej mówiąc, każdy z interfejsów wywołuje funkcję w identyczny sposób, ale dla każdego jej działanie (źródło danych) jest inne.

Tego tematu jednak nie śmiem powielać po tak doskonałych poradniach Mirka, do których serdecznie odsyłam.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 31 sie 2014, o 19:29 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 17 sie 2014
Posty: 8
Pomógł: 0

Zgodnie z radami użytkownika atmel poradziłem sobie z transmisją przy użyciu interfejsu SPI.
Ogromne podziękowania za pomoc :)
Powstały kod wklejam poniżej, niestety jest on "wyrwany" z mojego projektu więc jeżeli czegoś brakuje, lub coś jest źle proszę dać znać.
Ramki zapisywane są w dwóch uniach, jedna zawiera dane wysyłane, a druga odbierane. Do uni można już w prosty sposób "dobrać się" za pomocą : uniaramka2.ramka.zmienna1
Callback-i i Eventy na razie zostawiam na później, zaraz po tym jak zdobędę greenbook-a :)
Rozwiązanie wklejam również od pierwszego posta
Pozdrawiam serdecznie
Przemek

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


A oto otrzymany rezultat:

Obrazek

Obrazek

Przebiegi otrzymałem przy pomocy analizatora stanów logicznych Saleae logic , który polecam początkującym takim jak ja, aby na własne oczy zobaczyć "co w trawie piszczy" (oczywiście zdaję sobie sprawę, że to nie oscyloskop i należy o tym pamiętać).

[ panie szanowny kolego unter - bardzo proszę wstawiać miniaturki obrazków jeśli są TAK DUŻE bo rozjeżdża się forum .... jeśli kolega tego nie poprawi to będę zmuszony usunąć obrazki :( - mirekk36 ]

Edit: Wysyłałem oba obrazki przez forum i za każdym razem do tej grafiki nie tworzyło miniaturki
Przyznam szczerze, że nie mam pojęcia dlaczego... pomogło wklejenie obrazka do pliku który "dostawał" miniaturkę i wysłanie go na forum.
Za problemy przepraszam

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 7 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 3 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO