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

📄 all.c

📁 ds18b20测温程序,在keilc51调适通过
💻 C
📖 第 1 页 / 共 2 页
字号:
/*项目名称:数字式多路温度检测、显示与报警系统*/
/*创建  人:孙云辉                            */
/*创建时间:2008.05.25                        */
/*修改时间:2008.06.01                        */
/*功    能:全部功能                          */
/*版    本:V1.0                              */

#include<reg51.h>

/////////////////////////////////////////////////
/********************基本程序*******************/
/////////////////////////////////////////////////

/*短延时程序16us为单位 延时时间=24+Num*16 微秒*/
void Delay_short(unsigned int n)
{
 unsigned int i;
 for(i=0;i<n;i++)	
 {}
}

/*长延时程序,以5ms为单位*/
void Delay_long(unsigned char N)
{ unsigned char i;
  unsigned int j;
   for(i=0;i<N;i++)
   { for(j=0;j<315;j++)  //一个循环16us,共5ms
      {}
   }
}
 
/////////////////////////////////////////////////
/*******************键盘部分********************/
/////////////////////////////////////////////////

/*键盘键值定义*/
#define MENU    0xee  //KEY1 菜单键
#define UP      0xde  //KEY2 菜单上翻或加一键
#define SET     0xeb  //KEY3 确认键
#define CHANGE  0xe7  //KEY4 搜索ROM键
#define LEFT    0xed  //KEY5 光标左移
#define DOWN    0xdd  //KEY6 菜单下翻或减一键
#define	RIGHT   0xdb  //KEY7 光标右移
#define QUIT    0xd7  //KEY8 退出键

/*键盘接口定义*/
sbit R1= P2^4;	//第一列按键
sbit R2= P2^5; 	//第二列按键

/*键盘扫描程序,返回键值*/
unsigned char Key_scan(void)
{
  unsigned char i,j;
  R1=0;	            //扫描第一列
  i=P2;	            //读取键值
  Delay_long(2);	//延时10ms去抖动
  j=P2;			    //再次读取键值
  R1=1;			    //第一列初始化
  if(i==j)		    //两次键值相同表示有键按下
 {
  switch(j)
	{
	  case 0xee: return(j);break;//KEY1
	  case 0xed: return(j);break;//KEY5
	  case 0xeb: return(j);break;//KEY3
	  case 0xe7: return(j);break;//KEY4	  
	 }
  
 }
   R2=0;
   i=P2;
   Delay_long(2);
   j=P2;
   R2=1;
   if(i==j)
  {
   switch(j)
	{
	  case 0xde: return(j);break;//KEY2
	  case 0xdd: return(j);break;//KEY6
	  case 0xdb: return(j);break;//KEY7
	  case 0xd7: return(j);break;//KEY8	 
	  default:return(0);		 //无键按下返回0
	 }
  }     

}

/////////////////////////////////////////////////
/*******************报警部分********************/
/////////////////////////////////////////////////

/*蜂鸣器接口*/
sbit voice=P1^7;

bit Alarm_flag; //报警标志位  1报警 0取消报警

/*报警子程序                         */
/*全局变量:Alarm_flag=1报警=0报警解除*/
void Alarm(void)	      
{
 unsigned char i;
 if(Alarm_flag==1) 	  //当Alarm_flag有效
 { 
  for(i=0;i<10;i++)  //报警一段时间
  {
   voice=~voice;
   Delay_long(5);
  }
 }
}

/////////////////////////////////////////////////
/********************LCD部分********************/
/////////////////////////////////////////////////

/*LCD接口定义*/
sbit LcdRS	 = P1^0;	  //lcd数据/命令选择端  数据1命令0
sbit LcdRW	 = P1^1;	  //lcd读/写选择端	读1写0
sbit LcdEn   = P1^2;	  //lcd使能控制端  1有效
sfr  LcdIO   = 0x80;	  //lcd数据接口 P0=0x80


/****向LCD写入命令或数据部分****/
#define LCD_COMMAND			0         // 输出指令
#define LCD_DATA			1         // 输出数据

#define LCD_CLEAR_SCREEN	0x01      // 清屏指令
#define LCD_HOME    		0x02      // 光标返回原点指令

/*写LCD子程序 	                                     */
/*入口参数:数据style=1 指令style=0 input:写入的内容*/

