|
- #include<reg52.h>
- #include<intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit IO=P3^2;
- sbit lcden=P3^4;
- sbit lcdrs=P3^5;
- sbit lcdrw=P3^6;
- uchar data_byte;
- uchar RH,RL,TH,TL;
- void delay(uchar ms) // 延时模块
- {
- uint i,j;
- for(i=ms;i>0;i--)
- for(j=110;j>0;j--);
- }
- void delayms() //一个for循环大概需要8个多机器周期一个机器周期为1us
- { //本函数延时8us多
- uchar i;
- for(i=0;i<1;i++);
- }
- void writecom(uchar com)
- {
- lcdrs=0;
- P0=com;
- delay(5);
- lcden=1;
- delay(5);
- lcden=0;
- }
- void writedata(uchar date)
- {
- lcdrs=1;
- P0=date;
- delay(5);
- lcden=1;
- delay(5);
- lcden=0;
- }
- void lcd_init()
- {
- lcden=0;
- lcdrw=0;
- writecom(0x38);
- writecom(0x0c);
- writecom(0x06);
- writecom(0x01);
- }
- void display(uchar addr,uchar q)
- {
- delay(10);
- writecom(addr|0x80);
- writedata(q);
- delay(1);
- }
- //DHT11测试
- void start()// 开始信号
- {
- IO=1;
- delayms();
- IO=0;
- delay(25); // 主机把总线拉低必须大于 18ms 保证 DHT11 能检测到起始信号
- IO=1; //发送开始信号结束后 拉高电平延时 20-40us
- delayms(); // 以下三个延时函数差不多为 24us 符合要求
- delayms();
- delayms();
- }
- uchar receive_byte()//接收一个字节
- {
- uchar i,temp;
- for(i=0;i<8;i++) // 接收 8bit 的数据
- {
- while(!IO); // 等待 50us的低电平开始信号结束
- delayms(); //开始信号结束之后 延时 26us-28us 以下三个延时函数
- delayms();
- delayms();
- temp=0; //时间为 26us-28us 表示接收的为数据 '0'
- if(IO==1)
- temp=1; //如果 26us-28us之后 还为高电平 则表示接收的数据为 '1'
- while(IO); // 等待数据信号高电平 '0'为 26us-28us '1'为 70us
- data_byte<<=1; // 接收的数据为高位在前 右移
- data_byte|=temp;
- }
- return data_byte;
- }
- void receive()// 接收数据
- {
- uchar T_H,T_L,R_H,R_L,check,num_check,i;
- start();// 开始信号
- IO=1; //主机设为输入 判断从机 DHT11 响应信号
- if(!IO) // 判断从机是否有低电平响应信号
- {
- while(!IO); // 判断从机发出 80us 的低电平响应信号是否结束
- while(IO); // 判断从机发出 80us 的高电平是否结束 如结束则主机进入数据接收状态
- R_H=receive_byte();// 湿度高位
- R_L=receive_byte();// 湿度低位
- T_H=receive_byte();// 温度高位
- T_L=receive_byte();// 温度低位
- check=receive_byte();// 校验位
- IO=0; // 当最后一 bit 数据接完毕后 从机拉低电平 50us
- for(i=0;i<7;i++)// 差不多 50us 的延时
- delayms();
- IO=1; // 总线由上拉电阻拉高 进入空闲状态
- num_check=R_H+R_L+T_H+T_L;
- if(num_check==check) // 判断读到的四个数据之和是否与校验位相同
- {
- RH=R_H;
- RL=R_L;
- TH=T_H;
- TL=T_L;
- check=num_check;
- }}}
- void main()
- {
- lcd_init();// 初始化LCD
- while(1)
- {
- receive();// 接收数据
- display(0x00,'R');//LCD 的第一行显示
- display(0x01,':');
- display(0x02,RH/10+0x30); //0x30 表示 带字库的 LCD1602 中 0x30 的位置放有数字 0 RH/10+0x30 即表示湿度的十位数字在字库 RH/10+0x30 的位置处放着
- display(0x03,RH%10+0x30);
- display(0x04,'.');
- display(0x05,RL+0x30);
- display(0X06,'%');
- display(0x40,'T');
- display(0x41,':');
- display(0x42,TH/10+0x30);
- display(0x43,TH%10+0x30);
- display(0x44,'.');
- display(0x45,TL+0x30); //温度的小数部分就一位数,范围0-9
- display(0x46,0xdf); //温度单位
- display(0x47,0x43);
- } }
复制代码 |
|