最近这两天一直在研究一个问题,就是将ds18b20这个温度芯片实时的传送到数码管上,这个与我之前写的有点差别。以前的方法笨是笨了一点,但好在可以直接显示,没有一点毛病让你挑剔,但这次的就有点不一样。废了好大的劲与同学才搞出来。不多说,先上源码。
#include<reg51.h>
#include<stdio.h>
#include<math.h>
//#include"onewire.c"
//#include"onewire.h"
#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe
//IC引脚定义
sbit DQ = P1^4;
//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
code unsigned char tab[] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xc6};//0~9 灭 横杠
unsigned char dspbuft[]={10,10,10,10,10,10,10,12};
//unsigned char dspcom=0;
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
char z;
while(t--)
for(z=0;z<6;z++);
}
//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;
}
int read()
{
unsigned char low,high;
int temp;
Init_DS18B20();
Write_DS18B20(OW_SKIP_ROM);
Write_DS18B20(DS18B20_CONVERT);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(OW_SKIP_ROM);
Write_DS18B20(DS18B20_READ);
low=Read_DS18B20();
high=Read_DS18B20();
temp=(high&0x0f)<<8|low;
temp=temp*0.0625*10+0.5;
return temp;
}
void Delay5ms() //@12.000MHz
{
unsigned char a,b;
for(a=19;a>0;a--)
for(b=130;b>0;b--);
}
void display(int date)
{
unsigned char dspcom;
dspbuft[4]=date/100;
dspbuft[5]=date%100/10;
dspbuft[6]=date%10;
for(dspcom=4;dspcom<8;dspcom++)
{
P0=0xff;
P2=(P2&0x1f)|0xe0;
if(dspcom==5)P0=(tab[dspbuft[dspcom]]&0x7f);
else P0=tab[dspbuft[dspcom]];
P2&=0x1f;
P0=0x00;
P2=(P2&0x1f)|0xc0;
P0=1<<dspcom;
P2&=0x1f;
Delay5ms();
if(dspcom==7)
{
P2=(P2&0x1f)|0xc0;
P0=0;
P2&=0x1f;
}
}
}
void NO_buzzrelay()
{
P2&=0x1f;
P2|=0xa0;
P0&=0xaf;
P2&=0x1f;
}
void main()
{
NO_buzzrelay();
while(1)
{
display(read());
}
}
这次的这个就是将温度先放进一个教全局变量的缓冲区,然后在通过自己写的显示函数,显示在数码管上。为了保险起见,我还是稍微加一个关闭蜂鸣器的函数。延时五毫秒是我自己通过软件生成的。这样显示出来比较稳定,我以前写的程序效果不是太暗就是会不停地闪动,这让我很苦恼,原来结果是函数在调用的过程中耗费的时间太长,所以就用一个for循环作为弥补,每次显示就是将后四位一次性的全部显示出来,避免在函数调用过程中耗时太长的问题。
附:由于暂时还没有学会调用函数,所以我就先将给的底层驱动直接粘贴上来,一个叫read()函数是ds18b20这个芯片的协议,是我自己写出来的。就先到这儿吧!