void LCD_Write(bit style, unsigned char input) 
{
	LcdRS=style;         //数据style=1  指令style=0
    LcdRW=0;	         //写
	LcdIO=input;	     //P0口输出
	Delay_short(10);	 //延时
	LcdEn=1;		     //lcd使能
	Delay_short(10);	 //延时
	LcdEn=0;		     //停止
}

/****初始化LCD程序****/
void LCD_Initial()
{
	Delay_long(6);					           //延迟5*6=30ms
	LCD_Write(LCD_COMMAND,0x38);               //8位数据端口,2行显示,5*7点阵
    LCD_Write(LCD_COMMAND,0x38);
    LCD_Write(LCD_COMMAND,0x38);			   //发送三遍
	Delay_short(2);                            //延迟大于39us
	LCD_Write(LCD_COMMAND,0x0c);    //显示模式设置:开启显示, 无光标 0x0c
	Delay_short(2);							   //延迟大于39us
	LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);   //清屏			              0x01
	Delay_short(100);						   //延迟大于1.53ms
	LCD_Write(LCD_COMMAND,0x06);       //输入模式设置:AC递增, 画面不动 0x06
}


/*液晶字符输入的位置定位程序*/
/*入口参数:x范围:0-15	 y范围:1,2*/
void GotoXY(unsigned char x, unsigned char y) 
{
	unsigned char address;
	if(y==1)
		address=0x80+x;		 //y=1显示在第一行
     else
	    address=0xc0+x;      //y=2显示在第二行
    LCD_Write(LCD_COMMAND, address);
}

/*将字符串输出到液晶显示函数*/
/*入口参数:字符串指针      */
void Print(unsigned char *str)
{
	while(*str!='\0')
	{
		LCD_Write(LCD_DATA,*str);
		str++;
	}
}

/////////////////////////////////////////
/***********DS18B20部分*****************/
/////////////////////////////////////////

/*DS18B20接口定义*/
sbit DQ  =P1^6;			  //单总线接口

