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

📄 我的空调程序.c

📁 51单片机实现空调控制程序
💻 C
📖 第 1 页 / 共 2 页
字号:


#include <reg52.h>
#include <intrins.h>
#define uchar		unsigned char
#define uint     	unsigned int
#define	ulong		unsigned long
#define SYS_OK 			0
#define SYS_ERROR		1
#define DIS_SYS_WAIT	0x0
#define DIS_SYS_INPUT	0x10
#define DIS_VOID		0xFF
#define WAIT_cCurrTemp	0
#define WAIT_TIME		1
#define FLASH_SetTemp	0x18	// 0001 1000
#define	FLASH_PWM		0x06	// 0000 0110
#define DELAY_CLOSEDIS	5		//没按键,延时5秒关背光
#define DELAY_INPUT		5		//没按键,延时5秒返回显示温度
#define KEYCODE_UP		0x1		//加温度
#define KEYCODE_DOWN	0x2		//减温度
#define KEYCODE_FAN		0x4		//设置风速
#define KEYCODE_ONOFF 	0x8		//开关风机
#define KEYCODE_PWM		0xc		//设置PWM
#define WAIT_cCurrTemp	0
#define MAX_TEMP		32
#define MIN_TEMP		15

sbit bDQ 		= 	P1^0; 		// DS1820数据线
sbit bLED_light	=	P1^1;		// LED 背光驱动,低有效
sbit bKey1		=	P1^2;		// 键盘扫描线1,高有效
sbit bKey2		=	P1^3;		// 键盘扫描线2,高有效
sbit bKey3		=	P1^4;		// 键盘输入线1,低有效
sbit bKey4		=	P1^5;		// 键盘输入线2,低有效
sbit bFAN		=	P0^5;		// 开风机PWM, 低有效
sbit bAC_Zero	=	P3^2;		// 过零脉冲输入口
//uchar ucCount1;				// 记录过零脉冲宽度
uchar ucCount;					// 可控占空比0-95%宽度=10mS-ucCount1
uchar ucPWM; 					// 输出占空比
uchar bdata ucLED;
sbit bFAN_AUTO	= ucLED^3;
sbit bFAN_LOW	= ucLED^2;
sbit bFAN_MIN	= ucLED^1;
sbit bFAN_HIGH	= ucLED^0;
bit  bPowerON	= 0;			// 开机状态=1
uchar ucTimer;
/**************** LED显示相关变量 ********************/
//								  0,   1,   2,   3,   4,   5,   6,  7,   8,   9,   C,  度
const uchar code aucLEDNUMCODE[]={	0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x39,0x63};
const uchar code aucLEDcs[]={0x17,0x1b,0x1d,0x1e,0x0f};	//last one??????????/* LED位选 */  
uchar ucScanIndex;				/* 数码管位选控制 */
uchar ucLEDData[4];				/* 临时显示缓冲数组 */
uchar ucLEDFlash[5];			/* 显示缓冲数组 */
bit   bNeg;						/* 负号标志 */
uchar ucFlashType;
bit   bFlash;
uchar ucCurrSec;
uchar ucSystemStatus;
uchar ucDelaySec;				//切换延时秒数
uchar ucCloseDelaySec;			//关背光延时秒数

uchar aucTmpValue[2];
uchar ucFanSpeed;
char  cCurrTemp;
char  cSetTemp;
/**********************************************************************/
uchar ucLongDelay;				//长按键
uchar  ucDelayKey;
uint  nDelay100uS;
char  cKEYCode;
bit   bStill;
bit bUpdateDisOK;
//uchar x1;
//uchar x2;

/****************************** 函数声明 ******************************/
void SetFanStatus(void);
void DisposeKey(void);
void ScanLED(void);
uchar SCANKEY(void);
void DisplayTemp(char Temp);
void Key(uchar k);
void DisposeDelay(uchar LType);
void UpdateDis(uchar status);

