⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 18b20.c

📁 DSB1820的C51源码程序
💻 C
字号:
/*数字温度计,支持负温度,温度超限报警,远程采集温度等功能*/
/*下位机温度显示采用4位数码管显示,精确度:0.1*/
/*温度超限报警,设置温度高低限,超限触发蜂鸣器报警*/
/*远程温度采集,上位机软件实时读取现场温度*/
#include <REGX51.H>

//#include<port.h>
#include"intrins.h"
#define uchar unsigned char
#define uint  unsigned int 
sbit  DQ=P3^6;  	
void BeepOn();
//共阳段码表
//字节的高位对应数码管的H段,依次类推 

uint j=0;   
uchar dispbitcode[8]={0xf7,0xfb,0xfd,0xfe/*,0xef,0xdf,0xbf,0x7f*/};  //位扫描
uchar dispcode[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xc6,0xff};  
                            //共阳数码管字段码 0xc6表示C温度符号。
uchar dispbuf[4]={0x00,0x00,0x00,0x00};  

uchar data tplsb,tpmsb;		// 温度值低位、高位字节
uchar flag=0;           //负温度标志位    

//**************************************************************/
//  延时子函数11uS
void delay(uint t)
{	for (; t>0 ; t--)  ;
}


/************************************************************
/*DS18B20复位函数: 产生复位脉冲初始化DS18B20 */
void  ow_reset(void)
{  char presence=1;
   while(presence)
   {
      while(presence)
     {
        DQ=1;
		_nop_();
		_nop_();//从高拉倒低
	    DQ=0;                                       
	    delay(50);           //550 us
	    DQ=1;                                        
	    delay(6);            //66 us
	    presence=DQ;         //presence=0 复位成功,继续下一步
     } 
     delay(45);            //延时500 us
     presence=~DQ;         
   }
   DQ=1;                   //拉高电平
}
              

