系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
单片机与外设之间的数据通讯常用的主要有:I2C、SPI、SCI总线。
I2C:同步串行二线制(1时钟线1数据线)
SPI:同步串行三线制(1时钟线1输入线1输出线)
SCI:异步通讯(1输入线1输出线)
单总线:1根线,既有时钟,又有双向数据
提示:本章主要为了了解时序图及单总线操作原理
一、场景
示例:基于DSB18B20进行单总线通讯的底层配置,主要是看懂时序图,其它单总线器件原理相同。结合代码与时序图,相对容易理解点。
二、编程实现
1.初始化(复位)
检测是否存在单总线器件(若有则会返回一个低脉冲,无则一直是高电平)。
时序图如下:
代码如下(示例):
bit SingleWireRst()
{
bit ACK;
EA = 0;
DS18B20 = 0;
Delay600us();
DS18B20 = 1;
Delay60us();
ACK = DS18B20;
while(!DS18B20);
Delay240us();
EA = 1;
return ACK;
}
2.写入数据
时序图如下:
写0/1有共同点:拉低一段时间,等待18B20采样ok,再拉高总线
写0时,18B20采样15us~60us。
写1时,拉低总线后,大于1us到无穷大再拉高总线都可以,且18B20采样15 ~60us。
因此,可以都设计为60us,合在一起判断
提示:加深的采样块,代表DS18B20自身拉低/拉高电压
代码如下(示例):
unsigned char WriteSingleWire(unsigned char vdat)
{
UC tmp;
EA = 0;
for(tmp = 0x01; tmp != 0; tmp <<= 1)
{
DS18B20 = 0;
_nop_();
_nop_();
if(vdat & tmp)
{
DS18B20 = 1;
}
else
{
DS18B20 = 0;
}
Delay60us();
DS18B20 = 1;
}
EA = 1;
return 0;
}
3.读数据
提示:竖立加深的操作块,代表总线采样读取位操作要在总线被拉高之前。若位是0,会被DS18B20主动拉低,若是1,会被DS18B20主动拉高。
代码如下(示例):
unsigned char ReadSingleWire()
{
UC tmp;
UC dat;
EA = 0;
for(tmp = 0x01; tmp != 0; tmp <<= 1)
{
DS18B20 = 0;
_nop_();
_nop_();
DS18B20 = 1;
_nop_();
_nop_();
if(DS18B20)
{
dat |= tmp;
}
else
{
dat &= ~tmp;
}
Delay60us();
}
EA = 1;
return dat;
}
4.测试
若有BS18B20,数码管显示0,否则显示1
#if 0
UC ACK;
ACK = SingleWireRst();
SEG_DisBuf[0] = ACK;
SEG_DisBuf[1] = 23;
SEG_DisBuf[2] = 23;
SEG_DisBuf[3] = 23;
#endif
总结
1.微秒级操作,操作时序时关闭中断,完成后再打开,防止干扰
2.等待时间选最大,防止遗漏。上拉电阻体现在总线拉高
3.不同的单片机IC电路,软件延时需要注意调整
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)