Skocz do zawartości

STM32 UART wysyłanie danych typu uint16_t


radek04

Pomocna odpowiedź

A próbowałeś  czegoś takiego

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "string.h"
/* USER CODE END Includes */

i np.

char  msg[50];
uint32_t  but[3];

i

 /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim1);
  HAL_ADC_Start_DMA(&hadc1,but,3);

 

	sprintf(msg, " %ld %ld %ld\r\n",but[0],but[1],but[2] );

			  		  CDC_Transmit_FS(msg,strlen(msg));

To są fragmenty działającego programu odczytującego dane z trzech wejść ADC w stm32f103  i te dane są wysyłane przez USB do odbiornika z USB w moim przypadku do komputera.Zamiast USB dostosuj odpowiednio do UART. Opis sprintf()  jest na stronie https://www.tutorialspoint.com/c_standard_library/c_function_sprintf.htm   a List of all format specifiers in C programming na  stronie  https://codeforwin.org/2015/05/list-of-all-format-specifiers-in-c-programming.html .

O ile dobrze zrozumiałem to z jednego czujnika 9250  odczytujesz 18 bajtów(x,y,z - każda oś 2 bajty ;Gx,Gy,Gz po 2 bajty na oś; Mx,My,Mz po dwa bajty na oś)  czyli z 4 czujników 72bajty.Tak? Jeśli tak to 72x11(8 bitów +bit startu 2 bity stopu)=792 bityx500=396000bity/sek. Dużo!

Wydaje się,że zagadnienie nie jest proste bo warunki jakie sobie narzuciłeś nie są łatwe do spełnienia. 2ms na odczytanie, spakowanie z 4 akcelerometrów danych jest wyzwaniem ale ten Twój STM32h7 ma możliwości.Nie wiem czy do odczytu używasz I2C czy SPI.Nie wiem czy używasz jednego I2C lub SPI czy też dla każdego oddzielnie I2C lub SPI.Jeśli używasz jednego I2C lub SPI  to jest kłopot z wygospodarowaniem czasu.Natomiast jeśli użyjesz dla każdego inne SPI lub I2C i to I2C Fast Mode Plus oraz DMA no to raczej odniesiesz sukces.Według specyfikacji UART możesz  ustawić na transmisję w MHz.Pytanie jest do jakiego urządzenia chcesz to przesłać bo to limituje transmisję.A może w ogóle nie  trzeba używać UART.

Edytowano przez szymonw
brak umiejętności posługiwania się kalkulatorem w związku z tym wyszła zdecydowanie zawyżona liczba
Link do komentarza
Share on other sites

(edytowany)

Takiego kogu nie używałem. Próbowałem nieco inaczej ze sprintf i zauważyłem, że to mocno spowalnia transmisję. Ale może robiłem coś źle.
Używam tylko akcelerometru i żyroskopu, czyli 12 bajtów x 4 czujniki. Póki co korzystam z 2 linii I2C po 2 czujniki na linię, ale mogę zmienić konfigurację na 4 linie po 1 czujniku.

Na razie przesyłam gołe bajty. Dla większej czytelności przyjąłem 16 bajtów na czujnik zamiast docelowych 12.

uint8_t MPU_test[] =
{
	0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xaf, //czujnik A - 16 bajtów
	0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0xbf, //czujnik B - 16 bajtów
	0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0xcf, //czujnik C - 16 bajtów
	0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0xdf  //czujnik D - 16 bajtów
};

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == TIM10)	// przerwanie pochodzi od timera_10 - 500 Hz
	{
		timer_tim10++;
		if (timer_tim10 <= 500) // 1 sekunda
		{
			HAL_UART_Transmit(&huart3, MPU_test, sizeof(MPU_test), 10);
		}
    }
}

W czasie 1 sekundy przesyłam dokładnie 32000 bajtów (2000 linie po 16 bajtów). W tym czasie nie wykonują się (jawnie) żadne inne operacje. Dziwi mnie to, bo baudrate mam teraz 115200 bits/s. Ja ma się jedno do drugiego? 115200 bps to inaczej 14400 Bps, tak? Czy niekoniecznie?

W załączniku fragment danych zapisanych z terminala CoolTerm.

Pomimo że w przerwaniu zliczam do 500, to przesył danych odbywa się dłużej niż 1 sekundę. Nie wiem, czy gdzieś w buforze się zapisuje i przesyła dane aż do opróżnienia bufora (to jest dla mnie OK), czy jednak program działa dłużej niż sekundę (to już nie jest OK).Zrzut ekranu 2022-11-10 220102.png

Edit:
Dodałem mrugającą diodę bezpośrednio przed HAL_UART_Transmit() i mruga ona przez ok. 3 sekundy, a nie sekundę. Dlaczego?

