求AT89S52单片机与DS18B20传感器用Keil c语言设计程序

主要有初始化主程序和内部中断程序
我做的水温控制系统,但缺少C程序,主要就是初始主程序和内部中断程序,显示是用MX7219驱动LED,求求各位了,快急死我了!!!!拜托了!!!!

你好。看来志同道合,我也做过DS18B20温控设备,单总线传感这是一个不错的选择哦。下面是C语言程序,硬件接线如下:
(1)把“单片机系统”区域中的P0.0-P0.7用8芯排线连接到“动态数码显示”区域中的ABCDEFGH端子上。
(2)把“单片机系统”区域中的P2.0-P2.7用8芯排线连接到“动态数码显示”区域中的S1S2S3S4S5S6S7S8端子上。
(3)把DS18B20芯片插入“四路单总线”区域中的任一个插座中,注意电源与地信号不要接反。
(4)把“四路单总线”区域中的对应的DQ端子连接到“单片机系统”区域中的P3.7/RD端子上。

至于你的7219的话就要你自己硬件接线了。

#include <REG52.h>
#include <INTRINS.h>

unsigned char code displaybit[]={0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f};
unsigned char code displaycode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00,0x40};
unsigned char code dotcode[32]={0,3,6,9,12,16,19,22,
25,28,31,34,38,41,44,48,
50,53,56,59,63,66,69,72,
75,78,81,84,88,91,94,97};
unsigned char displaycount;
unsigned char displaybuf[8]={16,16,16,16,16,16,16,16};
unsigned char timecount;
unsigned char readdata[8];

sbit DQ=P3^7;
bit sflag;

bit resetpulse(void)
{
unsigned char i;

DQ=0;
for(i=255;i>0;i--);
DQ=1;
for(i=60;i>0;i--);
return(DQ);
for(i=200;i>0;i--);
}

void writecommandtods18b20(unsigned char command)
{
unsigned char i;
unsigned char j;

for(i=0;i<8;i++)
{
if((command & 0x01)==0)
{
DQ=0;
for(j=35;j>0;j--);
DQ=1;
}
else
{
DQ=0;
for(j=2;j>0;j--);
DQ=1;
for(j=33;j>0;j--);
}
command=_cror_(command,1);
}
}

unsigned char readdatafromds18b20(void)
{
unsigned char i;
unsigned char j;
unsigned char temp;

temp=0;
for(i=0;i<8;i++)
{
temp=_cror_(temp,1);
DQ=0;
_nop_();
_nop_();
DQ=1;
for(j=10;j>0;j--);
if(DQ==1)
{
temp=temp | 0x80;
}
else
{
temp=temp | 0x00;
}
for(j=200;j>0;j--);
}
return(temp);
}

void main(void)
{
TMOD=0x01;
TH0=(65536-4000)/256;
TL0=(65536-4000)%256;
ET0=1;
EA=1;

while(resetpulse());
writecommandtods18b20(0xcc);
writecommandtods18b20(0x44);
TR0=1;
while(1)
{
;
}
}

