2016-05-04 21 views
0

我试图从STM32f401c迪斯科的STM32f4105VC的ADC1得到的1000个样本的序列,使用DMA交易。我希望DMA在传输完成时产生一个中断,并在那里停止,这样就不会覆盖数据。下面是代码:执行从不跳转到DMA IRQHandler在stm32f4105x

/* Private macro -------------------------------------------------------------*/ 
#define M 5 
#define F_S 42000000 
#define LOG_SIZE 1000 
#define MEAS_PERIODS 1 
#define DMA_BUFFER_SIZE 1000 
/* Private variables ---------------------------------------------------------*/ 
__IO uint16_t uhADCxConvertedValue[DMA_BUFFER_SIZE] = {0}; 
__IO uint32_t uwADCxConvertedVoltage = 0; 
double voltage=0; 
double S=0, rms=0, F=0; // S quadratic sums, rms - the rms value, F the frequency 
uint32_t N; //number of samplings 
double unscaled_voltage=0; 
uint32_t max_N=0, steady_N = 0; 

typedef char MyString[50]; 
MyString Log[LOG_SIZE]; 



/* Private function prototypes -----------------------------------------------*/ 
/* Private functions ---------------------------------------------------------*/ 
static void ADC_Config(void); 


void DMA2_Stream0_IRQHandler(void) { 
    if(DMA_GetITStatus(DMA_STREAMx,DMA_IT_TCIF0)!=RESET) { 
    DMA_ClearITPendingBit(DMA_STREAMx,DMA_STREAMx,DMA_IT_TCIF0|DMA_IT_HTIF0); 
    } 
} 


/** 
    * @brief Main program 
    * @param None 
    * @retval None 
    */ 
int main(void) 
{ 
    /*!< At this stage the microcontroller clock setting is already configured, 
     this is done through SystemInit() function which is called from startup 
     files (startup_stm32f40_41xxx.s/startup_stm32f427_437xx.s/startup_stm32f429_439xx.s) 
     before to branch to application main. 
     To reconfigure the default setting of SystemInit() function, refer to 
     system_stm32f4xx.c file 
    */ 



    double R = 3.0/0xfff; //conversion ratio 
    double dc_offset = 1.5; 
    double ac_scaling = 0.0022; 
    double mv_filter[M]={0};//moving average filter 
    uint8_t wave_pos=0; //0 upper half wave, 1 lower half wave 
    uint32_t i=0; 
    uint8_t i_period = 1; 
    /* ADC configuration */ 
    ADC_Config(); 

    /* Start ADC Software Conversion */ 
// ADC_SoftwareStartConv(ADCx); 
    ADC_SoftwareStartConv(ADCx); 
    while (1) {} 
} 

static void ADC_Config(void) 
{ 
    ADC_InitTypeDef  ADC_InitStructure; 
    ADC_CommonInitTypeDef ADC_CommonInitStructure; 
    DMA_InitTypeDef  DMA_InitStructure; 
    GPIO_InitTypeDef  GPIO_InitStructure; 
    NVIC_InitTypeDef   NVIC_InitStructure; 

    /* Enable ADCx, DMA and GPIO clocks ****************************************/ 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
    RCC_AHB1PeriphClockCmd(ADCx_CHANNEL_GPIO_CLK, ENABLE); 
    RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE); 

    /* Enable the DMA2 Stream0 Global Interrupt (to handle the Transfer Complete Interrupt TCIF) */ 
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure); 

    /* DMA2 Stream0 channel15 configuration **************************************/ 
    DMA_InitStructure.DMA_Channel = DMA_CHANNELx; 
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADCx_DR_ADDRESS; 
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADCxConvertedValue[0]; 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
    DMA_InitStructure.DMA_BufferSize = DMA_BUFFER_SIZE; 
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 
    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(DMA_STREAMx, &DMA_InitStructure); 
    DMA_Cmd(DMA_STREAMx, ENABLE); 

    /* Configure ADC1 Channel15 pin as analog input ******************************/ 
    GPIO_InitStructure.GPIO_Pin = GPIO_PIN; 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; 
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; 
    GPIO_Init(GPIO_PORT, &GPIO_InitStructure); 

    /* ADC Common Init **********************************************************/ 
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; 
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; 
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; 
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 
    ADC_CommonInit(&ADC_CommonInitStructure); 

    /* ADC1 Init ****************************************************************/ 
    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(ADCx, &ADC_InitStructure); 

    /* ADC1 regular channel15 configuration **************************************/ 
    ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_3Cycles); 

