Skocz do zawartości

Pomocna odpowiedź

Napisano

Cześć,
kontynuuję przygodę z zapisem danych sensorycznych na kartę pamięci.
W przypadku czujników inercyjnych odczytywałem 8-bitowe rejestry, dzięki czemu w dość łatwy sposób mogłem przerobić te dane na char (fragment kodu poniżej).

uint8_t my_string[(ASCII_char_No)*rounds];
uint8_t MPU9250_Data_A[14];

sprintf(&my_string[(ASCII_char_No)*(round_No-1)],
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
MPU9250_Data_A[0],MPU9250_Data_A[1],MPU9250_Data_A[2],MPU9250_Data_A[3],MPU9250_Data_A[4],MPU9250_Data_A[5],MPU9250_Data_A[8],MPU9250_Data_A[9],MPU9250_Data_A[10],MPU9250_Data_A[11],MPU9250_Data_A[12],MPU9250_Data_A[13]);

Teraz do konwersji mam dane typu int16_t zapisane w tablicy o 16384 elementach i nie bardzo radzę sobie z nimi. W związku z rozmiarem nie wchodzi w grę ręczne wypisywanie elementów, jak poprzednim razem.

Pomożecie, jak taką tablicę danych zapisać do tablicy char? W nowej tablicy dane mogą być stałej długości, ale nie muszą. Wystarczy mi ich oddzielenie przecinkiem.

Każdy element muszę konwertować osobno w pętli, czy można to zrobić prościej?

(edytowany)

Ale taki rozwód czemu ma służyć? Sens danych się zmieni. Chociażby znak, ale jeśli już. Evil bit hack (Quake III Arena), żeby int16_t potraktować jako uint16_t: górne 8 bitów zostanie po przesunięciu o osiem w prawo, a dolne przypisać do char wprost z tego uint16_t. int16_t to pewnie z mikrofonu. Ja mam w głowie tylko pętlę, gdzie za każdym krokiem/elementem wektora int_16_t - tego początkowego zmienia się dwa elementy w wektorze końcowym char według instrukcji powyżej.

Edytowano przez matsobdev
(edytowany)

Cel główny to zapisać taką tablicę int16_t na kartę SD. Wcześniej robiłem to przy pomocy sprintf(), stąd mój pierwszy pomysł, by i tu zrobić podobnie. Natomiast niekoniecznie musi być w ten sposób. 

Najwygodniej byłoby, aby na karcie dane były od razu w postaci int-ów ze znakiem, ale ostatecznie inną postać mogę sobie przekonwertować już w PC, jeśli tak będzie łatwiej. 

Tak, są to dane z 4 mikrofonów PDM po konwersji na PCM.

Edytowano przez radek04

Tamten z MPU zapisuje szesnastkowo (rozważałem zapis binarny, ale zysk byłby nieznaczący - ten problem był poruszany w innym wątku).

Teraz muszę zapisac dane z mikrofonu. W zasadzie w dowolnej formie, byleby później (na PC) szło to "przerobić" na inty ze znakiem.

Nie bardzo rozumiem, gdzie kimbinowałem z uint16 i int16. No ale nieważne. Tam z MPU sobie (jakoś) poradziłem.

Teraz właśnie nie wiem. Kombinowałem w różny sposób, ale na karcie dzieją się cuda. Rozumiem, że tak wprost nie da rady zapisać 16-bitowych wartosci na karcie? Muszę zapisywać po 8 bitów (char), tak? 

(edytowany)

Nie, o kombinowaniu, o którym ja wspomniałem na początku, żeby zamienić najpierw int16_t na uint16_t. A funkcja typu write? Nie wiem, czy dobrze to rozumuję, sprintf przekazywał na standardowe wyjście, którym była karta (mogę coś pomieszać)? Coś takiego na Pico (no tam na serial szło) np.:

uint64_t n = 0xff00000000000000;
write(1, &n, 8);

Nie wiem, czy jakby mieć tą tablicę (znaczy jej pierwszy element) i podać nie 8, a tyle bajtów ile ma cała tablica. Może tutaj coś ciekawszego.

Edytowano przez matsobdev

Korzystam z FATFS, po uzyskaniu tablichy char-ów (dzięki sprintf) ribie zapis funkcją f_write(). Teraz chcialem analogicznie, ale okazało się, że 16-bitowe dane są dużo bardziej problematyczne.

(edytowany)

To tylko zostaje przerobić na 8 bitów, dwa razy więcej elementów, mierzyć ile to zajmie czasu. Np na Pico coś takiego działa:

#include <stdio.h>
#include "pico/stdlib.h"
#include <unistd.h>

void main() {
	stdio_init_all();
	stdio_set_translate_crlf(&stdio_usb, false);
	uint64_t i[] = {0xaa00000000000000};
	uint64_t j = 0xbb00000000000000;
    while (true) {
		fwrite(i, 8, 1, stdout);
		write(1, &j, 8);
		sleep_ms(500);
    }
}

Tylko fwrite() nie działa w sumie. Długo, długo nic, na raz wydrukuje kilkadziesiąt pozycji i znowu nic. Coś to wygląda jakby zapełniło bufor i wszystko na raz. Zobacz to. Zawsze więcej niż 1 bajt na wyjście. Albo tak, też więcej niż jeden bajt:

uint64_t i[] = {0xaa00000000000000, 0xbb00000000000000, 0xcc00000000000000,
                0xdd00000000000000, 0xee00000000000000, 0xff00000000000000};
sleep_ms(5000);
while (true) {
	fwrite(i, 8, 6, stdout);
	write(1, &i, 48);
	sleep_ms(50);
}

Jak to ma się do f_write na STM, nie wiem. Zostaje pierwsze zdanie. Pewnie będzie szybsze niż sprintf.

Powyższe to tak jak wcześniej powiedziane, serial. Nie możesz robić podziału na dwa 8 bitowe podczas pobierania danych z mikrofonu? Zamiast do 16 bitowej, to dzielisz i do 8 bitowej od razu zapisujesz - mniej pamięci na bufor, bez przerzucania z jednego do drugiego.

@radek04 W sumie tak, jak masz dane w buforze, z jakiegoś DMA, czy jak tam pozyskujesz je, to przed zapisem przerzucenie do drugiego, jeśli nie można w międzyczasie tak zapisywać (po 8 bitów) i normalnie tak jak f_write używałeś, albo jak tutaj, ale to sam wiesz jak już. Temat zamknięty, ale ten sprintf (teraz wiem do czego służy) też można takim przypisaniem z rejestrów zastąpić, może będzie szybciej.

Edytowano przez matsobdev
  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...