用遥控器控制pwm信号占空比的幅度。
//****************************************
//定义 STC12C2052 系列 PCA/PWM寄存器列表。
sfr CCON =0xd8;
sfr CMOD =0xd9;
sfr CCAPM0 =0xda;
sfr CCAPM1 =0xdb;
sfr CCAPM2 =0xdc;
sfr CCAPM3 =0xdd;
sfr CL =0xe9;
sfr CH =0xf9;
sfr CCAP0L =0xea;
sfr CCAP0H =0xfa;
sfr CCAP1L =0xeb;
sfr CCAP1H =0xfb;
sfr CCAP2L =0xec;
sfr CCAP2H =0xfc;
sfr CCAP3L =0xed;
sfr CCAP3H =0xfd;
sfr PCA_PWM0=0xf2;
sfr PCA_PWM1=0xf3;
sfr PCA_PWM2=0xf4;
sfr PCA_PWM3=0xf5;
//*****************************************
//***************************
sbit CR =CCON^6;
//***************************
unsigned char PWM_ZKB; //设置外部变量,对PWM占空比进行微调改变。
//*******************************
//关于红外线遥控器的一些定义。
#define uchar unsigned char
#define uint unsigned int
#define IR_RE P3_2
bit k=0; //红外解码判断标志位,为0则为有效信号,为1则为无效
uchar date[4]={0,0,0,0}; //date数组为存放地址原码,反码,数据原码,反码
//*******************************
/*--------------------------延时1ms程子程序-----------------------*/
delay1000()
{
uchar i,j;
i=200;
do{j=13;
do{j--;}
while(j);
i--;
}while(i);
}
//****************************************
/*---------------------------延时882us子程序-----------------------*/
delay882()
{
uchar i,j;
i=84;
do{j=30;
do{j--;}
while(j);
i--;
}while(i);
}
/*--------------------------延时2400us程子程序-----------------------*/
delay2400()
{
uchar i,j;
i=200;
do{j=34;
do{j--;}
while(j);
i--;
}while(i);
}
//**************************************************************
//**************************************************************
/*----------------------------------------------------------*/
/*-----------------------红外解码程序(核心)-----------------*/
/*----------------------------------------------------------*/
void IR_decode()
{
uchar i,j;
while(IR_RE==0);
delay2400();
if(IR_RE==1) //延时2.4ms后如果是高电平则是新码
{
delay1000();
delay1000();
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
while(IR_RE==0); //等待地址码第1位高电平到来
delay882(); //延时882us判断此时引脚电平
///CY=IR_RE;
if(IR_RE==0)
{
date[i]>>=1;
date[i]=date[i]|0x00;
}
else if(IR_RE==1)
{
delay1000();
date[i]>>=1;
date[i]=date[i]|0x80;
}
} //1位数据接收结束
} //32位二进制码接收结束
}
}
//*****************************************************************
//********************************************************************
/*------------------------外部中断0程序-------------------------*/
/*------------------主要用于处理红外遥控键值--------------------*/
void int0() interrupt 0
{
uchar i;
k=0;
EX0=0; //检测到有效信号关中断,防止干扰
for(i=0;i<4;i++)
{
delay1000();
if(IR_RE==1){k=~k;} //刚开始为9ms的引导码.
}
if(k==0)
{
// EX0=0; //检测到有效信号关中断,防止干扰
IR_decode(); //如果接收到的是有效信号,则调用解码程序
}
delay2400();
delay2400();
delay2400();
EX0=1; //开外部中断,允许新的遥控按键
}
//*********************************************************************
//***************************
//PCA计数器初始化程序。
void PCA_INIT()
{
CMOD=0x80; //PCA在空闲模式下停止。PCA时钟模式为fose/12.禁止PCA计数器溢出中断。
CCON=0x00; //禁止PCA计数器工作,清除中断标志、计数器溢出标志。
CL =0x00; //清0计数器。
CH =0x00;
//---------------
//设置模块0为8位PWM输出模式。
CCAPM0 =0x42;
PCA_PWM0=0x00;
//----------------
CR=1; //将PCA计数器打开。
}
//**************************
//******************************
//主函数。
void main()
{
SP=0x60;
PCA_INIT(); //PCA计数器的初始化。
EX0=1; //开外部中断。
EA=1;
//----------------------------------
//用红外线遥控器的若干按键微调PWM信号占空比。
while(1)
{
if(date[2]==0x0c) //确定一个固定占空比的PWM信号。
{
delay2400();
PWM_ZKB =0x80;
CCAP0H =PWM_ZKB;
date[2] =0xff;
}
if(date[2]==0x19) //微调PWM占空比。
{
delay2400();
if(PWM_ZKB>0xf0)
{
PWM_ZKB=0xf9;
CCAP0H =PWM_ZKB;
}
else
{
PWM_ZKB +=0x05; //由于设置PWM的寄存器是8位的,最小是0x00,最大是0xff.那么微调的
//设置是一次加0x05.
CCAP0H =PWM_ZKB;
}
date[2]=0xff;
}
if(date[2]==0x1d)
{
delay2400();
if(PWM_ZKB<0x10)
{
PWM_ZKB =0x09;
CCAP0H =PWM_ZKB;
}
else
{
PWM_ZKB -=0x05;
CCAP0H =PWM_ZKB;
}
date[2]=0xff;
}
}
}
//总结:此观点是我个人的看法:由于本人用的是STC12C5410单片机速度相对51系列是很快的,
//所以在遥控器解码的程序段上面我适当加了一些延迟
//例如:
// if(date[2]==0x1d)
// {
// delay2400();
//如果不加延迟,单片机就无法去执行以下的程序段(我在实验时已经验证过了)。所以我归纳
//是单片机速度太快而导致的原因。
//以上程序适宜使用STC5410系列的单片机.