void t0(void) interrupt 1 using 0
{
unsigned char x;
unsigned int result;

TH0=(65536-4000)/256;
TL0=(65536-4000)%256;
if(displaycount==2)
{
P0=displaycode[displaybuf[displaycount]] | 0x80;
}
else
{
P0=displaycode[displaybuf[displaycount]];
}
P2=displaybit[displaycount];
displaycount++;
if(displaycount==8)
{
displaycount=0;
}

timecount++;
if(timecount==150)
{
timecount=0;
while(resetpulse());
writecommandtods18b20(0xcc);
writecommandtods18b20(0xbe);
readdata[0]=readdatafromds18b20();
readdata[1]=readdatafromds18b20();
for(x=0;x<8;x++)
{
displaybuf[x]=16;
}
sflag=0;
if((readdata[1] & 0xf8)!=0x00)
{
sflag=1;
readdata[1]=~readdata[1];
readdata[0]=~readdata[0];
result=readdata[0]+1;
readdata[0]=result;
if(result>255)
{
readdata[1]++;
}
}
readdata[1]=readdata[1]<<4;
readdata[1]=readdata[1] & 0x70;
x=readdata[0];
x=x>>4;
x=x & 0x0f;
readdata[1]=readdata[1] | x;
x=2;
result=readdata[1];
while(result/10)
{
displaybuf[x]=result%10;
result=result/10;
x++;
}
displaybuf[x]=result;
if(sflag==1)
{
displaybuf[x+1]=17;
}
x=readdata[0] & 0x0f;
x=x<<1;
displaybuf[0]=(dotcode[x])%10;
displaybuf[1]=(dotcode[x])/10;
while(resetpulse());
writecommandtods18b20(0xcc);
writecommandtods18b20(0x44);
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2009-04-07
#include <reg51.h>
#include <intrins.h>

#define TEST_TIME
#undef TEST_TIME

sbit DQ =P1^0; //定义通信端口
sbit LCDE =P2^4; //定义通信端口 1602液晶
sbit LCDRS =P2^5; //定义通信端口
sbit LCDRW =P2^6; //定义通信端口
unsigned char code ID10=0x28,ID11=0x54,ID12=0xbd,ID13=0xe9,ID14=0x00,ID15=0x00,ID16=0x00,ID17=0x95;//传感器1
unsigned char code ID20=0x28,ID21=0x03,ID22=0xde,ID23=0xe9,ID24=0x00,ID25=0x00,ID26=0x00,ID27=0x61;//传感器2
unsigned char data ID0,ID1,ID2,ID3,ID4,ID5,ID6,ID7;//传感器2
//延时函数
void delay(unsigned int i) //经验表明,这里i=1时约等于6.9us
{
while(i--);
}

void LCDcommand(unsigned char dat)
{
P0=dat;
LCDE=0;
LCDRS=1;
LCDRW=1;//初试
delay(1);
LCDRS=0;
LCDRW=0;
delay(1);
LCDE=1;
delay(1);
LCDE=0;
LCDRS=1;//还原
LCDRW=1;
delay(100);
}
/*液晶写命令*/
/*液晶写数据*/
void LCDdata(unsigned char dat)
{
P0=dat;
LCDE=0;
LCDRS=0;
LCDRW=1;//初试
delay(1);
LCDRS=1;
LCDRW=0;
delay(1);
LCDE=1;
delay(1);
LCDE=0;
LCDRS=0;//还原
LCDRW=1;
delay(100);
}
/*液晶写数据*/
//初始化函数
void Init_DS18B20(void)
{
unsigned char x=0;
unsigned int time = 0;
DQ = 1; //DQ复位
delay(8); //稍做延时
DQ = 0; //单片机将DQ拉低
/*#ifdef TEST_TIME
TR0 = 0;
TH0 = 0;
TL0 = 0;
TR0 = 1;

#endif*/
delay(80); //精确延时 大于 480us
/*#ifdef TEST_TIME

TR0 = 0;
time = (TH0<<8) + TL0 -2;
*/
/*here time = 0x202 ,that means
514 * 12/11.0592 = 557.73 us.
that means every delay() is 6.9us.

#endif*/

DQ = 1; //拉高总线
delay(14);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay(20);
}

//读一个字节
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}

//写一个字节
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay(5);
DQ = 1;
dat>>=1;
}
}

