#include
#include
#include
#include
#define LCD_DB
sbit
sbit
sbit
P0
LCD_RS=P2^0;
LCD_RW=P2^1;
LCD_E=P2^2;
/******定义函数****************/
#define uchar unsigned char
#define uint unsigned int
void LCD_init(void);
void LCD_write_command(uchar command);
void LCD_write_data(uchar dat);
void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-15),y(1-2)
void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602 显示字符串函数
void delay_n10us(uint n);
//初始化函数
//延时函数
//写指令函数
//写数据函数
/*--------------------------------------
;模块名称:LCD_init();
;功
;占用资源:--
;参数说明:--
能:初始化 LCD1602
;-------------------------------------*/
void LCD_init(void)
{
delay_n10us(10);
LCD_write_command(0x38);//设置 8 位格式,2 行,5x7
delay_n10us(10);
LCD_write_command(0x0c);//开显示,关光标,不闪烁
delay_n10us(10);
LCD_write_command(0x06);//设定输入方式,增量不移位
delay_n10us(10);
LCD_write_command(0x01);//清除屏幕显示
delay_n10us(100);
}
//延时清屏,延时函数,延时约 n 个 10us
能:LCD1602 写指令函数
/*--------------------------------------
;模块名称:LCD_write_command();
;功
;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).
;参数说明:dat 为写命令参数
;-------------------------------------*/
void LCD_write_command(uchar dat)
{
delay_n10us(10);
LCD_RS=0;
LCD_RW=0;
LCD_E=1;
LCD_DB=dat;
delay_n10us(10);
LCD_E=0;
delay_n10us(10);
}
//指令
//写入
//允许
//实践证明,我的 LCD1602 上,用 for 循环 1 次就能完成普通写指令。
//实践证明,我的 LCD1602 上,用 for 循环 1 次就能完成普通写指令。
能:LCD1602 写数据函数
/*--------------------------------------
;模块名称:LCD_write_data();
;功
;占用资源: P2.0--RS(LCD_RS),P2.1--RW(LCD_RW),P2.2--E(LCD_E).
;参数说明:dat 为写数据参数
;-------------------------------------*/
void LCD_write_data(uchar dat)
{
delay_n10us(10);
LCD_RS=1;
LCD_RW=0;
LCD_E=1;
//数据
//写入
//允许
LCD_DB=dat;
delay_n10us(10);
LCD_E=0;
delay_n10us(10);
}
能:LCD1602 显示一个字符函数,在某个屏幕位置上显示一个字符,X(0-15),y(1-2)。
/*--------------------------------------
;模块名称:LCD_disp_char();
;功
;占用资源:--
;参数说明:X 为 1602 的列值(取值范围是 0-15),y 为 1602 的行值(取值范围是 1-2),dat 为所要显示字符对应的地
址参数。
;-------------------------------------*/
void LCD_disp_char(uchar x,uchar y,uchar dat)
{
uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
LCD_write_data(dat);
}
能:LCD1602 显示字符串函数,在某个屏幕起始位置{X(0-15),y(1-2)}上显示一个字符串。
/*--------------------------------------
;模块名称:LCD_disp_str();
;功
;占用资源:--
;参数说明:X 为 1602 的列值(取值范围是 0-15),y 为 1602 的行值(取值范围是 1-2),str 为所要显示字符串对应的
指针参数。
;-------------------------------------*/
void LCD_disp_str(uchar x,uchar y,uchar *str)
{
uchar address;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
while(*str!='\0')
{
LCD_write_data(*str);
str++;
}
}
能:延时函数,延时约 n 个 10us
/*--------------------------------------
;模块名称:delay_n10us();
;功
;占用资源:--
;参数说明:--
;-------------------------------------*/
void delay_n10us(uint n)
{
//延时 n 个 10us@12M 晶振
uint i;
for(i=n;i>0;i--)
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
sbit SCK = P2^6;
sbit DATA = P2^7;
//定义通讯时钟端口
//定义通讯数据端口
typedef union
{ unsigned int i;
float f;
} value;
//定义了两个共用体
enum {TEMP,HUMI};
//TEMP=0,HUMI=1
#define noACK 0
#define ACK
1
#define STATUS_REG_W 0x06
#define STATUS_REG_R 0x07
#define MEASURE_TEMP 0x03
#define MEASURE_HUMI 0x05
#define RESET
0x1e
//用于判断是否结束通讯
//结束数据传输
//adr
command
//000
//000
//000
//000
0011
0011
0001
0010
r/w
0
1
1
1
//000
1111
0
/****************定义函数****************/
//启动传输函数
void s_transstart(void);
//连接复位函数
void s_connectionreset(void);
char s_write_byte(unsigned char value);//DHT90 写函数
char s_read_byte(unsigned char ack);
//DHT90 读函数
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);//测量温湿度函数
void calc_dht90(float *p_humidity ,float *p_temperature);//温湿度补偿
/*--------------------------------------
;模块名称:s_transstart();
;功
能:启动传输函数
;占用资源:--
;参数说明:--
;-------------------------------------*/
void s_transstart(void)
// generates a transmission start
{
DATA=1; SCK=0;
_nop_();
SCK=1;
_nop_();
DATA=0;
_nop_();
SCK=0;
_nop_();_nop_();_nop_();
SCK=1;
_nop_();
DATA=1;
_nop_();
SCK=0;
}
//Initial state
能:连接复位函数
/*--------------------------------------
;模块名称:s_connectionreset();
;功
;占用资源:--
;参数说明:--
;-------------------------------------*/
void s_connectionreset(void)
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
{
unsigned char i;
DATA=1; SCK=0;
for(i=0;i<9;i++)
{
SCK=1;
SCK=0;
}
s_transstart();
}
/*--------------------------------------
//Initial state
//9 SCK cycles
//transmission start
;模块名称:s_write_byte();
;功
能:DHT90 写函数
;占用资源:--
;参数说明:--
;-------------------------------------*/
char s_write_byte(unsigned char value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge
{
unsigned char i,error=0;
for (i=0x80;i>0;i/=2)
{
if (i & value) DATA=1;
else DATA=0;
SCK=1;
_nop_();_nop_();_nop_();
SCK=0;
}
DATA=1;
SCK=1;
error=DATA;
沿将被 DHT90 自动下拉为低电平。
_nop_();_nop_();_nop_();
SCK=0;
DATA=1;
return error;
}
//shift bit for masking
//masking value with i , write to SENSI-BUS
//clk for SENSI-BUS
//pulswith approx. 3 us
//release DATA-line
//clk #9 for ack
//check ack (DATA will be pulled down by DHT90),DATA 在第 9 个上升
//release DATA-line
//error=1 in case of no acknowledge //返回:0 成功,1 失败
/*--------------------------------------
;模块名称:s_read_byte();
;功
能:DHT90 读函数
;占用资源:--
;参数说明:--
;-------------------------------------*/
char s_read_byte(unsigned char ack)
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
{
unsigned char i,val=0;
DATA=1;
for (i=0x80;i>0;i/=2)
{ SCK=1;
//release DATA-line
//shift bit for masking
//clk for SENSI-BUS
if (DATA) val=(val | i);
_nop_();_nop_();_nop_();
//read bit
//pulswith approx. 3 us
SCK=0;
}
if(ack==1)DATA=0;
else DATA=1;
_nop_();_nop_();_nop_();
SCK=1;
_nop_();_nop_();_nop_();
SCK=0;
_nop_();_nop_();_nop_();
DATA=1;
return val;
}
//in case of "ack==1" pull down DATA-Line
//如果是校验(ack==0),读取完后结束通讯
//pulswith approx. 3 us
//clk #9 for ack
//pulswith approx. 3 us
//pulswith approx. 3 us
//release DATA-line
能:测量温湿度函数
/*--------------------------------------
;模块名称:s_measure();
;功
;占用资源:--
;参数说明:--
;-------------------------------------*/
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
// makes a measurement (humidity/temperature) with checksum
{
unsigned error=0;
unsigned int i;
s_transstart();
switch(mode){
//transmission start
//send command to sensor
case TEMP : error+=s_write_byte(MEASURE_TEMP); break;
: error+=s_write_byte(MEASURE_HUMI); break;
case HUMI
default
: break;
}
for (i=0;i<65535;i++) if(DATA==0) break; //wait until sensor has finished the measurement
if(DATA) error+=1;
*(p_value) =s_read_byte(ACK);
*(p_value+1)=s_read_byte(ACK);
*p_checksum =s_read_byte(noACK);
return error;
// or timeout (~2 sec.) is reached
//read the first byte (MSB)
//read the second byte (LSB)
//read checksum
}
能:温湿度补偿函数
/*--------------------------------------
;模块名称:calc_dht90();
;功
;占用资源:--
;参数说明:--
;-------------------------------------*/
void calc_dht90(float *p_humidity ,float *p_temperature)
// calculates temperature [C] and humidity [%RH]
// input : humi [Ticks] (12 bit)
//
// output:
//
temp [C]
{ const float C1=-4.0;
temp [Ticks] (14 bit)
humi [%RH]
// for 12 Bit
// for 12 Bit
// for 12 Bit
// for 14 Bit @ 5V
// for 14 Bit @ 5V
const float C2=+0.0405;
const float C3=-0.0000028;
const float T1=+0.01;
const float T2=+0.00008;
float rh=*p_humidity;
float t=*p_temperature;
float rh_lin;
float rh_true;
float t_C;
Humidity [Ticks] 12 Bit
Temperature [Ticks] 14 Bit
// rh:
// t:
// rh_lin: Humidity linear
// rh_true: Temperature compensated humidity
// t_C
: Temperature [C]
t_C=t*0.01 - 40;
rh_lin=C3*rh*rh + C2*rh + C1;
rh_true=(t_C-25)*(T1+T2*rh)+rh_lin;
if(rh_true>100)rh_true=100;
if(rh_true<0.1)rh_true=0.1;
//calc. temperature from ticks to [C]
//calc. humidity from ticks to [%RH]
//calc. temperature compensated humidity [%RH]
//cut if the value is outside of
//the physical possible range
*p_temperature=t_C;
*p_humidity=rh_true;
}
//return temperature [C]
//return humidity[%RH]
//*********主函数*****************
void main(void)
{
value humi_val,temp_val;
unsigned char error,checksum;
unsigned int wendu,shidu;
LCD_init();
s_connectionreset();
LCD_disp_str(0,1,"TE");
LCD_disp_str(0,2,"RH");
//*********初始化温度显示区*********
LCD_disp_str(2,1,"TTT.TC");
//*********初始化湿度显示区*********