打印
[STM32F0]

AD转换愁死人了,请大神帮忙看看

[复制链接]
1277|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
无帝老三|  楼主 | 2015-9-10 18:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/***************************************************************
*  FileName              :    adc.c
*  Copyright             :
*  ModuleName            :
*  
*  CPU                   :
*  RTOS                  :

*  CreateData            :
*  Author/Corporation    :
*
*  Description           :    ad驱动
*
*---------------------Revision History------------------------
*  No    Version    Date    Revised By    Item    Description
*
*
***************************************************************/
#include "adc.h"
#include "stm32f0xx_adc.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_dma.h"
#include "stm32f0xx_misc.h"

#define ADC1_DR_Address              0x40012440          //外设地址


__IO  UINT16 ADC1ConvValue[3] = {0};                     //采样数据保存数组

__IO  UINT16 atomizevalue[ADCCONV_NUM];                  //雾化片电流保存数组
__IO  UINT16 batteryvalue[ADCCONV_NUM];                  //电池电压保存数组
__IO  UINT16 usbchargevalue[ADCCONV_NUM];                //USB充电电压保存数组

__IO  UINT8 adccount = 0;
__IO  UINT8 idxbuffer = 0;

/**************************************************************
*  Function Name         :   adcinit
*  Param                 :   void
*  Return Param          :   void
*  Description           :   adc初始化配置
***************************************************************/
void adcinit(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        ADC_InitTypeDef  ADC_InitStruct;
        DMA_InitTypeDef  DMA_InitStruct;
        NVIC_InitTypeDef NVIC_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);       
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;       
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        //GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_Init(GPIOA,&GPIO_InitStruct);

        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;       
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        //GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_Init(GPIOB,&GPIO_InitStruct);
       
        ADC_StructInit(&ADC_InitStruct);

        ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
        ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
        ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
        ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStruct.ADC_ScanDirection = ADC_ScanDirection_Upward;
        ADC_Init(ADC1,&ADC_InitStruct);

        ADC_ChannelConfig(ADC1,ADC_Channel_0,ADC_SampleTime_55_5Cycles);          
        ADC_ChannelConfig(ADC1,ADC_Channel_1,ADC_SampleTime_55_5Cycles);      
        ADC_ChannelConfig(ADC1,ADC_Channel_2,ADC_SampleTime_55_5Cycles);
       
        ADC_GetCalibrationFactor(ADC1);

        DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;   
        DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC1ConvValue;         //内存映射地址
        DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStruct.DMA_BufferSize = 3;
        DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStruct.DMA_Priority = DMA_Priority_High;
        DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel1,&DMA_InitStruct);

        NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
        NVIC_InitStruct.NVIC_IRQChannelPriority = 2;
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStruct);

        DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);                          //开DMA中断

        DMA_Cmd(DMA1_Channel1,ENABLE);

        ADC_DMARequestModeConfig(ADC1,ADC_DMAMode_Circular);

               
       
        ADC_DMACmd(ADC1,ENABLE);


        ADC_Cmd(ADC1,ENABLE);
}

/**************************************************************
*  Function Name         :   getadcvalue
*  Param                 :   const void * data, UINT8 length
*  Return Param          :   UINT16
*  Description           :   获取adc转换结果
***************************************************************/
UINT16 getadcvalue(void * data, UINT8 length)
{
        UINT16 adcresult = 0;
        if(length == 0)
        {
        return adcresult;
        }
       
        while(ADC_GetFlagStatus(ADC1,ADC_FLAG_ADRDY) == DISABLE);
        while((ADC1->CR & 0x04) != DISABLE);
        ADC_StartOfConversion(ADC1);
        //if(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOSEQ) == ENABLE)
        //{
    //   ADC_ClearFlag(ADC1,ADC_FLAG_EOSEQ);
        //}

        adcresult = buffer_avg(data,length);
        return adcresult;
}

