Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'DMA'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - DIY
    • Projekty - DIY roboty
    • Projekty - DIY (mini)
    • Projekty - DIY (początkujący)
    • Projekty - DIY w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie

Kategorie

  • Quizy o elektronice
  • Quizy do kursu elektroniki I
  • Quizy do kursu elektroniki II
  • Quizy do kursów Arduino
  • Quizy do kursu STM32L4
  • Quizy do pozostałych kursów

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Imię


Strona

Znaleziono 4 wyniki

  1. Cześć, od dłuższego czasu pracuję nad projektem o poniższych założeniach: - odczyt z 4 czujników IMU (24 osie) - szybkość akwizycji - 400-500 pomiarów na sekundę - mikrokontroler z serii F7 (wymogi późniejszej rozbudowy) - zapis na kartę SD lub bezprzewodowe przesłanie danych. Wpis ten jest tak naprawdę kontynuacją wątku STM32 UART wysyłanie danych typu uint16_t. Okazało się, że pomysł z bezprzewodowym przesyłaniem danych po UART jest trudny/nierealny do zrealizowania, więc postanowiłem wykorzystać zapis na kartę pamięci. Było z tym mnóstwo problemów (z zainteresowanymi chętnie się podzielę), ale koniec końców udało mi się zrealizować zapis w 4-bitowym trybie SDMMC. Obecnie zmagam się z problemem odpowiedniej szybkości pobierania danych z czterech MPU9250 podłączonych do dwóch linii I2C i ich zapisem na SD. Realizuję to w przerwaniu timera, które odpowiada za stałą szybkość akwizycji. Ustawiając zegary na maksymalne wartości pozwalające na skuteczny zapis na SD, podczas 1-minutowych testów z fs=400 Hz całkowity czas operacji wynosi ok. 65 sekund. Np. dla 100 Hz jest to dokładnie 60 sekund. Zatem program "nie wyrabia" owych 400 Hz. Wpadłem na pomysł, żeby czujniki podłączyć do 4 osobnych magistrali I2C i używać trybu IT, ale mój procesor ma tylko 1 pin (PC9) odpowiedzialny zarówno za I2C3_SDA, jak i MMC1_D1, czyli w moim przypadku nie da rady go użyć. Musiałbym wykorzystać wersję przynajmniej 176-pinową, a tych nie znalazłem dostępnych w Polsce. Póki co, aby nieco przyśpieszyć akwizycję, zastosowałem pewien (dziwny) trick i z każdej I2C jeden czujnik obsługuję trybem blokującym, a drugi z użyciem przerwania. Poniżej fragment kodu: uint8_t my_string[4*24+1]; //bez spacji void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM10) //przerwanie pochodzi od timera 10 { HAL_I2C_Mem_Read(&hi2c1, MPU9250_ACC_ADDRESS_A, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_A, 14, 50); //14 pomiarów od razu HAL_I2C_Mem_Read_IT(&hi2c1, MPU9250_ACC_ADDRESS_B, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_B, 14); //14 pomiarów od razu HAL_I2C_Mem_Read(&hi2c2, MPU9250_ACC_ADDRESS_C, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_C, 14, 50); //14 pomiarów od razu HAL_I2C_Mem_Read_IT(&hi2c2, MPU9250_ACC_ADDRESS_D, MPU9250_ACCEL_XOUT_H, 1, MPU9250_Data_D, 14); //14 pomiarów od razu timer_tim10++; if (timer_tim10 <= 6*4000) { sprintf(my_string, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%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], MPU9250_Data_B[0],MPU9250_Data_B[1],MPU9250_Data_B[2],MPU9250_Data_B[3],MPU9250_Data_B[4],MPU9250_Data_B[5],MPU9250_Data_B[8],MPU9250_Data_B[9],MPU9250_Data_B[10],MPU9250_Data_B[11],MPU9250_Data_B[12],MPU9250_Data_B[13], MPU9250_Data_C[0],MPU9250_Data_C[1],MPU9250_Data_C[2],MPU9250_Data_C[3],MPU9250_Data_C[4],MPU9250_Data_C[5],MPU9250_Data_C[8],MPU9250_Data_C[9],MPU9250_Data_C[10],MPU9250_Data_C[11],MPU9250_Data_C[12],MPU9250_Data_C[13], MPU9250_Data_D[0],MPU9250_Data_D[1],MPU9250_Data_D[2],MPU9250_Data_D[3],MPU9250_Data_D[4],MPU9250_Data_D[5],MPU9250_Data_D[8],MPU9250_Data_D[9],MPU9250_Data_D[10],MPU9250_Data_D[11],MPU9250_Data_D[12],MPU9250_Data_D[13]); if(f_lseek(&fil, f_size(&fil)) != HAL_OK) printf("f_lseek ERROR\n"); if(f_write(&fil, my_string, sizeof(my_string), &numread) != HAL_OK) printf("f_write ERROR\n"); }else if (timer_tim10 == 6*4000+1) { close_file(); unmount_sd(); printf("done\n"); } } } Jak widać (mam nadzieję), czujnik A i B znajdują się na I2C1, C i D na I2C2. B i D odczytuję z użyciem przerwania (IT) po zakończeniu odczytu odpowiednio A i C. Jak mogę to zrobić szybciej? Domyślam się, że DMA mogłoby pomóc, ale kompletnie nie umiem tego zrobić. Zwykła zamiana _IT na _DMA nie działa. W sieci znalazłem mnóstwo wątków z problemami użycia DMA na F7, ale bez skutecznych (w moim przypadku) rozwiązań. Proszę tu o Waszą pomoc. A może mogę jakoś przyśpieszyć zapis na kartę pamięci? Czy tutaj można jakoś zaprząc do pacy DMA lub inny szybki mechanizm? Wydaje mi się też, że funkcja sprintf zajmuje sporo czasu. Usunąłem z niej wszystkie zbędne znaki i przesyłam jedynie po 2 na każdy rejestr oraz znak nowej linii po zapisaniu wszystkich potrzebnych rejestrów (w liczbie 48), czyli w sumie 97 znaków w każdej iteracji. Czy są jakieś szybsze alternatywy? Trochę się rozpisałem. Temat jest wielowątkowy, generuje różne problemy i zaskakujące niespodzianki. Starałem się zawrzeć tylko najważniejsze informacje. Testy przeprowadzam na Nucleo F746. Docelowo chciałem użyć 100-pinowego F756VGT6, ale może być inny (dostępny od ręki) z serii F7. STM32CubeIDE 1.10.1 MCU Package 1.17.0
  2. Cześć. Może ktoś mi podpowie w czym jest problem, że nie mogę uruchomić odczytu z ADC z zastosowaniem DMA. Jeśli czytam jeden pomiar to nie ma problemu, ale gdy chce uruchomić ich kilka w trybie ciągłym to nie dostaję wogóle przerwania od zakończonego pomiaru. Procesor STM32H743. Poniżej zrzuty ekranu pokazujące fragment kodu oraz ustawienia w CubeMX
  3. Witam, jak osiągnąć maksymalny sampling rate na ADC + DMA? SysClock ustawiony na 72Mhz. APB2CLKDivider i APB1CLKDivider ustawione na 1. ADC leci w ContinuousConvMode = ENABLE i ExternalTrigConv = ADC_SOFTWARE_START; SamplingTime = ADC_SAMPLETIME_13CYCLES_5; DMA zapisuje do bufora[128] z jednego kanału ADC i wysyłam sobie to na ekran co jakiś czas. Oczekuję zapisu badania sygnału do 20kHz, jak na razie nie łapie mi poprawnie nawet sygnału 9kHz, Co tu zrobić, dać zewnętrzny trigger z jakiegoś timera ustawionego na przerwanie co 44.1kHz? Jest to szybsze?
  4. Dzień dobry, Korzystam z STM32F103C8, oprogramowanie CUBEIDE, debugowanie st-link v2. Problem polega na tym, że dobrze działające DMA w circular mode zawiesza program gdy dodaję do niego 4 linie obliczeń (sinusy, cosinusy, arcusy), #include <math.h> wpisałem. obliczenia z wyłączoną konwersją również wykonują się poprawnie /* USER CODE BEGIN 0 */ void set_coordinate (void) { ST=hour+(4*(18-15)); D = 23.45f*sinf(360*((284.f+day_of_year)/365)*rad)*rad;//////////////////////////////////blad Height = asinf(sinf(D)*sinf(W)+cosf(D)*cosf(W)*cosf((15*(hour-12))*rad))*rad;// nie dochodzi do tych obliczen A = acosf((sinf(D)-sinf(Height)*sinf(W))/(cosf(Height)*cosf(W)))*deg; H=Height*deg; } /* USER CODE BEGIN 2 */ HAL_ADC_Start_DMA(&hadc1, adc_val, 4); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ // set_coordinate(); motor_rad_1 = adc_val[0]/13.65;//podzielic przez zakres 4095/300 stopni motor_rad_2 = adc_val[1]/13.65; } /* USER CODE END 3 */ } hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 4; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_1; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ } /* Enable DMA controller clock */ static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Channel1_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); } Z kodu wyciąłem tylko najważniejsze rzeczy, mogę zamieścić dodatkowo screeny z konfiguracji ADC,DMA Nie wyskakuje żaden błąd, tylko program zawiesza się na liniach obliczeń. Dlaczego obliczenia zawieszają program? Czy to nie jest tak, że DMA nie korzysta z procesora? Moim pomysłem byłoby zastosowanie wyzwalania konwersji przez licznik, wykonywanie jej co 200 ms, ale nie wiem, czy ma to sens, drugim pomysłem jest odczyt ADC zaraz po obliczeniach, ale nie mam pojęcia jak się do tego zabrać. z góry dziękuję za odpowiedź
×
×
  • 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.