用遙控器控制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系列的單片機.