我们查看底板的原理图可以找到DS18B20,这是单总线的接法,数据通过P1.4进行传输。
赛点数据包给了最底层的代码,所以我们只需要编写驱动就行了。
因为赛点资源包给的是51的通信程序,而比赛用的是15单片机,在相同晶振条件下15单片机的速度是51单片机的8-12倍,所以将oneire.c里面的延迟函数统统乘以10倍。
修改后的 onewire.c
#include "onewire.h"
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
while(t--);
}
//单总线写操作
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(50);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(50);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
以下是从数据手册截取的,只用于读取温度数据的指令。
MASTER MODE | DATA (LSB FIRST) | COMMENTS |
Tx | CCh | Master issues Skip ROM command. (主机发送跳过ROM指令) |
Tx | 44h | Master issues Convert T command. (主机发送 只转换一次温度而无其他数据指令) |
Tx |
BEh
|
Master issues Read Scratchpad command.
(主机发送 读取暂存器的内容指令)
|
因为获取的是整数部分的值 所以8位就可以存储 温度数据
读取整数部分的驱动代码:
uchar read_temp()
{
uchar low,high,temp;
init_ds18b20(); //初始化
Write_DS18B20(0xcc); //跳过rom
Write_DS18B20(0x44); //温度转换命令
Delay_OneWire(200); //延时,等待转换结束
init_ds18b20(); //初始化
Write_DS18B20(0xcc); //跳过rom
Write_DS18B20(0xbe); //读取温度暂存器
low =Read_DS18B20(); //因为是低位先出,所以先读去低位
high=Read_DS18B20(); //读取高位
temp = (high<<4)|(low>>4); //将高八位数据左移4位后再
// 或上低八位数据右移4位后的值就是我们温度的整数部分
return temp;
}
如果是要获取全16位的数据则需要将变量 类型修改成 long
将所有有效数字组合得到的值乘以0.0625就可以得到真实的温度值。为了方便取 各个位上的值,这里将其真实值扩大100倍,即显示时精度到小数点后两位,可以根据需求控制精度。
long read_tempf()
{
uchar low,high;
long temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low =Read_DS18B20();
high=Read_DS18B20();
temp=high&0x0f;
temp=temp<<8;
temp=temp|low;
temp=temp*6.25;
return temp ;
}
使用通过定时中断进行检测:
定时器初始化:
void Timer_Init() //1ms定时
{
AUXR |= 0x80;
TL0 = 0xCD;
TH0 = 0xD4;
TR0 = 1;
ET0 = 1;
EA = 1;
}
定时中断:
void timer0() interrupt 1
{
static uint temp_cnt=0;
temp_cnt++;
if(temp_cnt==100)
{
temp=read_temp();
temp_cnt=0;
}
}
数码管显示:
void display()
{
uchar dis[8],i;
dis[0]=0X8E;
dis[1]=0XFF ;
dis[2]=LedChar[temp_f/100000%10];
dis[3]=LedChar[temp_f/10000%10];
dis[4]=LedChar[temp_f/1000%10];
dis[5]=LedChar[temp_f/100%10];
dis[6]=LedChar[temp_f/10%10] ;
dis[7]=LedChar[temp_f%10] ;
for(i=1;i<8;i++)
{
if(dis[i]==LedChar[0])
{
dis[i]=0xff;
}
else break;
}
for(i=0;i<8;i++){
P2&=0x1f;
P0=1<<i;
P2|=0xc0;
P2&=0x1f;
P0=dis[i];
P2|=0xe0;
Delay100us(); //移植别漏了
P0=0xff;
}
P2&=0x1f;
}
//可以在STC-isp中生成 无需记忆
void Delay100us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}