//读取温度
unsigned int ReadTemperature(bit flag)
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0x55); // 符合ROM命令
if(flag==0) // 为第一个温度传感器
{
WriteOneChar(0x28);
WriteOneChar(0x54);
WriteOneChar(0xbd);
WriteOneChar(0xe9);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x95);
}
else // 为第二个温度传感器
{
WriteOneChar(0x28);
WriteOneChar(0x03);
WriteOneChar(0xde);
WriteOneChar(0xe9);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x61);
}
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a = ReadOneChar();
b = ReadOneChar();
t=b;
t<<=8;
t=t|a;
tt=t *0.625; //将温度的高位与低位合并
t= tt*10+0.5; //对结果进行4舍5入
return(t);
}
/*void SetAlarm(unsigned char TH, unsigned char TL,bit flag)
{
Init_DS18B20();
WriteOneChar(0x55); // 跳过读序号列号的操作
if(flag==0)
{
WriteOneChar(0x28);
WriteOneChar(0x54);
WriteOneChar(0xbd);
WriteOneChar(0xe9);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x95);
}
else
{
WriteOneChar(0x28);
WriteOneChar(0x03);
WriteOneChar(0xde);
WriteOneChar(0xe9);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x00);
WriteOneChar(0x61);
}
WriteOneChar(0x4E);
WriteOneChar(TH);
WriteOneChar(TL);
}*/
/*void ReadId() //读ROM信息
{
Init_DS18B20();
WriteOneChar(0x33); //读ROM信息
ID0=ReadOneChar();
ID1=ReadOneChar();
ID2=ReadOneChar();
ID3=ReadOneChar();
ID4=ReadOneChar();
ID5=ReadOneChar();
ID6=ReadOneChar();
ID7=ReadOneChar();
}
void MatcnId()
{
Init_DS18B20();
WriteOneChar(0x33);
ID0=ReadOneChar();
ID1=ReadOneChar();
ID2=ReadOneChar();
ID3=ReadOneChar();
ID4=ReadOneChar();
ID5=ReadOneChar();
ID6=ReadOneChar();
ID7=ReadOneChar();
}*/
/*void AlarmSearch()
{
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0xec);
//WriteOneChar(0x33);
ID0=ReadOneChar();
ID1=ReadOneChar();
ID2=ReadOneChar();
ID3=ReadOneChar();
ID4=ReadOneChar();
ID5=ReadOneChar();
ID6=ReadOneChar();
ID7=ReadOneChar();
}*/

void main()
{
unsigned int t = 0;
unsigned char a1,b1,c1,d1;
unsigned char a2,b2,c2,d2;

//以下为定时器初始化。
LCDcommand(0x38);//显示模式设置
LCDcommand(0x01);//显示清屏
LCDcommand(0x06);//显示光标移动设置
LCDcommand(0x0c);// 开显示
//ReadId();
/*SetAlarm(0x1e,0x00,0);
SetAlarm(0x1e,0x00,1);
AlarmSearch();*/
while(1)
{

t = ReadTemperature(0);
d1=t/1000;
a1=(t-d1*1000)/100;
b1=(t-d1*1000-a1*100)/10;
c1=t-d1*1000-a1*100-b1*10;
LCDdata(d1+48);
LCDdata(a1+48);
LCDdata('.');
LCDdata(b1+48);
LCDdata(c1+48);
LCDcommand(0xc0);
t = ReadTemperature(1);
d2=t/1000;
a2=(t-d2*1000)/100;
b2=(t-d2*1000-a2*100)/10;
c2=t-d2*1000-a2*100-b2*10;
LCDdata(d2+48);
LCDdata(a2+48);
LCDdata('.');
LCDdata(b2+48);
LCDdata(c2+48);
delay(20000);
LCDcommand(0x02); //显示回车,数据指针清零
LCDcommand(0x01); //显示清屏,数据指针清零,所有显示清零
}

}
第2个回答  2009-04-07
没有给出显示方式,这边设计到18b20的温度读取数据,显示模块具体问题具体分析:
//晶振12m,P0口为数据口,P2.6和P2.7为扫描端口,共阳LED数码管,P2.2为数据输入口

//如果晶振为24M,把所有延时都乘以2倍

#include <reg51.h>
sbit warmer=P1^4;
sbit led_run=P1^0;
sbit k_power=P3^3;
sbit ge=P2^7;
sbit shi=P2^6;
sbit DQ =P2^2; //定义通信端口
//延时函数
unsigned char tab[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90};
//0, 1, 2 3 4 5 6 7 8 9
void delay(unsigned int i)
{
while(i--);

}
//初始化函数
Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay(80); //精确延时 大于 480us
DQ = 1; //拉高总线
delay(14);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay(20);
}
//读一个字节
ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
//写一个字节
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay(5);
DQ = 1;
dat>>=1;
}
delay(4);
}
//读取温度
ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar(); //读取温度值低位
b=ReadOneChar(); //读取温度值高位
a=a>>4; //低位右移4位,舍弃小数部分
t=b<<4; //高位左移4位,舍弃符号位
t=t|a;
return(t);
}
void display_tempmain(unsigned char i) //主程序温度显示函数
{
P0=tab[i/10];
shi=0;
ge=1;
delay(1000);
P0=tab[i%10];
shi=1;
ge=0;
}
void main(void)
{unsigned int temp;

while(1) //主循环
{ temp=ReadTemperature();
display_tempmain(temp);

}
}

