前言
基于蓝桥杯单片机,以实战为主,详细解析代码,理解原理。
1.Onewire单总线
1.定义:主机和从机通过1根线进行通信,在一条总线上可挂接的从器件数量几乎不受限制。
2.特点:这是由达拉斯半导体公司推出的一项通信技术。它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的。
3.优点:单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等。
①Onewire单总线通信
1.初始化
初始化过程 = 复位脉冲 + 从机应答脉冲。
主机通过拉低单总线480 ~ 960 us产生复位脉冲,然后释放总线,进入接收模式。主机释放总线时,会产生低电平跳变为高电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产生应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。
初始化时序图如下所示:
2.写间隙
写间隙有两种,包括写0的时间隙和写1的时间隙。
当数据线拉低后,在15 ~ 60 us的时间窗口内对数据线进行采样。如果数据线为低电平,就是写0,如果数据线为高电平,就是写1。主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高。主机要产生一个写0时间隙,就必须把数据线拉低并保持60 us。
写时间隙时序图如下所示:
3.读时间隙
当主机把总线拉低是,并保持至少1 us后释放总线,必须在15 us内读取数据。
读时间隙时序图如下所示:
②代码解析
第一步:单总线复位
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80); // 延时大于480us
DQ = 1;
Delay_OneWire(10); // 14
initflag = DQ; // initflag等于1初始化失败
Delay_OneWire(5);
return initflag;
}
第二步:单总线的写操作
必须连续写八个字,即一个字节;有写0和写1两个操作
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
第三步:单总线的读操作
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
// unsigned char index = 0;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
Delay_us();
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
单总线延时函数
单总线延时函数
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
2.DS18B20芯片
DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。 DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。
①DS18B20用法
上电后默认为85C。
字节3和字节4分别为设置过温警告和过低警告
在EEPROM上的数据断电是不会丢失的
当只有一个设备的时候,直接跳过ROM寻址,ROM寻址用于多个设备公用,用于判断具体是哪一个芯片
让DS18B20开启温度转换模式,且转换结束后会响应1,所以需在代码后面加上while(!DQ)来等待DS18B20的转换
操作实例二(仅包含一个DS18B20):
②代码解析
1:读取温度(仅仅包含整数部分)
unsigned char temperature()
{
char temp;
uchar HI_temp, LOW_temp;
Init_DS18B20(); //DS18B20重置
Write_DS18B20(0xcc); //跳过ROM寻址
Write_DS18B20(0x44); //设置为温度读取模式 (跳过了对暂存寄存器的写取)
Delay_OneWire(200); //等待温度读取模式的转换
Init_DS18B20(); //DS18B20重置
Write_DS18B20(0xcc); //跳过ROM寻址
Write_DS18B20(0xbe); //读取暂存寄存器的内容(先低位,再高位)
LOW_temp = Read_DS18B20();
HI_temp = Read_DS18B20();
temp=high<<4;
temp|=(low>>4);
return temp;
}
2:读取温度(含小数部分)
float rd_temperature(void)
{
unsigned char MSH,MSL;
unsigned int temp;
float temperature;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
Delay_OneWire(200);
while(!DQ);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
MSL=Read_DS18B20();
MSH=Read_DS18B20();
temp=(MSH&0x0f);
temp<<=8;
temp|= MSL;
temperature=0.0625*temp;
return temperature*10; //返回值为真实温度*10;
}