请问STM32L053怎么设置ADC实现多通道采集?

2019-07-14 14:14发布

请问哪位高手用过STM32L053 ,怎样设置ADC实现多通道采集
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
6条回答
60user124
1楼-- · 2019-07-14 17:31
要用dma读
60user124
2楼-- · 2019-07-14 20:20
/**
  * @file   ADC_Configuration
  * @brief  完成ADC和DMA的初始化
  * @param  无
  * @retval 无
  */
void ADC_Configuration(uint32_t _ulFreq)
{

  GPIO_InitTypeDef GPIO_InitStructure;
  ADC_InitTypeDef ADC_InitStructure;
        DMA_InitTypeDef   DMA_InitStructure;
        TIM_TimeBaseInitTypeDef timer_init_structure;
        NVIC_InitTypeDef  NVIC_InitStructure;
       
        uint16_t usPeriod;
        uint16_t usPrescaler;
        uint32_t uiTIMxCLK;
       
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
       
        /*设置ADC分频因子为4 ,ADC最大时间不能超过14M*/
        RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);        

        /* ADC1 Periph clock enable */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
       
        /* 使能DMA时钟 */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
  
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
        /*-----------------------------------------------------------------------
        system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:

        HCLK = SYSCLK / 1     (AHB1Periph)
        PCLK2 = HCLK / 2      (APB2Periph)
        PCLK1 = HCLK / 4      (APB1Periph)

        因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
        因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;

        APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14
        APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11

        ----------------------------------------------------------------------- */

        uiTIMxCLK = SystemCoreClock;


        if (_ulFreq < 100)
        {
                                        usPrescaler = 10000 - 1;                                        /* 分频比 = 10000 */
                                        usPeriod = (uiTIMxCLK / 10000) / _ulFreq - 1;                /* 自动重装的值 */
        }
        else if (_ulFreq < 3000)
        {
                                        usPrescaler = 100 - 1;                                        /* 分频比 = 100 */
                                        usPeriod = (uiTIMxCLK / 100) / _ulFreq - 1;                /* 自动重装的值 */
        }
        else        /* 大于4K的频率,无需分频 */
        {
                                        usPrescaler = 0;                                        /* 分频比 = 1 */
                                        usPeriod = uiTIMxCLK / _ulFreq - 1;        /* 自动重装的值 */
        }       

        /*复位TIM2*/
        TIM_DeInit(TIM2);

        /*初始化TIMBASE结构体*/
        TIM_TimeBaseStructInit(&timer_init_structure);                    
               
        /*系统时钟,不分频,48M*/
        timer_init_structure.TIM_ClockDivision = TIM_CKD_DIV1;           

        /*向上计数模式*/                
        timer_init_structure.TIM_CounterMode = TIM_CounterMode_Up;      
                       
        /*每312 uS触发一次中断,开启ADC*/
        timer_init_structure.TIM_Period = usPeriod;                           

        /*计数时钟预分频,f=1M,systick=1 uS */                
        timer_init_structure.TIM_Prescaler = usPrescaler;                     

        /*发生0+1次update事件产生中断 */                
        timer_init_structure.TIM_RepetitionCounter = 0x00;            
                       
        TIM_TimeBaseInit(TIM2, &timer_init_structure);  
               
        /*使能TIM2中断  */
        TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                     
                       
        /*选择TIM2的update事件更新为触发源*/
        TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);           
               
        /*使能TIM2*/
        TIM_Cmd(TIM2, ENABLE);                        

        /* ADC1 DeInit */  
        ADC_DeInit(ADC1);
       
        /*初始化ADC结构体,此句必须加,不加的话多路ADC数据会交换*/
        ADC_StructInit(&ADC_InitStructure);                        

        /*配置ADC分辨率为12位*/
        ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

        /*开启连续转换*/
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

        /*禁止触发检测,使用软件触发*/
        ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConv_T2_TRGO;

        /*ADC采集数据右对齐*/
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

        /*向上扫描*/
        ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;

        /*ADC初始化*/
        ADC_Init(ADC1, &ADC_InitStructure);
                                                                                               
        /*配置采样通道及时间*/
        ADC_ChannelConfig(ADC1,  GPIO_Pin_2 | ADC_Channel_3 | ADC_Channel_5 | GPIO_Pin_6 , ADC_SampleTime_28_5Cycles);

        /* ADC 校准 */
        ADC_GetCalibrationFactor(ADC1);

        /* 循环模式下的 ADC DMA 请求 */
        ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);

        /* 使能 ADC_DMA */
        ADC_DMACmd(ADC1, ENABLE);  

        /* 使能 ADC1 */
        ADC_Cmd(ADC1, ENABLE);     

        /* 等待 ADCEN 标志 */
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));

        /*  ADC1 常规软件启动转换 */  
        ADC_StartOfConversion(ADC1);
       
        /* 复位DMA1_Channel1 */
        DMA_DeInit(DMA1_Channel1);
       
        /*DMA外设ADC基地址*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
       
        /*DMA内存基地址*/
        DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;
       
        /*外设作为数据传输源*/
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
       
        /*DMA通道的DMA缓存的大小*/
        DMA_InitStructure.DMA_BufferSize = 4 * AD_Count;
       
        /*外设地址寄存器不变*/
        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循环模式,即完成后重新开始覆盖*/
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
       
        /*DMA优先级设置为高*/
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
       
        /*DMA通道x禁用内存到内存传输*/
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
       
        /*DMA初始化*/
        DMA_Init(DMA1_Channel1, &DMA_InitStructure);
       
        /*清除一次DMA中断标志*/
        DMA_ClearITPendingBit(DMA1_IT_TC1);                                 
       
        /*使能DMA传输完成中断*/
        DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
       
        /*选择DMA1通道中断*/
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;  

        /*中断使能*/
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
       
        /*优先级设为0 */
        NVIC_InitStructure.NVIC_IRQChannelPriority = 0;  
       
        /*使能 DMA 中断*/
        NVIC_Init(&NVIC_InitStructure);  

        /* DMA1 Channel1 enable */
        DMA_Cmd(DMA1_Channel1, ENABLE);
       
}


