stc12c4052AD读取DHT11数据并显示
硬件说明: 单片机:STC12C4052AD 晶振:12M 数码管:共阴4位数码管
关于DHT11这个传感器的时序,你可以自己百度 为了读取这个传感器,我花了很多时间,网上搜索的计时程序不可靠。STC-ISP在终于解决时序问题之前,在上面找到了标准的计时函数。 目前,该程序无法实现温度的实时变化,并考虑定期中断。改天再试一次; 本程序参考了众多大神的内容,感谢众神。
/******** programename: DHT11 hardware: STC12C2052AD /*****/ #include <STC12C2052AD.h> //STC12C2052AD header file #include <stdio.h> // #include <intrins.h> ///用于引用_NOP_语句; sbit BUS=P3^7;// 接P3^不,不知道为什么 //**************定义数字管段 #define D0{a=1;b=1;c=1;d=1;e=1;f=1;g=0;} #define D1{a=0;b=1;c=1;d=0;e=0;f=0;g=0;} #define D2{a=1;b=1;c=0;d=1;e=1;f=0;g=1;} #define D3{a=1;b=1;c=1;d=1;e=0;f=0;g=1;} #define D4{a=0;b=1;c=1;d=0;e=0;f=1;g=1;} #define D5{a=1;b=0;c=1;d=1;e=0;f=1;g=1;} #define D6{a=1;b=0;c=1;d=1;e=1;f=1;g=1;} #define D7{a=1;b=1;c=1;d=0;e=0;f=0;g=0;} #define D8{a=1;b=1;c=1;d=1;e=1;f=1;g=1;} #define D9{a=1;b=1;c=1;d=1;e=0;f=1;g=1;} //*定义数字管位 sbit w1=P3^3; sbit w2=P3^2; sbit w3=P3^1; sbit w4=P3^0; //*定义数字管段端口 sbit a=P1^0; sbit b=P1^6; sbit c=P1^4; sbit d=P1^2; sbit e=P1^1; sbit f=P1^7; sbit g=P1^5; sbit h=P1^3; //声明全局变量 unsigned char RH_L_temp,RH_H_temp,TP_L_temp,TP_H_temp,check_temp;
unsigned char RH_L,RH_H,TP_L,TP_H,check_num;
// 延时函数区
// 40us延时,本程序没有用到
void Delay40us() //@12.000MHz
{
unsigned char i;
i = 117;
while (--i);
}
//45us 延时
void Delay45us() //@12.000MHz
{
unsigned char i, j;
i = 1;
j = 131;
do
{
while (--j);
} while (--i);
}
//20ms延时
void Delay20ms() //@12.000MHz
{
unsigned char i, j, k;
i = 1;
j = 234;
k = 113;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
//1s延时
void Delay1000ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 46;
j = 153;
k = 245;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
//数据接收函数
unsigned char receive_temp(){
unsigned char i,mask=0;
for (i=0;i<8;i++){
//一次接收8个数据位
while(!BUS); //错开50us的低电平
Delay45us(); //延时45us后,检测端口电位
mask=mask<<1; //不管电位高低,mask都要左移一位,用于接收数据位
if(BUS==1) //如果是高电平,则加1
mask++;
while(BUS); //等待表示数据结束的高电平
}
return mask; //接收完数据后,返回mask;
}
//*******************
unsigned char read_temp(){
BUS=0; //给传感器发低电平信号,让传感器准备工作,低电平信号保持18ms以上即可
Delay20ms();
BUS=1; //拉高端口电位,等待传感器反馈
Delay45us();
if (BUS==1) //如果延时后是高电平,则表示传感器没有工作,返回1,表示错误;
return 1;
else{
while(!BUS);//等待低电平信号结束
while (BUS);//等待高电平信号结束
RH_H_temp=receive_temp();//接收湿度高位数据
RH_L_temp=receive_temp();//接收湿度低位数据
TP_H_temp=receive_temp();//接收温度高位数据
TP_L_temp=receive_temp();//接收温度低位数据
check_temp=receive_temp();//接收校验位
BUS=0; //清空数据端口
Delay45us();
BUS=1; //拉高,等待下一次读取
}
check_num=RH_L_temp+RH_H_temp+TP_L_temp+TP_H_temp; //校验数据
if (check_num==check_temp){
RH_H=RH_H_temp;
RH_L=RH_L_temp;
TP_H=TP_H_temp;
TP_L=TP_L_temp;
return 0;
}
else
return 1;
}
//***************//
void display(unsigned char m,n){
//采用推挽输出,不然电流不够,无法点亮全部数码管
P1M0=0x00;
P1M1=0xff;
while(1){
// 计划同时显示温度和湿度的,但STC12C2052AD内存不够,本程序只显示温度的整数位
switch(n/10){
case 1:D1;break;
case 2:D2;break;
case 3:D3;break;
case 4:D4;break;
case 5:D5;break;
case 6:D6;break;
case 7:D7;break;
case 8:D8;break;
case 9:D9;break;
default:D0;
}
w3=0;
Delay20ms();
w3=1;
switch(n%10){
case 1:D1;break;
case 2:D2;break;
case 3:D3;break;
case 4:D4;break;
case 5:D5;break;
case 6:D6;break;
case 7:D7;break;
case 8:D8;break;
case 9:D9;break;
default:D0;
}
w4=0;
Delay20ms();
w4=1;
}
}
//**************//
// SBUF串口通讯初始化,用串口来检验程序有没有按计划执行
void UART_init (void){
TMOD = 0x20; //
SCON = 0x50; //
TH1 = 0xF3; //
TL1 = 0xF3; //
PCON = 0x80; //
TR1 = 1;
}
//**********************************
void main(){
unsigned char result,count=0;
UART_init();
Delay1000ms();
while (1){
Delay1000ms();
Delay1000ms();
result=read_temp();
if (result==1){
//如果读取失败,串口数据区显示0x11;文字区显示faile
SBUF = 0x11;
printf("faile\r\n");
while(TI==0);
TI = 0;
}
else{
display(RH_H,TP_H); //读取成功则数码管显示数字
}
}
}