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

📄 18b20.c

📁 单片机开发板演示程18B20数字温度计/数码管晶体:12M MCU:STC89S51
💻 C
字号:
#include<at89x51.h>
//#include<port.h>
#include"intrins.h"
#define uchar unsigned char
#define uint  unsigned int 
sbit  DQ=P3^6;  	
//	uchar code  tv[]={0xf7,0xfb,0xfd,0xfe};
//	uchar code  a[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff};
//	uchar  data  led[4];
//共阳段码表
//字节的高位对应数码管的H段,依次类推 
//static unsigned char code number_Tab[21]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90//0-9共阳段码表 
unsigned int j=0;                                                     //,0xbf,0xff};      //-和清0共阳段码表
unsigned char dispbitcode[8]={0xf7,0xfb,0xfd,0xfe/*,0xef,0xdf,0xbf,0x7f*/};  //位扫描
unsigned char dispcode[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xc6,0xff};  
                            //共阳数码管字段码 0xc6表示C温度符号。
unsigned char dispbuf[4];                    
					  //  延时子函数
//**************************************************************/
void delay(uint t)
{	for (; t>0 ; t--)  ;
}


/************************************************************
/* 产生复位脉冲初始化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;         // 一直等到得到存在脉冲DQ=0 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~60ms之间对数据线进行采样,如果是高电平就写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位
  }
//	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_(); //4us
  	DQ = 1; _nop_();_nop_();_nop_();_nop_();_nop_();//5us
  	if(DQ) 
     {	value|= 0x80 ; }					   
//	 	delay(13); //66us 注意延时的长短,如果是delay(6) 会造成LED闪烁
  }												
  DQ = 1;
  return(value)	;
}



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

 /*--------------------------------------------------------------------------------------
                              读取温度并完成转化,
-----------------------------------------------------------------------------------------*/
 void  Read_Temperature(void)
{
    uchar tplsb,tpmsb;		// 温度值低位、高位字节
    uchar flag=0;
   // unsigned int j=0; //暂存计算得温度的整数部分
    float tt;
    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位为符号位
    //转换温度

    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[3]=j/1000; //百位	 
/*此程序用的是三极管驱动4位数码管显示,考虑到为数有限,将百位和负号位屏蔽掉*/
   	dispbuf[0]=10;  //表示温度符号C
}
/*------------------------------------------------------------------------
							温度显示
-------------------------------------------------------------------------*/
void disp(void)
{
	uint k;
/*此程序用的是三极管驱动4位数码管显示,考虑到为数有限,将百位和负号位屏蔽掉*/	  
//if(tpmsb>7)	//表示负温度
// {           //把负号标志放在整数最高位不是0的前一位
//	if(temperature_tab[0]==0&&temperature_tab[1]!=0) temperature_tab[0]=10;
//	if(temperature_tab[0]==0&&temperature_tab[1]==0){ temperature_tab[0]=11;temperature_tab[1]=10;}
//}
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; 
  }
}

 

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


main ()
{ 		
  Setting_DS18B20();    
  while(1) 
	{
	   
	Read_Temperature(); 	_nop_(); _nop_(); _nop_();	
	disp();    
  	
	}

}
//**********************配置寄存器******************************//
//该字节各位的意义如下: 

//表3: 配置寄存器结构 
//TM R1 R0 1 1 1 1 1 

//低五位一直都是"1",TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。
//在DS18B20出厂时该位被设置为0,用 户不要去改动。R1和R0用来设置分辨率,如下表所示:(DS18B20出厂时被设置为12位) 

//表4: 温度分辨率设置表
//R1 R0 分辨率 温度最大转换时间 
//0  0  9位    93.75ms  
//0  1  10位   187.5ms  
//1  0  11位   375ms  
//1  1  12位   750ms 
///****************温度符号的说明********/////
//12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,
//如果测得的温度大于0, 这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;
//如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际 温度。 
//例如+125℃的数字输出为07D0H,+25.0625℃的数字输出为0191H,-25.0625℃的数字输出为FF6FH,
//-55℃的数字输出为FC90H 。 

⌨️ 快捷键说明

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