/************************************************************
向 1-WIRE 总线上写一个字节**数据线从高电平拉至低电平,产生写起始信号。
             15ms之内将所需写的位送到数据线上
**************************************************************/
void write_byte(uchar val)
{
  uchar i;
  for (i=8; i>0; i--) //在15~60us之间对数据线进行采样,如果是高电平就写1,低写0发生。           
  {
    DQ = 1;
	_nop_(); 
	_nop_();  //在开始另一个写周期前必须有1us以上的高电平恢复期。               
   	DQ = 0;
	 _nop_();
	 _nop_(); 
	 _nop_(); 
	 _nop_();
	 _nop_(); //5us
	DQ = val&0x01;   //最低位移出
	delay(6) ;  //66us
	val = val/2; //右移1位	val=val>>=1;
	
  }
	delay(1);
}
/************************************************************
//读1字节 //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
**************************************************************/
uchar read_byte (void)
{
  uchar i;
  uchar value = 0;
  for(i = 8;i>0;i--)
  {	
  	DQ = 1;	 // 给脉冲信号
    _nop_(); 
	_nop_(); 
  	value>>= 1;
  	DQ = 0;	  // 给脉冲信号
	 _nop_(); 
	 _nop_();
	 _nop_(); 
	 _nop_();
	 _nop_(); //5us
  	DQ = 1; 
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();//5us
  	if(DQ) 
     {	value|= 0x80 ; }
	 					   
	 delay(13); // 注意延时的长短,如果是delay(6) 会造成LED闪烁
  }												
  DQ = 1;
  return(value)	;
}



  
  /*--------------------------------------------------------------------------------------
     设置DS18B20转换精度及报警**见配置寄存器说明** 增加功能,在此设置,如温度报警
-----------------------------------------------------------------------------------------*/
 void Setting_DS18B20(void)
{
   ow_reset();
  write_byte(0xCC);    // 跳过读序号列号的操作
  write_byte(0x4e);	  //向18B20的暂存器TH和TL中写入数据
  
  write_byte(0x64);   //不使用DS18B20本身的温度告警设置,为进行转换精度设定,凑两个写寄存器操作
  write_byte(0x8a);   //-10
  write_byte(0x7f);   //设置DS18B20 为12位转换精度	 R1,R0的值决定转换精度	 R1=R0=1对应12位 
}

 /*--------------------------------------------------------------------------------------
                              读取温度并完成转化,
-----------------------------------------------------------------------------------------*/
 void  Read_Temperature(void)
{

   
    float tt,cc;
    ow_reset();
    write_byte(0xCC); // 跳过读序号列号的操作
    write_byte(0x44); // 启动温度转换
    ow_reset();
    write_byte(0xCC); //跳过读序号列号的操作
    write_byte(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
    
    tplsb=read_byte();	 // 温度值低位字节(其中低4位为二进制的“小数”部分)
    tpmsb=read_byte();	  // 高位值高位字节(其中高5位为符号位
	ow_reset();

	 j=tpmsb;
   	j<<=8;
    j+=tplsb; 	 //写为j=j|tplsb;也可以。// 两字节合成一个整型变量。
	if(tpmsb>7)
	{	
		j=(j^0xffff);//异或
        j=j+1;        //如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际 温度。
    } 
    tt=(j*0.0625);
    j=tt*10+0.5; //四舍五入成整数,并扩大十倍   此处暂不考虑符号 
	

  	dispbuf[3]=j/100%10; //十位
	dispbuf[2]=j/10%10;	 //个位
	dispbuf[1]= j%10;//取温度小数点1位 
   	dispbuf[0]=10;  //表示温度符号C	  
 
	///////////////////////温度报警。。。。。设置
	  cc=j;
	  cc=cc/10;
   	 if(cc>30.0)			  //设置温度上限为30摄氏度
 	{
	 	BeepOn();
	 
	}  
	///////////////////////
	

}	

void BeepOn()
{
	uchar i;
	for(i=0;i<10;i++)
		{
			P3_3=~P3_3;
			delay(50);
		}
}

  
/*------------------------------------------------------------------------
							温度显示
-------------------------------------------------------------------------*/
void Display(void)
{
	uint k;
/*******************温度为负,求补码*******************************/
	if(tpmsb>127)
	{
		tpmsb=256-tpmsb;
		tplsb=256-tplsb;
		flag=1;
	}
/****************************************************************/

//////////////////////////////////////////
	if(flag)  //负温度时,最高位显示“-”,温度为依次左移,屏蔽掉最低位的C
	{
		dispbuf[3]=0x0B;	
		dispbuf[2]=j/100%10; //十位
		dispbuf[1]=j/10%10;	 //个位
		dispbuf[0]= j%10;//取温度小数点1位
		for(k=0;k<4;k++)
  		{
			P0 = dispbitcode[k];
		  	P2 = dispcode[dispbuf[k]];
		    delay(30);
		    if(k==1)	  //加上数码管的dp小数点
		  	P2&=0x7f;
		    delay(40);
		  	P0=0xff; 
  		}
	}

/////////////////////////////////////////
for(k=0;k<4;k++)
  {
	P0 = dispbitcode[k];
  	P2 = dispcode[dispbuf[k]];
    delay(30);
    if(k==2)	  //加上数码管的dp小数点
  	P2&=0x7f;
    delay(40);
  	P0=0xff; 
  }
}

 

/*------------------------------------------------------------------------
							主函数
--------------------------------------------------------------------*/


void main ()
{ 	
	unsigned char h;	
///////////开机显示8888/////////////////
	for(h=0;h<4;h++)
  {							  
	P0 = dispbitcode[h];
  	P2 = dispcode[8];
    delay(60000);
  	P0=0xff; 

  }
////////////////////////////////////////// 	
//初始化DS18B20
  Setting_DS18B20();    

  while(1) 
	{
	   
	Read_Temperature(); 	
	_nop_(); 
	_nop_(); 
	_nop_();	
	Display();    
  	
	}

}
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -