TA的每日心情 | 奋斗 2016-8-25 12:42 |
---|
签到天数: 692 天 连续签到: 1 天 [LV.9]以坛为家II
|
本帖最后由 fengye5340 于 2012-11-15 15:10 编辑
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[32]={0.0};
/*******************************************************************************
* 函数名称: ADC_GPIO_Init();
* 功能描述: ADC--GPIO输入引脚配置---在此可以设置16路外部输入通道
* 输入参数: void
* 返回参数: 无
********************************************************************************/
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
* 返回参数: 无
********************************************************************************/
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
* 返回参数: 无
********************************************************************************/
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
* 返回参数: 无
********************************************************************************/
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);
}
}
/*******************************************************************************
* 函数名称: ADC_Test()
* 功能描述: 电压采集测试--没有进行滤波算法处理
* 输入参数: void
* 返回参数: 无
********************************************************************************/
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[32] ;
extern float Ad_Val ;
extern float sum ;
extern void Delay(unsigned int ucout);
/*******************************************************************************
* 函数名称: ADC1_COMP_IRQHandler()
* 功能描述: ADC1中断处理函数
* 输入参数: void
* 返回参数: 无
********************************************************************************/
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[index++] = 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);
}
}
|
-
串口显示--2
-
串口显示--1
-
电路实物--2
-
电路实物-1
|