/**********************************************************************/
bit Init_DS18B20(void)
{
	bit sysOK = 0;
	bDQ = 0;    				// 单片机将DQ拉低
	nDelay100uS = 6;
	while(nDelay100uS);			// 精确延时 大于 500us
	bDQ = 1;    				// 拉高总线
	nDelay100uS = 4;
	while(bDQ && nDelay100uS);	// 稍做延时后 如果bDQ=0则初始化成功 bDQ=1则初始化失败
                                //bDQ=1???????????????????????????????????????????
	if(nDelay100uS != 0)
	{
		nDelay100uS = 4;
		while(~bDQ && nDelay100uS);
		if(nDelay100uS != 0)
		{
			sysOK = 1;			// 在延时时间内18B20有应答证明初始化成功
		}
	}
	return(sysOK);
}

/**********************************************************************/
char ReadOneChar(void)
{
	uchar i;
	uchar j;
	uchar dat = 0;
	for (i=8; i>0; i--)
	{
		bDQ = 0; 			// 给脉冲信号
		bDQ = 0;
		dat >>= 1;
		bDQ = 1; 			// 给脉冲信号
		if(bDQ)
		{
			dat |= 0x80;
		}
		j = 8;			 	// 延时15~30uS后再读下一位数据
		while(j--)
		{
		}
	}
	return(dat);
}

/**********************************************************************/
void WriteOneChar(uchar dat)
{
	uchar i, j;
	for (i = 8; i > 0; i--)
	{
		bDQ = 0;
		bDQ = 0;
		bDQ = dat & 0x01;
		j = 8;			 	// 保持数据电平15~30uS
		while(j--)
		{
		}
		bDQ = 1;
		dat >>= 1;
	}
}

/**********************************************************************/
char ReadTemperature(void)
{
	bit f;
	union UniTEMP							
	{
		uint  T;
		uchar T_byte[2];
	}idata uT;
	
	f=Init_DS18B20();			
	if(f != 0)					// 18B20初始化成功?
	{
		ET0 = 0;
		ET1 = 0;
		WriteOneChar(0xCC); 	// 跳过读序号列号的操作
		WriteOneChar(0xBE); 	// 读取温度寄存器等(共可读9个寄存器) 前两个就是温度
		uT.T_byte[1] = ReadOneChar();
		uT.T_byte[0] = ReadOneChar();
		ET0 = 1;
		ET1 = 1;
	}
	else
	{
		return(99);
	}
	f = Init_DS18B20();
	if(f != 0)
	{
		ET0 = 0;
		ET1 = 0;
		WriteOneChar(0xCC); 	// 跳过读序号列号的操作
		WriteOneChar(0x44); 	// 启动温度转换
 		nDelay100uS = 1100;		// 等待AD转换结束9位AD约100mS
		ET0 = 1;
		ET1 = 1;
	}
	else
	{
		return(99);
	}
	bNeg = 0;
	if((uT.T_byte[0] & 0x80) != 0)// 负数标志位为1?
	{
		uT.T = ~uT.T+1;			// 转换成正数
		bNeg = 1;				// 负数标志置位
	}
	uT.T += 8;					// 四舍五入
	uT.T >>= 4;					// 取整
	return(uT.T_byte[1]);
}

/********************* 初始化变量 **********************/
void INITVar(void)
{
	ucSystemStatus = DIS_SYS_WAIT;//=0 //系统初始状态
	ucFlashType = WAIT_cCurrTemp;//=0  //初始闪烁方式
	bPowerON = 1;
	ucFanSpeed = 4;				//风扇自动4/停止0
	cSetTemp = 24;				//初始设定温度
	cCurrTemp = -1;				//默认温度=-1
}

