Skocz do zawartości

Kurs STM32 - #8 - DMA, czyli bezpośredni dostęp do pamięci


Komentator

Pomocna odpowiedź

radek04, tematyka FFT nie dotyczy kursu, więc załóż, proszę, nowy wątek. Podpowiem tylko, że to co potrzebujesz to nie tyle szybkie zapisywanie wyników z ADC, ale raczej pobieranie danych w stałych odstępach czasu. Częstotliwość próbkowania to ważny parametr, który musi być stały. Natomiast jego wartość to już decyzja projektowa i "szybko" nie zawsze jest dobrą wartością.

  • Lubię! 1
Link do komentarza
Share on other sites

Chciałem wykonać zadanie 8.3 z tej części kursu, podłączając 2 potencjometry oraz 1 fotorezystor, z wykorzystaniem DMA. Napisałem poniższy kod, jednak wartości z kanału fotorezystora (ADC_Channel_2), który podłączyłem do Pinu_0 GPIOC nie zmieniają się. Nie mogę namierzyć błędu. 

#include <stdio.h>
#include <stdint.h>
#include "stm32f10x.h"

#define ADC_CHANNELS    3

volatile uint32_t timer_ms = 0;

uint16_t     adc_value[ADC_CHANNELS]; // bufor na odebrane wyniki

void SysTick_Handler()
{
    if (timer_ms)
        timer_ms--;
}

void delay_ms(int time)
{
    timer_ms = time;
    while (timer_ms);
}

void send_char(char c)
{
    while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    USART_SendData(USART2, c);
}

int __io_putchar(int c)
{
    if (c=='\n')
        send_char('\r');
    send_char(c);
    return c;
}

int main(void)
{
    int i;
    GPIO_InitTypeDef gpio;
    USART_InitTypeDef uart;
    DMA_InitTypeDef dma;
    ADC_InitTypeDef adc;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    RCC_ADCCLKConfig(RCC_PCLK2_Div6); // należy zmniejszyc częstotliwośc pracy zegara
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    GPIO_StructInit(&gpio);
    gpio.GPIO_Pin = GPIO_Pin_5;
    gpio.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &gpio);

    gpio.GPIO_Pin = GPIO_Pin_2;
    gpio.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &gpio);

    gpio.GPIO_Pin = GPIO_Pin_3;
    gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &gpio);

    USART_StructInit(&uart);
    uart.USART_BaudRate = 9600;
    USART_Init(USART2, &uart);
    USART_Cmd(USART2, ENABLE);

    gpio.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
    gpio.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &gpio);

    gpio.GPIO_Pin = GPIO_Pin_0;
    gpio.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOC, &gpio);

    DMA_StructInit(&dma);
    dma.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; 
    dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
    dma.DMA_MemoryBaseAddr = (uint32_t)adc_value;
    dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
    dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    dma.DMA_DIR = DMA_DIR_PeripheralSRC;
    dma.DMA_BufferSize = ADC_CHANNELS; 
    dma.DMA_Mode = DMA_Mode_Circular; 
    DMA_Init(DMA1_Channel1, &dma);
    DMA_Cmd(DMA1_Channel1, ENABLE); 

    ADC_StructInit(&adc);
    adc.ADC_ScanConvMode = ENABLE; 
    adc.ADC_ContinuousConvMode = ENABLE; 
    adc.ADC_NbrOfChannel = ADC_CHANNELS; 
    adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // konwersja jest programowa dlatego można wyłączyc
    ADC_Init(ADC1, &adc);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_71Cycles5);

    ADC_DMACmd(ADC1, ENABLE); 
    ADC_Cmd(ADC1, ENABLE);

    // niżej dodatkowa kalibracja i sprawdzenie całgeo przetwornika
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));

    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    SysTick_Config(SystemCoreClock / 1000);

    while (1) {
        for (i = 0; i < ADC_CHANNELS; i++){
            printf("ADC%d = %d   ", i, adc_value);
            if( i == 2) printf("\n");

        }

        GPIO_SetBits(GPIOA, GPIO_Pin_5);
        delay_ms(100);
        GPIO_ResetBits(GPIOA, GPIO_Pin_5);
        delay_ms(400);
    }
}


forbot_1.thumb.png.a39babb0c62a42bc6739f0c40f998d82.png

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

@Micak zapytam tylko najpierw dla pewności - masz świadomość, że korzystasz ze starej wersji kursu i jest już dostępna nowa (bazująca na bibliotece HAL)? Zestaw elementów nie uległ zmianie, ale pojawił się zupełnie nowy kurs 🙂

Link do komentarza
Share on other sites

@Treker Tak, zdaję sobie z tego sprawę. Ten chciałbym skończyć chyba czystą siłą rozpędu, przy początku nauki obsługi STM'ów błędnie oceniłem i uznałem, tę wersję jako "podstawową" i łatwiejszą. Rozumiem, że nie do końca poprawnie.

Moim celem obecnie jest wykonanie prostej konstrukcji robota typu LineFollow'er. Polecasz zatem, żeby nadrobić zaległości z HAL'a i potem zająć się konstrukcją?

 

Link do komentarza
Share on other sites

20 godzin temu, Micak napisał:

przy początku nauki obsługi STM'ów błędnie oceniłem i uznałem, tę wersję jako "podstawową" i łatwiejszą. Rozumiem, że nie do końca poprawnie.

@Micak kiedyś był taki "trend", że sporo osób zaczynało od metody opisanej w tej kursie, a później przechodziła do HAL-a. Aktualnie HAL to jedyna sensowna opcja (oprócz LL i rejestrów), więc na spokojnie możesz sobie odpuścić ten materiał. Lepiej zająć się tamtym kursem - szczególnie, że sprzęt już masz 🙂

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.