#include "adc.h"
#if 0 //寄存器编程
/*******************************************************
*函数名:void ADC1_Init(void)
*功 能:ADC1初始化
*参 数:无
*返 回:无
*备 注:
传感器 引脚 ADC1通道号
光照 PA3 通道3
MQ2烟雾 PA2 通道2
MQ135有害 PA1 通道1
********************************************************/
void ADC1_Init(void)
{
/* 1.时钟配置 */
RCC->APB2ENR |=1<<2; //开启PA口的时钟
RCC->APB2ENR |=1<<9; //开启ADC1的时钟
RCC->CFGR &=~(3<<14); //清零
RCC->CFGR |= (2<<14); //ADC时钟设置为6分频 72/6=12M .ADC时钟不能大于14M
RCC->APB2RSTR |= 1<<9; //开启复位ADC1的接口
RCC->APB2RSTR &=~(1<<9); //关闭ADC1复位
/* 2.GPIO配置 */
GPIOA->CRL &= 0xffff000f; //PA1、PA2、PA3设置为模拟输入
/* 3.ADC配置 */
ADC1->CR1 &= ~(1<<23); //禁用规则通道的模拟看门狗
ADC1->CR1 &= ~(1<<22); //禁用注入通道的模拟看门狗
ADC1->CR1 &= ~(0XF<<16);//独立模式
ADC1->CR1 &= ~(0X7<<13);//选1个通道
ADC1->CR1 &= ~(1<<8); //不用扫描模式
ADC1->CR1 &= ~(1<<5); //不使用ADC的任何中断
ADC1->CR2 |= 1<<20; //规则通道启用外部触发事件
ADC1->CR2 |= 7<<17; //规则通道启用软件触发
ADC1->CR2 &=~(1<<15); //不启用注入通道
ADC1->CR2 &=~(1<<11); //得到的AD值采用右对齐方式
ADC1->CR2 &=~(1<<8); //不启用DMA
ADC1->SMPR2 &=~(7<<3); //设置通道1的采样时间。
ADC1->SMPR2 |= (7<<3); //采样周期设置为239.5个周期 +12.5
ADC1->SQR1 &= ~(0XF<<20); //设置为只有一个转换
ADC1->SQR1 |= ( 0 <<20);
ADC1->CR2 |= 1<<0; //ADC从掉电模式,变为上电模式
ADC1->CR2 |= 1<<3; // 初始化校准寄存器
while (ADC1->CR2 & (1<<3)); //等待校准寄存器初始化完成
ADC1->CR2 |= 1<<2; //开始校准
while (ADC1->CR2 & (1<<2)); //等待校准完成
}
/*******************************************************
*函数名:u16 ADC1_Get(u8 ch)
*功 能:按通道号获取AD值
*参 数:通道号
*返 回:AD值
*备 注:
传感器 引脚 ADC1通道号
光照 PA3 通道3
MQ2烟雾 PA2 通道2
MQ135有害 PA1 通道1
********************************************************/
u16 ADC1_ReadData(u8 ch)
{
ADC1->SQR3 &= ~(0X1F<<0); //设置通道3为第一个转换
ADC1->SQR3 |= ch; // 通道号
ADC1->CR2|= 1<<22; //开启规则转换通道,这时才开始转换
while (!(ADC1->SR & (1<<1))); //等待AD转换完成
return ADC1->DR; //返回AD值.
}
#else //库函数编程
/*******************************************************
*函数名:void ADC1_Init(void)
*功 能:ADC1初始化
*参 数:无
*返 回:无
*备 注:
传感器 引脚 ADC1通道号
光照 PA3 通道3
MQ2烟雾 PA2 通道2
MQ135有害 PA1 通道1
********************************************************/
void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* 1.时钟配置 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启PA口的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ADC1时钟6分频(小于等于14MHz)
/* 2.GPIO配置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 3.ADC配置 */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //每次转换通道数目
ADC_Init(ADC1,&ADC_InitStructure); //初始化ADC1
ADC_Cmd(ADC1,ENABLE); //使能ADC
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准结束
//ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
/*******************************************************
*函数名:u16 ADC1_Get(u8 ch)
*功 能:按通道号获取AD值
*参 数:通道号
*返 回:AD值
*备 注:
传感器 引脚 ADC1通道号
光照 PA3 通道3
MQ2烟雾 PA2 通道2
MQ135有害 PA1 通道1
********************************************************/
u16 ADC1_ReadData(u8 ch)
{
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_1Cycles5);
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
return ADC_GetConversionValue(ADC1);
}
#endif
//中值平均滤波
#define N 10 //采样个数
u16 ADC1_ReadAvgData(u8 ch)
{
u16 sum=0;
u16 ADC1_ValueBuf[N];
for(u8 i=0;i<N;i++)
{
ADC1_ValueBuf[i] = ADC1_ReadData(ch);
}
//从小到大排列(冒泡法)
for(u8 j=0;j<N-1;j++) // 趟数
{
for(u8 i=0;i<N-1-j;i++) // 一趟比较的次数
{
if(ADC1_ValueBuf[i]>ADC1_ValueBuf[i+1]) // 把最大值往后放
{
//交换
u16 temp;
temp = ADC1_ValueBuf[i];
ADC1_ValueBuf[i] = ADC1_ValueBuf[i+1];
ADC1_ValueBuf[i+1] = temp;
}
}
}
for(u8 i=2;i<N-2;i++) // 去掉最低两位与最高两位
{
sum+=ADC1_ValueBuf[i];
}
return sum/(N-4); // 求平均值
}
u16 Light_Data(void)//光照
{
u16 ad;
ad=ADC1_ReadAvgData(3);
ad=(4095-ad)*1000/4095;
return ad;
}
u16 MQ2_Data(void)//烟雾
{
u16 ad;
ad=ADC1_ReadAvgData(2);
ad=ad*100/4095;
return ad;
}
u16 MQ135_Data(void)//有害气体
{
u16 ad;
ad=ADC1_ReadAvgData(1);
ad=ad*100/4095;
return ad;
}
|