📄 p87lpc764+万能遥控调光调速器.c
字号:
//P87LPC764+万能遥控调光调速器
//2006年11月
//Philips公司的51LPC系列
/*
一概述
本产品能实现白炽灯及各种灯具的控制手控遥控均可实现相同功能
其最大特点是不需特定遥控器对任何遥控器的任何按键都可以学习后进行操
作所以具有很大的灵活性及实用性
二使用说明
1 产品设置
1 10A 红外线遥控开关CPU 第19 脚接地20 脚悬空可选择可控硅或继电器
2 800W 红外线调光开关CPU 第19 20 脚均悬空
3 500VA 风机红外线调速CPU 第19 脚悬空20 脚接地
2 红外学习
1 10A 遥控开关学习方式为持续按下手控按钮4 秒钟进入学习状态指
示灯闪烁按下遥控器上的某个指定键指示灯闪烁两下学习成功
不按遥控键10 秒后开关进入正常状态
2 其他两种产品的学习方式为连续点击两下后持续按住进入学习状态后同
3 操作说明
1 10A 红外线遥控开关按一次键改变工作状态一次] 即开变关或关变开
2 800W 红外线调光开关
点动一次关渐亮到上一次调定的亮度亮渐暗到最小亮度后关断
连续两次点动关立即达到前一次亮度亮立即熄灭
持续按住亮度逐渐增加合适即可放开
点动后再持续按住亮度逐渐减小合适即可放开
3 500VA 风机红外线调速
点动一次关中速启动5 秒后逐渐转变为上次调定的转速转动断电
持续按住逐渐增加转速到合适放开按钮
点动后再持续按住逐渐减小转速到合适放开按钮
*/
#include <REG764.H> //87LPC768寄存器定义头文件
#include <stdio.h>
#include <intrins.h>
#define AngleLimit 300 /*消除相角误差*/
#define SpeedLimit 700 /*控制最高和最低速度*/
/* 以控制u i 之间的相位差*/
sbit SDA=P1^2;
sbit SCL=P1^3;
sbit Led=P0^7;
sbit Key=P1^1;
sbit FIRE=P1^6;
sbit CtlLamp=P0^1;
sbit NO_R_SW=P0^2;
sbit SW=P1^0;
/*预留堆栈*/
unsigned char bdata SP1;
unsigned char bdata SP2;
unsigned char bdata SP3;
unsigned char bdata SP4;
unsigned char bdata SP5;
unsigned char bdata SP6;
unsigned char bdata SP7;
unsigned char bdata SP8;
unsigned char bdata FLAG;
sbit ON=FLAG^0;
sbit KeyDown=FLAG^1; /*用于识别按键口线为1 时,是否被按下过*/
sbit CONTI=FLAG^2; /*标志键被持续按下*/
sbit Task_Ovr=FLAG^3; /*任务处理标志*/
sbit FuncSet=FLAG^4; /*功能处理标志*/
sbit KeyStart=FLAG^5; /*键识别周期开始标志*/
sbit IsStudy=FLAG^6; /*红外学习标志*/
sbit StudyOK=FLAG^7; /*红外学习成功标志*/
unsigned char bdata FLAG1;
sbit RmtOK =FLAG1^0; /*遥控键正确识别标志*/
sbit CONTI_R=FLAG1^1; /*遥控键被持续按下*/
sbit RKeySt1=FLAG1^2; /*遥控键状态1*/
sbit RKeySt2=FLAG1^3; /*遥控键状态2*/
sbit RmtStart=FLAG1^4;
unsigned char data AGE; /*按键年龄*/
unsigned char data SwStyTime; /*开关状态时,按键按下时间*/
unsigned char data FuncCode; /*功能代码*/
unsigned char data DownTimes; /*按键连击次数*/
unsigned int data Fire_Angle;
unsigned int data MaxFireAngle; /*交流电半周期值对应的定时器值*/
unsigned int Last_FireAngle;
unsigned char data IRCLK; /*遥控识别计时时间,在过零中断每10ms 增1*/
unsigned char data IKCLK; /*键识别时间,在过零中断每10ms 增1*/
unsigned char data Buf[50];
unsigned char data Buf1[2];
void Delay(unsigned int);
int WriteEE(unsigned char SubAdr,unsigned char Num,unsigned char *Wbuf);
int ReadEE(unsigned char SubAdr,unsigned char Num,unsigned char *Rbuf);
unsigned char ReadByte();
int SendByte(unsigned char);
void Start(void);
void Stop(void);
void SendACK(void);
void SendNoACK(void);
void WDFeed(void);
void Task_10ms(void);
void FuncHandle(void);
void Calc_MaxFireAngle(void);
void Read_Last_FireAngle(void);
void Write_FireAngle(void);
void Read_MaxFireAngle(void);
void Write_MaxFireAngle(void);
unsigned char Get_L_Width();
unsigned char Get_H_Width();
/*定时器0 中断服务程序,用于可控硅点火*/
void Service_Timer0() interrupt 1
{
FIRE=0; /*产生点火脉冲*/
FIRE=0;
FIRE=0;
FIRE=1;
FIRE=1;
FIRE=1;
FIRE=0; /*产生点火脉冲*/
FIRE=0;
FIRE=0;
FIRE=1;
FIRE=1;
FIRE=1;
FIRE=0; /*产生点火脉冲*/
FIRE=0;
FIRE=0;
FIRE=1;
FIRE=1;
FIRE=1;
TR0=0; /*关闭定时器,禁止中断*/
ET0=0;
}
/*外部中断1 服务程序,用于遥控操作*/
void Service_Int1() interrupt 2
{
unsigned char data i,j,k;
EX1=0;
if(IsStudy==0){
/*遥控识别*/
if(StudyOK==1) goto Int1_reti;/*等待处理学习结果*/
if(FuncSet==1) goto Int1_reti;/*等待功能处理*/
if(CONTI_R==1) goto Int1_reti;/*持续按键,不再进行码识别*/
while(IRCLK<100){
WDRST=0X1E;
WDRST=0XE1; /*清除看门狗*/
RmtOK=1;
TH1=TL1=0;
TR1=1; /*启动定时器*/
while(INT1!=1);
TR1=0;
/*宽度小于0.25ms,是干扰脉冲*/
if(TH1==0 && TL1<120) {
if(RmtStart)
goto Ignore;
else
goto Int1_reti;/*干扰脉冲,且为首次,退出中断*/
}
j=(TH1*256+TL1 )/250;
j/=2;
if(j!=Buf[0]) break;
k=Get_H_Width();
if(k!=Buf[1]) break;
for(i=1;i<25;i++){
j=Get_L_Width();
k=Get_H_Width();
if(k==255) break;/*检测到255,不再比较*/
if(j!=Buf[2*i]) {RmtOK=0;break;}
if(k!=Buf[2*i+1]) {RmtOK=0;break;}
}
if(RmtOK==0) break;
/*是遥控开关,设定状态,退出*/
if(!NO_R_SW){
RKeySt1=1;
RKeySt2=0;
IRCLK=120;
i=250; /*延迟250ms*/
while(i--) for(j=0;j<125;j++);
break;
}
if(RKeySt1==0 && RKeySt2==0)
{RmtStart=1;IRCLK=0;RKeySt1=1;RKeySt2=0;}/*开始计时*/
/*接收成功,更新状态*/
else {RKeySt1=0;RKeySt2=1;}
/*检测连续按键*/
k=0;
while(k<8){
TF1=0;
TH1=TL1=0;
TR1=1; /*启动定时器*/
while(INT1!=0){
WDRST=0X1E;
WDRST=0XE1; /*清除看门狗*/
if(TF1==1) break;
}
TR1=0;
if(TF1==1) break;
j=(TH1*256+TL1)/250;
if(j<50) continue;/*间隔>25ms,表示为下一帧信号*/
/*获取低电平宽度(抗干扰)*/
TH1=TL1=0;
TR1=1;
while(INT1!=1);
TR1=0;
if(TH1>0 || TL1>120) k++; /*干扰脉冲不计数*/
}
if(k>7){
CONTI_R=1;
goto Int1_reti;
}
else
CONTI_R=0;
Ignore:
while(INT1){ /*等待INT1 变低*/
WDRST=0X1E; /*清看门狗*/
WDRST=0XE1;
if(IRCLK>120) goto Int1_reti;
}
}
}
else{
/*红外学习*/
if(StudyOK==1) goto Int1_reti;/*等待处理学习结果*/
EA=0;
for(i=0;i<25;i++){
Buf[2*i]=Get_L_Width();
Buf[2*i+1]=Get_H_Width();
}
for(i=0;i<6;i++) WriteEE(i*8,8,Buf+i*8);/*写学习结果*/
WriteEE(48,2,Buf+48);
EA=1;
i=150; /*延迟150ms 滤除后续信号*/
while(i--) for(j=0;j<125;j++);
StudyOK=1; /*置完成标志*/
}
Int1_reti:
EX1=1;
}
/*比较器中断,检测过零,作为相移控制的起始点(每10ms 中断一次)*/
void Service_Cmp1() interrupt 12
{
CMP1 &= 0xFE; /*清比较器1 中断标志*/
/*根据触发角设置时间常数*/
TH0= -(Fire_Angle)/256;
TL0=-(Fire_Angle)%256;
if(ON==1){
TR0=1; /*启动定时器0,开定时器0 中断*/
ET0=1;
}
else{
TR0=0;
ET0=0;
}
Task_Ovr=1; /*设置任务进程*/
if(RmtStart) IRCLK++; /*遥控识别计时时间+*/
/*以下处理按键*/
if(KeyStart){
IKCLK++; /*计时*/
if(Key==0){
KeyDown=1; /*键已按下*/
AGE++; /*按键年龄增长*/
if(NO_R_SW){ /*不是遥控开关,才能设置为持续方式*/
if(AGE>=30){
CONTI=1;
goto retu;
}/*按下按键超过0.3s,为持续方式*/
}
else{/*开关模式下,按下2.5s 进行红外学习*/
if(AGE==50) SwStyTime++;
if(SwStyTime==6){
SwStyTime=0;
CONTI=1;
DownTimes=2;
IKCLK=120;
goto retu;
}
}
}
else{
if(KeyDown==1 && AGE>=3 && AGE<=30){
DownTimes++;
if(!NO_R_SW) IKCLK=120; /*是遥控开关,立即执行功能*/
}
KeyDown=0; /*键已释放*/
AGE=0; /*按键弹起时,清除年龄*/
SwStyTime=0;
CONTI=0; /*清除持续标志*/
}
}
if(Key==1) CONTI=0; /*键已释放,清除持续标志*/
retu:;
}
/*主程序*/
main()
{
WDFeed(); /*清看门狗*/
WDCON=0X16; /*设置看门狗*/
/*初始化比较器,用于过零检测,Vref=5V*/
CMP1 &= 0xFE; /*清比较器中断标志*/
PT0AD=0X30; /* 禁止CN1A,CMPREF 作为数字输入口 */
P0M2 &= 0XCF; /* 禁止CN1A,CMPREF 作为数字输出口*/
P0M1 |= 0X30; /*开放比较器功能*/
CMP1=0X24; /*CHN1A 作为比较器正输入端,CMPREF 为参考电压,比较结果送CMP1*/
Delay(1); /*延时1ms*/
CMP1 &= 0xFE; /*清比较器1 中断标志*/
EC1=1;/*使能比较器一中断*/
/*设置定时器*/
TMOD=0X11; /*定时器0,1 方式1*/
IT1=1; /*外部中断1 为边沿触发方式*/
EX1=1;
Led=0; /*LED ON*/
Calc_MaxFireAngle(); /*计算半周期对应的定时器值*/
Write_MaxFireAngle();
IP1H=0X20; /*比较器1 中断最高优先级*/
ReadEE(0,50,Buf);
Read_Last_FireAngle(); /*从存储器中读出上一次的速度(亮度)值*/
Fire_Angle=Last_FireAngle;
EA =1; /*开中断*/
do{
WDFeed(); /*清看门狗*/
ReadEE(0,50,Buf); /*循环读出,加强抗干扰能力*/
Read_MaxFireAngle();
if(Task_Ovr==1) Task_10ms();
if(FuncSet==1) FuncHandle();
}while(1);
}
/*任务处理,由电压过零激活*/
void Task_10ms()
{
if(KeyStart==0 && Key==0){/*检测键处理周期中的第一次按键*/
AGE=0; /*清除按键年龄*/
IKCLK=0; /*清除识别计时器*/
DownTimes=0; /*清除击键次数*/
KeyStart=1; /*开始进行按键处理*/
}
if(IKCLK<100) goto Remote;/*未完,等待下一次任务*/
if(CONTI==0) /*识别时间完,设置功能代码*/
FuncCode=DownTimes;
else
FuncCode=DownTimes+4;
FuncSet=1; /*允许进行功能处理*/
IKCLK=0;
DownTimes=0;
KeyStart=0; /*关闭按键处理*/
goto Task_Ret;
Remote:
if(IRCLK<100) goto Task_Ret;
IRCLK=0;
if(CONTI_R){
if(RKeySt1) FuncCode=4;
else if(RKeySt2) FuncCode=5;
else FuncCode=0;
}
else{
if(RKeySt1) FuncCode=1;
else if(RKeySt2) FuncCode=2;
else FuncCode=0;
}
RKeySt1=0; /*清除状态*/
RKeySt2=0;
RmtStart=0;
FuncSet=1; /*允许进行功能处理*/
Task_Ret:
Task_Ovr=0; /*清任务进程标志*/
}
void FuncHandle()
{
unsigned char data i;
switch(FuncCode){
case 1: /*点击一次*/
if(!NO_R_SW){ /*遥控开关*/
if(ON){
ON=0;
Led=0;
SW=1;
}
else{
Fire_Angle=AngleLimit;/*可控硅全导通*/
ON=1;
Led=1;
SW=0;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -