一.PCA寄存器的資料
1,stc12c5a60s2一般pwm頻率=PCA時鐘源/256
2,PCA時鐘源設置有4種方式,一般都有T0的溢出率,來設置PCA時鐘源,
一般在COMD這個寄存器的B2,B1兩位來確定是那種方式,10方式就是T0溢出方式(1T更快),可以做可變PCA時鐘源時鐘源,從而得到可變頻率的pwm輸出。
3,理論可生成(1-65535)個頻率級別,如12MHz主頻,(1T)方式最小可以做到12MHz,但實際是到了的最快也就是1/2SYsclk,即6MHz,然後除以256,理想可以輸出23Khz~0.5Hz左右的頻率範圍
在8位單片機C語言編程中,sfr用來定義特殊功能寄存器,一般佔一個字節,8位;sbit用來定義特殊功能寄存器中可以位尋址的位,佔1位。
在51單片機中,特殊功能寄存器只有16進制地址尾數爲0或者8,其包含的各個位纔可以位尋址。
sfr CCON = 0xD8; //PCA 控制寄存器。 CF CR - - - - CCF1 CCF0 00xx,xx00
//-----------------------
sbit CF = CCON^7; //PCA計數器溢出標誌,由硬件或軟件置位,必須由軟件清0。
sbit CR = CCON^6; //1:允許 PCA 計數器計數, 必須由軟件清0。
//-
//-
sbit CCF1 = CCON^1; //PCA 模塊1 中斷標誌, 由硬件置位, 必須由軟件清0。
sbit CCF0 = CCON^0; //PCA 模塊0 中斷標誌, 由硬件置位, 必須由軟件清0。
//-----------------------
sfr CMOD = 0xD9; //PCA 工作模式寄存器。 CIDL - - - CPS2 CPS1 CPS0 ECF 0xxx,x000
/*
CIDL: idle 狀態時 PCA 計數器是否繼續計數, 0: 繼續計數, 1: 停止計數。
CPS2: PCA 計數器脈衝源選擇位 2。
CPS1: PCA 計數器脈衝源選擇位 1。
CPS0: PCA 計數器脈衝源選擇位 0。
CPS2 CPS1 CPS0
0 0 0 系統時鐘頻率 fosc/12。
0 0 1 系統時鐘頻率 fosc/2。
0 1 0 Timer0 溢出。
0 1 1 由 ECI/P3.4 腳輸入的外部時鐘,最大 fosc/2。
1 0 0 系統時鐘頻率, Fosc/1
1 0 1 系統時鐘頻率/4,Fosc/4
1 1 0 系統時鐘頻率/6,Fosc/6
1 1 1 系統時鐘頻率/8,Fosc/8
ECF: PCA計數器溢出中斷允許位, 1--允許 CF(CCON.7) 產生中斷。
*/
//-----------------------
sfr CL = 0xE9; //PCA 計數器低位 0000,0000
sfr CH = 0xF9; //PCA 計數器高位 0000,0000
//-----------------------
// 7 6 5 4 3 2 1 0 Reset Value
sfr CCAPM0 = 0xDA; //PCA 模塊0 PWM 寄存器 - ECOM0 CAPP0 CAPN0 MAT0 TOG0 PWM0 ECCF0 x000,0000
sfr CCAPM1 = 0xDB; //PCA 模塊1 PWM 寄存器 - ECOM1 CAPP1 CAPN1 MAT1 TOG1 PWM1 ECCF1 x000,0000
//ECOMn = 1:允許比較功能。
//CAPPn = 1:允許上升沿觸發捕捉功能。
//CAPNn = 1:允許下降沿觸發捕捉功能。
//MATn = 1:當匹配情況發生時, 允許 CCON 中的 CCFn 置位。
//TOGn = 1:當匹配情況發生時, CEXn 將翻轉。
//PWMn = 1:將 CEXn 設置爲 PWM 輸出。
//ECCFn = 1:允許 CCON 中的 CCFn 觸發中斷。
//ECOMn CAPPn CAPNn MATn TOGn PWMn ECCFn
// 0 0 0 0 0 0 0 0x00 未啓用任何功能。
// x 1 0 0 0 0 x 0x21 16位CEXn上升沿觸發捕捉功能。
// x 0 1 0 0 0 x 0x11 16位CEXn下降沿觸發捕捉功能。
// x 1 1 0 0 0 x 0x31 16位CEXn邊沿(上、下沿)觸發捕捉功能。
// 1 0 0 1 0 0 x 0x49 16位軟件定時器。
// 1 0 0 1 1 0 x 0x4d 16位高速脈衝輸出。
// 1 0 0 0 0 1 0 0x42 8位 PWM。
//ECOMn CAPPn CAPNn MATn TOGn PWMn ECCFn
// 0 0 0 0 0 0 0 0x00 無此操作
// 1 0 0 0 0 1 0 0x42 普通8位PWM, 無中斷
// 1 1 0 0 0 1 1 0x63 PWM輸出由低變高可產生中斷
// 1 0 1 0 0 1 1 0x53 PWM輸出由高變低可產生中斷
// 1 1 1 0 0 1 1 0x73 PWM輸出由低變高或由高變低都可產生中斷
//-----------------------
sfr CCAP0L = 0xEA; //PCA 模塊 0 的捕捉/比較寄存器低 8 位。 0000,0000
sfr CCAP0H = 0xFA; //PCA 模塊 0 的捕捉/比較寄存器高 8 位。 0000,0000
sfr CCAP1L = 0xEB; //PCA 模塊 1 的捕捉/比較寄存器低 8 位。 0000,0000
sfr CCAP1H = 0xFB; //PCA 模塊 1 的捕捉/比較寄存器高 8 位。 0000,0000
//-----------------------
// 7 6 5 4 3 2 1 0 Reset Value
sfr PCA_PWM0 = 0xF2; //PCA 模塊0 PWM 寄存器。 - - - - - - EPC0H EPC0L xxxx,xx00
sfr PCA_PWM1 = 0xF3; //PCA 模塊1 PWM 寄存器。 - - - - - - EPC1H EPC1L xxxx,xx00
//PCA_PWMn: 7 6 5 4 3 2 1 0
// - - - - - - EPCnH EPCnL
//B7-B2: 保留
//B1(EPCnH): 在 PWM 模式下,與 CCAPnH 組成 9 位數。
//B0(EPCnL): 在 PWM 模式下,與 CCAPnL 組成 9 位數。
/*******************************************************/
二.示例程序
pwm.c文件
#include "main.h"
unsigned char speed=0xff;//¿ØÖÆÕ¼¿Õ±ÈCCAP0H
unsigned char module=0;
sfr CCON = 0xD8; //PCA¿ØÖƼĴæÆ÷
sfr CMOD = 0xD9; //PCAģʽ¼Ä´æÆ÷
sfr CCAPM0 = 0xDA; //PCAÄ£¿é0ģʽ¼Ä´æÆ÷ //Ä£¿é0¶ÔÓ¦P1.3/CEX0/PCA0/PWM0(STC12C5A60S2??)
sfr CCAPM1 = 0xDB; //PCAÄ£¿é1ģʽ¼Ä´æÆ÷ //Ä£¿é1¶ÔÓ¦P1.4/CEX1/PCA1/PWM1(STC12C5A60S2??)
sfr CL = 0xE9; //PCA ¶¨Ê±¼Ä´æÆ÷µÍλ
sfr CH = 0xF9; //PCA ¶¨Ê±¼Ä´æÆ÷¸ßλ
sfr CCAP0L = 0xEA; //PCAÄ£¿é0µÄ²¶»ñ¼Ä´æÆ÷µÍλ
sfr CCAP0H = 0xFA; //PCAÄ£¿é0µÄ²¶»ñ¼Ä´æÆ÷¸ßλ
sfr CCAP1L = 0xEB; //PCAÄ£¿é1µÄ²¶»ñ¼Ä´æÆ÷µÍλ
sfr CCAP1H = 0xFB; //PCAÄ£¿é1µÄ²¶»ñ¼Ä´æÆ÷¸ßλ
sfr PCA_PWM0 = 0xF2; //PCA PWM ģʽ¸¨Öú¼Ä´æÆ÷0
sfr PCA_PWM1 = 0xF3; //PCA PWM ģʽ¸¨Öú¼Ä´æÆ÷1
sbit CF = 0xDF; //PCA¼ÆÊýÒç³ö±ê־λ CCON^7
sbit CR = 0xDE; //PCA¼ÆÊýÆ÷ÔËÐпØÖÆλ CCON^6
sbit CCF1 = 0xD9; //PCAÄ£¿é1Öжϱê־λ CCON^1
sbit CCF0 = 0xD8; //PCAÄ£¿é0Öжϱê־λ CCON^0
void pwm_clock(unsigned char clock)
{
CMOD |= (clock<<1);
CL = 0x00;
CH = 0x00;
}
void pwm_init(unsigned char module, unsigned char mode)
{
CCAP0L = 0xff;
CCAP0H = 0Xff; //Ä£¿é0³õʼÊä³ö Õ¼¿Õ±È0%
CCAP1L = 0Xff;
CCAP1H = 0Xff; //Ä£¿é1³õʼÊä³ö Õ¼¿Õ±È0%
if(module==0)//Ä£¿é0ÉèÖÃ
{
switch(mode)
{
case 0: CCAPM0 = 0X42;break; //8λPWMÊä³ö,ÎÞÖжÏ
case 1: CCAPM0 = 0X53;break; //8λPWMÊä³ö,ϽµÑØÖжÏ
case 2: CCAPM0 = 0X63;break; //8λPWMÊä³ö,ÉÏÉýÑØÖжÏ
case 3: CCAPM0 = 0X73;break; //8λPWMÊä³ö,Ìø±äÑØÖжÏ
default: break;
}
}
else
if(module==1)//Ä£¿é1ÉèÖÃ
{
switch(mode)
{
case 0: CCAPM1 = 0X42;break; //8λPWMÊä³ö,ÎÞÖжÏ
case 1: CCAPM1 = 0X53;break; //8λPWMÊä³ö,ϽµÑØÖжÏ
case 2: CCAPM1 = 0X63;break; //8λPWMÊä³ö,ÉÏÉýÑØÖжÏ
case 3: CCAPM1 = 0X73;break; //8λPWMÊä³ö,Ìø±äÑØÖжÏ
default: break;
}
}
else
if(module==2)//Ä£¿é0ºÍ1ÏàͬÉèÖÃ
{
switch(mode)
{
case 0: CCAPM0 = CCAPM1 = 0X42;break; //8λPWMÊä³ö,ÎÞÖжÏ
case 1: CCAPM0 = CCAPM1 = 0X53;break; //8λPWMÊä³ö,ϽµÑØÖжÏ
case 2: CCAPM0 = CCAPM1 = 0X63;break; //8λPWMÊä³ö,ÉÏÉýÑØÖжÏ
case 3: CCAPM0 = CCAPM1 = 0X73;break; //8λPWMÊä³ö,Ìø±äÑØÖжÏ
default: break;
}
}
CR=1; //PCA¼ÆÊýÆ÷¿ªÊ¼¼ÆÊý
}
void PCA_Intrrpt(void) interrupt 7
{
//Èí¼þÖÃÁã
if(CCF0) CCF0=0;//Ä£¿é0Öжϱê־λ
if(CCF1) CCF1=0;//Ä£¿é1Öжϱê־λ
if(CF) CF=0; //¼ÆÊýÒç³ö±ê־λ
if(flag==5)//¼ÓËÙ
{
if(module==1)
{
if(speed>64)
{
speed-=64;
CCAP0H=speed;
}
}
else
if(module==2)
{
if(speed>64)
{
speed-=64;
CCAP1H=speed;
}
}
flag=0;
}
else
if(flag==4)//¼õËÙ
{
if(module==1)//´Ëʱ¹¤×÷ÔÚÄ£¿é0ģʽ
{
if(speed<0xff)
{
speed+=64;
CCAP0H=speed;
}
}
else
if(module==2)//´Ëʱ¹¤×÷ÔÚÄ£¿é1ģʽ
{
if(speed<0xff)
{
speed+=64;
CCAP1H=speed;
}
}
flag=0;
}
}
void ir_pwm_pro()
{
if(flag==1)//Õýת
{
pwm_init(0,1); //¿ªÆôÄ£¿é0 ϽµÑØÖÐ¶Ï Í¬Ê±ÈÃÄ£¿é1Ò»Ö±Êä³öµÍµçƽ
module=1;//±íʾ¿ªÆôÄ£¿é0
speed=0xff;//³õʼËÙ¶ÈΪ0
CCAP1L = 0Xff;
CCAP1H = 0Xff;
CCAPM1=0x00;
flag=0;
}
if(flag==2)//·´×ª
{
pwm_init(1,1); //¿ªÆôÄ£¿é1 ͬʱÈÃÄ£¿é0Ò»Ö±Êä³öµÍµçƽ
module=2;//±íʾ¿ªÆôÄ£¿é1
speed=0xff;//³õʼËÙ¶ÈΪ0
CCAP0L = 0xff;
CCAP0H = 0Xff;
CCAPM0=0x00;
flag=0;
}
}
ir.c文件
#include "main.h"
unsigned char irtime=0;
unsigned char startflag=0; //´ú±í¿ªÊ¼½ÓÊÕ
unsigned char irdate[33]={0};
unsigned char IRcode[4]={0};//´æ´¢½ÓÊÕµ½µÄËÄ×éÊý¾Ý
unsigned char ir_revok=0; //´ú±í½ÓÊÕok
unsigned char ir_decodeok=0; //´ú±í½âÂëok
unsigned char flag=0;
void ISR_TIMER0(void) interrupt 1
{
irtime++;
}
void ISR_INT1() interrupt 2 //ÔÚÍⲿÖжϴ¦Àíº¯ÊýÖнÓÊÕºìÍâÐźţ¬¿ÉÑ¡INT0»òINT1
{
static unsigned char index = 0;
if(startflag==1)
{
if((irtime>33)&&(irtime<62)) //ÅжÏÊÇ·ñ³öÏÖÒýµ¼Âë
{
index=0;
}
irdate[index] = irtime;//³ýÒýµ¼ÂëÍâ½ÓÊÕµÄÊý¾ÝÖ»ÄÜÊÇ0ºÍ1
index++;
irtime = 0;
if(index == 33) //33´Î½ÓÊÕÍê³É
{
index=0;
ir_revok = 1;
}
}
else //µÚÒ»´Î½øÀ´
{
startflag = 1;
irtime=0;
}
}
void IR_Decode(void)
{
unsigned char i,j,k;
unsigned char cord, value;
k=1;
for(i=0; i<4; i++)
{
for(j=0; j<8; j++)
{
cord=irdate[k];
if(cord>7)
{
value |= 0x80;
}
if(j<7)
value >>= 1;
k++;
}
IRcode[i]=value;
value=0;
}
ir_decodeok =1; //½âÂëÍê³É¿ÉÒÔʹÓÃ
}
void ir_rev() //½ÓÊÕº¯Êý
{
if(1 ==ir_revok) //½ÓÊÕÍê³É
{
IR_Decode(); //¿ªÊ¼½âÂë
ir_revok =0;
}
if(1 ==ir_decodeok) //½âÂëÍê³É
{
switch(IRcode[2])
{
case 0x40: flag=1; break; //Ç°½ø
case 0x19: flag=2; break; //ºóÍË
//case 0x15: flag=3; break; //Í£Ö¹
case 0x7: flag=4; break; //¼õËÙ
case 0x9: flag=5; break; //¼ÓËÙ
default: break;
}
}
ir_decodeok =0;
}
timer.c文件
#include "main.h"
void TIMER0_INIT() //¶¨Ê±¼ÆÊýÆ÷0³õʼ»¯
{
TMOD = TMOD | 0x02; //¹¤×÷·½Ê½2 8λ×Ô¶¯ÖØ×°
TH0 = 0;
TL0 = 0;
ET0 = 1;//´ò¿ªÖжÏÔÊÐí¿ØÖÆλ
EA = 1;
TR0 = 1;
}
void TIMER1_INIT() //¶¨Ê±¼ÆÊýÆ÷T1³õʼ»¯,¹¤×÷·½Ê½1 16λ
{
TMOD = TMOD | 0x10;
TH1 =(65536 - 100) / 256;
TL1 =(65536 - 100) % 256;
ET1 = 1;//´ò¿ªÖжÏÔÊÐí¿ØÖÆλ
EA = 1;
TR1 = 1;
}
void INT0_INIT() //ÍⲿÖжÏ0³õʼ»¯;
{
//1.Ñ¡Ôñ´¥·¢·½Ê½ ϽµÑØ(1)µÍµçƽ(0);
IT0 = 1;
EX0 = 1;//´ò¿ªÖжÏÔÊÐí¿ØÖÆλ
EA = 1;
}
void INT1_INIT() //ÍⲿÖжÏ1³õʼ»¯;
{
//1.Ñ¡Ôñ´¥·¢·½Ê½ ϽµÑØ(1)µÍµçƽ(0);
IT1 = 1;
EX1 = 1;//´ò¿ªÖжÏÔÊÐí¿ØÖÆλ
EA = 1;
}
main.c文件
#include "main.h"
void main()
{
TIMER0_INIT();
TIMER1_INIT();
INT0_INIT();
INT1_INIT();
PWM_ON=0;
pwm_clock(2);//Timer0 Òç³ö
while(1)
{
ir_rev();
ir_pwm_pro();
//ir_rev_pro();
}
}