/**************************************************************
*  Function Name         :   buffer_avg
*  Param                 :   void
*  Return Param          :   UINT16
*  Description           :   获取平均值
***************************************************************/
UINT16 buffer_avg(void * data, UINT8 length)
{
    UINT16 avgdata = 0;
        UINT16 sum = 0;
        UINT8 idx;
        if(length == 0)
        {
        return avgdata;
        }
       
        for(idx = 0;idx < length;idx++)
        {
        sum += ((UINT16 *)data)[idx];
        }
       
        avgdata = (UINT16)(sum / length);
        return avgdata;
}

/**************************************************************
*  Function Name         :   DMA1_Channel1_IRQHandler
*  Param                 :   void
*  Return Param          :   void
*  Description           :   DMA中断获取adc转换结果
***************************************************************/
void DMA1_Channel1_IRQHandler(void)
{
   while(DMA_GetITStatus(DMA_IT_TC) == RESET);
   adccount++;
   if(0 == (adccount % 3))
   {
      atomizevalue[idxbuffer] = ADC1ConvValue[0];                  
      batteryvalue[idxbuffer] = ADC1ConvValue[1];                  
      usbchargevalue[idxbuffer] = ADC1ConvValue[2];
          idxbuffer++;          
   }   
   if((3 * ADCCONV_NUM) == adccount)
   {
              adccount = 0;
           idxbuffer = 0;
       ADC_StopOfConversion(ADC1);          
           DMA_ClearITPendingBit(DMA_IT_TC);
   }
   DMA_ClearITPendingBit(DMA_IT_TC);
}

数组存放三个通道的转换值,再存到各自数组中以求平均值,为什么数组中通道值会来回切换??

沙发
mmuuss586| | 2015-9-10 19:44 | 只看该作者
时钟源分频改大点,降低采样频率看看;

使用特权

评论回复
板凳
无帝老三|  楼主 | 2015-9-25 11:04 | 只看该作者
mmuuss586 发表于 2015-9-10 19:44
时钟源分频改大点,降低采样频率看看;

确实这个原因,中断里面使用还是要多加小心,
谢谢您

使用特权

评论回复
地板
侣行天下| | 2015-9-25 11:11 | 只看该作者
你先测一个通道的,看看会不会变化

使用特权

评论回复
5
Thor9| | 2015-9-25 14:31 | 只看该作者
时钟源分频改大点,降低采样频率看看;

为什么这样就可以了,是不是都是这个套路

使用特权

评论回复
6
追逐浪花| | 2015-9-25 15:05 | 只看该作者
/***************************************************************
*  FileName              :    adc.c
*  Copyright             :
*  ModuleName            :
*  
*  CPU                   :
*  RTOS                  :

*  CreateData            :
*  Author/Corporation    :
*
*  Description           :    ad驱动
*
*---------------------Revision History------------------------
*  No    Version    Date    Revised By    Item    Description
*
*
***************************************************************/
#include "adc.h"
#include "stm32f0xx_adc.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_dma.h"
#include "stm32f0xx_misc.h"

#define ADC1_DR_Address              0x40012440          //外设地址


__IO  UINT16 ADC1ConvValue[3] = {0};                     //采样数据保存数组

__IO  UINT16 atomizevalue[ADCCONV_NUM];                  //雾化片电流保存数组
__IO  UINT16 batteryvalue[ADCCONV_NUM];                  //电池电压保存数组
__IO  UINT16 usbchargevalue[ADCCONV_NUM];                //USB充电电压保存数组

__IO  UINT8 adccount = 0;
__IO  UINT8 idxbuffer = 0;

