LCD1602能够正常显示,但是读取到的温湿度数据保持不变,并且明显是错误的数据。程序下载:
DHT11.rar
(35.73 KB, 下载次数: 12)
- #include<reg51.h>
- #include<intrins.h>
- #include"1602.h"
- #define uchar unsigned char
- #define uint unsigned int
- sbit Data=P3^6; //定义数据线
- uchar rec_dat[9]; //用于显示的接收数据数组
- void delay_us(uchar n)
- {
- unsigned char a;
- while(--n);
- for(a=3;a>0;a--);
- }
- void delay_ms(uint z)
- {
- uint i;
- unsigned char a,b,c;
- for(i=z;i>0;i--)
- for(c=1;c>0;c--)
- for(b=43;b>0;b--)
- for(a=127;a>0;a--);
- }
- void DHT11_start()
- {
- Data=1;
- delay_us(1);
- Data=0;
- delay_ms(20); //延时18ms以上
- Data=1;
- delay_us(40);
- }
- uchar DHT11_rec_byte() //接收一个字节
- {
- uchar i,dat=0;
- for(i=0;i<8;i++) //从高到低依次接收8位数据
- {
- while(!Data); //等待50us低电平过去
- delay_us(70); //延时60us,如果还为高则数据为1,否则为0
- dat<<=1; //移位使正确接收8位数据,数据为0时直接移位
- if(Data==1) //数据为1时,使dat加1来接收数据1
- {
- dat+=1;
- }
- while(Data); //等待数据线拉低
- }
- return dat;
- }
- void DHT11_receive() //接收40位的数据
- {
- uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
- DHT11_start();
- if(Data==0)
- {
- while(Data==0); //等待拉高
- delay_us(90); //拉高后延时80us
- R_H=DHT11_rec_byte(); //接收湿度高八位
- R_L=DHT11_rec_byte(); //接收湿度低八位
- T_H=DHT11_rec_byte(); //接收温度高八位
- T_L=DHT11_rec_byte(); //接收温度低八位
- revise=DHT11_rec_byte(); //接收校正位
- delay_us(25); //结束
- if((R_H+R_L+T_H+T_L)==revise) //校正
- {
- RH=R_H;
- RL=R_L;
- TH=T_H;
- TL=T_L;
- }
- /*数据处理,方便显示*/
- rec_dat[0]='0'+(RH/10);
- rec_dat[1]='0'+(RH%10);
- rec_dat[2]='%';
- rec_dat[3]='R';
- rec_dat[4]='H';
- rec_dat[5]=' ';
- rec_dat[6]='0'+(TH/10);
- rec_dat[7]='0'+(TH%10);
- rec_dat[8]='C';
- }
- }
- void main()
- {
- uchar i;
- Init_LCD1602(); //lcd1602初始化
- displaystring(0, 0, "Happy new year!");
- while(1)
- {
-
- delay_ms(1500); //DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令
- DHT11_receive();
- for(i=0;i<9;i++)
- displaychar(i,1, rec_dat[i]);//写入当前字符并显示
-
-
- }
- }
复制代码
- //使用方法: 使用前调用Init_LCD1602()初始化,显示方法displaystring(0, 0, "This is a test.");
- #ifndef _LCD1602_
- #define _LCD1602_
-
- #define uchar unsigned char
- #define uint unsigned int
- //#define _PORT_REV_ //如果数据端口高低位交换,请去掉此注释
- #include <intrins.h> //包含_nop_()指令
- sbit LCD1602_RS = P2^0; //控件引脚定义,移植请修改
- sbit LCD1602_RW = P2^1;
- sbit LCD1602_E = P2^2;
- #define LCD_PORT P1 //输出数据总线端口定义,移植请修改
- #define LCD_COMMAND 0 // Command
- #define LCD_DATA 1 // Data
- #define LCD_CLEAR_SCREEN 0x01 // 清屏
- #define LCD_HOMING 0x02 // 光标返回原点
- #define LCD_SHOW 0x04 //显示开
- #define LCD_HIDE 0x00 //显示关
- #define LCD_CURSOR 0x02 //显示光标
- #define LCD_NO_CURSOR 0x00 //无光标
- #define LCD_FLASH 0x01 //光标闪动
- #define LCD_NO_FLASH 0x00 //光标不闪动
- #define LCD_AC_UP 0x02
- #define LCD_AC_DOWN 0x00 // default
- #define LCD_MOVE 0x01 // 画面可平移
- #define LCD_NO_MOVE 0x00 //default
- void delay10us(unsigned char t) //误差 -0.234375us
- {
- while(--t)
- {
- unsigned char i;
- _nop_();
- _nop_();
- _nop_();
- i = 24;
- while (--i);}
- }
- /*********************************************************************************************
- 函数名:8位数据高低位交叉互换
- 调 用:uchar = DataReverse(uchar);
- 参 数:输入的端口(0000 0XXX 其中XXX是设置输入端口号,可用十进制0~7表示,0表示P1.0,7表示P1.7)
- 返回值:交换后的8位数据
- 结 果:交换数据高低位D7→D0,D6→D1.....,D0→D7,并返回交换后的结果
- 备 注:
- /**********************************************************************************************/
- unsigned char DataReverse(unsigned char datOld)
- {
- unsigned char datNew=0,i;
- for (i=0; i<8; i++)
- {
- if (datOld & (1<<i)) //如果某位为1,则或上一个1
- datNew |= (0x80>>i);
- }
- return datNew;
- }
- /**********************************************************************************************/
- /*********************************************************************************************
- 函数名:LCD1602等待函数
- 调 用:uchar = LCD_Wait();
- 参 数:无
- 返回值:LCD1602数据总线的值
- 结 果:等待LCD1602内部指令执行完成
- 备 注:返回结果可不用
- /**********************************************************************************************/
- unsigned char LCD_Wait(void)
- {
- LCD1602_RS = 0;
- LCD1602_RW = 1; delay10us(2);
- LCD1602_E = 1; delay10us(2);
- #ifdef _PORT_REV_ //如果数据线高低位交换,则需要处理数据
- while(DataReverse(LCD_PORT)&0x80);
- LCD1602_E = 0;
- return DataReverse(LCD_PORT);
- #else //正常情况下不需要交换
- while(LCD_PORT&0x80);
- LCD1602_E = 0;
- return LCD_PORT;
- #endif
- }
- /**********************************************************************************************/
- /*********************************************************************************************
- 函数名:LCD1602数据写函数
- 调 用:LCD_Wait(bit, uchar);
- 参 数:数据类型,数据值
- 返回值:无
- 结 果:将指定数据类型的数据写入1602
- 备 注:数据类型:LCD_COMMAND(0)、LCD_DATA(1)
- /**********************************************************************************************/
- void LCD_Write(bit DataStyle, unsigned char DAT)
- {
- LCD1602_E = 0;
- LCD1602_RS = DataStyle;
- LCD1602_RW = 0; delay10us(2);
- #ifdef _PORT_REV_
- LCD_PORT = DataReverse(DAT);
- #else
- LCD_PORT = DAT;
- #endif
- _nop_();
- LCD1602_E = 1; delay10us(2);//注意顺序
- LCD1602_E = 0; delay10us(2);
- LCD_Wait(); //等待1602内部执行完,proteus仿真时请注释此句
- }
- /**********************************************************************************************/
- /*********************************************************************************************
- 函数名:LCD1602显示设置函数
- 调 用:LCD_SetDisplay(uchar);
- 参 数:显示模式
- 返回值:无
- 结 果:正常设置1602显示模式
- 备 注:内部函数,初始化时调用
- /**********************************************************************************************/
- void LCD_SetDisplay(unsigned char DisplayMode)
- {
- LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
- }
- /**********************************************************************************************/
- /*********************************************************************************************
- 函数名:LCD1602显示设置函数
- 调 用:LCD_Setinput(uchar);
- 参 数:显示模式
- 返回值:无
- 结 果:正常设置1602显示模式
- 备 注:内部函数,初始化时调用
- /**********************************************************************************************/
- void LCD_SetInput(unsigned char InputMode)
- {
- LCD_Write(LCD_COMMAND, 0x04|InputMode);
- }
- /**********************************************************************************************/
- /*********************************************************************************************
- 函数名:LCD1602初始化函数
- 调 用:Init_LCD1602();
- 参 数:无
- 返回值:无
- 结 果:初始化1602函数
- 备 注:
- /**********************************************************************************************/
- void Init_LCD1602()
- {
- LCD_Write(LCD_COMMAND, 0x38); //8位数据端口,2行显示,5*7点阵
- LCD_Write(LCD_COMMAND, 0x38);
- LCD_Write(LCD_COMMAND, 0x38);
- LCD_SetDisplay(LCD_SHOW | LCD_NO_CURSOR); //开启显示, 无光标
- LCD_Write(LCD_COMMAND, LCD_CLEAR_SCREEN); //清屏
- LCD_SetInput(LCD_AC_UP | LCD_NO_MOVE); //AC递增, 画面不动
- }
- /**********************************************************************************************/
- /*********************************************************************************************
- 函数名:LCD1602数据写函数
- 调 用:LCD1602_DispString(uchar, uchar, *uchar);
- 参 数:x坐标,y坐标,字符串
- 返回值:无
- 结 果:在指定坐标显示字符串
- 备 注:x: 0~15; y:0、1
- /**********************************************************************************************/
- void displaystring(unsigned char x, unsigned char y, unsigned char *s)
- {
- if(y == 0)
- LCD_Write(LCD_COMMAND, 0x80|x);
- if(y == 1)
- LCD_Write(LCD_COMMAND, 0x80|(x-0x40));
- while(*s != ' ')
- {
- LCD_Write(LCD_DATA, *s);
- s++;
- }
- }
- /**********************************************************************************************/
- //字符显示初始地址设置
- void LCD_SET_XY(uchar X,uchar Y)
- {
- if(Y == 0)
- LCD_Write(LCD_COMMAND, 0x80|X);
- if(Y == 1)
- LCD_Write(LCD_COMMAND, 0x80|(X-0x40));
- }
- //在第X行Y列开始显示Wdata所对应的单个字符
- void displaychar(uchar X,uchar Y,uchar Wdata)
- {
- LCD_SET_XY(X,Y);//写地址
- LCD_Write(LCD_DATA, Wdata);//写入当前字符并显示
- }
- #endif
复制代码
一周热门 更多>