/*全局变量定义*/
unsigned char DS_Temp[5][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; //存放温度值(负数用补码表示)
																	   //0:符号1:整数2:小数
unsigned char DS_Tl[5]={0,0,0,0,0};		            //温度报警上限
unsigned char DS_Th[5]={0,0,0,0,0};	                //温度报警下限
unsigned char ID[5][8]={{0},{0},{0},{0},{0}};	    //存放序列号

//*DS18B20指令定义*/
#define  READ_ROM      0x33	   //读ROM指令
#define  MATCH_ROM	   0x55	   //匹配ROM指令
#define  SKIP_ROM      0xCC	   //跳过ROM指令
#define  ALARM_SEARCH  0xEC	   //报警搜索指令
#define  CONVERT_T     0x44	   //温度转换指令
#define  WRITE_SCR     0x4E    //写暂存器指令
#define  READ_SCR      0xBE	   //读暂存器指令
#define  COPY_SCR      0x48	   //复制暂存器指令



/*ds18b20初始化函数 返回初始化状态*/
unsigned char DS_Reset(void) 
{
  unsigned char presence;
  DQ = 1;          //DQ复位
  Delay_short(1);  //稍做延时
  DQ = 0;          //单片机将DQ拉低
  Delay_short(29); //精确延时480us
  DQ = 1;          //拉高总线
  Delay_short(3);  //等待存在信号
  presence=DQ;     //稍做延时后 如果presence=0则初始化成功 =1则初始化失败
  Delay_short(25);
  if(presence==0)
    return 1;	   //初始化成功返回1
  else
    return 0;	   //初始化失败返回0
} 

/*从ds18b20读一个字节 dat为返回值*/  
unsigned char DS_ReadByte(void)
{
  unsigned char i=0;
  unsigned char j=0;
  unsigned char dat=0;
	for (i=0;i<8;i++)
	 {
		  DQ = 0;               //给脉冲信号
		  dat>>=1;              //右移位等待接收一位数据
		  DQ = 1;               //给脉冲信号
		  for(j=0;j<3;j++) ;    //延时15微秒
		  if(DQ)                //从低位开始接收数据
		  dat|=0x80; 
		  Delay_short(6);       //等待复位
	 }
   return(dat);
}

/*向ds18b20写一个字节 dat为待写入字节*/ 
void DS_WriteByte(unsigned char dat)
{
 	unsigned char i=0;
 	for (i=0; i<8; i++)
 	{
  		DQ = 0;  //给脉冲信号
 		DQ = dat&0x01;	//从低位开始发送数据
    	Delay_short(5);
 		DQ = 1;	 //给脉冲信号
    	dat>>=1; //右移位等待发送
    }
  Delay_short(5) ;
}

/*读DS18B20序列号程序*/
/*入口参数:器件序号*/
/*全局变量:ID[5][8]*/
void DS_ReadID(unsigned char Num)
{
  signed char i;
  DS_Reset();
  DS_WriteByte(READ_ROM) ;
  for(i=7;i>-1;i--)			  //从最低位开始读取
   {
	ID[Num][i]=DS_ReadByte();
    }
}	

/*匹配序列号程序           */
/*入口参数:器件序号(0-4)*/
/*全局变量:ID[5][8]       */
unsigned char Match_ID(unsigned char Num)
{
  signed char i;
  if(DS_Reset()==1)				 //有器件响应
   {
   	 DS_WriteByte(MATCH_ROM);	 //发送ID
	 for(i=7;i>-1;i--)
	  {
	  	DS_WriteByte(ID[Num][i]);
	  }
	 return 1;				     //返回1表示成功
   }
  else
     return 0;					 //返回0表示失败
}

/*显示序列号程序         */
/*入口参数为器件序号(0-4)*/
/*全局变量:ID[5][8]     */
void Show_ID(unsigned char Num)   //Num为序号
{ 
  unsigned char i;
  GotoXY(0,2);					  //显示NO:
  Print("NO:");
  GotoXY(3,2);
  LCD_Write(LCD_DATA,Num+1+0x30); //显示序号(1-5)对应ID0-ID4
  GotoXY(0,1);
  for(i=0;i<8;i++)
	{
	 unsigned char l=ID[Num][i]&0x0f;	    //取低4位
	 unsigned char h=ID[Num][i]&0xf0;		//取高4位
	 h>>=4;
	 if((h>=0x00)&&(h<=0x09))
	  LCD_Write(LCD_DATA,h+0x30);	       //取ASCII码
	 else  
	  LCD_Write(LCD_DATA,h+0x37);	       //取ASCII码

	 if((l>=0x00)&&(l<=0x09))
	  LCD_Write(LCD_DATA,l+0x30);	       //取ASCII码
	 else  
	  LCD_Write(LCD_DATA,l+0x37);	       //取ASCII码
	}
}

/*读取ds18b20当前温度 和Th,Tl              */
/*入口参数:器件编号(0-4)                 */
/*全局变量DS_Temp[5][3] DS_Th[5] DS_Tl[5]*/

void DS_ReadTemp(unsigned char Num)
{
	unsigned char temp_lsb=0; //温度寄存器低字节
	unsigned char temp_msb=0; //温度寄存器高字节
	unsigned char Temp=0;

	DS_Reset();			            //初始化
	DS_WriteByte(SKIP_ROM);        	//跳过读序号列号的操作
	DS_WriteByte(CONVERT_T); 	    //启动温度转换

	Delay_short(5);                 //延时过程
	DS_Reset();			            //初始化
	Match_ID(Num);                  //匹配ROM
	DS_WriteByte(READ_SCR);         //读取温度寄存器前两个就是温度

	temp_lsb=DS_ReadByte();    	    //读取温度寄存器低字节
	temp_msb=DS_ReadByte();   	    //读取温度寄存器高字节
	DS_Th[Num]=DS_ReadByte();		//读取TH
	DS_Tl[Num]=DS_ReadByte();		//读取TL
	
	 if(temp_msb>0xf0)
	   DS_Temp[Num][0]=1;			//取温度符号(正为0,负为1)
     else
	   DS_Temp[Num][0]=0;	

	DS_Temp[Num][1]=temp_msb<<4;         //取温度整数部分的高四位
	DS_Temp[Num][1]+=(temp_lsb&0xf0)>>4; //取温度整数部分的低四位
	Temp=DS_Temp[Num][1];
    DS_Temp[Num][2]=temp_lsb&0x0f;       //取温度小数部分      

	 if(DS_Temp[Num][0]==1)				 //温度为负的处理
	  {
		DS_Temp[Num][1]=~DS_Temp[Num][1];  //整数取反
		DS_Temp[Num][2]=~DS_Temp[Num][2]+1;//小数取反加1
		  if(DS_Temp[Num][2]==0x10)		   //如果有进位(在温度为负整数时)
		    {
			  DS_Temp[Num][1]=DS_Temp[Num][1]+1;    //整数加1   
			  DS_Temp[Num][2]= 0;	//小数清0
			}
	  }              
	if((Temp+1>DS_Th[Num])||(Temp<DS_Tl[Num]))
	  Alarm_flag=1;
	else
	  Alarm_flag=0;
}

/*温度数据转换成液晶字符显示      */
/*全局变量 DS_Temp[5][3]          */
/*入口参数 器件序号(0-4)          */
void TempDisp(unsigned char Num)   
{
  GotoXY(0,1);					  
  Print("NO.");				     //显示NO.
  GotoXY(3,1);
  LCD_Write(LCD_DATA,Num+1+'0');	 //显示器件序号(1-5)
  LCD_Write(LCD_DATA,':');		 //显示“:”
   if(DS_Temp[Num][0]==0)
     LCD_Write(LCD_DATA,'+') ;	 //温度为正显示“+”否则显示“-”
   else
     LCD_Write(LCD_DATA,'-') ;

  LCD_Write(LCD_DATA,DS_Temp[Num][1]/100+'0') ;		       //百位
  LCD_Write(LCD_DATA,(DS_Temp[Num][1]%100)/10+'0') ;       //十位
  LCD_Write(LCD_DATA,DS_Temp[Num][1]%10+'0') ;		       //个位
  LCD_Write(LCD_DATA,'.') ;							       //小数点
  LCD_Write(LCD_DATA,DS_Temp[Num][2]*10/16+'0') ;	       //十分位
}


/*显示TH和TL程序                              */
/*入口参数:器件序号Num(0-4)位置坐标y(1,2)  */
/*全局变量:DS_Tl[5] DS_Th[5]                 */

void ThTlDisp(unsigned char Num,unsigned char y)
{
  unsigned char Th=DS_Th[Num];	 //
  unsigned char Tl=DS_Tl[Num];
  
  GotoXY(1,y);
  Print("TH=");					 //显示TH
    if(Th>=0x80)			     //为负显示“-”并取绝对值  
	 {
	  LCD_Write(LCD_DATA,'-');
	  Th=~Th+1;
	 }
    else
      LCD_Write(LCD_DATA,'+');	 //为正显示“+”

  LCD_Write(LCD_DATA,Th/100+'0');		 //百位
  LCD_Write(LCD_DATA,(Th%100)/10+'0');	 //十位
  LCD_Write(LCD_DATA,Th%10+'0');		 //个位

  GotoXY(9,y);
  Print("TL=");				     //显示TL
    if(Tl>=0x80)			     //为负显示“-”并取绝对值
	 {
	  LCD_Write(LCD_DATA,'-');
	  Tl=~Tl+1;
	 }
    else
      LCD_Write(LCD_DATA,'+');   //为正显示“+”

  LCD_Write(LCD_DATA,Tl/10+'0');  //十位
  LCD_Write(LCD_DATA,Tl%10+'0');  //个位
}


/////////////////////////////////////////////////////
/***************STC单片机ISP功能部分****************/
/////////////////////////////////////////////////////

/*STC新增特殊功能寄存器声明*/
sfr ISP_DATA  = 0xe2; //ISP数据寄存器
sfr ISP_ADDRH = 0xe3; //EEPROM地址高8位
sfr ISP_ADDRL = 0xe4; //EEPROM地址高8位
sfr ISP_CMD   = 0xe5; //ISP命令模式寄存器:0无操作,1读,2写,3擦除
sfr ISP_TRIG  = 0xe6; //ISP命令触发寄存器:先写46H再写B9H则ISP_CMD生效
sfr ISP_CONTR = 0xe7; //ISP控制寄存器:取81H允许ISP功能

/*定义ISP命令模式*/
#define  ISP_ReadByte  0x01	//字节读指令
#define  ISP_WeiteByte 0x02	//字节写指令
#define  ISP_Erase     0x03	//扇区擦除指令


/*ISP读DS18B20 ID程序                                */
/*入口参数:1,DS18b20编号(0-4)                     */
/*全局变量:DS18B20的ID号存储区:ID[5][8]            */
/*功    能:读出某个扇区内的8字节DS18B20的ID载入RAM  */
void ISP_Read8(unsigned char Num)
{
  unsigned char i;
  ISP_CONTR=0x81;		    //允许ISP功能,并配制等待时间
  ISP_CMD=ISP_ReadByte;	    //送ISP字节读指令
  ISP_ADDRH=0x20+Num*0x02;  //送地址高字节
  for(i=0;i<8;i++)			//读8字节

⌨️ 快捷键说明

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