快速导航
STC12已封装好的函数库
DTH11器件说明书:
https://note.youdao.com/s/A3ez5ubT
/*
*程序名:DHT11驱动程序
*硬件支持:STC12C5A60S2 DH11
*接口说明:DHT11:Vcc GND DATA
*晶振说明:11.0592MHZ
*作者:小途
*/
#include <STC12C5A60S2.H>
#define uchar unsigned char
#define uint unsigned int
#define JUDGE 30 //用于判断通信的0和1,与单片机速度和晶振频率有关
sbit DATA = P2^0; //定义数据引脚
uchar dat_r[5]; //用于存放从DHT11读取到的数值
/*********************************************************************************************
函数名称:Delay30us();/Delay20ms();/Delay1s();
函数功能:延时函数
参 数:无
返回值:无
结 果:延时相应时间
备 注:振荡晶体为11.0592MHz(所有延时函数Copy自STC-ISP(v6.85).exe)
**********************************************************************************************/
void Delay30us() //@11.0592MHz
{
unsigned char i;
i = 80;
while (--i);
}
void Delay20ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 1;
j = 216;
k = 35;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay1s() //@11.0592MHz
{
unsigned char i, j, k;
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
//==============================================================================================
//串口初始化,晶振11.0592,波特率9600
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //独立波特率发生器时钟为Fosc,即1T
BRT = 0xDC; //设定独立波特率发生器重装值
AUXR |= 0x01; //串口1选择独立波特率发生器为波特率发生器
AUXR |= 0x10; //启动独立波特率发生器
EA = 1;//开总中断
ES = 1;//开串口中断
}
//向串口发送一段字符串
void prints(char *s)
{
while(*s != '\0')//发送字符串,直到遇到0才结束
{
SBUF = *s++;
while(!TI);
TI = 0;
}
}
//向串口发送一个字符
void putchar(char ch)
{
SBUF = ch;
while(!TI);TI = 0;
}
/********************************************************
* 函数名称:GetData(void)
* 函数功能:DHT11读数据函数
* 输入:无
* 返回:失败->-1,-2,-3,-4;成功->0
* 结果:读DHT11数据并保存到数组dat_r[]
*
********************************************************/
char GetData (void)
{
uchar i,j; //for循环变量
uchar t; //超时判断
uchar dat8=0; //一次读取的8位数据,需要读5次
DATA = 0; //主机发起始信号
Delay20ms(); //主机拉低总线至少18ms
DATA = 1; //主机拉高总线20~40us
Delay30us();
t = 80; //设置超时等待时间
while(DATA && t--); //等待DHT11拉低总线
if(t == 0) //超时
{
DATA = 1;
return -1; //通信错误退出,返回错误信号:-1
}
//等80us响应信号
t = 250; //设置超时等待时间
while(!DATA && t--); //等待DHT11拉高总线
if(t == 0) //超时
{
DATA = 1;
return -2; //通信错误退出,返回错误信号:-2
}
//等80us响应信号
t = 250; //设置超时等待时间
while(DATA && t--); //等待DHT11拉低总线
if(t == 0) //超时
{
DATA = 1;
return -3; //通信错误退出,返回错误信号:-3
}
for(j=0; j<5; j++) //5次读取
{
for(i=0; i<8; i++) //1次8个位
{
//等待50us开始时隙
t = 150; //设置超时等待时间
while(!DATA && t--); //等待DHT11拉高总线
if(t == 0) //超时
{
DATA = 1;
return -4; //通信错误退出,返回错误信号:-4
}
t = 0; //记录时间清零
while(DATA && ++t); //等待并记录高电平持续时间
dat8 <<= 1;
if(t > JUDGE) //高电平持续时间较长(70us)
dat8 += 1; //传输值为1
//else dat8 += 0;
}
dat_r[j] = dat8;
}
Delay30us(); //等待DHT11拉低50us
Delay30us();
DATA = 1; //结束,拉高总线
return 0; //返回成功信号
}
/*********************************************************************************************
函数名:数据校验函数
调 用:? = Check();
参 数:无
返回值:成功->0;失败->-1;
结 果:数据校验
备 注:数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
**********************************************************************************************/
char Check(void)
{
uchar i; //for循环变量
uint chk=0; //校验和
for(i=0; i<4; i++)
chk += dat_r[i]; //累加
if((uchar)chk != dat_r[4]) //比对
return -1; //返回错误信号:-1
else
return 0; //返回正确信号:0
}
/********************************************************
* 函数名称:SendOutData()
* 函数功能:向串口发送DH11温湿度数据原始数据
* 输入:无
* 返回:无
* 注意事项:需要初始化串口、函数运行过程要核验数据函数
* 数据格式:8bit温度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数据+8bit校验和
*
********************************************************/
void SendOutData()
{
char i;
i = GetData(); //读数据
if(i != 0) //有错误
{
//UART_T(-i); //返回错误值
return; //重新开始
}
i = Check(); //数据校验
if(i != 0) //有错误
{
//UART_T(-i); //返回错误值
return; //重新开始
}
putchar(dat_r[0]); //湿度整数
putchar(dat_r[1]); //湿度小数(根据数据手册,DHT11小数部分一直是0没用)
putchar(dat_r[2]); //温度整数
putchar(dat_r[3]); //温度小数(根据数据手册,DHT11小数部分一直是0没用)
putchar(dat_r[4]); //校验值
Delay1s(); //经测试,两次连读要至少延时80ms
}
/*****************************************
*函数名称:SendOutDH11Str()
*函数功能:向串口发送温湿度数据
*输入:无
*返回:无
*****************************************/
void SendOutDH11Str()
{
char i;
uchar HD11_str[13];//发送的数据
uchar RH,RL,TH,TL,revise;
i = GetData(); //读数据
if(i != 0) //有错误
{
//UART_T(-i); //返回错误值
return; //重新开始
}
i = Check(); //数据校验
if(i != 0) //有错误
{
//UART_T(-i); //返回错误值
return; //重新开始
}
RH = dat_r[0];//湿度整数
RL = dat_r[1];//湿度小数(根据数据手册,DHT11小数部分一直是0没用)
TH = dat_r[2];//温度整数
TL = dat_r[3];//温度小数(根据数据手册,DHT11小数部分一直是0没用)
revise = dat_r[4];//校验值
//数据处理
HD11_str[0]=RH/10+'0';
HD11_str[1]=(RH%10)+'0';
HD11_str[2]='%';
HD11_str[3]='R';
HD11_str[4]='H';
HD11_str[5]=' ';
HD11_str[6]=' ';
HD11_str[7]=(TH/10)+'0';
HD11_str[8]=(TH%10)+'0';
HD11_str[9]='^';
HD11_str[10]='C';
prints(HD11_str);
Delay1s(); //经测试,两次连读要至少延时80ms
}
void main()
{
UartInit(); //串口初始化
Delay1s(); //等待DHT11稳定
while (1)
{
/*
备注:Demo程序只能选择一种发送方式,编译警告提示有未调用段,属于正常现象可忽略
*/
/*向串口发送一段原始数据*/
// SendOutData();
/*向串口已字符串形式发送数据*/
SendOutDH11Str();
}
}
运行结果