本文出现的程序在之前有讲:
蓝桥杯单片机(四)动态数码管
新更新了负数和小数显示:
蓝桥杯单片机(九)DS18B20温度测量(四位小数和负数显示)
如图
开发板上的DS18B20主要由P14控制的,采用的是软件模拟单总线通讯协议。可以通过蓝桥杯官方提供的DS18B20的数据手册。手册是英文的,可以通过翻译软件翻译一下,或者找翻译好了的中文手册,由于本人英语也不是很好hhhh,所以摘取文章部分内容来解读。
主要的步骤为:
(一)初始化
(二)发送ROM指令
(三)发送DS18B20指令
蓝桥杯官方在比赛的时候也会提供单总线的软件模拟程序,主要有:
初始化函数
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
单总线写和读的程序
//通过单总线向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;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
所以只需要按照数据手册初始化的方式进行读取就行,
按照步骤,首先要初始化,然后输入ROM指令,ROM指令在数据手册中也有
ROM COMMANDS
SEARCH ROM [F0h]
READ ROM [33h]
MATCH ROM [55h]
SKIP ROM [CCh]
ALARM SEARCH [ECh]
由于开发板上只有一个DS18B20,所以不用管ROM地址来匹配是不是对应的DS18B20,直接忽略ROM(CCH)就行,然后就是DS18B20功能指令
DS18B20 FUNCTION COMMANDS
CONVERT T [44h]
WRITE SCRATCHPAD [4Eh]
READ SCRATCHPAD [BEh]
COPY SCRATCHPAD [48h]
RECALL E2 [B8h]
READ POWER SUPPLY [B4h]
由于一次只能发送一个功能指令,所以我们要先进行温度转化(44H),然后第二次进行读程序(BEH)
所以读取温度程序如下
unsigned char rd_temperature(void)
{
uchar low,high;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
return((low>>4)|(high<<4));
}
由于数据是每8位存放在寄存器中,所以要分为两次读,先读低八位,再读高八位。
所以最后读取温度并显示到数码管程序为:
#include <stc15f2k60s2.h>
#include "intrins.h"
sbit DQ = P1^4;
#define uchar unsigned char
#define uint unsigned int
void SMG_output(void);
void init(void);
void Delay1ms(void);
bit init_ds18b20(void);
unsigned char rd_temperature(void);
void Delay_OneWire(unsigned int t);
unsigned char Read_DS18B20(void);
void Write_DS18B20(unsigned char dat);
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
uchar SMG[8]={10,10,10,10,10,10,10,10};//初始显示10,全息数码管
uchar temp=0;
void main(void)
{
init();
while(1)
{
temp=rd_temperature();
SMG[0]=temp/10;
SMG[1]=temp%10;
SMG_output();
}
}
void SMG_output(void)
{
uchar i;
for(i=0;i<8;i++)
{
P2=(P2&0X1F)|0Xc0;
P0=(1<<i);
P2=(P2&0X1F)|0Xe0;
P0=tab[SMG[i]];
Delay1ms();
}
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
void init(void)
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0Xff;
P2=(P2&0X1F)|0Xc0;
P0=0Xff;
P2=(P2&0X1F)|0Xe0;
P0=0Xff;
}
unsigned char rd_temperature(void)
{
uchar low,high;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
return((low>>4)|(high<<4));
}
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t=t*8;
while(t--);
}
//通过单总线向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;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
void Delay1ms(void) //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
效果如下:
值得注意的是使用蓝桥杯官方提供的单总线协议需要将延时函数更改一下:
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t=t*8;
while(t--);
}
因为官方是用STC89C52RC,是12T的单片机(一个机器周期只需要十二个时钟周期),本开发板是1T的单片机(一个机器周期只需要一个时钟周期)。
有不同的可以私信和评论。