Skocz do zawartości
Komentator

Kurs STM32 F1 HAL - #8 - bezpośredni dostęp do pamięci

Pomocna odpowiedź

html_mig_img
Podczas 6 części kursu poznaliśmy możliwości przetwornika ADC. Uruchamiane przykłady były jednak pod pewnym względem niedoskonałe.Dziś poznamy nową, efektywną metodę. Zamiast aktywnie czekać na odczyt, wykorzystamy moduł DMA, który będzie robił to w tle.

UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.

Przeczytaj całość »

Poniżej znajdują się komentarze powiązane z tym wpisem.

Udostępnij ten post


Link to post
Share on other sites

Dzień dobry

1) Z jaką częstotliwością pracuje DMA tzn jak szybko jest odświeżana zawartość pamięci w przypadku kopiowania z ADC do pamięci?

2)Jak rozwiązano problem jednoczesnego dostępu do komórek pamięci przez DMA i procedurę?

Udostępnij ten post


Link to post
Share on other sites

To jak często są wykonywane odczyty z przetwornika ustala konfiguracja ADC - samo DMA ma tutaj niewiele do powiedzenia. Po pobraniu kolejnej próbki moduł generuje zdarzenie, w wyniku którego DMA odczytuje dane z rejestru i zapisuje w pamięci. Częstotliwość próbkowania można obliczyć znając częstotliwość zegara ADC, czas samplowania oraz przetwarzania danych.

Natomiast jak chodzi o jednoczesny dostęp to opisywany przykład jest faktycznie mocno uproszczony. Typowe zastosowania DMA wykorzystują raczej dwa bufory - jeden do zbierania danych z przetwornika oraz drugi, w którym są dane gotowe dla CPU. Chcieliśmy jednak uprościć opisywane przykłady, więc po prostu CPU odczytuje dane zapisywane przez DMA.

Udostępnij ten post


Link to post
Share on other sites

Czy procedura inicjalizacji DMA z I2C wygląda inaczej ? Jeżeli tak to czy mogłbyś przybliżyć mi różnice.

Udostępnij ten post


Link to post
Share on other sites

W zadaniu gdzie kopiowane są dane z pamięci do pamięci można jeszcze przyspieszyć cały proces 4-krotnie przez kopiowanie bloków po 4 bajty jednocześnie (DMA_PDATAALIGN_WORD zamiast DMA_PDATAALIGN_BYTE). Trzeba tylko pamiętać żeby zmieną BUFFER_SIZE podzielić przez 4 (przesunąć logicznie o 2 bity w prawo).

Fragmenty kodu przed zmianą:

void copy_dma()
{
    HAL_DMA_Start(&dma, (uint32_t)src_buffer, (uint32_t)dst_buffer, BUFFER_SIZE);
    HAL_DMA_PollForTransfer(&dma, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
}

    dma.Instance = DMA1_Channel1;
    dma.Init.Direction = DMA_MEMORY_TO_MEMORY;
    dma.Init.PeriphInc = DMA_PINC_ENABLE;
    dma.Init.MemInc = DMA_MINC_ENABLE;
    dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    dma.Init.MemDataAlignment = DMA_PDATAALIGN_BYTE;
    dma.Init.Mode = DMA_NORMAL;
    dma.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&dma);

Fragmenty kodu po zmianie:

void copy_DMA(void) {
	HAL_DMA_Start(&dma, (uint32_t)src_buffer, (uint32_t)dst_buffer, (BUFFER_SIZE >> 2));
	HAL_DMA_PollForTransfer(&dma, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
}

	dma.Instance = DMA1_Channel1;
	dma.Init.Mode = DMA_NORMAL;
	dma.Init.Direction = DMA_MEMORY_TO_MEMORY;
	dma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
	dma.Init.MemInc = DMA_MINC_ENABLE;
	dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
	dma.Init.PeriphInc = DMA_PINC_ENABLE;
	dma.Init.Priority = DMA_PRIORITY_HIGH;
	HAL_DMA_Init(&dma);

Mam nadzieję że komuś się ta informacja przyda.

Pozdrawiam

  • Lubię! 1

Udostępnij ten post


Link to post
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!

Gość
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...