STM32通过TIM,ADC,DMA的配合使用实现双通道数据采样

第一次写博客,奉献给STM32了,一直以来都是潜水看博客,希望能够自己也能写一点东西,对自己学习和工作的一个总结,希望能够坚持下去。

项目背景:以57.6kbps的速率采集两个通道的数据
芯片:STM32F205VCT6
总体的思路通过57.6kHz的定时器去触发ADC采样,采样后的数据在通过DMA存放于缓冲区定时产生中断。
由于需要产生57.6KHz的频率,晶振选择9.6MKHz,CPU主频为115.2MHz。
STEP1:配置定时器
通过TIM2去触发两路ADC,详见配置如下

void TIM2_Configuration(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM2 , ENABLE );

    TIM_DeInit ( TIM2 );

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_Period        = (57600000/(ADC_SAMPLING_MUL*AIS_MODUL_RATE) - 1 );    //28.8M*2/100/10 = 57.6kHz
    TIM_TimeBaseStructure.TIM_Prescaler     = ( 1 - 1 );//28.8M*2 = 57.6MHz
    TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;
    TIM_TimeBaseInit ( TIM2, &TIM_TimeBaseStructure );

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);
    //TIM_ITConfig(TIM2,TIM_IT_CC2,ENABLE); //开定时器中断测试使用

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC3Init(TIM2, &TIM_OCInitStructure);
   // TIM_ITConfig(TIM2,TIM_IT_CC3,ENABLE); //开定时器中断测试使用

    TIM_Cmd ( TIM2, ENABLE );
    TIM_InternalClockConfig(TIM2);
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
    TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
    TIM_UpdateDisableConfig(TIM2, DISABLE);
}

STEP2:配置ADC
首先需要配置GPIO复用

//GPIO -PB0 PB1 -ADC1 ADC2
    GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
    GPIO_Init ( GPIOB, &GPIO_InitStructure );

然后配置ADC

void ADC_Configuration(void)
{                                       
    ADC_InitTypeDef       ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 , ENABLE);

//ADC Common Init 
    ADC_CommonInitStructure.ADC_Mode                = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler           = ADC_Prescaler_Div4;
    ADC_CommonInitStructure.ADC_DMAAccessMode       = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay    = ADC_TwoSamplingDelay_20Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

//ADC1 Init
    ADC_InitStructure.ADC_Resolution                = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode              = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode        = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge      = ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStructure.ADC_ExternalTrigConv          = ADC_ExternalTrigConv_T2_CC2;
    ADC_InitStructure.ADC_DataAlign                 = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion           = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

// ADC1 regular channel 8 configuration
    ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_144Cycles);

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

//Enable ADC1 DMA 
    ADC_DMACmd(ADC1, ENABLE);
// Enable ADC1 
    ADC_Cmd(ADC1, ENABLE);  

// ADC2 Init 
    ADC_InitStructure.ADC_Resolution                = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode              = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode        = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge      = ADC_ExternalTrigConvEdge_Rising;
    ADC_InitStructure.ADC_ExternalTrigConv          = ADC_ExternalTrigConv_T2_CC3;
    ADC_InitStructure.ADC_DataAlign                 = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion           = 1;
    ADC_Init(ADC2, &ADC_InitStructure);

// ADC2 regular channel 9 configuration 
    ADC_RegularChannelConfig(ADC2, ADC_Channel_9, 1, ADC_SampleTime_144Cycles);

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

// Enable ADC2 DMA 
    ADC_DMACmd(ADC2, ENABLE);

// Enable ADC2 
    ADC_Cmd(ADC2, ENABLE);
}

STEP3 配置DMA
首先定义DMA中断标志和缓冲区的定义,其中DMA采用乒乓BUF的方式存储和读取数据。

#define DMA_ADC_BUF_BIT                         = 96 //该数据定义了多长时间产生一次DMA中断
Uint8   Dma2Stream0Flag                         = 0;//ADC1    接收    数据标志位1--表示有数据 0--表示无数据
Uint8   Dma2Stream2Flag                         = 0;//ADC2    接收    数据标志位1--表示有数据 0--表示无数据
Uint16  Adc1Buf0[DMA_ADC_BUF_BIT]               = {0};//ADC1接收缓存区0
Uint16  Adc1Buf1[DMA_ADC_BUF_BIT]               = {0};//ADC1接收缓存区1
Uint16  Adc2Buf0[DMA_ADC_BUF_BIT]               = {0};//ADC2接收缓存区0
Uint16  Adc2Buf1[DMA_ADC_BUF_BIT]               = {0};//ADC2接收缓存区1

然后对DMA进行参数配置

