Na rozgrzewkę:
Obliczenia zawarte w dwóch poprzednich wpisach z serii dotyczącej FFT wykonane były za pomocą płytki ewaluacyjnej STM32F401C-DISCO, w docelowym projekcie użyłem procesora STM32F103VET6, który dysponuje trzema niezależnymi przetwornikami analogowo-cyfrowymi. Dobierając ten procesor, sprawdziłem, że ma on trzy niezależne przetworniki ADC, lecz nie sprawdziłem, czy każdy z nich dysponuje swoim DMA. W projekcie chciałem mierzyć dokładne przesunięcie fazowe między przebiegami prądu i dwoma przebiegami napięcia stąd zależało mi na pomiarze przebiegów z wykorzystaniem DMA. Po wykonaniu PCB, konfigurując procesor i dalej podczas zgłębiania dokumentacji dowiedziałem się, że jeden z przetworników nie posiada DMA. Dalej przeglądając dokumentację, zastanawiałem się jak rozwiązać problem. Wyczytałem, że jest możliwość pomiaru z wykorzystaniem DMA drugiego przetwornika, kiedy pierwszy przetwornik jest masterem, a drugi slave. We wpisie zajmę się implementacją pomiaru z wykorzystaniem DMA w konfiguracji master i slave.
Jeśli chcesz nabyć płytki deweloperskie lub mikrokontrolery STM32, na których będziesz mógł wykonać projekty związane z przetwarzaniem sygnałów, zapraszam do sklepu msalamon.pl
Sponsorem wpisu jest msalamon.pl
WWW: https://msalamon.pl/
Sklep: https://sklep.msalamon.pl/
Zakres wpisu:
- Procesor STM32F103VET6
- Konfiguracja STM32F103VET6 w STM32CubeIDE
- Program dla STM32F103VET6
- Działanie programu
Procesor STM32F103VET6:
Do swojego projektu dobrałem procesor STM32F103VET6, który charakteryzuje się następującymi parametrami:
Dobierając ten procesor, zależało mi na następujących aspektach:
- minimum 3 niezależne przetworniki ADC z DMA,
- możliwość podłączenia zewnętrznej referencji analogowej (dostępne w obudowie LQFP100),
- niski błąd przetwornika ADC (Total Unadjusted Error),
- dwa przetworniki DAC.
Po wykonaniu PCB dowiedziałem się, że ADC2 nie posiada DMA. Znalazłem rozwązanie tego problemu, którego opis przedstawiłem poniżej z Reference Manual STM32F103 [1]:
Konfiguracja STM32F103VET6 w STM32CubeIDE:
Przetworniki ADC1 i ADC2 mogą pracować ze sobą, używając tego samego DMA. Przetwornik ADC1 jest masterem, ADC2 slave. Tryb pracy, o którym wspominam, nazywa się Dual regular simultaneous + alternate trigger mode. Konwersja przetworników ADC1, ADC2 i ADC3 wyzwalana jest za pomocą tego samego timera (Timer 8).
Konfiguracja ADC1:
Istotnym aspektem jest zmiana szerokości przesyłanych danych poprzez DMA z Half Word do Word zarówno po stronie przetwornika, jak i pamięci. Wynika to z tego, że jednocześnie przesyłane są dane z ADC1, jak i ADC2.
Konfiguracja ADC2:
Konfiguracja ADC3:
Program dla STM32F103VET6:
Liczba próbek zbierana przez pierwszy, jak i drugi przetwornik musi być równa, a długość bufora, w którym będą przechowywane próbki, musi być sumą próbek zbieranych przez przetworniki. W moim przypadku zbieram 512 próbek za pomocą ADC1 i 512 próbek za pomocą ADC2, więc bufor powinien mieć długość 1024 próbek.
Poniżej umieszczone są funkcje, które startują przetworniki ADC1, ADC2 oraz ADC3. Przetworniki pierwszy i drugi będą pracowały w trybie master, slave, ADC3 niezależnie.
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)&Buffer_ADC1_ADC2, BUFFER_SIZE); HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&Source_Voltage, BUFFER_SIZE);
Kolejnym krokiem będzie rozdzielenie wartości z ADC1 od wartości z ADC2. Wartości z ADC1 przechowywane są w pozycjach parzystych tablicy, a wartości z ADC2 w pozycjach nieparzystych. Rozdzielenie zrealizowałem za pomocą pętli for.
if(Current_FFT_status==1) { for(uint16_t i=0; i<BUFFER_SIZE; i++) { Current_Value[i]= (Buffer_ADC1_ADC2[i*2]); } }
if(Current_FFT_status==1) { for(uint16_t i=0; i<BUFFER_SIZE; i++) { Voltage_Value[i]= (Buffer_ADC1_ADC2[i*2+1]); } }
Informację o zebraniu wymaganej ilości próbek pobierane są z funkcji Callback:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc->Instance == ADC1) { Current_FFT_status=1; } if(hadc->Instance == ADC3) { Voltage_Source_FFT_status=1; } }
Działanie programu:
Korzystając z programu STMStudio, odczytałem zebrane próbki sprawdzając je. Jak widać na Rys. 10, dane są prawidłowo zebrane oraz występuje przesunięcie fazowe pomiędzy prądem i napięciem. Tak zebrane dane można dalej wykorzystywać do kolejnych operacji, w moim przypadku FFT.
Podsumowanie:
Finalnie moje niedopatrzenie wyszło nawet lepiej z perspektywy projektu, ponieważ przetwornik 1, jak i 2 są wyzwalane z tego samego timera oraz przesyłane do CPU poprzez to samo DMA, wykorzystując jeden bufor. Sytuacja ta daje gwarancję, że nie jest wprowadzane dodatkowe przesunięcie fazowe podczas pomiarów.
[1] Dostep w internecie: https://www.st.com/en/microcontrollers-microprocessors/stm32f103/documentation.html