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

📄 multi-points.c

📁 单总线多点温度测量系统(DS18B20)
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************************/
/*单片机采用STC89C52,晶振为12MHz。P1.0与DS18B20的数据端相连*/
/*P0为数码管的字段码口,P2口为位选码口*/
/*P3.2与按键0相连,P3.3与按键1相连*/
/*MAXNUM是单总线上最大可扫描DS18B20个数*/
/*flag为温度的正负号标志单元,flag为"1"时表示温度值为负值,为"0"时表示温度值为正值*/
/*温度测量范围为(-55.0~99.9摄氏度)。*/
/*变量cc中保存计算出的温度值的整数部分,xs保存计算出的温度值的小数部分的第一位*/
/*num记录当前单总线上DS18B20的个数*/
/*z是按键标志位,z为1时表明有按键按下*/
/*a,b分别是按键0和按键1的记录变量*/
/*m是轮换显示各DS18B20温度值和序列号的全局标志变量*/
/*二维数组ID用于记录各DS18B20的ROM序列号*/
/*数组disbuffer是LCD显示缓存数组*/
/*数组RomID_temp用于匹配DS18B20时临时记录要匹配DS18B20的序列号*/
/*共用体temp用于存放从DS18B20读入的数据*/
/**************************************************************************************/

#include <reg51.h>	 
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define MAXNUM 4        //宏定义单总线上最大可扫描DS18B20个数
sbit DS=P1^0; 			//用P1.0口作为各DS18B20与单片机的I/O口
sbit Key0=P3^2;			//P3.2用作按键0的输入,采用外部中断方式获取按键信号
sbit Key1=P3^3;			//P3.3用作按键1的输入,采用外部中断方式获取按键信号

union{					//定义共用体temp用于存放从DS18B20读入的数据,Keil C51采用大端格式,c[1]是高地址.
	uchar c[2];			//其中存放读取温度数值的低字节;c[0]是低地址,其中存放读取温度数值的高字节.
	uint x;				//这样根据大端格式的要求,即数据的高字节存储在低地址中,数据的低字节存放在高地址中,
}temp;					//x便刚好是读出的温度数值.
						

uchar idata flag;		//温度的正负号标志,flag为"1"时表示温度值为负值,为"0"时表示温度值为正值
uint cc,xs;				//变量cc中保存计算出的温度值的整数部分,xs保存计算出的温度值的小数部分的第一位
uchar idata disbuffer[6];	//LCD显示缓存数组
uchar idata ID[4][8]={0};	//用于记录各DS18B20的ROM序列号
uchar idata RomID_temp[8];	//匹配DS18B20时临时记录要匹配DS18B20的序列号
uchar m=0;				//m是轮换显示各DS18B20温度值和序列号的全局标志变量
uchar num=0;			//num记录当前单总线上DS18B20的个数
uchar z=0;				//z是按键标志位,z为1时表明有按键按下
uchar a=0;				//a是按键0的记录变量
uchar b=0;				//b是按键1的记录变量


void delay(uint i)      //延时i*9.62us 
{
	uint j;
	for(j=i;j>0;j--);
}

void delay_ms(uchar i)  //延时(j*2+1+2)*i+5 个机器周期    
{ uchar j;			    //12MHz时,延时 0.5*i ms
  do{j=248; 		 
     do{j--;}while(j); 
     i--; 
    }while(i); 
}


void delay_2us(uchar i)	  //延时 2*i+5 us
{
  while(--i);
}

uchar DS_init(void)       //18B20复位,初始化函数
{
  uchar presence;
  DS=0;          delay_2us(250); //根据DS18B20的复位时序.先把总线拉低555us
  DS=1;          delay_2us(30);	 //再释放总线,65us后读取DS18B20发出的信号
  presence=DS;   delay_2us(250); //如果复位成功,则presence的值为0;否则为1
  return (presence);	  		 //返回0则初始化成功,否则失败
}

uchar read_byte(void)       //读1字节
{
  uchar i,j,dat=0;
  for(i=1;i<=8;i++)			//作8个循环,读出的8位组成一个字节
    {DS=0;   _nop_();       //先将总线拉低1us, 
     DS=1;   delay_2us(2);	//再释放总线,产生读起始信号,延迟9us后读取总线上的DS18B20发出的值
     j=DS;   delay_2us(30);	//一位读完后,延迟65us后读下一位
     dat=(j<<7)|(dat>>1);   //读出的数据最低位在一个字节的最低位,这样刚好一个字节在DAT里
    }
  return(dat);
}

uchar read_2bit(void)       //读2位
{
  uchar i=0,j=0;
  DS=0;   _nop_();          //先将总线拉低1us, 
  DS=1;   delay_2us(2);		//再释放总线,产生读起始信号,延迟9us后读取总线上的DS18B20发出的值
  j=DS;   delay_2us(30);	//一位读完后,延迟65us后读下一位
  DS=0;   _nop_();          
  DS=1;   delay_2us(2);
  i=DS;   delay_2us(30);
  i=j*2+i;  			//将读出的两位放到变量i中,其中第一个读出的位处于i的第1位;而第二个读出的位处于i的第0位
  return(i);
}


