- #include "reg52.h"
- #include <intrins.h>
- #include <string.h>
-
- #define dataBuf P0
-
- sfr AUXR = 0x8e;
-
- sbit RS = P1^0;
- sbit RW = P1^1;
- sbit EN = P1^2;
- sbit dht11 = P1^3;
-
- char dht11Data[5];
- char temperature[9];
- char humidity[9];
-
- void Delay40us() //@11.0592MHz
- {
- unsigned char i;
-
- _nop_();
- i = 15;
- while (--i);
- }
-
- void Delay5ms() //@11.0592MHz
- {
- unsigned char i, j;
-
- i = 9;
- j = 244;
- do
- {
- while (--j);
- } while (--i);
- }
-
- void Delay15ms() //@11.0592MHz
- {
- unsigned char i, j;
-
- i = 27;
- j = 226;
- do
- {
- while (--j);
- } while (--i);
- }
-
- void Delay30ms() //@11.0592MHz
- {
- unsigned char i, j;
-
- i = 54;
- j = 199;
- do
- {
- while (--j);
- } while (--i);
- }
-
- void Delay1000ms() //@11.0592MHz
- {
- unsigned char i, j, k;
-
- _nop_();
- i = 8;
- j = 1;
- k = 243;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
-
- //配置DHT11输出数据
- void dht11Start()
- {
- dht11 = 1;
- dht11 = 0;
- Delay30ms();
- dht11 = 1;
- while(dht11); //等待自己拉到低电平
- while(!dht11); //等待自己拉到高电平
- while(dht11); //等待自己拉到低电平
- }
-
- //获取DHT11的数据
- void obtainDht11Data()
- {
- int i,j;
- char tmp;
- char flag;
- dht11Start(); //开始输出数据
- for (i = 0; i < 5; i++){ //总共获取5个字符(40bit)的数据
- for (j = 0; j < 8; j++){
- //一次获取一个bit数据
- while(!dht11); //等待自己拉到高电平
- Delay40us(); //高电平时间为27微秒左右表示0,高电平时间为70微秒左右表示1
-
- if(dht11 == 1){ //40微秒后为高电平即输出1
- while(dht11);
- flag = 1;
- }else{ //40微秒后为低电平即输出0
- flag = 0;
- }
- tmp = tmp << 1; //由于dht11的数据是高位先出,所以用左移的方式
- tmp = tmp | flag; //(|1成1,|0不变),即对于前面7个bit,flag都为0,不改变tmp的值
- }
- dht11Data[i] = tmp;
- }
-
-
- }
-
- //发送数据到字符数组,用于LCD1602显示
- void sendStrData()
- {
- humidity[0] = 'H';
- humidity[1] = ':';
- humidity[2] = dht11Data[0]/10 + 0x30;
- humidity[3] = dht11Data[0]%10 + 0x30;
- humidity[4] = '.';
- humidity[5] = dht11Data[1]/10 + 0x30;
- humidity[6] = dht11Data[1]%10 + 0x30;
- humidity[7] = '%';
- humidity[8] = '\0';
- temperature[0] = 'T';
- temperature[1] = ':';
- temperature[2] = dht11Data[2]/10 + 0x30;
- temperature[3] = dht11Data[2]%10 + 0x30;
- temperature[4] = '.';
- temperature[5] = dht11Data[3]/10 + 0x30;
- temperature[6] = dht11Data[3]%10 + 0x30;
- temperature[7] = 'C';
- temperature[8] = '\0';
- }
-
- //检测忙信号,读数据线的D7位
- void checkBusySignal()
- {
- char tmp = 0x80;
- dataBuf = 0x80;
- while(tmp & 0x80){ //当忙标志位(数据位D7)为高电平时,此时模块不能接收命令或者数据
- RS = 0;
- RW = 1;
- EN = 0;
- _nop_();
- EN = 1;
- _nop_();
- _nop_();
- tmp = dataBuf; //读八位数据线的数据,当不忙时,硬件会自动将该位置0,当检测到D7为低电平时将退出死循环
- EN = 0;
- _nop_();
- }
- }
-
- //写指令
- void writeCmd(char cmd)
- {
- checkBusySignal();
- RS = 0; //选择写指令寄存器
- RW = 0;
- EN = 0;
- _nop_(); //该函数为延时函数,延时一微秒
- dataBuf = cmd; //将指令存入八位数据线中
- EN = 1;
- _nop_();
- _nop_();
- EN = 0;
- _nop_();
- }
-
- //写数据
- void writeData(char myData)
- {
- checkBusySignal();
- RS = 1; //选择写数据寄存器
- RW = 0;
- EN = 0;
- _nop_(); //该函数为延时函数,延时一微秒
- dataBuf = myData; //将数据存入八位数据线中
- EN = 1;
- _nop_();
- _nop_();
- EN = 0;
- _nop_();
- }
-
- //LCD1602初始化
- void lcd1602Init()
- {
- Delay15ms(); //延时 15ms
- writeCmd(0x38); //写指令 38H(不检测忙信号)
- Delay5ms(); //延时 5ms
- checkBusySignal();//以后每次写指令,读/写数据操作均需要检测忙信号
- writeCmd(0x38); //写指令 38H:显示模式设置
- writeCmd(0x08); //写指令 08H:显示关闭
- writeCmd(0x01); //写指令 01H:显示清屏
- writeCmd(0x06); //写指令 06H:显示光标移动设置
- writeCmd(0x0C); //写指令 0CH:显示开及光标设置
- }
-
- //LCD1602显示一行字符
- void lcd1602ShowData(char rows,char columns,char *str)
- {
- switch (rows){ //选择行
- case 1:
- writeCmd(0x80 + columns); //选择列
- while(*str != '\0'){
- writeData(*str); //显示字符
- str++;
- }
- break;
-
- case 2:
- writeCmd(0x80 + 0x40 +columns); //选择列
- while(*str != '\0'){
- writeData(*str); //显示字符
- str++;
- }
- break;
-
- default:
- break;
- }
- }
-
- void main()
- {
- lcd1602Init();
- //dht11上电后,需要延时1-2s度过不稳定状态
- Delay1000ms();
- Delay1000ms();
-
- //每1s获取空气中的温湿度
- while(1){
- obtainDht11Data();
- sendStrData();
- lcd1602ShowData(2,0,humidity);
- lcd1602ShowData(1,0,temperature);
- Delay1000ms();
- }
- }
-
复制代码
|