参考资料:http://www.shenzhenwangzhanyouhua.com/seo/18b20.html

第3个回答  2009-04-10
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P2^4;//ds18b20与单片机连接口
sbit RS= P2^1;
sbit RW = P2^2;
sbit EN = P2^3;
unsigned char code str1[]={"zongtao benbi "};
unsigned char code str2[]={" "};
uchar data disdata[5];
uint tvalue;//温度值
uchar tflag;//温度正负标志
/*************************lcd1602程序**************************/
void delay1ms(unsigned int ms)//延时1毫秒(不够精确的)
{unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<100;j++);
}
void wr_com(unsigned char com)//写指令//
{ delay1ms(1);
RS=0;
RW=0;
EN=0;
P1=com;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void wr_dat(unsigned char dat)//写数据//
{ delay1ms(1);;
RS=1;
RW=0;
EN=0;
P1=dat;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void lcd_init()//初始化设置//
{delay1ms(15);
wr_com(0x38);delay1ms(5);
wr_com(0x08);delay1ms(5);
wr_com(0x01);delay1ms(5);
wr_com(0x06);delay1ms(5);
wr_com(0x0c);delay1ms(5);
}

void display(unsigned char *p)//显示//
{
while(*p!='\0')
{
wr_dat(*p);
p++;
delay1ms(1);
}
}
init_play()//初始化显示
{ lcd_init();
wr_com(0x80);
display(str1);
wr_com(0xc0);
display(str2);
}
/******************************ds1820程序***************************************/
void delay_18B20(unsigned int i)//延时1微秒
{
while(i--);
}
void ds1820rst()/*ds1820复位*/
{ unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于480us
DQ = 1; //拉高
delay_18B20(40);
}

uchar ds1820rd()/*读数据*/
{ unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{ DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
void ds1820wr(uchar wdata)/*写数据*/
{unsigned char i=0;
for (i=8; i>0; i--)
{ DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
}
}
read_temp()/*读取温度值并转换*/
{uchar a,b;
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0x44);//*启动温度转换*/
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0xbe);//*读取温度*/
a=ds1820rd();
b=ds1820rd();
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
if(tvalue<0x0fff)
tflag=0;
else
{tvalue=~tvalue+1;
tflag=1;
}
tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
return(tvalue);
}
/*******************************************************************/
void ds1820disp()//温度值显示
{ uchar flagdat;
disdata[0]=tvalue/1000+0x30;//百位数
disdata[1]=tvalue%1000/100+0x30;//十位数
disdata[2]=tvalue%100/10+0x30;//个位数
disdata[3]=tvalue%10+0x30;//小数位

if(tflag==0)
flagdat=0x20;//正温度不显示符号
else
flagdat=0x2d;//负温度显示负号:-
if(disdata[0]==0x30)
{disdata[0]=0x20;//如果百位为0,不显示
if(disdata[1]==0x30)
{disdata[1]=0x20;//如果百位为0,十位为0也不显示
}
}
wr_com(0xc0);
wr_dat(flagdat);//显示符号位
wr_com(0xc1);
wr_dat(disdata[0]);//显示百位
wr_com(0xc2);
wr_dat(disdata[1]);//显示十位
wr_com(0xc3);
wr_dat(disdata[2]);//显示个位
wr_com(0xc4);
wr_dat(0x2e);//显示小数点
wr_com(0xc5);
wr_dat(disdata[3]);//显示小数位
}
/********************主程序***********************************/
void main()
{ init_play();//初始化显示
while(1)
{read_temp();//读取温度
ds1820disp();//显示
}
}
相似回答