void DMA2_Configuration(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

//DMA2 Stream0 channel0 configuration------ADC1
    DMA_InitStructure.DMA_Channel               = DMA_Channel_0;  
    DMA_InitStructure.DMA_PeripheralBaseAddr    = (Uint32)&ADC1->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr       = (Uint32)Adc1Buf0;
    DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize            = DMA_ADC_BUF_BIT;
    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_Circular;
    DMA_InitStructure.DMA_Priority              = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode              = DMA_FIFOMode_Enable;         
    DMA_InitStructure.DMA_FIFOThreshold         = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst           = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst       = DMA_PeripheralBurst_Single;

//DMA double buffer mode
    DMA_DoubleBufferModeConfig(DMA2_Stream0,(Uint32)Adc1Buf1,DMA_Memory_0);//DMA_Memory_0首先被传输
    DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE);
    DMA_Init(DMA2_Stream0, &DMA_InitStructure);

    DMA_ITConfig( DMA2_Stream0, DMA_IT_TC, ENABLE );
    DMA_ClearITPendingBit ( DMA2_Stream0, DMA_IT_TCIF0 );

    DMA_Cmd(DMA2_Stream0, ENABLE);

//DMA2 Stream2 channel1 configuration------ADC2
    DMA_InitStructure.DMA_Channel               = DMA_Channel_1;  
    DMA_InitStructure.DMA_PeripheralBaseAddr    = (Uint32)&ADC2->DR;
    DMA_InitStructure.DMA_Memory0BaseAddr       = (Uint32)Adc2Buf0;
    DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize            = DMA_ADC_BUF_BIT;
    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_Circular;
    DMA_InitStructure.DMA_Priority              = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode              = DMA_FIFOMode_Enable;         
    DMA_InitStructure.DMA_FIFOThreshold         = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst           = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst       = DMA_PeripheralBurst_Single;
    DMA_DoubleBufferModeConfig(DMA2_Stream2,(Uint32)Adc2Buf1,DMA_Memory_0);//DMA_Memory_0首先被传输
    DMA_DoubleBufferModeCmd(DMA2_Stream2,ENABLE);
    DMA_Init(DMA2_Stream2, &DMA_InitStructure);

    DMA_ITConfig( DMA2_Stream2, DMA_IT_TC, ENABLE );
    DMA_ClearITPendingBit ( DMA2_Stream2, DMA_IT_TCIF2 );

    DMA_Cmd(DMA2_Stream2, ENABLE);      
}

最后再去定义DMA的中断优先级,中断入口函数以及数据的使用

void NVIC_Configuration ( void )
{
    NVIC_InitTypeDef    NVIC_InitStructure;

    NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 );

    NVIC_InitStructure.NVIC_IRQChannel                      = DMA2_Stream0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel                      = DMA2_Stream2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);     
}

void DMA2_Stream0_IRQHandler( void )
{
    if( DMA_GetITStatus( DMA2_Stream0, DMA_IT_TCIF0 ) != RESET )
    {
        DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
        Dma2Stream0Flag  = 1;
    }
}

void DMA2_Stream2_IRQHandler( void )
{
    if( DMA_GetITStatus( DMA2_Stream2, DMA_IT_TCIF2 ) != RESET )
    {
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2);
        Dma2Stream2Flag  = 1;
    }
}

void RECV_Schedule( void )
{
    Uint16  i                           = 0;
    Uint16  j                           = 0;
    Uint16   Din[DMA_ADC_BUF_BIT]       = {0};

//处理ADC1采样通道A的数据
    if( Dma2Stream0Flag == 1 )
    {
        Dma2Stream0Flag = 0;

        if( DMA_GetCurrentMemoryTarget(DMA2_Stream0) == DMA_MEMORY_NO_0 )
        {            
            for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
            {
                Din[i] = Adc1Buf1[i];
            }
        }
        else
        {            
            for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
            {
                Din[i] = Adc1Buf0[i];
            }
        }
    }

//处理ADC2采样通道B的数据
    if( Dma2Stream2Flag == 1 )
    {
        Dma2Stream2Flag = 0;
        if( DMA_GetCurrentMemoryTarget(DMA2_Stream2) == DMA_MEMORY_NO_0 )
        {
            for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
            {
                Din[i] = Adc2Buf1[i];
            }
        }
        else
        {        
            for( i = 0; i < DMA_ADC_BUF_BIT; i++ )
            {
                Din[i] = Adc2Buf0[i];
            }
        }      
    }
}

至此,第一篇博客完成了,写的好粗糙,编辑工具也不会~~~~~~~~还是要多写些~

你可能感兴趣的:(STM32)