本文通过keil与Proteus联合软件模拟驱动SHT21。
现象:实现单片机将SHT21的数值获得后保存在EEPROM中,在读取EEPROM将数据显示在LCD1602上。
本文简单的从SHT21的开始、结束、读取、应答代码展开。
首先上数据手册
开始和结束的时序
命令字
数据读取
代码部分
void start() //SHT21启动
{
ROM_SDA=1;
delay(1);
ROM_SCL=1;
delay(1);
ROM_SDA=0;
delay(1);
}
void stop() //SHT21关闭
{
ROM_SDA=0;
delay(1);
ROM_SCL=1;
delay(1);
ROM_SDA=1;
delay(1);
}
SHT21的启动与停止与IIC协议的启动与停止相同。
void respons() //IIC响应
{
ROM_SCL=1;
delay(1);
ROM_SCL=0;
delay(1);
}
void write_byte(uchar date) //写数据
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
ROM_SCL=0;
delay(1);
ROM_SDA=CY;
delay(1);
ROM_SCL=1;
delay(1);
}
ROM_SCL=0;
delay(1);
ROM_SDA=1;
delay(1);
}
uchar read_byte() //读数据
{
uchar i,k;
ROM_SCL=0;
delay(1);
ROM_SDA=1;
delay(1);
for(i=0;i<8;i++)
{
ROM_SCL=1;
delay(1);
k=(k<<1)|ROM_SDA;
ROM_SCL=0;
delay(1);
}
return k;
}
SHT21读取函数
uchar read_SHT21(uchar dowhat)//SHT21读取函数
{
long int temp_return;
uchar low,high;
start();
write_byte(0x80);
respons();
if(dowhat == 0xf3)//读取湿度
{
write_byte(0xf3);
delay_ms(60);//手册当中的规定的处理时间
}
if(dowhat == 0xf5)//读取温度
{
write_byte(0xf5);
delay_ms(29);
}
respons();
start();
write_byte(0x81);
respons();
delay(1);
high = read_byte(); //读高8位
low = read_byte(); //读低8位
respons();
stop();
low &= 0xfc;
if(dowhat == 0xf3)//温度换算
temp_return = (high<<8|low)*175.72/65536-46.85;
if(dowhat == 0xf5)
temp_return = (high<<8|low)*125.0/65536.0-6;
return temp_return;
}
主函数
void main()
{
uint Temp_value=0;
uchar shi,ge;
uchar i = 0;
LCD_E = 0;
WriteVD(0,0x38);
WriteVD(0,0x0F);
WriteVD(0,0x06);
WriteVD(0,0x80);
while(1)
{
for(i = 0;i<200;i++)
{
ROM_SDA=1;
ROM_SCL=1;
Temp_value = (uchar)read_SHT21(0xf5);
write_add(20,Temp_value);//写EEPROM
delay(100);
Temp=read_add(20);
shi = Temp/10;
ge = Temp%10;
WriteVD(0,0x80);
WriteVD(1,shi+48);//在LCD1602上显示
WriteVD(1,ge+48);
}
};
}
EEPROM读写
void write_add(uchar address,uchar date)//写EEPROM
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
uchar read_add(uchar address) //读EEPROM
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
respons();
stop();
return date;
}
LCD1602驱动
void WriteVD(unsigned char a,unsigned char b) //写LCD1602
{
LCD_RS = a;
P2 = b;
delay(1);
LCD_E = 1;
delay(1);
LCD_E = 0;
delay(1);
}
注意此处由于LCD1602只写,故LCD1602引脚RW直接接地。
延时函数
void delay(unsigned int z) //
{
while(z--);
}
void delay_ms(unsigned int z) //ms延时
{
uint x,y;
for (x=z;x>0;x--)
{
for(y=115;y>0;y--);
}
}