前置知识:
- 单总线只有一根数据线,发挥控制总线+数据总线+地址总线的功能;
- One-Wire Bus的通信线缩写:DQ;
- 异步,半双工;
- 开漏输出:弱上拉、强下拉;
时序拼图:
先写入和先读出的是低位Bit;
One-Wire的代码解析:
初始化单总线,主机拉低500us后释放,等待50us,读取从机的响应,等待500us走完初始化流程;
unsigned char OneWire_Init(void)
{
unsigned char Ack;
unsigned char i;
OneWire_DQ=1;
OneWire_DQ=0; //主机拉低单总线;
i = 230; while (--i); //Delay500us;
OneWire_DQ=1; //主机释放;
i = 22; while (--i); //Delay50us;
Ack=OneWire_DQ; //从机拉低响应主机;
i = 230; while (--i); //Delay500us;
return Ack;
}
发送(写入)一位,主机拉低10us,是否继续拉低看形参Bit是0还是1;
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ=1;
OneWire_DQ=0; //主机拉低0、1共同的时间段;
i = 4; while (--i); //Delay10us;
OneWire_DQ=Bit;
i = 27; while (--i); //Delay60us;
OneWire_DQ=1; //主机释放单总线;
}
发送(写入)一个字节,从低到高位读取,读Bit后调用函数发送Bit;
void OneWire_SendByte(unsigned char Byte)
{
unsigned char i,Bit;
for(i=0;i<8;i++)
{
Bit=Byte&(0x01<<i);
OneWire_SendBit(Bit);
}
}
读取一位,主机拉低5us后释放,再等待5us后读取单总线上值,等待读取时序结束;
unsigned char OneWire_ReceiveBit(void)
{
unsigned char Bit;
unsigned char i;
OneWire_DQ=1;
OneWire_DQ=0; //主机拉低0、1共同的时间段;
Delay5us(); //Delay5us;
OneWire_DQ=1;
Delay5us(); //Delay5us;
Bit=OneWire_DQ;
i = 27; while (--i); //Delay60us;
return Bit;
}
读取一个字节,把读取到的Bit从低位到高位赋值给Byte,然后return Byte;
unsigned char OneWire_ReceiveByte(void)
{
unsigned char i,Bit,Byte=0;
for(i=0;i<8;i++)
{
Bit=OneWire_ReceiveBit();
if(Bit) {Byte|=(0x01<<i);}
}
return Byte;
}
DS18B20的代码解析:
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_SCRATCHPAD 0xBE
void DS18B20_ConventT(void)
{
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM); //跳过ROM
OneWire_SendByte(DS18B20_CONVERT_T); //转换温度
}
float DS18B20_ReadT(void)
{
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_SCRATCHPAD);
TLSB=OneWire_ReceiveByte(); //存储低位温度信息
TMSB=OneWire_ReceiveByte(); //存储高位温度信息
Temp=(TMSB<<8)|TLSB; //int为4字节,char1字节,高位信息左移8位和低位信息存储到一个单元Temp
T=Temp/16.0; //TLSB的低四位是小数部分信息,此操作处理成10进制浮点数
return T;
}