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

📄 pwm_tempctrl.c

📁 PWM温度控制的
💻 C
字号:
#include<AT89X52.H>
#define uchar unsigned char
#define uint unsigned int
#define KEYDELAYTIME 2000		//按加减键不放,连续变化的速度
#define SYS_OK 		0
#define SYS_ERROR	1
#define f0	   0.1

///////////////////////////////  AD  ///////////////////////////////////////////
bit firstT;						// 开机初次采样标志
char FirstWD;					// 环境温度
char WD;						// 加热温度
char SetTemp;					// 设置温度
uchar AntiCountTem;
uchar OldTB_T;
uchar ADTimer;
float OldTemp;
float WTemp;
bit AD_OK;
uchar PWM; 			
uint count;						/* 调节占空比0-99% */

union UniTEMP					// 温度采样值
{
	uint  TEMP;
	uchar TEMP_AD[2];
}idata uTEMP;
union UniREF					// 5V参考采样值
{
	uint REF;
	uchar REF_AD[2];
}idata uREF;

uint DelayKey;
uchar Key;
uchar LongDelay;
uchar KeyCode;
bit bStill;

uchar code segcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};/* 7段码 */
					/*	0	 1	  2    3    4    5    6    7    8    9 */	
uchar LEDCS[]={0xfe,0xfd,0xfb,0xf7}; 	/* LED位选 */
bit DisMode;							/* 显示模式 */
uchar LED[4];							/* LED显示缓冲区 */	
uchar LEDIndex;							/* LED位选指针 */
sbit bADRESET =P3^2; 					/* 三角波控制 */
sbit PWMLED=P2^3;						/* 加热控制(LED模拟) */

/***************************函数声明***********************************/
DisposePWM();
DisposeKey(uchar KeyCode);
void GetADValue();

/**********************************************************************/
Display()
{
	if(DisMode == 0)
	{
		LED[0]=segcode[WD/10];
		LED[1]=segcode[WD%10];
		LED[2]=segcode[SetTemp/10];
		LED[3]=segcode[SetTemp%10];
	}
	else
	{
		LED[0]=0x73;	   /* "P" 显示占空比*/
		LED[1]=0x40;	   /* "-" */
		LED[2]=segcode[PWM/10];
		LED[3]=segcode[PWM%10];
	}
}
/**********************************************************************/
void DisposeKey()
{
	switch(KeyCode)
	{
		case 0x06:	//KEYCODE_UP:
			if(SetTemp < 99)SetTemp++;
			DelayKey=2000; 		// 按住键不动可连续改变设置
			break;
		case 0x05:	//KEYCODE_DOWN:
			if(SetTemp > WD)SetTemp--;
			DelayKey=2000; 		// 按住键不动可连续改变设置
			break;
		case 0x03:	//KEYCODE_MODE:
			if(bStill == 0)
			{
				bStill = 1;
				DisMode = !DisMode;
			}
			break;
		default :break;
	}
}
/**********************************************************************/
DisposePWM()
{
	if(WD <SetTemp)PWM=100*(WD-FirstWD)/(SetTemp-FirstWD);
	else PWM = 99;
}
/*****************************每100uS定时中断************************************/
void t0() interrupt 1
{
	if(DelayKey==0)
	{
		Key = P2 & 0x07;   					//若没按键则扫描按键
		if(Key != 0x07)DelayKey=100;		// 设置延迟时间削颤
		else
		{
			bStill=0;
			LongDelay=0;
		}									// 松键
	}
	else		   							//有按键利用DelayKey按键消颤
	{
		DelayKey--;
		if(DelayKey==0)
		{
			KeyCode = P2 &0x07;				//取键值P20、P21、P22
			if(Key != KeyCode)
			{
				KeyCode = 0;				
			}
		}
	}

	P0=LED[LEDIndex];		   
	P2=LEDCS[LEDIndex];
	LEDIndex++;                       //循环点亮数码管
	LEDIndex &= 3;
	
	if(count++ == 100){count = 0;}	   /* 占空比 */
	if(count >= PWM)PWMLED = 0;
	else PWMLED = 1;
}
/***************************** 主函数初始化 ************************************/
void main()
{
	TMOD=0x12;
	TH0=-200;		/* 约每100uS定时中断 */
	IT0=0;
	TR0=1;
	TR1=1;
	ET0=1;
	EX0=1;
	EX1=1;
	EA=1;
	while(1)
	{
		if(AD_OK==SYS_OK)GetADValue();		// 采样记时器值后计算成AD值
		Display();
		if(KeyCode != 0)DisposeKey();		// 处理键盘数据
/////////////////////////////// AD定时器控制 ////////////////////////////////
		if(TH1>0xc0 && AD_OK==SYS_ERROR)
		{
			bADRESET=0;						// 三角波充电
			TL1=0;
			TH1=0;
		}
	   	if(TH1>0xa0){bADRESET=1;}			// 三角波放电
	}
}
void GetADValue()
{
	uchar TB;	
	float x,y,z;

	y=uREF.REF;
	x=uTEMP.TEMP;
	z=73.6 - 20 * (x * (5 - f0) / y + f0);

	if(firstT==SYS_OK)
	{
		firstT=SYS_ERROR;
		OldTB_T = FirstWD = z;
	}
	if(OldTemp-z < 1 && OldTemp-z>-1)		/* 相邻2次采样超过1度认为是突变数据 */
	{
		OldTemp=z;
		WTemp=(WTemp*7+z)/8;				/* 加权平均 */
		z=WD-WTemp;
		if(z >= 1.2 || z<=-1.2)
		{
			if(WTemp >= 0)WD = WTemp + 0.5;	/* 转换成整数 */
			else WD = WTemp - 0.5;
		}		
		AntiCountTem=0;
	}
	else 
	{
		TB=z;
		if(OldTB_T==TB)AntiCountTem++;
		if(AntiCountTem==2)
		{
			OldTemp=z;
			WTemp=z;
			AntiCountTem=0;
		}/* 记录突变 */
		else OldTB_T=TB;
	}
	AD_OK=SYS_ERROR;
	DisposePWM();
}
/* 外部中断1:5V参考电压中断 */
void Interrupt1() interrupt 2
{
	EX0=0;
	uREF.REF_AD[1]=TL1;
	uREF.REF_AD[0]=TH1;
	AD_OK=SYS_OK;
}
/* 外部中断0:温度电压中断 */
void Interrupt0() interrupt 0
{
	EX1=0;
	uTEMP.TEMP_AD[1]=TL1;
	uTEMP.TEMP_AD[0]=TH1;
}

⌨️ 快捷键说明

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