void write_byte(uchar dat)	//写1字节
{  
  uchar i;
  for(i=0;i<8;i++)			//作8个循环,写入的8位组成一个字节
    {DS=0;					//先将总线拉低
     DS = dat&0x01;			//向总线上放入要写的值
     delay_2us(50);			//延迟105us,以使DS18B20能采样到要写入的值
     DS = 1;				//释放总线,准备写入下一位
     dat>>=1;				//将要写的下一位移到dat的最低位		
   	}
}


void write_bit(bit dat)	//写1位
{  
  DS=0;				//先将总线拉低
  DS=dat;			//向总线上放入要写的值
  delay_2us(50);	//延迟105us,以使DS18B20能采样到要写入的值
  DS = 1;			//释放总线
}


void display_ROMID(void)			//定义显示序列号的函数
{	
	uchar i,p,t,k;
	uint q;
	uchar disbuffer_rom[8];
	uchar codevalue[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xbf};
							//共阳极的字段码
	uchar chocode[]={0xf7,0xfb,0xfd,0xfe,0x7f,0xbf,0xdf,0xef};
							//位选码表



		z=0; //z归零,表明没有按键按下
	
	 	for(q=0;q<500;q++)	//显示各DS18B20的序号
	 	{		if(z==1)	//如果z为1,有按键按下,表明要显示不同的内容,此时从这个显示循环中跳出
				break;		
				t=chocode[7];		//取当前的位选码
  				P2=t;				//送出位选码
  				t=codevalue[m+10];	//查得显示字符的字段码
 				P0=t;				//送出字段码
				delay(100);			
		}
		
		P2=0xFF;			//关断LCD一段时间,产生闪屏效果
		for(q=0;q<500;q++)
		{	if(z==1)		//如果z为1,有按键按下,表明要显示不同的内容,此时从这个循环中跳出
			break;
			delay(100);
		 }
		
		for(k=0;k<8;k=k+4)	//依次显示序列号的低32位或高32位
		{		if(z==1)	//如果z为1,有按键按下,表明要显示不同的内容,此时从这个循环中跳出
				break;
				 									//接下来将序列号的低32位或高32位值取出放入disbuffer_rom存储
				 disbuffer_rom[0]=(ID[m][k]&0x0F);
				 disbuffer_rom[1]=((ID[m][k]&0xF0)>>4);
				 disbuffer_rom[2]=(ID[m][k+1]&0x0F);
				 disbuffer_rom[3]=((ID[m][k+1]&0xF0)>>4);
				 disbuffer_rom[4]=(ID[m][k+2]&0x0F);
				 disbuffer_rom[5]=((ID[m][k+2]&0xF0)>>4);
				 disbuffer_rom[6]=(ID[m][k+3]&0x0F);
				 disbuffer_rom[7]=((ID[m][k+3]&0xF0)>>4);	
	    
				for(q=0;q<250;q++)		//显示序列号的低32位或高32位
				{	if(z==1)			//如果z为1,有按键按下,表明要显示不同的内容,此时从这个显示循环中跳出
					break;
		 			for (i=0;i<8;i++)
					{	if(z==1)
						break;
  						t=chocode[i];		//取当前的位选码
  						P2=t;				//送出位选码
  						p=disbuffer_rom[i];	//取当前显示的字符
  						t=codevalue[p];		//查得显示字符的字段码
 						P0=t;				//送出字段码
						delay(40);			
					}
				}		
				P2=0xFF;			 //显示完一轮,灯灭
				for(q=0;q<500;q++)
				{
					if(z==1)		//如果z为1,有按键按下,表明要显示不同的内容,此时从这个显示循环中跳出
					break;
					delay(100);        
				}
		  }
		  
	  	 	
		

        
}


void display_error(void)			//定义显示总线上没有DS18B20时的函数
{	
	uchar i,p,t;
	uint q;
	uchar disbuffer_temp[8]={0,2,8,1,16,0x0f,0x0f,0}; //显示内容为"OFF 1820"
	uchar codevalue[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xbf};
							//共阳极的字段码
	uchar chocode[]={0xf7,0xfb,0xfd,0xfe,0x7f,0xbf,0xdf,0xef};
							//位选码表
				
	    
				for(q=0;q<250;q++)
				{
		 			for (i=0;i<8;i++)
					{
  						t=chocode[i];		 //取当前的位选码
  						P2=t;				 //送出位选码
  						p=disbuffer_temp[i]; //取当前显示的字符
  						t=codevalue[p];		 //查得显示字符的字段码
 						P0=t;				 //送出字段码
						delay(40);			
					}
				}

		  
	  	 	

        
}

uchar search_rom(void)   //遍历搜索单线上所连的所有18b20的序列号
{ 
  uchar k,l=0,chongtuwei,m,n,a;  
  uchar _00web[MAXNUM]={0};
  do
   {
     DS_init();         //复位单总线上的所有DS18B20

⌨️ 快捷键说明

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