打印
[STM32F0]

STM32F051 ADC单通道数据采集(中断方式实现)

[复制链接]
7012|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
shi910229|  楼主 | 2014-7-28 13:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32F0 #02进程帖(三)---STM32F051 ADC单通道数据采集(中断方式实现)
  按照正常的进度,应该是先把ADC方面的内容传上来的,后来因为采用DMA 中断方式-采集多通道数据时,出现了点小问题,一直没有解决好,后只有先放手去解决别的问题了。直到今天,终于解决了那个小问题,ADC数据采集方面的工作进度算是全部完成。
    由于本人以前采用LM系列ARM M3,对STM32不太熟悉,故利用此机会系统的实验了一下STM32的ADC模块。主要包括:
   A--软件查询方式实现的ADC采集(单路)。
   B--中断方式实现的ADC采集(单路)。
   C--DMA软件查询方式实现的ADC采集(单路)。
   D--DMA中断方式实现的ADC采集(多路)。
  实验只是简单的测试一下,并没有进行滤波或只简单的进行了平均,如果用在项目中的话,需要实现更复杂的滤波算法才行(目前流行的滤波算法也有十几种吧)。个人感觉,相比较其他的M3/MO,STM32最大的特色就在于其12位ADC,高精度,高速度。对ADC模块整个STM32F0来说,目前的学习也仅是一点皮毛,只有后续不断的努力,才能更好的应用它。
  下面上一个用ADC中断方式实现的采集进度图和部分代码。
【部分代码】
/*********************************Copyright (c)*********************************                                      
  *                              fengye5340@163.com                     
  ******************************************************************************
  * 文件名称:ADC_51R8T6.C
  * 描    述:ADC模块
  * 创 建 者: fengye5340
  * 创建日期: 2012-11-1     
  * 修 改 者:            
  * 修改日期: 2012-11-8   
  * 版    本: v1.0.1
  ******************************************************************************
  * attention
  *
  ******************************************************************************
  */
/*Includes --------------------------------------------------------------------*/
#include  "stm32f0xx.h"
#include  "stm32f0xx_it.h"
#include  "stm32f0xx_adc.h"
#include  "ADC_51R8T6.H"
#include  "UART_51R8T6.H"
#include  "TIMER_51R8T6.H"
/* 类型定义 typedef-----------------------------------------------------------*/
/* 预定义字符     ------------------------------------------------------------*/
/* 宏定义        -------------------------------------------------------------*/
/* 变量定义          ---------------------------------------------------------*/
extern unsigned int  Adc_val = 0;
extern float         Ad_Val =0;
extern float         Ad_Val_Averge={0.0};
/*******************************************************************************
* 函数名称: ADC_GPIO_Init();
* 功能描述: ADC--GPIO输入引脚配置---在此可以设置16路外部输入通道
********************************************************************************/
void ADC_GPIO_Init(void)
{
     GPIO_InitTypeDef  GPIO_InitStructure;
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);   
     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 ;
     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AN;
     //GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
     //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; // 做输入时不用设置速率
     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
* 函数名称:  ADC_Reset()
* 功能描述:  ADC模块初始化
********************************************************************************/
void ADC_Reset(void)
{   
     ADC_InitTypeDef  ADC_InitStructure;
   
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);  //使能ADC1通道时钟
     ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
     ADC_StructInit(&ADC_InitStructure);
     ADC_GPIO_Init(); //ADC-GPIO引脚初始化
     /* 配置 ADC1 连续采集模式-12位精度 */
     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //12位精度
     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;     // 连续转换模式
     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //转换由软件而不是外部触发启动
     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
     ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward ; //后前:0--18通道
     ADC_Init(ADC1, &ADC_InitStructure);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    #if TEMP_TEST
        ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor, ADC_SampleTime_55_5Cycles);
      /* 配置ADC1 温度传感器239.5 周期(>2.2us)采样时间
      1--ADC_SampleTime_1_5Cycles                    
      2--ADC_SampleTime_7_5Cycles                    
      3--ADC_SampleTime_13_5Cycles                  
      4--ADC_SampleTime_28_5Cycles                 
      5--ADC_SampleTime_41_5Cycles               
      6--ADC_SampleTime_55_5Cycles                  
      7--ADC_SampleTime_71_5Cycles               
      8--ADC_SampleTime_239_5Cycles
      */
       ADC_TempSensorCmd(ENABLE); //使能内部温度传感器
   #endif
   #if VREF_TEST
       ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles);
       ADC_VrefintCmd(ENABLE);
     #endif
     #if ADC_TEST
       ADC_ChannelConfig(ADC1, ADC_Channel_8 , ADC_SampleTime_55_5Cycles);
     #endif
   #if ADC_IPQ  
         ADC_ChannelConfig(ADC1, ADC_Channel_8 , ADC_SampleTime_239_5Cycles);
         ADC_ITConfig(ADC1, ADC_IT_EOC,ENABLE);//开启ADC转换结束中断。
     #endif
