#include //12M
#include
typedef unsigned char uint8;
typedef signed char fuint8;
typedef unsigned int uint16;
typedef signed int fuint16;
#define uchar unsigned char
#define uintunsigned int
#define ulong unsigned long
#define TC0xF3 //温度测量
#define SH0xF5 //湿度测量
#define WR 0xE6 //写寄存器
#define RD0xE7 //读寄存器
#define RST 0xFe //软复位
/*================================================================
【Name】
【Function】SHT20的I2C地址
【Notes 】
【 Author 】dingshidong
【Data】.08.07
================================================================*/
#define SHT20ADDR 0x80
/*================================================================
【Name】
【Function】应答位电平定义
【Notes 】
【 Author 】dingshidong
【Data】.08.07
================================================================*/
#define ACK 0 //应答信号
#define NACK 1//非应答信号
#define led_duan P0 //数码管段选//
#define led_wei P2 //数码管位选//
fuint16 value;
fuint16 ys;
bit dian = 0;
bit ad_ok = 0;
sbit wei_1 = P2^0;
sbit wei_2 = P2^1;
sbit wei_3 = P2^2;
sbit wei_4 = P2^3;
sbit wei_5 = P2^4;
sbit wei_6 = P2^5;
sbit wei_7 = P2^6;
sbit led_dian = P0^5;
sbit SDA = P3^4;
sbit SCL =P3^3;
uint8 xsjs = 0;
uint16 pca_s=0;
uint16 wendu,shidu;
uint8 xszc[7]; //显示缓冲区
uint8 code duan_ma[] = {
0x28,/*0*/
0x7E,/*1*/
0xA2,/*2*/
0x62,/*3*/
0x74,/*4*/
0x61,/*5*/
0x21,/*6*/
0x7A,/*7*/
0x20,/*8*/
0x60,/*9*/
};
uint8 code wei_ma [] = {0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD};
/*================================================================
【Name】void Delay(uint t)
【Function】delay Nms
【Notes 】
【 Author 】dingshidong
【Data】.08.07
================================================================*/
void Delay(uint t)
{
uchar i;
while(t--)
{
for(i=0;i<200;i++);
}
}
/*------------------------------------------------------------*/
/**********************Simulation I2C Function*****************/
/*------------------------------------------------------------*/
/*================================================================
【Name】void I2CDelay (uchar t)
【Function】模拟IIC用的短延时 us
【Notes 】
【 Author 】dingshidong
【Data】.08.07
================================================================*/
void I2CDelay (uchar t)
{
while(t--);
}
/*================================================================
【Name】void I2CInit(void)
【Function】I2C初始化,空闲状态
【Notes 】
【 Author 】dingshidong
【Data】.08.07
================================================================*/
void I2CInit(void)
{
SDA = 1;
I2CDelay(1);
SCL = 1;
I2CDelay(1);
}
/*================================================================
【Name】void I2CStart(void)
【Function】I2C起始信号
【Notes 】SCL、SDA同为高,SDA跳变成低之后,SCL跳变成低
【 Author 】dingshidong
【Data】.08.07
================================================================*/
void I2CStart(void)
{
SDA = 1;//发送起始条件的数据信号--ZLG
SCL = 1;
I2CDelay(5);//起始条件建立时间大于4.7us,延时--ZLG
SDA = 0;//发送起始信号-ZLG
I2CDelay(5);//起始条件锁定时间大于4μs--ZLG
SCL = 0;//钳住I2C总线,准备发送或接收数据--ZLG
I2CDelay(5);
}
/*================================================================
【Name】void I2CStop(void)
【Function】I2C停止信号
【Notes 】SCL、SDA同为低,SCL跳变成高之后,SDA跳变成高
【 Author 】dingshidong
【Data】.08.07
================================================================*/
void I2CStop(void)
{
SDA = 0; //发送结束条件的数据信号--ZLG
SCL = 0;
I2CDelay(5);
SCL = 1; //发送结束条件的时钟信号--ZLG
I2CDelay(5);//结束条件建立时间大于4μs--ZLG
SDA = 1; //发送I2C总线结束信号--ZLG
I2CDelay(5);
}
/*================================================================
【Name】uchar I2C_Write_Byte(uchar WRByte)
【Function】I2C写一个字节数据,返回ACK或者NACK
【Notes 】从高到低,依次发送
【 Author 】dingshidong
【Data】.08.07
================================================================*/
uchar I2C_Write_Byte(uchar Write_Byte) //Sendbyte
{
uchar i;
for(i=0;i<8;i++) //要传送的数据长度为8位--ZLG
{
if(Write_Byte&0x80) //判断发送位--ZLG
{
SDA = 1;
}
else
{
SDA = 0;
}
I2CDelay(1);
SCL=1; //输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样
I2CDelay(5); //保证时钟高电平周期大于4μs--ZLG
SCL=0;
I2CDelay(1);
Write_Byte <<= 1;
}
I2CDelay(4);
SDA = 1; //8位发送完后释放数据线,准备接收应答位-ZLG
SCL = 1; //MCU告知SHT2X数据发送完毕,等待从机的应答信号
I2CDelay(5);
/*以下是判断I2C总线接收应到应答信号是ACK还是NACK*/
if(SDA==1) //SDA为高,收到NACK
return NACK;
else//SDA为低,收到ACK
return ACK;
SCL=0;
I2CDelay(15);
}
/*================================================================
【Name】uchar I2C_Read_Byte(uchar AckValue)
【Function】I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK
【Notes 】从高到低,依次接收
【 Author 】dingshidong
【Data】.08.07
================================================================*/
uchar I2C_Read_Byte(uchar AckValue)//receivebyte
{
uchar i,RDByte=0;
SCL=0;//置时钟线为低,准备接收数据位--ZLG
SDA = 1; //释放总线,置数据线为输入方式--ZLG
for (i=0;i<8;i++)
{
SCL = 1; //SCL高电平期间,采集SDA信号,并作为有效数据 //置时钟线为高使数据线上数据有效--ZLG
I2CDelay(2);
RDByte <<= 1;//移位
if(SDA==1) //采样获取数据
{
RDByte |= 0x01;
}
else
{
RDByte &= 0xfe;
}
I2CDelay(1);
SCL = 0; //下降沿,从机给出下一位值
I2CDelay(6);
}
/*以下是I2C总线发送应答信号ACK或者NACK*/
SDA = AckValue; //应答状态
I2CDelay(3);
SCL = 1;
I2CDelay(5);//时钟低电平周期大于4μs--ZLG
SCL = 0; //清时钟线,钳住I2C总线以便继续接收--ZLG
I2CDelay(15);
//SDA = 1;
return RDByte;
}
/*================================================================
【Name】void SoftReset(void)
【Function】SHT20软件复位,主函数中调用
【Notes 】从高到低,依次接收
【 Author 】dingshidong
【Data】.08.07
================================================================*/
void SoftReset(void)
{
I2CInit(); //I2C initialize
I2CStart(); //start I2C
I2C_Write_Byte(SHT20ADDR&0xfe);//I2C address + write
I2C_Write_Byte(0xfe); //soft reset
I2CStop(); //stop I2C
}
/*================================================================
【Name】void SET_Resolution(void)
【Function】写寄存器,设置分辨率
【Notes 】
【 Author 】dingshidong
【Data】.08.07
================================================================*/
void SET_Resolution(void)
{
I2CStart();//Start I2C
if(I2C_Write_Byte(SHT20ADDR&0xfe)==ACK) //I2C address + write + ACK
{
if(I2C_Write_Byte(0xe6)==ACK)//写用户寄存器
{
if(I2C_Write_Byte(0x83)==ACK);//设置分辨率 11bit RH% 测量时间:12ms(typ.) & 11bit T℃ 测量时间:9ms(typ.)
}
}
I2CStop(); //Stop I2C
}
/*================================================================
【Name】float ReadSht20(char whatdo)
【Function】非主机模式,读取函数函数
【Notes 】
【 Author 】dingshidong
【Data】.08.07
================================================================*/
float ReadSht20(char whatdo)
{
float temp;
uchar MSB,LSB;
float Humidity,Temperature;
SET_Resolution();
I2CStart();
// if(I2C_Write_Byte(SHT20ADDR&0xfe)==ACK)//I2C address + write + ACK 这个函数屏蔽掉才读出数据但是数据好像不对,读出的温度50多度环境温度只有20几度
{
if(I2C_Write_Byte(whatdo)==ACK) //Command
{
do
{
Delay(6);
I2CStart();
}while(I2C_Write_Byte(SHT20ADDR|0x01)==NACK); //I2C address + read + NACK
MSB = I2C_Read_Byte(ACK);//Data(MSB)
LSB = I2C_Read_Byte(ACK);//Data(LSB)
I2C_Read_Byte(NACK);//Checksum+ NACK
I2CStop();//Stop I2C
LSB &= 0xfc; //Data (LSB) 的后两位在进行物理计算前前须置‘0’
temp = MSB*256 + LSB;//十六进制转成十进制
if (whatdo==((char)0xf5)) //No Hold Master Mode,read humidity
{
/*-- calculate relative humidity [%RH] --*/
Humidity =(temp*125)/65536-6;//公式: RH%= -6 + 125 * SRH/2^16
return Humidity;//返回值:humidity
}
else //No Hold Master Mode,read temperature
{
/*-- calculate temperature [°C] --*/
Temperature = (temp*175.72)/65536-46.85; //公式:T= -46.85 + 175.72 * ST/2^16
return Temperature; //返回值:temperature
}
}
}
return 0;
}
//=========================================显示数据分解===========================================
void pv3_3_DATA(uint16 x)
{
uint8 a,b,c,d,e;
a = x/10000;
b = x%10000/1000;
c = x%1000/100;
d = x%100/10;
e = x%10;
xszc[2]=a;
xszc[3]=b;
xszc[4]=c;
xszc[5]=d;
xszc[6]=e;
}
//=====================================================================================
void main(void)
{
TMOD = 0x01;
TH0 = 0xF6;
TL0 = 0x3C;
TR0 = 1;
ET0 = 1;
EA = 1;
while(1)
{
if(ad_ok == 1)
{
// EA = 0;
shidu=(ReadSht20(TC)*100);//湿度
// EA = 1;
ad_ok = 0;
}
pv3_3_DATA(shidu);
}
}
//================================================================================================
void timer0(void) interrupt 1 using 2//
{
TH0 = 0xF6;
TL0 = 0x3C;
pca_s++;
if(pca_s == 200)
{
ad_ok = 1;
pca_s = 0;
}
led_wei = 0xFF;;
switch(xsjs)
{
case 0: led_duan = duan_ma[xszc[xsjs]];wei_1=0;break;
case 1: led_duan = duan_ma[xszc[xsjs]];wei_2=0;break;
case 2: led_duan = duan_ma[xszc[xsjs]];wei_3=0;break;
case 3: led_duan = duan_ma[xszc[xsjs]];wei_4=0;break;
case 4: led_duan = duan_ma[xszc[xsjs]];led_dian=dian;wei_5=0;break;
case 5: led_duan = duan_ma[xszc[xsjs]];wei_6=0;break;
case 6: led_duan = duan_ma[xszc[xsjs]];wei_7=0;
}
xsjs++;
if(xsjs == 7)xsjs = 0;
}