在网上找了好多代码都不能运行,有的讲原理有的驱动起来有问题,对小白太不友好,找了好久终于找到能用的驱动,感谢b站大神毛毛雨分享dh11.c
#include "dht11.h"
/**********************************
*函数名:DHT11_start
*函数功能:DHT11开始信号
*输入:无
*输出:无
***********************************/
void DHT11_start()
{
Data = 1;
DelayUs(2);
Data = 0;
DelayMs(30); //主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号
Data = 1;
DelayUs(15); //15*2+5=35us主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号
}
/*******************************************
*函数名:DHT11_rec_byte
*函数功能:接收8位二进制
*输入:无
*输出:dat
**********************************************/
uchar DHT11_rec_byte()
{
uchar i,dat=0;
for(i=0;i<8;i++)
{
while(!Data); //每一bit数据都以50us低电平时隙开始,等待拉高
DelayUs(20); //0-高电平持续26~28us;1-高电平持续116~118us,
//此处延时时间过长会死循环,过短读出的数据不正确
//(仿真中偏大255,根据仿真情况调整时长;实物中会出现不随环境变化或部分变化的情况)
dat <<= 1; //位读取先高后低
if(Data == 1)
dat += 1;
while(Data);
}
return dat;
}
/**********************************************
*函数名:DHT11_receive
*函数功能:接收40位的数据
*输入:无
*输出:结构体dht11_t,含温度湿度整数和小数部分
**********************************************/
dht11_t DHT11_receive(void)
{
uchar R_H,R_L,T_H,T_L,revise;
dht11_t dht11;
DHT11_start();
if(Data == 0)
{
while(Data == 0); //等待DHT11拉高
DelayUs(38); //等待80us DHT11发送数据
R_H=DHT11_rec_byte(); //接收湿度高八位
R_L=DHT11_rec_byte(); //接收湿度低八位
T_H=DHT11_rec_byte(); //接收温度高八位
T_L=DHT11_rec_byte(); //接收温度低八位
revise=DHT11_rec_byte(); //接收校正位
if(revise == (R_H+R_L+T_H+T_L))
{
//温度整数部分
dht11.temp_i = T_H;
//温度小数部分
dht11.temp_d = T_L;
//湿度整数部分
dht11.humi_i = R_H;
//湿度小数部分
dht11.humi_d = R_L;
}
DelayUs(23); //拉低总线50us,随后总线由上拉电阻进入空闲状态
}
return dht11;
}
///////////////////////////////////////////////////
dh11.h
#ifndef __DHT11_H__
#define __DHT11_H__
#include "delay.h"
#include <reg51.h>
//注意:
//DHT11一次通讯时间最大3ms,主机连续采样间隔建议不小于100ms,最好2秒以上。
sbit Data = P3^2;
#define uchar unsigned char
#define uint unsigned int
typedef struct {
uchar temp_i;
uchar temp_d;
uchar humi_i;
uchar humi_d;
}dht11_t;
void DHT11_start();
uchar DHT11_rec_byte();
dht11_t DHT11_receive(void) ;
#endif
1602.c
#include "1602.h"
#include "delay.h"
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/*******************************************
函数名称:LcdReset
功 能:对1602液晶模块进行复位操作
参 数:无
返回值 :无
使用方法:初始化1
********************************************/
void LcdReset(void)
{
DelayMs(50);
LcdWriteCommand(0x38, 1); //显示模式设置
LcdWriteCommand(0x08, 1); //显示关闭
LcdWriteCommand(0x01, 1); //显示清屏,光标加左上角
LcdWriteCommand(0x06, 1); //写字符时整体不移动,地址指针及光标+1
LcdWriteCommand(0x0c, 1); //显示开,不开游标,不闪烁
}
/*********************************************
功 能:清屏
参 数:无
返回值 :无
使用方法:初始化2或必要时使用
*********************************************/
void LcdClear(void)
{
LcdWriteCommand(0x01,1);
DelayMs(5);
}
/*******************************************
函数名称:Disp1Char
功 能:在某个位置显示一个字符
参 数:x--列坐标
y--行坐标
data--显示的字符
返回值 :无
********************************************/
void Disp1Char(uchar x,uchar y,uchar Data)
{
PosXY( x, y );
LcdWriteData( Data );
}
/************************************************************************
函数名称:DispStr
功 能:从某个位置起连续显示一个字符串,一行结束,不再显示
参 数:x--列坐标
y--行坐标
Str--待显示的字符串指针/数组
返回值 :无
*************************************************************************/
void DispStr(uchar x,uchar y,uchar *Str)
{
uchar *temp;
uchar i,n = 0;
temp = Str;
while(*Str++ != '\0') n++;//计算字符的个数n
for (i=0;i<n;i++)
{
Disp1Char(x++,y,temp);//在同一行逐个显示
if (x == 0x10)//一行结束,不再显示
{
break;
}
}
}
/**************************************************************************
函数名称:DispNchar
功 能:从某个位置起连续显示N个字符,一行结束,继续换行或从头显示
参 数:x--列坐标
y--行坐标
n--字符个数
str--指向字符存放位置的指针
返回值 :无
**************************************************************************/
void DispNChar(uchar x,uchar y, uchar n,uchar *str)
{
uchar i;
for (i=0;i<n;i++)
{
Disp1Char(x++,y,str);//在同一行逐个显示
if (x == 0x10)//一行结束,继续换行或从头显示
{
x = 0;
y ^= 1;
}
}
}
/*******************************************
函数名称:PosXY
功 能:输入显示字符坐标信息
参 数:x--列坐标
y--行坐标
返回值 :无
********************************************/
void PosXY(uchar x,uchar y)
{
uchar temp;
temp = x&0x0f;
y &= 0x01;
if(y) temp |= 0x40; //如果在第2行
temp |= 0x80;
LcdWriteCommand(temp,1);
}
/*******************************************
函数名称:LcdWriteCommand
功 能:写入命令
参 数:cmd--命令,
chk--是否判忙的标志,1:判忙,0:不判
返回值 :无
********************************************/
void LcdWriteCommand(uchar cmd, uchar chk)
{
if (chk) WaitForEnable(); // 检测忙信号,仿真时可屏蔽
RS = 0;
RW = 0;
_nop_();
DataPort = cmd; //将命令字写入数据端口
_nop_();
EN = 1; //产生使能脉冲信号
_nop_();
_nop_();
EN = 0;
}
/*******************************************
函数名称:LcdWriteData
功 能:向当前地址写入显示数据
参 数:data--显示字符数据
返回值 :无
********************************************/
void LcdWriteData( uchar Data )
{
WaitForEnable(); //等待液晶不忙
RS = 1;
RW = 0;
EN = 1;
_nop_();
DataPort = Data; //将显示数据写入数据端口
_nop_();//产生使能脉冲信号
_nop_();
_nop_();
EN = 0;
}
/*******************************************
函数名称:WaitForEnable
功 能:等待1602液晶完成内部操作或超时跳出
参 数:无
返回值 :无
********************************************/
void WaitForEnable(void)
{
unsigned int later=0;
DataPort=0xff;
RS = 0;
RW = 1;
_nop_();
EN = 1;
_nop_();
_nop_();
while(((DataPort&0x80)!=0)&&(later<1000)) //检测忙标志
{
DelayUs(2);
later++;
}
EN = 0;
}
1602.h
#ifndef __LCD1602_H__
#define __LCD1602_H__
/************************************************************************/
#include<reg51.h>
#include<intrins.h>
sbit RS = P2^6; //定义端口
sbit RW = P2^5;
sbit EN = P2^7;
#define DataPort P0
/*******************************************
函数名称:LcdReset
功 能:对1602液晶模块进行复位操作
参 数:无
返回值 :无
使用方法:初始化1
********************************************/
void LcdReset(void);
/*********************************************
功 能:清屏
参 数:无
返回值 :无
使用方法:初始化2或必要时使用
*********************************************/
void LcdClear(void);
/*******************************************
函数名称:Disp1Char
功 能:在某个位置显示一个字符
参 数:x--列坐标0-15
y--行坐标0-1
data--显示的字符
返回值 :无
********************************************/
void Disp1Char(unsigned char x,unsigned char y,unsigned char Data);
/*****************************************************************
函数名称:DispStr
功 能:从某个位置起连续显示一个字符串,一行结束,不再显示
参 数:x--列坐标
y--行坐标
Str--待显示的字符串指针/数组
返回值 :无
*****************************************************************/
void DispStr(unsigned char x,unsigned char y,unsigned char *str);
/****************************************************************
函数名称:DispNchar
功 能:从某个位置起连续显示N个字符,一行结束,继续换行或从头显示
参 数:x--列坐标
y--行坐标
n--字符个数
str--指向字符存放位置的指针
返回值 :无
**************************************************************************/
void DispNChar(unsigned char x,unsigned char y, unsigned char n,unsigned char *str);
//以下为函数内部调用
/*********************************************
函数名称:PosXY
功 能:输入显示字符坐标信息
参 数:x--列坐标
y--行坐标
返回值 :无
**********************************************/
void PosXY(unsigned char x,unsigned char y);
/*******************************************
函数名称:LcdWriteCommand
功 能:写入命令
参 数:cmd--命令,
chk--是否判忙的标志,1:判忙,0:不判
返回值 :无
********************************************/
void LcdWriteCommand(unsigned char cmd,unsigned char chk);
/*******************************************
函数名称:LcdWriteData
功 能:向当前地址写入显示数据
参 数:data--显示字符数据
返回值 :无
********************************************/
void LcdWriteData( unsigned char Data);
/*******************************************
函数名称:WaitForEnable
功 能:等待1602液晶完成内部操作或超时跳出
参 数:无
返回值 :无
********************************************/
void WaitForEnable(void);
#endif
delay.h
#ifndef __DELAY_H__
#define __DELAY_H__
void DelayUs(unsigned char t);
void DelayMs(unsigned int t);
#endif
delay.c
#include "delay.h"
/*------------------------------------------------
us延时函数
输入参数: unsigned char t
无返回值
晶振12M
实际延时时间= t*2 + 5 us
------------------------------------------------*/
void DelayUs(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
ms延时函数
含有输入参数 unsigned int t
无返回值
晶振12M
------------------------------------------------*/
void DelayMs(unsigned int z)
{
unsigned int i,j;
for(i=z;i>0;i--)
for(j=123;j>0;j--);
}
wenshidu.rar
(4.12 KB, 下载次数: 0)
|