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

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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版