简体   繁体   English

STM32F4 ADC DMA配置不起作用

[英]STM32F4 ADC DMA config not working

I'm trying to get ADC with DMA working on my STM32F411RE nucleo board. 我正在尝试在STM32F411RE核板上使用带DMA的ADC。 the signal is connected to the PC0 pin (ADC channel 10, DMA2), but whenever I check, the uhADC1ConvertedValue is 0. Am I missing something? 该信号连接到PC0引脚(ADC通道10,DMA2),但是每当我检查时,uhADC1ConvertedValue都为0。我是否缺少某些东西? Is my config wrong? 我的配置错了吗?

__IO uint32_t uhADC1ConvertedValue;

unsigned int getADCVal(){
    return uhADC1ConvertedValue;
}


void ADC2_Init(){
    ADC_InitTypeDef       ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    DMA_InitTypeDef       DMA_InitStructure;
    GPIO_InitTypeDef      GPIO_InitStructure;

    uhADC1ConvertedValue = 1;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    DMA_InitStructure.DMA_Channel = DMA_Channel_0;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADC1ConvertedValue;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = 1;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);
    DMA_Cmd(DMA2_Stream0, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

    ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

    ADC_DMACmd(ADC1, ENABLE);

    ADC_Cmd(ADC1, ENABLE);

    ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE);


}


int main(void)
{
    int rev = 0;

    uC_Init();


    rev = getADCVal(); //enc28j60getrev();

    simple_server();

    return rev;
}

I can't really tell what was wrong with my previous code (probably the part where i didn't start the timer that would start the ADC), but here is a working one (this code keeps ADC doing conversions continously (well, started by a timer) and loads the measured value into a variable): 我真的不能说出我以前的代码出了什么问题(可能是我没有启动将启动ADC的计时器的那一部分),但是这是一个有效的代码(此代码使ADC连续进行转换(嗯,开始了)通过计时器)并将测量值加载到变量中):

volatile uint32_t uhADC1ConvertedValue;

uint32_t getADCVal(){
    return uhADC1ConvertedValue;
}
void adc_init(void)
{
    GPIO_InitTypeDef      GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
    RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;

    //konfiguracja ADC
    ADC1->CR2 = ADC_CR2_ADON |                          //włącz ADC
                ADC_CR2_EXTEN_0 |                       //wyzwalanie przetwornika zboczem opadającym i narastającym
                ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_0 |   //wyzwalanie przetwornika kanałem 4 timera 4
                ADC_CR2_DDS |                           //kontynuuj przesył DMA po ostatnim przesyle (konieczne dla circular mode)
                ADC_CR2_DMA;                            //włącz DMA dla ADC

    //włączenie skanowania i przerwania dla zakonczonej konwersji
    ADC1->CR1 = ADC_CR1_SCAN; //| ADC_CR1_EOCIE;

    //Ustawienie czasu konwersji na 3 + 12 cykli zegara ADC, zegar ADC == 42MHz częstotliwosć próbkowania ~1Ms
    ADC1->SMPR1 = 0;//ADC_SMPR1_SMP11_1 | ADC_SMPR1_SMP12_1;

    //Ustawienie ilosci kanałów do skanowania
    ADC1->SQR1 = (1)<<20;

    //Ustawienie kanałów 11 i 12 do skanowania
    ADC1->SQR3 = 10<<5;

    //Konfiguracja DMA dla przetwornika ADC1
    DMA2_Stream0->NDTR = 1;                 //ilosc bajtów do przesłania
    DMA2_Stream0->PAR = (uint32_t)&ADC1->DR;
    DMA2_Stream0->M0AR = (uint32_t)&uhADC1ConvertedValue;

    DMA2_Stream0->CR =  DMA_SxCR_PL_1 |     //priority high
                        DMA_SxCR_MSIZE_0 |  //memory size 16bit
                        DMA_SxCR_PSIZE_0 |  //pheriperial size 16bit
                        DMA_SxCR_MINC |     //inkrementuj wskaźnik po stronie pamięci
                        DMA_SxCR_CIRC |     //zapętlenie bufora pamięci
                        DMA_SxCR_EN;        //włączenie kontrolera DMA

    //konfiguracja timera dla przetwornika
    RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
    TIM4->CR1 = 0;                          //resetowanie rejestru konfiguracji
    TIM4->PSC = 0;                          //prescaller na 0
    TIM4->ARR = 167;                        //reload register na 83
    TIM4->CCR4 = 167;                       //rejesrt compare dla wyzwalania przetwornika
    TIM4->CCMR2 |= TIM_CCMR2_OC4M_0 | TIM_CCMR2_OC4M_1; //przełączanie wyjcia przy compare
    TIM4->CCER |= TIM_CCER_CC4E;            //włączenie wyjcia 4

    //konfiguracja NVIC
    NVIC_EnableIRQ(ADC_IRQn);               //przerwanie od zakonczenia konwersji ADC

    //uruchom przetwornik
    ADC1->CR2 |= ADC_CR2_ADON;

    //uruchom timer
    TIM4->CR1 = TIM_CR1_CEN;


}



int main(void)
{
    uint32_t rev;
    int bb= 0;
    uC_Init();
    //ADC2_Init();
    adc_init();
    rev = uhADC1ConvertedValue;
    rev = uhADC1ConvertedValue;
    rev = uhADC1ConvertedValue;
    for (bb=0; bb< 100000; bb++) // tu dociera i sie wywala
        {;;}

    rev = uhADC1ConvertedValue;
    rev = uhADC1ConvertedValue;
    rev = uhADC1ConvertedValue;
    rev = uhADC1ConvertedValue;

//  rev = 20;

    /**/
    simple_server(); //petla nieskonczona

    return rev;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM