ADC输入数组值移入一项

时间:2019-05-28 19:51:41

标签: c timer stm32 dma adc

问题与微控制器STM32L031G6UxS有关。 我使用计时器来触发ADC,然后使用DMA将数据(整个序列)传输到RAM。 使用ADC,我扫描通道1、8和9。实际上,由于SCANDIR = 0(从CH0扫描到CHx),因此读出阵列中的数据应遵循该方向:

ADCReadOut [0] = ValueCH1

ADCReadOut [1] = ValueCH8

ADCReadOut [2] = ValueCH9

我目前有以下奇怪行为:

ADCReadOut [0] = ValueCH9

ADCReadOut [1] = ValueCH1

ADCReadOut [2] = ValueCH8

正如您所看到的,这些值被替换为一个条目。

下面的代码显示了适当的实现。

#define GPIO_ADC_VP_PORT                    (ps_GPIO_PORT_A)
#define GPIO_ADC_VP_BIT                     (u32_GPIO_PIN_1)
#define GPIO_ADC_PREAMP_POS_PORT            (ps_GPIO_PORT_B)
#define GPIO_ADC_PREAMP_POS_BIT             (u32_GPIO_PIN_0)
#define GPIO_ADC_PREAMP_NEG_PORT            (ps_GPIO_PORT_B)
#define GPIO_ADC_PREAMP_NEG_BIT             (u32_GPIO_PIN_1)

#define ADC1_TRIGGER                        ( ADC_CFGR1_EXTSEL_2 )   /* TIM22 (TRGO) connected to TRG4 of ADC1 */
#define ADC1_SMPT                           ( ADC_SMPR_SMP_1 | ADC_SMPR_SMP_0 )   /* Sampling time: 12.5 ADC clock cylce */
#define ADC1_CHANNELS                       ( ADC_CHANNEL_1 | ADC_CHANNEL_8 | ADC_CHANNEL_9 )   /* VP, Preamp pos, Preamp neg */

#define ADC1_DMA                            ( DMA1_Channel1 )
#define DMA_DATA_COUNT                      ( 3 )

...    

/*--- TIM22 / ADC1 / DMA1 ---*/
v_Timer22_Init( pb_UseEdsk_Flag );
v_Adc1_Init( &au16_ReadoutBufferAdc1[0] );
v_Adc1_Calibrate();

/*--- Enable second level hardware ---*/
/* Enable DMA1 */
ADC1_DMA->CCR |= DMA_CCR_EN;

/* Enable ADC1 */
ADC1->CR |= ADC_CR_ADEN;

/* Start ADC1 and corresponding timer */
ADC1->CR |= ADC_CR_ADSTART;
v_StartTimer22();

...

static void v_Timer22_Init( bool_t* pb_UseEdsk_Flag )
{
    /* OC1REF signal is used as trigger output: TRGO triggers ADC1 */
    ADC1_TIMER->CR2 |= TIM_CR2_MMS_2;

    /* Prescaler */
    if( *pb_UseEdsk_Flag )
    {
         ADC1_TIMER->PSC = ADC1_TIMER_PRESCALER_EDSK;
    }
    else
    {
         ADC1_TIMER->PSC = ADC1_TIMER_PRESCALER_ANALOG;
    }
    /* Auto reload register */
    ADC1_TIMER->ARR = ADC1_TIMER_RELOAD_VALUE;
    /* Delay until ADC1 is triggerd: duty cycle off time */
    ADC1_TIMER->CCR1 = ACD1_TIMER_CYCLE_OFF_VALUE;

    /* Configure channel 1 as output */
    ADC1_TIMER->CCMR1 &= ~TIM_CCMR1_CC1S;
    /* Configure channel 1 to PWM Mode 2 (OC1M = 0b111),
       channel 1 is inactive as long as TIM22_CNT < TIM22_CCR1 */
    ADC1_TIMER->CCMR1 |= ( TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 );
}

static void v_StartTimer22( void )
{
    /* Reset timer count register */
    ADC1_TIMER->CNT = 0;
    /* Start timer */
    ADC1_TIMER->CR1 |= TIM_CR1_CEN;
}

static void v_Adc1_Init( uint16_t* pu16_MemAdr )
{
    /*--- ADC1 part ----*/    
    /* Select PCLK divided by 1 as ADC clock */
    ADC1->CFGR2 |= ADC_CLOCKPRESCALER_PCLK_DIV1;

    /* Enable voltage regulator */
    ADC1->CR |= ADC_CR_ADVREGEN;
    /* Every time a trigger is received, 1 sequence is sampled */
    ADC1->CFGR1 &= ~ADC_CFGR1_DISCEN;
    /* Insert a delay after each conversion until the DR register is read */
    ADC1->CFGR1 |= ADC_CFGR1_WAIT;
    /* Enable hardware trigger on rising edge */
    ADC1->CFGR1 |= ADC_CFGR1_EXTEN_0;
    /* Set ADC1_TIMER as trigger source */
    ADC1->CFGR1 |= ADC1_TRIGGER;

    /* DMA circular mode selected */
    ADC1->CFGR1 |= ADC_CFGR1_DMACFG;
    /* Enable DMA */
    ADC1->CFGR1 |= ADC_CFGR1_DMAEN;

    /* Sampling time in ADC clock cycles */
    ADC1->SMPR |= ADC1_SMPT;

    /* ADC1 Channels */
    ADC1->CHSELR |= ADC1_CHANNELS;

    /*--- DMA part ---*/
    /* Peripheral address */
    ADC1_DMA->CPAR = ( uint32_t )&ADC1->DR;    
    /* Memory address */
    ADC1_DMA->CMAR = ( uint32_t )pu16_MemAdr;    
    /* Number of data to transfer */
    ADC1_DMA->CNDTR = DMA_DATA_COUNT;    
    /* Priority: Very high */
    ADC1_DMA->CCR |= DMA_CCR_PL;    

    /* Disable Memory-To-Memory mode */
    ADC1_DMA->CCR &= ~DMA_CCR_MEM2MEM;
    /* Memory size: 16-Bit */
    ADC1_DMA->CCR |= DMA_CCR_MSIZE_0;
    /* Peripheral size: 16-Bit */
    ADC1_DMA->CCR |= DMA_CCR_PSIZE_0;
    /* Enable memory increment mode */
    ADC1_DMA->CCR |= DMA_CCR_MINC;
    /* Disable peripheral increment mode */
    ADC1_DMA->CCR &= ~DMA_CCR_PINC;
    /* Enable circular mode */
    ADC1_DMA->CCR |= DMA_CCR_CIRC;
    /* Data direction: Read from peripheral and write to memory */
    ADC1_DMA->CCR &= ~DMA_CCR_DIR;
    /* Disable transfer complete interrupt */
    ADC1_DMA->CCR &= ~DMA_CCR_TCIE;
}

static void v_Adc1_Calibrate( void )
{
    /* Make sure that ADC1 is stabilized before the calib process starts */
    v_SysClk_BusyWaitUs( 10 );

    /* Stops ADC1 */
    ADC1->CR |= ADC_CR_ADSTP;

    /* Check if ADC1 is disabled */
    if( ADC1->CR & ADC_CR_ADEN )
    {
        /* Disable ADC1 */
        ADC1->CR |= ADC_CR_ADDIS;
    }

    /* Wait until ADC1 is disabled */
    while( ADC1->CR & ADC_CR_ADEN ) {}

    /* Start calibration */
    ADC1->CR |= ADC_CR_ADCAL;

    /* Wait until ADC1 is calibrate */
    while( ADC1->CR & ADC_CR_ADCAL ) {}
}

有人有什么想法吗? 我猜想,当定时器,ADC和DMA开始工作时,RAM上显示的DMA指针已经增加了一个。这通常可以想象吗?

0 个答案:

没有答案