/**
  * @brief  ADC滤波
  * @param  无
  * @retval 无
  */
void ADC_Filter(void)
{
        uint8_t i, j;
        /*从DMA缓存中取出AD数据*/
        for(i=0; i<4; i++)
        {
                for(j=0; j<AD_Count; j++)
                {
                        ADCresults[j] = ADC_ConvertedValue[j];
                }       
        }

        /*取值求和取平均*/
        for(i=0; i<4; i++)
        {
                AD_Data = 0;
                for(j=0; j<AD_Count; j++)
                {
                        AD_Data += ADCresults[j];
                }               
                AD_Data =(AD_Temp*75 + ((AD_Data)/ (AD_Count))*25)/100;
                AD_Temp = AD_Data;
        }
//        printf(" AD_value1=%d  AD_value2=%d ",AD_Data[0], AD_Data[1]);        
                       
}


/**
  * @brief  DMA1_Channel1中断服务函数
  * @param  无
  * @retval 无
  */
void DMA1_Channel1_IRQHandler()  
{  
        /*判断DMA传输完成中断*/
        if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)                        
        {
//                AD_Count_flag++;
//                if(AD_Count_flag==64)
                  flag_ADC = 1;
        }       
        /*清除DMA中断标志位*/       
        DMA_ClearITPendingBit(DMA1_IT_TC1);                     
}  
billbian
3楼-- · 2019-07-14 21:45
 精彩回答 2  元偷偷看……
吔屎蛋拉雷
4楼-- · 2019-07-15 02:27
billbian 发表于 2019-2-13 10:15
假如不用DMA,可以获得多通道的数据?

不用 DMA  可以使用 ADC 断续模式  例如选用 内部软件触发,一个序列 每触发一次 转换一个通道,检测EOC标志 就好了,读取出数据。手册上有的
吔屎蛋拉雷
5楼-- · 2019-07-15 03:34
billbian 发表于 2019-2-13 10:15
假如不用DMA,可以获得多通道的数据?

使用 DMA很简单的   不复杂 使用 cube
billbian
6楼-- · 2019-07-15 09:21
但是CUBE生成代码中只有配置,没有启动,没有多通道读取部分,如何处理呢?加1个qq,咨询下,24039851

一周热门 更多>