Edit 2:
Po zamianie HAL_UART_Transmit() na HAL_UART_Transmit_IT() dioda mruga 1 sekundę i przesyłanych jest 10688 Bajtów (668 linii).
To już wydaje się być prawdziwym wynikiem biorąc pod uwagę bity stopu i takie tam...

Edit 3:
Po zmianie boudrate na 230400 uzyskałem dokładnie 1000 linii po 16 bajtów, czyli równo 16 000 B.
Jeśli ograniczę się do akcelerometru lub żyroskopu, to teoretycznie mi wystarczy. Ale przy łączności bezprzewodowej to już strach. Pewnie musiałbym sprawdzać poprawność przesłanych danych. I nawet nie wiem, czy moduły BT lub WiFi w ogóle obsługują takie wartości.

Edytowano przez radek04
Link do komentarza
Share on other sites

1 minutę temu, Elvis napisał:

115200bps to jakieś 11520 B/s, więc przesłanie 32000 bajtów zajmie co najmniej 2778 ms. To chyba się zgadza.

Zrobiłem Edit 2. Faktycznie wszystko pasuje, ale jednak zwykły HAL_UART_Transmit() mnie "oszukuje".

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

(edytowany)

Mam kilka pomysłów:

1. (chyba głupi) Czy zamiast używać 2 rejestrów (2 bajtów) czujnika, mogę odczytywać jedynie starszy bajt? Ale wtedy precyzja spadnie mi 256 razy, prawda? Sporo...

2. Użyć np. 2 modułów BT (albo BT i WiFi), jednym przesyłać dane z akcelerometru, drugim z żyroskopu jednocześnie na 2 różnych UART-ach?

3. Zamienić UART na zapis na kartę SD. Orientujecie się, czy z taką ilością danych uda mi się zapisywać wszystko w czasie rzeczywistym?

4. Czy przypadkiem poprzez WiFi (np. ESP8266) nie jestem w stanie ustawić dużo wyższego boud rate? CoolTerm nie pozwala na większe predkości, ale może jakims innym terminalem (albo w zupełnie inny sposób)?

Edytowano przez radek04
Link do komentarza
Share on other sites

Jaki zakres wartości przyspieszeń liniowych i prędkości kątowych będzie mierzony? Jaka jest wymagana dokładność pomiaru? Zawsze schodzi w grę jakaś kompresja. Albo gotowa biblioteka, albo coś własnego, np. pierwsza liczba podana w całości, a następne jako plus/minus mała różnica. Zapis na kartę pewnie da radę, tylko trzeba by mieć np. dwa bufory i albo całość jako ciągły zapis, albo duże paczki, nie np. 500 razy na sekundę komplet danych dla czujników zapisywać, kończyć zapis i od nowa zapisywać. BT/WiFi - zawsze można wykorzystać inny mikrokontroler, który już ma BT/WiFi bez pośrednika w postaci UARTu.

Link do komentarza
Share on other sites

Co do pomysłów:

1) Odczytywanie pojedynczego bajtu mija się z celem - wysłanie adresu rejestru i odczytanie rejestru trwa co najmniej tyle samo (jeśli nie dłużej) co wczytanie dwóch kolejnych bajtów. A biorąc pod uwagę, że możesz z czujnika odczytać w jednej transakcji całą tablicę to już w ogóle traci sens.

Możesz natomiast ograniczyć się np. do 12 bitów (zależy do czego wykorzystujesz dane) - dokładność, czyli w trzech bajtach wysyłasz dwie liczby (w sumie dziewięć bajtów zamiast dwunastu na jeden czujnik). Dokładność 0.1° wystarczy? Czy tam 0.025% w przyspieszeniu?

3) Prędkość zapisu na kartę to też nie jest turbo - może ktoś inny się wypowie, ja z tym miałem niewiele do czynienia i to tylko w trybie SPI.

4) Baud rate i WiFi nie mają ze sobą nic wspólnego. Teoretycznie można osiągnąć większe prędkości, w praktyce średnio to się sprawdza. Ogólnie układy typu ESP działają świetnie przy krótkich paczkach, przy ciągłej transmisji strasznie kwękają.

Pomysł z kompresja jest w teorii fajny... tylko kto będzie robił kompresję po stronie nadajnika? Bo w porównaniu z najprostszymi algorytmami kompresji sprintf to demon prędkości... w dodatku można kompresować tylko dłuższe fragmentu (np. z 500 pomiarów), w przypadku pojedynczego pomiaru raczej nie istnieją odpowiednie algorytmy.

 

 

Link do komentarza
Share on other sites

Wartość z pojedynczego pomiaru nie musi być wysyłana w całości, ale też wpływ ma na to rozpiętość przedziału pomiarowego. Np. liczby od 128 do 256 można by wysyłać 7 bitami przyjmując za poziom "zerowy" 128. 1 bit, niewiele, ale może zrobić różnicę, czy interfejs się wyrobi, czy nie.

Link do komentarza
Share on other sites

