求老师大侠帮忙看看一个关于和51单片机相连的sht11温湿度传感器/读取一个字节/函数c语言
/*读一个字节*/charread(){unsignedchari,val=0;temp_LL=0;temp_h=0;DATA=1;//释放数据总线for(i=0x80;...
/*读一个字节*/
char read()
{
unsigned char i,val=0;
temp_LL=0;
temp_h=0;
DATA=1; //释放数据总线
for(i=0x80;i>0;i/=2) //位移8位
{
SCK=1; //上升沿读入
if(DATA)
val=(val | i); //确定值
SCK=0;
}
DATA=0; //读应答信号,有应答为1,为应答为0 通过CPU下拉为应答
SCK=1; //第9个脉冲
_nop_(); _nop_(); _nop_(); //pulswith approx. 5 us
SCK=0;
DATA=1; //释放数据总线
temp_h=val;
val=0;
////低8位/////////////////////////////
DATA=1; //释放数据总线
for(i=0x80;i>0;i/=2) //位移8位
{ SCK=1; //上升沿读入
if(DATA)
val=(val | i); //确定值
SCK=0;
}
DATA=1;//0; //不需要应答 通过CPU下拉为应答
SCK=1; //第9个脉冲
_nop_(); _nop_(); _nop_(); //pulswith approx. 5 us
SCK=0;
DATA=1; //释放数据总线
temp_LL=val;
return 0;
}
如上所示是从sht11读取一个字节的代码,求大侠好好解释解释我只知道一些很浅的东西。如果能带入具体数据说明一下(比如从开始到后面算出val的具体值)就好理解了,麻烦了,解释好了绝对大大的给加分。 展开
char read()
{
unsigned char i,val=0;
temp_LL=0;
temp_h=0;
DATA=1; //释放数据总线
for(i=0x80;i>0;i/=2) //位移8位
{
SCK=1; //上升沿读入
if(DATA)
val=(val | i); //确定值
SCK=0;
}
DATA=0; //读应答信号,有应答为1,为应答为0 通过CPU下拉为应答
SCK=1; //第9个脉冲
_nop_(); _nop_(); _nop_(); //pulswith approx. 5 us
SCK=0;
DATA=1; //释放数据总线
temp_h=val;
val=0;
////低8位/////////////////////////////
DATA=1; //释放数据总线
for(i=0x80;i>0;i/=2) //位移8位
{ SCK=1; //上升沿读入
if(DATA)
val=(val | i); //确定值
SCK=0;
}
DATA=1;//0; //不需要应答 通过CPU下拉为应答
SCK=1; //第9个脉冲
_nop_(); _nop_(); _nop_(); //pulswith approx. 5 us
SCK=0;
DATA=1; //释放数据总线
temp_LL=val;
return 0;
}
如上所示是从sht11读取一个字节的代码,求大侠好好解释解释我只知道一些很浅的东西。如果能带入具体数据说明一下(比如从开始到后面算出val的具体值)就好理解了,麻烦了,解释好了绝对大大的给加分。 展开
展开全部
嗯,默认你已经对硬件及时序比较熟悉了,直接解释一下数据读取过程了
先看一下初值部分
unsigned char i,val=0;
....
for(i=0x80;i>0;i/=2)
....
先注意到val的初值为0,
i的初值为0x80(对应的二进制为 1000 0000)
每次循环之后有个'i/=2' 即i的值减半
1000 0000 0x80
0100 0000 0x40
0010 0000 0x20
....
再来看循环部分
{
SCK=1; //上升沿读入
if(DATA)
val=(val | i); //确定值
SCK=0;
}
对于该串行端口,控制器输出时钟SCK下降沿之后sht11更新数据总线DATA,所以高电平的时候读取数据是可靠的(具体你可以分析琢磨一下,一般的串行口是上升沿锁存输入指令,下降沿更新输出数据)
下面假设串行口将要输出的数据位0x58即依次输出 0101 1000,高位数据首先输出
第一次循环(此时val=0,i=0x80)
SCK=1;
上升沿之后判断数据总线的电平(这之前SCK应该一直是低电平的,具体看一下你的初始化部分)
对于0x58 二进制的最高位为0,此时DATA总线为0, “ if(DATA)”不满足
val保持不变
然后SCK=0,产生下降沿,sht11更新DATA数据(执行之后DATA输出次高位‘1’)
第二次循环(此时val=0,i=0x40)
SCK=1;
上升沿之后判断数据总线的电平
对于0x58 二进制的第二位为1,此时DATA总线为1, “ if(DATA)”满足,
val=(val | i);
执行后val=0x40,即将次高位数据更新
然后SCK=0,产生下降沿,更新DATA数据(执行之后DATA输出第3位数据)
第三次循环(此时val=0(0x40,i=0x20)
SCK=1;
上升沿之后判断数据总线的电平
对于0x58 二进制的第三位为0,此时DATA总线为0, “ if(DATA)”不满足,
val保持不变
然后SCK=0,产生下降沿,更新DATA数据(执行之后DATA输出第4位数据)
....
第8次循环(此时val=0(0x58,i=0x01)
SCK=1;
上升沿之后判断数据总线的电平
对于0x58 二进制的第8位为0,此时DATA总线为0, “ if(DATA)”不满足,
val保持不变
然后SCK=0,产生下降沿,更新DATA数据
这样就把完成的8个字节读出来了
然后
temp_h=val;
val=0;
把高8位的数据暂存一下,并把val清零,准备读取低8位数据
接下来的就和上面的读取过程很相像了,不再过多解释...
先看一下初值部分
unsigned char i,val=0;
....
for(i=0x80;i>0;i/=2)
....
先注意到val的初值为0,
i的初值为0x80(对应的二进制为 1000 0000)
每次循环之后有个'i/=2' 即i的值减半
1000 0000 0x80
0100 0000 0x40
0010 0000 0x20
....
再来看循环部分
{
SCK=1; //上升沿读入
if(DATA)
val=(val | i); //确定值
SCK=0;
}
对于该串行端口,控制器输出时钟SCK下降沿之后sht11更新数据总线DATA,所以高电平的时候读取数据是可靠的(具体你可以分析琢磨一下,一般的串行口是上升沿锁存输入指令,下降沿更新输出数据)
下面假设串行口将要输出的数据位0x58即依次输出 0101 1000,高位数据首先输出
第一次循环(此时val=0,i=0x80)
SCK=1;
上升沿之后判断数据总线的电平(这之前SCK应该一直是低电平的,具体看一下你的初始化部分)
对于0x58 二进制的最高位为0,此时DATA总线为0, “ if(DATA)”不满足
val保持不变
然后SCK=0,产生下降沿,sht11更新DATA数据(执行之后DATA输出次高位‘1’)
第二次循环(此时val=0,i=0x40)
SCK=1;
上升沿之后判断数据总线的电平
对于0x58 二进制的第二位为1,此时DATA总线为1, “ if(DATA)”满足,
val=(val | i);
执行后val=0x40,即将次高位数据更新
然后SCK=0,产生下降沿,更新DATA数据(执行之后DATA输出第3位数据)
第三次循环(此时val=0(0x40,i=0x20)
SCK=1;
上升沿之后判断数据总线的电平
对于0x58 二进制的第三位为0,此时DATA总线为0, “ if(DATA)”不满足,
val保持不变
然后SCK=0,产生下降沿,更新DATA数据(执行之后DATA输出第4位数据)
....
第8次循环(此时val=0(0x58,i=0x01)
SCK=1;
上升沿之后判断数据总线的电平
对于0x58 二进制的第8位为0,此时DATA总线为0, “ if(DATA)”不满足,
val保持不变
然后SCK=0,产生下降沿,更新DATA数据
这样就把完成的8个字节读出来了
然后
temp_h=val;
val=0;
把高8位的数据暂存一下,并把val清零,准备读取低8位数据
接下来的就和上面的读取过程很相像了,不再过多解释...
追问
非常非常感谢,我再问一下不是从sht11读取一个字节的数据吗?怎么有高八位第八位,这不是两个字节了吗?还有,你这举的例子中每次更新得到的val值是多少?我只有结合具体值才能看明白,因为基础参差不齐。麻烦你了,一会儿马上给分
追答
SH11的分辨率可达14bit,但是一个字节只有8位,所以需要读两次才能获得一个完整的数据
两个字节是16bit ,所以有2bit是富余的,多了可以,少了是没法正确表征测得数据的
再说更新之后得到的val
val 初值为0,假设串行口将要输出的数据位0x58即依次输出 0101 1000,
i=0x80,第1次 更新最高位 0000 0000
i=0x40,第2次 更新次高位 0100 0000
i=0x20,第3次 更新第3 位 0100 0000
i=0x10,第4次 更新第4 位 0101 0000
i=0x08,第5次 更新第5 位 0101 1000
i=0x04,第6次 更新第6 位 0101 1000
i=0x02,第7次 更新第7 位 0101 1000
i=0x01,第8次 更新第8 位 0101 1000
最终,i=0,退出循环
val=0x58(即 0101 1000)
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询