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

📄 wdbj.c

📁 一个可控温度报警装置的源码,用DS18B20采集温度,用4个按键设置温度的上下限并存在EEPROM中,按键可实现单击和长按,且时间精确,也是一个不错的键盘程序.4个数码管显示温度,4个数码管用来设定.
💻 C
字号:
#include<intrins.h>     
#include<reg52.h>
#include<absacc.h>
#define uint  unsigned int
#define uchar unsigned char

#define	liangtime	40					//设置闪烁时间
#define	mietime		40					
#define MaxRate 50						//重复前的延迟值600MS
#define MinRate 20						//重复速度240MS
#define 	N	2						//设定去抖时间

//定时器1的时间常数和方式控制字2ms
#define V_TH0	(65535-10000)/256
#define V_TL0 	(65535-10000)%256
#define	V_TMOD	0x01
sbit	ds18b20_IO=P1^0;
sbit	duX=P2^7;	//段选使能
sbit	weX=P2^6;	//位选使能
sbit 	K1=P3^7;	//设置键
sbit 	K2=P3^5;	//加数键
sbit 	K3=P3^6;	//减数键
sbit	K4=P3^4;
sbit	led4=P1^3;	
sbit	led8=P1^7;
sbit 	sda=P1^2;	
sbit 	scl=P1^1;
uchar	buffer[]={0,0,0,0,0,0,0,0};		//数码管键显缓存
uchar 	*pb=&buffer[0];
uchar   code	duma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                 	0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//数码管段码表
uchar	code	wema[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选
uchar 	tempL,tempH;
uchar 	task;                   			//task:按键状态,0:去抖,1:重复的延缓,2:重复
bit		keydone,keyprocess;					//keydone:按键任务完成标志,为1时已完成
										//keyprocess:按键有效标志,为1时对按键执行
bit 	shans;								//shans 为闪烁使能位,1时LED闪,shanz为闪烁状态位,
bit		shanz;								//1时为灭
bit 	keymark;						//设定状态标志位
uchar 	blink;						//闪烁控制器,某位为1时闪烁。
uchar 	ledtime;						//闪烁时间
uchar 	sdate;						//显示位置变量

uchar 	funcnt;						//功能键的个数
uchar 	funval;						//最后扫描到的功能键的值
uchar 	keypre=0x00; 				//存放上次功能键的键值
uint	num1;
void 	keyXZ(void);
void 	display(uchar pos);
/****************************************************************************/
/*                                                                          */
/*                         所用的延时子程序                                 */
/*                                                                          */
/****************************************************************************/
void DelayM(uint a)										//延时函数 1MS/次	
{
		unsigned char i;
		while( --a != 0)
		{		
			for(i = 0; i < 125; i++);  					//一个 ; 表示空语句,CPU空转。
		}   				  			 				//i 从0加到125,CPU大概就耗时1毫秒
}
void DelayU(uint b)										//延时函数 US级别	
{
		unsigned char i;
		while( --b != 0)
		{		
			for(i = 0; i < 20; i++);  					//一个 ; 表示空语句,CPU空转。
		}   				  
}
void delay_5us(uchar c)         //(2.17*y+5)us延时,11.0592M晶振
{
    while(--c);
}
void	delay(void)
{;;}
/******************************************************************/
/******************************************************************/
/*						DS18B20驱动函数							  */
/******************************************************************/
void DS18b20_w_byte(uchar dat);
uchar DS18b20_r_byte(void);
DS18b20_init(void);
uint DS18b20_readTemp(void);
/******************************************************************/
/*						写一字节函数							  */
/*						入口参数dat								  */
/******************************************************************/
void DS18b20_w_byte(uchar dat)    		//向18b20写一个字节dat是要写的内容
{
    uchar i;
    for(i=0;i<8;i++)
    {
        ds18b20_IO=0;
        ds18b20_IO=0x01&dat;
        delay_5us(15);                  //要求总时间在60-120us
        ds18b20_IO=1;                  	//释放总线    
        dat=dat>>1;
    }    
}

/******************************************************************/
/*						读一字节函数							  */
/*																  */
/******************************************************************/
uchar DS18b20_r_byte(void)        		//从18b20读一个字节.返回读到的内容
{
    uchar i,dat;
    dat=0;                              
    for(i=0;i<8;i++)
    {

        ds18b20_IO=0;
        dat=dat>>1;
        ds18b20_IO=1;                  	//释放总线
        if(ds18b20_IO)
             dat|=0x80;
        delay_5us(15);                  //要求总时间在60-120us
    }
    return dat;    
}

/******************************************************************/
/*						ds18b20初始化函数						  */
/*																  */
/******************************************************************/
DS18b20_init(void)         				//每次上电都给18b20初始化,设置18b20的参数
{
	uchar x=0;
    ds18b20_IO=1;
	delay_5us(25);
	ds18b20_IO=0;
    delay_5us(255);                     //要求480-960us
    ds18b20_IO=1;                      	//释放总线
    delay_5us(40);                      //要求60-120us
	x=ds18b20_IO;						//用X值来判断初始化是否成功
	delay_5us(60);
}

/******************************************************************/
/*						向DS18B20读温度值						  */
/*						出口参数DS18b20_temp					  */
/******************************************************************/
uint DS18b20_readTemp(void)     				//读18b20温度值
{
	uint DS18b20_temp,t;  				//读出的18b20温度值存放地
	uchar	i;
	float tt=0;
	DS18b20_init();
	DS18b20_w_byte(0xcc);         		//发送Skip ROM命令
    DS18b20_w_byte(0x44);         		//发送温度转换命令
	for(i=0;i<7;i++)
	{
		for(sdate=0;sdate<=7;sdate++)
		{
			display(sdate);
			DelayM(3);
		}
		keyXZ();
	}
	DS18b20_init();
	DS18b20_w_byte(0xcc);         		//发送Skip ROM命令
    DS18b20_w_byte(0xbe);         		//读温度寄存器(头两个值分别为温度的低和高位
	tempL=DS18b20_r_byte();    			//读温度低字节	
	tempH=DS18b20_r_byte();    			//读温度高字节
	t=tempH;
	t<<=8;
	t|=tempL;
	tt=t*0.0625;
	DS18b20_temp=tt*10+0.5;
	return(DS18b20_temp); 
}
//以下为EEPROM所用子函数
//起始信号
void start()
{
	sda=1;
	delay();
	scl=1;
	delay();
	sda=0;
	delay();
	scl=0;
	delay();
}
//停止信号
void stop()
{
	sda=0;
	delay();
	scl=1;
	delay();
	sda=1;
	delay();
}
//应答
void yingda()
{
	uchar i=0;
	scl=1;
	delay();
	while((sda==1)&&(i<250))i++;
	scl=0;
	delay();
}
//初始
void init()
{
	scl=1;
	delay();
	sda=1;
	delay();	
}
//写一个字节
void write_byte(uchar date)
{
	uchar i,temp;
	temp=date;
	for(i=0;i<8;i++)
	{
		temp=temp<<1;
		scl=0;
		delay();
		sda=CY;
		delay();
		scl=1;
		delay();	
	}
	scl=0;
	delay();
	sda=1;
	delay();
}
//读一个字节
uchar read_byte()
{	
	uchar i,j,k;
	scl=0;
	delay();
	sda=1;
	for(i=0;i<8;i++)
	{
		delay();
		scl=1;
		delay();
		if (sda==1) j=1;
		      else j=0;
		k=(k<<1)|j;
		scl=0;		
	}
	delay();
	return k;
}

void write_add(uchar dizhi,uchar date)
{
	start();
	write_byte(0xa0);
	yingda();
	write_byte(dizhi);
	yingda();
	write_byte(date);
	yingda();
	stop();
	EA=1;
	DelayM(5);
}

uchar read_add(uchar dizhi)
{	
	uchar date;
	start();
	write_byte(0xa0);
	yingda();
	write_byte(dizhi);
	yingda();
	start();
	write_byte(0xa1);
	yingda();
	date=read_byte();
	stop();
	DelayM(5);
	return date;
}
/*************************************************
**************************************************
下面是数码管所用的函数,包括闪烁和动态扫描
**************************************************
*************************************************/
//LED闪烁子函数
void flash()
{
	if(shans&&blink)
	{
		if(ledtime--==0)
		{
			if(!shanz) ledtime=mietime;
			else	ledtime=liangtime;
			shanz=~shanz;
		}
	}
	else shanz=0;
}

void display(uchar pos)	//按位显示函数POS表示第几位数码管
{
	bit sflag;
	duX=1;				//关显示
	P0=0x00;
	duX=0;

	duX=1;				
	sflag=(blink>>pos)&0x01;
	if(!sflag||(sflag&!shanz))
	{
		if(pos==2||pos==6)	P0=duma[buffer[pos]]|0x80;
		else	P0=duma[buffer[pos]];
	}
	else P0=0x00;
	duX=0;		

	weX=1;
	P0=wema[pos];		//送位码
	weX=0;	
}

void key()
{
	static uchar keycnt;						//按键年龄计数器
	static bit keyesc;							//按键释放置位标志
	funcnt=0x00;
	funval=0x00;
	if(keydone)									//上次按键任务已完成
	{
		if(K1==0&&K2&&K3&&K4) 	{funcnt++;funval=0x01;}
		else if(K2==0&&K1&&K3&&K4) {funcnt++;funval=0x02;}
		else if(K3==0&&K2&&K1&&K4) {funcnt++;funval=0x03;}
		else if(K4==0&&K2&&K1&&K3) {funcnt++;funval=0x04;}
	}
	if(!funcnt)//无键按下或上档键个数多于一个
	{	
		shans=1;
		keypre=0x00;
		keyesc=0x00;task=0x00;keycnt=0x00;
	}
	else	if(!keyesc)							//键已释放
	{
		if(funcnt>1) keyesc=1;
		else if(funval!=keypre)					//如果本次键值和上次不同
		{
			keypre=funval;						//用本次键值替换上次值
			keycnt=0x00;
		}
		else 
		{	
			keycnt++;
			switch(task)
			{
			case 0:
				if(keycnt==N)
				{
					shans=1;
					keyprocess=1;
					if(K1==0||K4==0) keyesc=1;
					else
					{			
						task++;
						keycnt=0;
					}			
				}
				break;
			case 1:
				if(keycnt==MaxRate)
				{
					shans=0;
					keyprocess=1;
					keycnt=0;
					task++;
				}
				break;
			case 2:
				if(keycnt==MinRate)
				{
					shans=0;
					keyprocess=1;
					keycnt=0;
				}
				break;
			}
		}
	}
}
//功能键处理
void key1()
{
	if(!keymark)
	{
		pb=&buffer[0];
		blink=0x01;
		keymark=1;
		shans=1;
	}
	else
	{
		pb++;
		blink<<=1;
		if(pb>=&buffer[4])
		{
			pb=&buffer[0];
			blink=0x01;
		}
	}
}
//*************************************//
void key2()
{	
	if(keymark)
	{
		*pb+=1;
		if(*pb>=0x0a)
			*pb=0x00;
	}
}

//*************************************//
void key3()
{

	if(keymark)
	{
		if(*pb<=0)	*pb=9;
		else		*pb-=1;
	}	
}
void key4()
{

	if(keymark)
	{
		blink=0x00;
		keymark=0;
		write_add(9,buffer[1]);
		write_add(10,buffer[2]);
		write_add(11,buffer[3]);
	}	
}

void keyXZ()
{
	if(keyprocess)
	{	
		keydone=0;
		keyprocess=0;
		switch(keypre)
		{
			case 0x01:key1();break;
			case 0x02:key2();break;
			case 0x03:key3();break;
			case 0x04:key4();break;
		}
		keydone=1;
	}
}
//*************************************//
/*********************************************
	功能:定时器0中断服务程序
*********************************************/
void timer0() interrupt 1
{
	TH0=V_TH0;
	TL0=V_TL0;
		flash();
		key();

}
void main()
{
	uint num=0;
	uchar a,b,c;
	uchar	n;

	TMOD=V_TMOD;TH0=V_TH0;TL0=V_TL0;
	TR0=1;ET0=1;EA=1;
	sdate=0x00;
	keyprocess=0;keydone=1;
	ledtime=liangtime;
	shanz=0;
	keymark=0;

	buffer[1]=read_add(9);
	buffer[2]=read_add(10);
	buffer[3]=read_add(11);
	while(1)
	{
		num1=buffer[1]*100+buffer[2]*10+buffer[3];
		num=DS18b20_readTemp();						//读温度并送显
		a=num/100;
		b=(num%100)/10;
		c=(num%100)%10;
		buffer[5]=a;
		buffer[6]=b;
		buffer[7]=c;
		for(n=0;n<5;n++)
		{
			for(sdate=0;sdate<=7;sdate++)
			{
				display(sdate);
				DelayM(3);
			}
			keyXZ();
		}
		if(num1>num) {led4=0,led8=1;}
		else	{led4=1,led8=0;}
	}
}


⌨️ 快捷键说明

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