@matsobdev próbowałeś to robić z tego typu danymi (odczyty akcelerometru/żyroskopu)? W dodatku musisz wiedzieć, czy właśnie wysłano 8 czy 16 bitów. Śmiem podejrzewać, że w najlepszych przypadkach będzie to kilka procent, w najgorszych komunikat będzie dłuższy niż wielkość tablicy.

Link do komentarza
Share on other sites

14 godzin temu, szymonw napisał:

396000bity/sek. Dużo!

Duzo? My używamy protokołu działającego na porcie UART z prędkością prawie 1Mbps jeszcze w komunikacji między modułami w obie strony, na F030. A tu wystarczy tyko wysłać dane w jedną stronę. Zapakować to tylko w jeden pakiet i wysłać via DMA, w tym czasie robiąc odczyty do kolejnego pakietu. 

Jak dobrze liczę odczyt z 16 bajtów w jednej transakcji z 3 urządzeń I2C @400kHz zajmuje poniżej 2ms, więc jak będziesz robił odczyty podczas wysyłki danych po UART to jeszcze zostaje jakieś 800uS na przygotowanie danych. Ot nie używaj floatów, w ostateczności wyślij nieprzetworzone dane z MPU.

Link do komentarza
Share on other sites

W mojej karcie z akcelerometrem mpu6050  zapis jest na kartę sd  przy prędkości transmisji jest 5,25 MHz.Z prędkością transmisji 21 MHz też działa bez zarzutu.Gdybym miał budować na nowo kartę z akcelerometrem to zrobiłbym ją nie na mpu6050 czy 9250 tylko na czymś takim LIS344ALH .Dlaczego ? Bo na wyjściu jest goły sygnał analogowy co powoduje uwolnienie się od ograniczeń związanych z komunikacją I2C lub SPI do 1MHz.Z drugiej strony w zastosowaniach tak duże gęstości pomiarów są niepotrzebne.Bezwładność układów mechanicznych jest  bardzo duża i nie mierzy się jej w µs a w dziesiątkach o ile nie w setkach ms.Wracając do tematu głównego to radzę koledze Radek04 jednak ściągnąć i dobrze przeczytać datasheet 9250 oraz  mpu9250-register-map oraz adekwatny plik RMxxxx opisujący procesor stm32h7xxxx,który posiadasz.

Link do komentarza
Share on other sites

(edytowany)

Register map znam dosć dobrze, szczególnie, że ustawienie niektórych parametrów zależy od 3 różnych rejestrów. Datasheet czujnika też czytałem, ale nie wiem, o czym dokladnie piszesz. Podobnie z RM od procka. Tam jest tak wiele zagadnień... 

Szybkość taką (no może ograniczę się do 400 Hz) potrzebuję do wykrywania drgań o częstotliwości ok. 200 Hz. Faktycznie tym czujnikiem nie robiłem wcześniej tak szybkich pomiarów, ale skoro producent umożliwia pomiary z szybkościa ponad tysiąc na sekundę, to 500 Hz powinno dać mi rzetelne wyniki? Czy jestem naiwny? 

@szymonw, jesteś s stanie mi pomóc z konfiguracją zapisu na kartę SD na STMF746? Od razu mówię, że kiedyś już próbowałem i po kilku dniach sie poddałem. Ale ekspert ze mnie żaden.

Co mi da sygnał analogowy, skoro i tak muszę go przesłać cyfrowo do PC lub zapisać na SD?

Edytowano przez radek04
Link do komentarza
Share on other sites

1 godzinę temu, radek04 napisał:

W zasadzie już porzuciłem pomysł przesyłania floatów.

Samo ich przesyłanie to jeszcze pół biedy, obliczenia za to są kosztowne czasowo.

1 godzinę temu, radek04 napisał:

@kaworu, jak przesyłacie dane z predkoscią prawie 1 Mbps? Jaki to protokół?

To jest własna radosna twórczość, bo nie mogliśmy znaleźć już gotowego protokołu multimaster/CSCA działającego na rs458. Ale generalnie używaj DMA, bo możesz wtedy przygotować pakiet, rozpocząć wysyłkę i wtedy zamiast czekać na zakończenie wysyłania w jakiejś głupiej pętli zrobić obliczenia, przygotować kolejny pakiet etc. Przy okazji, przy takich prędkościach bez DMA ani rusz, bo co z tego ze uart (albo SPI) nadaje bajty szybko, jak miedzy bajtami wkradają sie długie przerwy.

Link do komentarza
Share on other sites

1 godzinę temu, kaworu napisał:

Samo ich przesyłanie to jeszcze pół biedy, obliczenia za to są kosztowne czasowo.

Akurat na F7 idzie to bardzo szybko.

DMA będzie szybsze od IT?

Już wcześniej wspominałem, że CubeIDE ma jakiś problem z UART_DMA na F7.

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.