2016-05-04 17 views
0

DMAトランザクションを使用して、STM32f401c-discoのSTM32f4105VCのADC1から1000サンプルのシーケンスを取得しようとしています。転送が完了するとDMAが割り込みを生成し、そこで停止してデータが上書きされないようにします。ここでは、コードは次のようになります。実行は決してDMAにジャンプしません。stm32f4105xのIRQHandler

/* 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は停止し、DMA2_Stream0_IRQHandler機能にブレークポイントを一度だけ有効にしているが、フラグTCIF0HTIF0は、レジスタDMA_LISRに設定されています。どうして?

+0

DMAを使用しているために、プログラムの応答が遅すぎるか、CPUを解放するだけの理由がありますか?後者の場合は、このコメントを無視してください。前者の場合、1000個のサンプルが続いて割り込みが発生するソリューションは、割り込みを処理する必要があることを意味します。また、DMA割り込みは、単純なADC割り込みよりも複雑な可能性があります。したがって、プログラムがすでにADC割り込みを処理できなかった場合は、DMA割り込みも処理できません。 – Lundin

+0

これは2番目のケースです。 –

+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は1回呼び出されますが、それ以上は呼び出されません。 –

+0

DMA Half転送割り込みを処理していますか?クリアHTIF0 – cleblanc

+0

はい。しかし、それは助けにはならない。私はコードを更新します。 –

関連する問題