//char code DX516[3] _at_ 0x3b;	//保留0x3b开始的3个字节
/****************************** 主函数 *********************************/
void main() 
{
	TMOD = 0x11;
	TH0 = -30;					// 定时器0
	TL0 =39;					// 定时中断
	TR0 = 1;
	ET0 = 1;
	TH1 = -3;					// 定时器1
	TL1 = 0;					// 定时中断
	TR1 = 1;
	ET1 = 1;
	EA  = 1;
//	IP=8;

	Init_DS18B20();
	if(Init_DS18B20())
	{					   	
		bLED_light = 0;			// 开机DS18B20正常就开背光
		ucCloseDelaySec = 3;	// 延时3秒关背光
	}
	WriteOneChar(0xCC); 		// 跳过读序号列号的操作
	WriteOneChar(0x44); 		// 启动温度转换
	nDelay100uS = 1100;			// 等待AD转换结束9位AD约100mS

	INITVar();                   //初始化变量
	while(1)
	{
		if(nDelay100uS == 0)     //nDelay100us是和18b20采集温度相关的延时控制
		{                        //延时时间到,启动温度转换
			cCurrTemp = ReadTemperature();
			if(ucFlashType != FLASH_PWM)
			{
				SetFanStatus();
			}
		}

		if(cKEYCode != 0)
		{
			DisposeKey();	//处理键盘数据
		}

		UpdateDis(ucSystemStatus);  //????????/

		if(ucDelaySec == 0)
		{
			DisposeDelay(ucSystemStatus);//处理延时
		}

		if(ucCloseDelaySec == 0)
		{
			bLED_light = 1;		//关背光
		}
	}	
}

/***************** 定时器1中断:多任务分时处理 **************************/
void timer1() interrupt 3			//约840uS中断1次,11次约为10mS,即100Hz波的1个周期
{
	TH1 = -3;						//定时器1重装
//////////////////// 任务1:PWM输出 //////////////////////////////////
	if(bAC_Zero == 0)
	{
		if(ucCount < 100)           //可控占空比0-95%宽度=10mS-ucCount1
		ucCount += 5;				// 定时器1中断记数有效控制宽度
//		if(ucCount1)
//		{
//			x1 = ucCount1;
//			ucCount1 = 0;
//		}
	}
	else
	{
//		ucCount1++;					// 定时器1中断记数过零脉冲宽度
//		if(ucCount)
//		{
//			x = ucCount;
			ucCount = 0;
//		}
	}
	if(ucCount <= 100 - ucPWM)
	{
		bFAN = 1;
	}
	else
	{ 
		bFAN = 0;
	}
///////////////////// 任务2:显示刷新 ////////////////////////
	ScanLED();
///////////////////// 任务3:延时 ////////////////////////////
	if(nDelay100uS)
	{
		nDelay100uS--;
	}
}

/***************** 定时器0中断:多任务分时处理 **************************/
void timer0() interrupt 1			// 1/240秒中断1次,240次为1S
{
	TL0 = 39;
	TH0 = -30;
///////////////////// 任务1:秒处理 /////////////////////
	ucTimer++;						// 定时器0中断次数记数
	if(ucTimer == 240)
	{			
		ucTimer = 0;
		ucCurrSec++;
		if(ucDelaySec)
		{
			ucDelaySec--;
		}
		if(ucCloseDelaySec != 0)
		{
			ucCloseDelaySec--;
		}
	}					
/////////////////// 任务2:闪烁 ////////////////////////////////
	if(ucTimer == 120||ucTimer == 0)// 半秒切换闪烁
	{
		bFlash = !bFlash;
	}
/////////////////// 任务3:按键扫描 ////////////////////////////
	if(ucDelayKey == 0)				// 若刚才没按键则扫描按键
	{
		if(SCANKEY() != 0)			// 若有按键动作
		{
			ucDelayKey = 3;			// 设置延迟时间消颤约12mS
		}
		else
		{
			bStill = 0;				// 松键状态标志
		}
	}
	else		   					// 有按键利用DelayKey按键消颤
	{
		if(--ucDelayKey == 0)		// 消颤或延时时间到?
		{
			bLED_light = 0;			// 开背光

⌨️ 快捷键说明

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