你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32L053如何设置ADC实现多通道采集

[复制链接]
czm.gold 提问时间:2016-10-19 13:41 /
请问哪位高手用过STM32L053 ,怎样设置ADC实现多通道采集

收藏 1 评论7 发布时间:2016-10-19 13:41

举报

7个回答
xmshao 回答时间:2016-10-19 22:00:27
你用STM32CUBEMX自己配置个吧。 这些基本操作是免不了的。
安静ing 回答时间:2016-10-20 11:08:53
要用dma读
安静ing 回答时间:2016-10-20 11:10:28
/**
  * @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[i][j] = ADC_ConvertedValue[j][i];
                }       
        }

        /*取值求和取平均*/
        for(i=0; i<4; i++)
        {
                AD_Data[i] = 0;
                for(j=0; j<AD_Count; j++)
                {
                        AD_Data[i] += ADCresults[i][j];
                }               
                AD_Data[i] =(AD_Temp[i]*75 + ((AD_Data[i])/ (AD_Count))*25)/100;
                AD_Temp[i] = AD_Data[i];
        }
//        printf("\r\n AD_value1=%d  AD_value2=%d \r\n",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);                     
}  

semionlg 回答时间:2017-4-16 18:06:32
假如不用DMA,可以获得多通道的数据?
jtc_88 回答时间:2017-4-17 15:14:01
semionlg 发表于 2017-4-16 18:06
假如不用DMA,可以获得多通道的数据?

不用 DMA  可以使用 ADC 断续模式  例如选用 内部软件触发,一个序列 每触发一次 转换一个通道,检测EOC标志 就好了,读取出数据。手册上有的
jtc_88 回答时间:2017-4-17 15:14:38
semionlg 发表于 2017-4-16 18:06
假如不用DMA,可以获得多通道的数据?

使用 DMA很简单的   不复杂 使用 cube
semionlg 回答时间:2017-4-18 10:48:11
但是CUBE生成代码中只有配置,没有启动,没有多通道读取部分,如何处理呢?加1个qq,咨询下,24039851
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版