#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;
}
|