找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2880|回复: 0
收起左侧

STM32F103的光照、烟雾MQ2、有毒气体MQ135的ADC配置(寄存器版与库函数版)

[复制链接]
ID:763998 发表于 2020-6-2 19:46 | 显示全部楼层 |阅读模式
#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;
}



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表