百度网盘资料链接:https://pan.baidu.com/s/1J6AuQpoDJbjMko3kSD4aZw
提取码:81f5
取走点个赞~
1、用 DHT11 温湿度传感器获取温湿度信息,显示到OLED屏上
2、用 MQ-135 空气质量传感器获取空气质量信息,显示到OLED屏上
3、设计一个报警系统,可以设置温湿度与空气质量的上限,超过这个值蜂鸣器发出声响报警
(一)、主控芯片stm32f103c8t6核心板
(二)DHT11温湿度传感器
(一)DHT11驱动
DHT11.c
#include "DHT11.h"
#include "delay.h"
//???DHT11
//??:??????(????)
u8 DHT11_Init()
{
GPIO_InitTypeDef GPIO_InitStruce;
RCC_APB2PeriphClockCmd(DHT11_DQ_RCC,ENABLE); //????PA0
GPIO_InitStruce.GPIO_Pin = DHT11_DQ_PIN;
GPIO_InitStruce.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruce.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_DQ_PORT,&GPIO_InitStruce);
DHT11_Rst();
return DHT11_Check();
}
//??DHT11
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //SET OUTPUT
DHT11_DQ_OUT=0; //??DQ
delay_ms(20); //????18ms
DHT11_DQ_OUT=1; //DQ=1
delay_us(30); //????20~40us
}
//??DHT11???
//??1:????DHT11???
//??0:??
u8 DHT11_Check(void)
{
u8 retry=0;
DHT11_IO_IN();//SET INPUT
while (DHT11_DQ_IN&&retry<100)//DHT11???40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
else retry=0;
while (!DHT11_DQ_IN&&retry<100)//DHT11????????40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
return 0;
}
//?DHT11?????
//???:1/0
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while(DHT11_DQ_IN&&retry<100)//???????
{
retry++;
delay_us(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)//??????
{
retry++;
delay_us(1);
}
delay_us(40);//??40us
if(DHT11_DQ_IN)
return 1;
else
return 0;
}
//?DHT11??????
//???:?????
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//?DHT11??????
//temp:???(??:0~50? humi:???(??:20%~90%)
//???:0,??;1,????
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//??40???
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humi=buf[0];
*temp=buf[2];
}
}else return 1;
return 0;
}
DHT11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "sys.h"
#define DHT11_IO_IN() {GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=8<<20;}
#define DHT11_IO_OUT() {GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=3<<20;}
#define DHT11_DQ_OUT PAout(5)
#define DHT11_DQ_IN PAin(5)
#define DHT11_DQ_RCC RCC_APB2Periph_GPIOA
#define DHT11_DQ_PIN GPIO_Pin_5
#define DHT11_DQ_PORT GPIOA
u8 DHT11_Init(void);
u8 DHT11_Read_Data(u8 *temp,u8 *humi);
u8 DHT11_Read_Byte(void);
u8 DHT11_Read_Bit(void);
void DHT11_Rst(void);
u8 DHT11_Check(void);
#endif
(二)MQ-135驱动,由于用的是ADC,直接上ADC代码
#include "adc.h"
#include "delay.h"
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
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通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
(三)主程序
main.c部分代码
int main(void)
{
u16 key;
int adc,cnt=0;
float volt;
delay_init();
NVIC_Configuration();
BEEP_Init();
OLED_Init();
OLED_Clear();
uart_init(115200);
printf("欢迎使用化作尘健康小工具\r\n");
KEY_Init();
LED_Init();
TIM3_Int_Init(500-1,720-1);
DEV_Init();
OLED_Clear();
OLED_Dis_Menu();
while(1)
{
if(cnt++ ==1000)
{
cnt = 0;
LED0=!LED0;
adc = Get_Adc_Average(0,5);
volt = adc*3.3/4096;
air = pow((3.4880*10*volt)/(5-volt),(1.0/0.3203));
printf("air :%d\r\n",air);
//获取温湿度
DHT11_Read_Data( &temp, &humi);
if(last_temp!=temp || last_humi!=humi)
{
OLED_Dis_DHT(temp,humi,air);
}
}
key = Key_GetValue(); //按键扫描
if(key)
DealKeyVal(key);
if(!KEY1_IO())
{
printf("%d\r\n",GetTime());
}
if(temp>Max_temp || humi>Max_humi || air>Max_air)
{
if(cnt<500)BEEP=1;
else if(cnt<1000)BEEP=0;
}else BEEP=0;
delay_ms(1);
}
}