// /* Enable DMA request after last transfer (Single-ADC mode) */ 
    ADC_DMARequestAfterLastTransferCmd(ADCx, ENABLE); 

// /* Enable ADC1 DMA */ 
    ADC_DMACmd(ADCx, ENABLE); 

    /* Enable ADC1 */ 
    ADC_Cmd(ADCx, ENABLE); 

    DMA_ITConfig(DMA_STREAMx,DMA_IT_TC,ENABLE); 
} 

当我一段时间的DMA停止,TCIF0HTIF0在寄存器DMA_LISR设置标志后,调试程序,尽管在DMA2_Stream0_IRQHandler功能断点只激活一次。为什么?

+0

是您正在使用DMA,该方案是在不回应太慢的原因,还是只是释放了CPU?如果是后者,请忽略此评论。在前者的情况下,具有1000个样本并随后出现中断的解决方案意味着中断仍将被处理。而DMA中断可能比简单的ADC中断更复杂。所以如果你的程序已经无法处理ADC中断,它也将无法处理DMA中断。 – Lundin

+0

这是第二种情况。 –

+0

顺便说一句这个代码的第一个例子甚至在理论上是不可能的:)。 –

回答

0

只为那些面临类似问题。当同时触发DMA_IT_TCIF0时,ADC中出现溢出中断。因此,程序需要根据RM0090第403页中描述的顺序进行恢复,13.8.1使用DMA。这里是更新的IRQHandler:

void DMA2_Stream0_IRQHandler(void) { 
    if(DMA_GetITStatus(DMA_STREAMx,DMA_IT_TCIF0)!=RESET) { 
     //clear the ADC->CR2 DDS and DMA flag to disable further DMA requests 
     ADCx->CR2 &= ~(ADC_CR2_DDS|ADC_CR2_DMA); 
     //do processing 
     DMA_ClearITPendingBit(DMA_STREAMx,DMA_IT_TCIF0|DMA_IT_HTIF0); 
     //abjust the DMA NDTR counter 
     DMA_STREAMx->NDTR = (uint32_t)DMA_BUFFER_SIZE; 
     DMA_STREAMx->CR |= (uint32_t)DMA_SxCR_EN; 
     //set the DMA bit 
     ADCx->CR2 |= (ADC_CR2_DMA|ADC_CR2_DDS); 
     //clear the overload 
     ADCx->SR &= ~(ADC_SR_OVR|ADC_SR_STRT); 
     //start the ADC 
     ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; 
    } 
    ; 
} 

除此之外,其他一切都是一样的。

0

您还没有配置正确DMA中断。您需要发送IT配置功能DMA2_Stream0。将行DMA_ITConfig(DMA_CHANNELx, DMA_IT_TC, ENABLE);更改为DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

+0

这是一个错字。对于那个很抱歉。 –

0

确保它在startup_stmf4xx.S文件中定义,并在正确的矢量点声明。

.long DMA2_Stream0_IRQHandler   // DMA2 Stream 0 
+0

这是如此。 DMA2_Stream0_IRQHandler被调用一次,但没有更多。 –

+0

你正在处理DMA半传输中断吗?清除HTIF0 – cleblanc

+0

现在是。但这没有帮助。我会更新代码。 –