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

[复制链接]
1582|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 | 显示全部楼层
你先测一个通道的,看看会不会变化
Thor9 发表于 2015-9-25 14:31 | 显示全部楼层
时钟源分频改大点,降低采样频率看看;

为什么这样就可以了,是不是都是这个套路
追逐浪花 发表于 2015-9-25 15:05 | 显示全部楼层
  1. /***************************************************************
  2. *  FileName              :    adc.c
  3. *  Copyright             :
  4. *  ModuleName            :
  5. *  
  6. *  CPU                   :
  7. *  RTOS                  :

  8. *  CreateData            :
  9. *  Author/Corporation    :
  10. *
  11. *  Description           :    ad驱动
  12. *
  13. *---------------------Revision History------------------------
  14. *  No    Version    Date    Revised By    Item    Description
  15. *
  16. *
  17. ***************************************************************/
  18. #include "adc.h"
  19. #include "stm32f0xx_adc.h"
  20. #include "stm32f0xx_gpio.h"
  21. #include "stm32f0xx_dma.h"
  22. #include "stm32f0xx_misc.h"

  23. #define ADC1_DR_Address              0x40012440          //外设地址


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

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

  28. __IO  UINT8 adccount = 0;
  29. __IO  UINT8 idxbuffer = 0;

  30. /**************************************************************
  31. *  Function Name         :   adcinit
  32. *  Param                 :   void
  33. *  Return Param          :   void
  34. *  Description           :   adc初始化配置
  35. ***************************************************************/
  36. void adcinit(void)
  37. {
  38.         GPIO_InitTypeDef GPIO_InitStruct;
  39.         ADC_InitTypeDef  ADC_InitStruct;
  40.         DMA_InitTypeDef  DMA_InitStruct;
  41.         NVIC_InitTypeDef NVIC_InitStruct;

  42.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  43.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);      
  44.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);
  45.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

  46.         GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;      
  47.         GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
  48.         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  49.         //GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
  50.         GPIO_Init(GPIOA,&GPIO_InitStruct);

  51.         GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;      
  52.         GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
  53.         GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  54.         //GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
  55.         GPIO_Init(GPIOB,&GPIO_InitStruct);
  56.       
  57.         ADC_StructInit(&ADC_InitStruct);

  58.         ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
  59.         ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
  60.         ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  61.         ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
  62.         ADC_InitStruct.ADC_ScanDirection = ADC_ScanDirection_Upward;
  63.         ADC_Init(ADC1,&ADC_InitStruct);

  64.         ADC_ChannelConfig(ADC1,ADC_Channel_0,ADC_SampleTime_55_5Cycles);         
  65.         ADC_ChannelConfig(ADC1,ADC_Channel_1,ADC_SampleTime_55_5Cycles);      
  66.         ADC_ChannelConfig(ADC1,ADC_Channel_2,ADC_SampleTime_55_5Cycles);
  67.       
  68.         ADC_GetCalibrationFactor(ADC1);

  69.         DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;   
  70.         DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC1ConvValue;         //内存映射地址
  71.         DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
  72.         DMA_InitStruct.DMA_BufferSize = 3;
  73.         DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  74.         DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
  75.         DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  76.         DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  77.         DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
  78.         DMA_InitStruct.DMA_Priority = DMA_Priority_High;
  79.         DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
  80.         DMA_Init(DMA1_Channel1,&DMA_InitStruct);

  81.         NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  82.         NVIC_InitStruct.NVIC_IRQChannelPriority = 2;
  83.         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  84.         NVIC_Init(&NVIC_InitStruct);

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

  86.         DMA_Cmd(DMA1_Channel1,ENABLE);

  87.         ADC_DMARequestModeConfig(ADC1,ADC_DMAMode_Circular);

  88.                
  89.       
  90.         ADC_DMACmd(ADC1,ENABLE);


  91.         ADC_Cmd(ADC1,ENABLE);
  92. }

  93. /**************************************************************
  94. *  Function Name         :   getadcvalue
  95. *  Param                 :   const void * data, UINT8 length
  96. *  Return Param          :   UINT16
  97. *  Description           :   获取adc转换结果
  98. ***************************************************************/
  99. UINT16 getadcvalue(void * data, UINT8 length)
  100. {
  101.         UINT16 adcresult = 0;
  102.         if(length == 0)
  103.         {
  104.         return adcresult;
  105.         }
  106.       
  107.         while(ADC_GetFlagStatus(ADC1,ADC_FLAG_ADRDY) == DISABLE);
  108.         while((ADC1->CR & 0x04) != DISABLE);
  109.         ADC_StartOfConversion(ADC1);
  110.         //if(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOSEQ) == ENABLE)
  111.         //{
  112.     //   ADC_ClearFlag(ADC1,ADC_FLAG_EOSEQ);
  113.         //}

  114.         adcresult = buffer_avg(data,length);
  115.         return adcresult;
  116. }

  117. /**************************************************************
  118. *  Function Name         :   buffer_avg
  119. *  Param                 :   void
  120. *  Return Param          :   UINT16
  121. *  Description           :   获取平均值
  122. ***************************************************************/
  123. UINT16 buffer_avg(void * data, UINT8 length)
  124. {
  125.     UINT16 avgdata = 0;
  126.         UINT16 sum = 0;
  127.         UINT8 idx;
  128.         if(length == 0)
  129.         {
  130.         return avgdata;
  131.         }
  132.       
  133.         for(idx = 0;idx < length;idx++)
  134.         {
  135.         sum += ((UINT16 *)data)[idx];
  136.         }
  137.       
  138.         avgdata = (UINT16)(sum / length);
  139.         return avgdata;
  140. }

  141. /**************************************************************
  142. *  Function Name         :   DMA1_Channel1_IRQHandler
  143. *  Param                 :   void
  144. *  Return Param          :   void
  145. *  Description           :   DMA中断获取adc转换结果
  146. ***************************************************************/
  147. void DMA1_Channel1_IRQHandler(void)
  148. {
  149.    while(DMA_GetITStatus(DMA_IT_TC) == RESET);
  150.    adccount++;
  151.    if(0 == (adccount % 3))
  152.    {
  153.       atomizevalue[idxbuffer] = ADC1ConvValue[0];                  
  154.       batteryvalue[idxbuffer] = ADC1ConvValue[1];                  
  155.       usbchargevalue[idxbuffer] = ADC1ConvValue[2];
  156.           idxbuffer++;         
  157.    }   
  158.    if((3 * ADCCONV_NUM) == adccount)
  159.    {
  160.               adccount = 0;
  161.            idxbuffer = 0;
  162.        ADC_StopOfConversion(ADC1);         
  163.            DMA_ClearITPendingBit(DMA_IT_TC);
  164.    }
  165.    DMA_ClearITPendingBit(DMA_IT_TC);
  166. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

64

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部