用stc12c5a60s2單片機的PCA寄存器輸出PWM波,通過MX214B芯片控制直流電機



一.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();
   
  }

   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章