/**************************************************************
*  Function Name         :   adcinit
*  Param                 :   void
*  Return Param          :   void
*  Description           :   adc初始化配置
***************************************************************/
void adcinit(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        ADC_InitTypeDef  ADC_InitStruct;
        DMA_InitTypeDef  DMA_InitStruct;
        NVIC_InitTypeDef NVIC_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);      
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;      
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        //GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_Init(GPIOA,&GPIO_InitStruct);

        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;      
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
        //GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
        GPIO_Init(GPIOB,&GPIO_InitStruct);
      
        ADC_StructInit(&ADC_InitStruct);

        ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
        ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
        ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
        ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStruct.ADC_ScanDirection = ADC_ScanDirection_Upward;
        ADC_Init(ADC1,&ADC_InitStruct);

        ADC_ChannelConfig(ADC1,ADC_Channel_0,ADC_SampleTime_55_5Cycles);         
        ADC_ChannelConfig(ADC1,ADC_Channel_1,ADC_SampleTime_55_5Cycles);      
        ADC_ChannelConfig(ADC1,ADC_Channel_2,ADC_SampleTime_55_5Cycles);
      
        ADC_GetCalibrationFactor(ADC1);

        DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;   
        DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC1ConvValue;         //内存映射地址
        DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStruct.DMA_BufferSize = 3;
        DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStruct.DMA_Priority = DMA_Priority_High;
        DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel1,&DMA_InitStruct);

        NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
        NVIC_InitStruct.NVIC_IRQChannelPriority = 2;
        NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStruct);

        DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);                          //开DMA中断

        DMA_Cmd(DMA1_Channel1,ENABLE);

        ADC_DMARequestModeConfig(ADC1,ADC_DMAMode_Circular);

               
      
        ADC_DMACmd(ADC1,ENABLE);


        ADC_Cmd(ADC1,ENABLE);
}

/**************************************************************
*  Function Name         :   getadcvalue
*  Param                 :   const void * data, UINT8 length
*  Return Param          :   UINT16
*  Description           :   获取adc转换结果
***************************************************************/
UINT16 getadcvalue(void * data, UINT8 length)
{
        UINT16 adcresult = 0;
        if(length == 0)
        {
        return adcresult;
        }
      
        while(ADC_GetFlagStatus(ADC1,ADC_FLAG_ADRDY) == DISABLE);
        while((ADC1->CR & 0x04) != DISABLE);
        ADC_StartOfConversion(ADC1);
        //if(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOSEQ) == ENABLE)
        //{
    //   ADC_ClearFlag(ADC1,ADC_FLAG_EOSEQ);
        //}

        adcresult = buffer_avg(data,length);
        return adcresult;
}

/**************************************************************
*  Function Name         :   buffer_avg
*  Param                 :   void
*  Return Param          :   UINT16
*  Description           :   获取平均值
***************************************************************/
UINT16 buffer_avg(void * data, UINT8 length)
{
    UINT16 avgdata = 0;
        UINT16 sum = 0;
        UINT8 idx;
        if(length == 0)
        {
        return avgdata;
        }
      
        for(idx = 0;idx < length;idx++)
        {
        sum += ((UINT16 *)data)[idx];
        }
      
        avgdata = (UINT16)(sum / length);
        return avgdata;
}

/**************************************************************
*  Function Name         :   DMA1_Channel1_IRQHandler
*  Param                 :   void
*  Return Param          :   void
*  Description           :   DMA中断获取adc转换结果
***************************************************************/
void DMA1_Channel1_IRQHandler(void)
{
   while(DMA_GetITStatus(DMA_IT_TC) == RESET);
   adccount++;
   if(0 == (adccount % 3))
   {
      atomizevalue[idxbuffer] = ADC1ConvValue[0];                  
      batteryvalue[idxbuffer] = ADC1ConvValue[1];                  
      usbchargevalue[idxbuffer] = ADC1ConvValue[2];
          idxbuffer++;         
   }   
   if((3 * ADCCONV_NUM) == adccount)
   {
              adccount = 0;
           idxbuffer = 0;
       ADC_StopOfConversion(ADC1);         
           DMA_ClearITPendingBit(DMA_IT_TC);
   }
   DMA_ClearITPendingBit(DMA_IT_TC);
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

64

帖子

1

粉丝