////////////////////////////////////////////////////////////////////////////////////////   
   
   
     ADC_GetCalibrationFactor(ADC1);        // 开始ADC校准
     ADC_Cmd(ADC1, ENABLE);                //  使能指定的ADC1
     
     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));   /* 等待ADC准备好 */
  
     ADC_StartOfConversion(ADC1); //开始温度转换;
}  
/*******************************************************************************
* 函数名称:  Temperature_Test()
* 功能描述:  软件查询方式实现的内部温度传感器测试
********************************************************************************/
void Temperature_Test(void)
{
     unsigned int  Temperature = 0;
if(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)
    {
    Delay_Ms(1000);
     Temperature = ADC_GetConversionValue(ADC1);
     Temperature= (1.42 - Temperature*3.3/4096)*1000/4.35 + 25; //计算算法
     printf("The temperature = %d℃ \r\n", Temperature);
      
    }
   
}
/*******************************************************************************
* 函数名称:  Vref_Test()
* 功能描述:  内部参考电压采集测试---没有进行滤波算法处理
********************************************************************************/
void Vref_Test(void)
{
     unsigned int  Vref = 0;
    float  Vref_Value =0;
   if(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)
    {
     Delay_Ms(1000);
      Vref=ADC_GetConversionValue(ADC1);
      Vref_Value =(float)Vref/4096*3.3; //计算算法
      printf("The Voltage = %f V \r\n", Vref_Value);
      
    }
   
}


沙发
shi910229|  楼主 | 2014-7-28 13:58 | 只看该作者
继续没发完的,唉,还有长度限制~~~[em:12:][em:12:][em:12:][em:12:][em:12:]


/*******************************************************************************
* 函数名称:  ADC_Test()
* 功能描述:  电压采集测试--没有进行滤波算法处理
********************************************************************************/
void ADC_Test(void)
{   
     unsigned int  Adc_value = 0;
     float        Ad_Value =0;
      if(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)
    {
     Delay_Ms(1000);
      Adc_value =ADC_GetConversionValue(ADC1);
      Ad_Value =(float)Adc_value/4096*3.3; //计算算法
      Ad_Value = (1.2*Ad_Value)/1.36;      //精度误差补偿  
      printf("The Voltage = %f V \r\n", Ad_Value);
      
    }
}


//主程序--数据处理部分
while (1)
   {     
      // 1--闪灯程序
         // Led_Test();
   
      
                      // 2--DS18B20模块
      
        // DS18B20_Test();
      
         //3-- ADC内部测温
         #if  TEMP_TEST
              Temperature_Test();
         #endif
         #if  VREF_TEST
            Vref_Test();
       #endif
           #if ADC_TEST
              ADC_Test();
           #endif  
           #if ADC_IPQ
              printf("当前电压是 %f V \r\n", sum);
           #endif  
   
   }
// 中断处理部分
extern unsigned int  Adc_val;
extern float         Ad_Val_Averge ;
extern float         Ad_Val ;
extern float            sum ;
extern void Delay(unsigned int ucout);
/*******************************************************************************
* 函数名称: ADC1_COMP_IRQHandler()
* 功能描述: ADC1中断处理函数
********************************************************************************/
void ADC1_COMP_IRQHandler(void)  
{   
   static unsigned char index;

    if(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)
    {   
   
      
     Delay(50000);
      Adc_val =ADC_GetConversionValue(ADC1);
      Ad_Val =(float)Adc_val/4096*3.3; //计算算法
      Ad_Val = (1.2*Ad_Val)/1.36;      //精度误差补偿 --采集内部电压误差大,需进一步修正
         Ad_Val_Averge = Ad_Val;
      if(index ==31)
     {
            unsigned char i;      
       sum =0;
       for(i = 0; i < 32; i++)
                sum += Ad_Val_Averge;
            sum = sum/32;                           //除以32求平均值     
            index = 0;
      
         }
         ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
         }
}

使用特权

评论回复
板凳
Rain_King| | 2014-7-28 14:39 | 只看该作者
顶贴.........

使用特权

评论回复
地板
yyxlmq1314| | 2014-8-30 15:41 | 只看该作者
不错~

使用特权

评论回复
5
yyxlmq1314| | 2014-8-30 15:41 | 只看该作者
最近也在用STM0的片子,好好学习一下

使用特权

评论回复
6
牛牛牛| | 2014-9-5 14:03 | 只看该作者
中断函数,取平均值的计算中,怎么没有找到index++,计算有问题吧

使用特权

评论回复
7
saviourxx| | 2014-9-5 16:23 | 只看该作者
中断加delay不可取吧!

使用特权

评论回复
8
davy_wy| | 2019-3-30 11:47 | 只看该作者
【研究了1天,没搞清STM32F0的ADC的时钟怎么启动的】
http://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=612901&fromuid=3487168
求解释

使用特权

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

本版积分规则

21

主题

114

帖子

5

粉丝