📄 pwm_tempctrl.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 + -