可以的
我給你來個范例程序試試
- /*------------------------------------------------------------------*/
- /* --- STC MCU International Limited -------------------------------*/
- /* --- STC 1T Series MCU Programme Demo ----------------------------*/
- /* --- Fax: 86-755-82944243 ----------------------------------------*/
- /* --- Tel: 86-0513-55012928,55012929,55012966----------------------*/
- /* If you want to use the program or the program referenced in the */
- /* article, please specify in which data and procedures from STC */
- /*------------------------------------------------------------------*/
- /* 本程序經過測試完全正常, 不提供電話技術支持, 如不能理解, 請自行補充相關基礎. */
- /*
- 功能: 使用STC內帶的PCA做9~16位的PWM。在PWMn.h中選擇是STC12C5201AD系列還是STC12C5A60S2系列。
- 原理說明:
- 本示例程序介紹在一些應用中所需要的高于8位分辨率的9~16位PWM,而8位的PWM可以直接使用STC的硬件PWM,請參考有關的的(Datasheet)。
- 本應用所需要資源:PCA可編程計數器陣列,捕獲寄存器,匹配中斷向量。
- 程序用到兩個16位變量:
- PWM_high 保存PWM輸出高電平的PCA時鐘數。
- PWM_low 保存PWM輸出低電平的PCA時鐘數。
- PWM的周期 = PWM_HIGH + PWM_LOW。
- PCA時鐘源有8種選擇。
- PCA模塊被配置為16位高速輸出方式,當PCA計數值與捕獲寄存器數值匹配時,將CCP0輸出取反,同時發生比較匹配中斷。
- 比較匹配中斷里判斷高速輸出的電平,如果是高電平,則向捕獲寄存器裝入高電平的PCA時鐘數。如果是低電平,則裝入低電平的PCA時鐘數。
- 由于中斷處理需要一點時間,所以輸出的占空比不能到0%或100%,所以對PWM_high有最小和最大值,中斷處理絕對時間大約為100個SYSCLK。
- 本示例程序的測試是基于如下假設:
- PCA時基信號為系統時鐘Fosc,PCA中斷優先級為最高。
- 提示:其它中斷服務開銷很長時間時,有可能會影響本程序的正常運行。
- 本示例程序用戶可以在"用戶配置宏"中選擇以下參數:
- PCA_IDLE_DISABLE 在IDLE模式是否禁止PCA工作,選擇1: MCU在IDLE模式時禁止PCA工作, 選擇0: MCU在IDLE模式時允許PCA工作。
- PCA_SOURCE_SELECT 選擇PCA的基準時鐘源,本示例使用系統時鐘Fosc做PCA時鐘源。
- PWM_DUTY 定義PWM的周期,數值為PCA所選擇的時鐘脈沖個數,用戶只需要裝載PWM_high,PWM_low是根據這個周期計算出來的。
- PWM_HIGH_MAX 限制PWM輸出的最大占空比,原因如前所述。如果裝載PWM_high大于此數值,將返回錯誤。
- PWM_HIGH_MIN 限制PWM輸出的最小占空比,原因如前所述。如果裝載PWM_high小于此數值,將返回錯誤。
- */
- #include "reg51.h"
- #define MAIN_Fosc 24576000L //定義時鐘
- #define PCA_IDLE_DISABLE 0 //1: MCU在IDLE模式時禁止PCA工作。 0: MCU在IDLE模式時允許PCA工作。
- #define PCA_SOURCE_SELECT 4 //選擇PCA的基準時鐘源。
- //0:系統時鐘Fosc/12。
- //1:系統時鐘Fosc/2。
- //2:定時器0的溢出。
- //3:ECI/P3.4腳的外部時鐘輸入(最大=Fosc/2)。
- //4:系統時鐘Fosc。
- //5:系統時鐘Fosc/4。
- //6:系統時鐘Fosc/6。
- //7:系統時鐘Fosc/8。
- #define PWM_DUTY 4096 //定義PWM的周期,數值為PCA所選擇的時鐘脈沖個數。
- /**********************************************************************************************************/
- sfr P_SW1 = 0xA2; //外設功能切換寄存器1
- #define CCP_S0 0x10 //P_SW1.4
- #define CCP_S1 0x20 //P_SW1.5
- sfr CCON = 0xD8; //PCA控制寄存器
- sbit CCF0 = CCON^0; //PCA模塊0中斷標志
- sbit CCF1 = CCON^1; //PCA模塊1中斷標志
- sbit CR = CCON^6; //PCA定時器運行控制位
- sbit CF = CCON^7; //PCA定時器溢出標志
- sfr CMOD = 0xD9; //PCA模式寄存器
- sfr CL = 0xE9; //PCA定時器低字節
- sfr CH = 0xF9; //PCA定時器高字節
- sfr CCAPM0 = 0xDA; //PCA模塊0模式寄存器
- sfr CCAP0L = 0xEA; //PCA模塊0捕獲寄存器 LOW
- sfr CCAP0H = 0xFA; //PCA模塊0捕獲寄存器 HIGH
- sfr CCAPM1 = 0xDB; //PCA模塊1模式寄存器
- sfr CCAP1L = 0xEB; //PCA模塊1捕獲寄存器 LOW
- sfr CCAP1H = 0xFB; //PCA模塊1捕獲寄存器 HIGH
- sfr CCAPM2 = 0xDC; //PCA模塊2模式寄存器
- sfr CCAP2L = 0xEC; //PCA模塊2捕獲寄存器 LOW
- sfr CCAP2H = 0xFC; //PCA模塊2捕獲寄存器 HIGH
- sfr PCA_PWM0 = 0xf2; //PCA模塊0的PWM寄存器
- sfr PCA_PWM1 = 0xf3; //PCA模塊1的PWM寄存器
- sfr PCA_PWM2 = 0xf4; //PCA模塊2的PWM寄存器
- sfr P1M0 = 0x92;
- sfr P1M1 = 0x91;
- sbit CCP0 = P1^1;
- sbit CCP1 = P1^0;
- #define PWM_HIGH_MAX PWM_DUTY-32 //限制PWM輸出的最大占空比。
- #define PWM_HIGH_MIN 32 //限制PWM輸出的最小占空比。
- /************* 本地變量聲明 **************/
- unsigned int pwm; //定義用戶操作的PWM變量
- /************* 本地函數聲明 **************/
- void delay_ms(unsigned char ms);
- /**************** 外部函數聲明和外部變量聲明 *****************/
- extern unsigned int PWM_high; //PWM空比寄存器,即PWM輸出高電平的PCA時鐘脈沖個數(占空比寫入變量)。
- void PWMn_SetHighReg(unsigned int high);
- void PWMn_init(unsigned int high);
- /******************** 主函數 **************************/
- //========================================================================
- // 函數: void main(void)
- // 描述: 不斷更新PWM值,用示波器觀察占空比變化。
- // 參數: 無。
- // 返回: 無。
- // 版本: VER1.0
- // 日期: 2011-4-11
- // 備注:
- //========================================================================
- void main(void)
- {
- pwm = 1000; //pwm初值
- pwm = PWM_HIGH_MIN; //pwm初值
- PWMn_init(pwm); //初始化pwm
- while (1)
- {
- delay_ms(10); //延時
- pwm += 10;
- if(pwm >= PWM_HIGH_MAX) pwm = PWM_HIGH_MIN;
- PWMn_SetHighReg(pwm); //更新PWM的占空比
- }
- }
- /**********************************************/
- //========================================================================
- // 函數: void delay_ms(unsigned char ms)
- // 描述: 延時函數。
- // 參數: ms,要延時的ms數.
- // 返回: none.
- // 版本: VER1.0
- // 日期: 2010-12-15
- // 備注:
- //========================================================================
- void delay_ms(unsigned char ms)
- {
- unsigned int i;
- do
- {
- i = MAIN_Fosc / 14000L; //1T
- while(--i) ;
- }while(--ms);
- }
- unsigned int PWM_high; //定義PWM占空比寄存器,即PWM輸出高電平的PCA時鐘脈沖個數(占空比寫入變量)。
- unsigned int PWM_low; //定義PWM輸出低電平的PCA時鐘脈沖個數。
- unsigned int CCAP0_tmp; //定義CCAP0重裝載影射寄存器。
- //========================================================================
- // 函數: void PWMn_SetHighReg(unsigned int high)
- // 描述: 寫入占空比數據。
- // 參數: high: 占空比數據,即PWM輸出高電平的PCA時鐘脈沖個數。
- // 返回: 無
- // 版本: VER1.0
- // 日期: 2009-12-30
- // 備注:
- //========================================================================
- void PWMn_SetHighReg(unsigned int high)
- {
- if(high > PWM_HIGH_MAX) high = PWM_HIGH_MAX; //如果寫入大于最大占空比數據,強制為最大占空比。
- if(high < PWM_HIGH_MIN) high = PWM_HIGH_MIN; //如果寫入小于最小占空比數據,則返回錯誤代碼2。
- CR = 0; //停止PCA。
- PWM_high = high; //數據在正確范圍,則裝入占空比寄存器。
- PWM_low = PWM_DUTY - high; //計算并保存PWM輸出低電平的PCA時鐘脈沖個數。
- CR = 1; //啟動PCA。
- }
- //========================================================================
- // 函數: void PWMn_init(unsigned int high)
- // 描述: 初始化程序。
- // 參數: high: 初始化占空比數據,即PWM輸出高電平的PCA時鐘脈沖個數。
- // 返回: 無
- // 版本: VER1.0
- // 日期: 2009-12-30
- // 備注:
- //========================================================================
- void PWMn_init(unsigned int high)
- {
- ACC = P_SW1;
- ACC &= ~(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=0
- P_SW1 = ACC; //(P1.2/ECI, P1.1/CCP0, P1.0/CCP1, P3.7/CCP2)
- // ACC = P_SW1;
- // ACC &= ~(CCP_S0 | CCP_S1); //CCP_S0=1 CCP_S1=0
- // ACC |= CCP_S0; //(P3.4/ECI_2, P3.5/CCP0_2, P3.6/CCP1_2, P3.7/CCP2_2)
- // P_SW1 = ACC;
- //
- // ACC = P_SW1;
- // ACC &= ~(CCP_S0 | CCP_S1); //CCP_S0=0 CCP_S1=1
- // ACC |= CCP_S1; //(P2.4/ECI_3, P2.5/CCP0_3, P2.6/CCP1_3, P2.7/CCP2_3)
- // P_SW1 = ACC;
- P1M1 &= ~0x02, P1M0 |= 0x02; //CCAP0使用PUSH-PULL輸出模式
- CCON = 0; //清除CF、CR、CCF0、CCF1
- CMOD = (PCA_IDLE_DISABLE << 7) | (PCA_SOURCE_SELECT << 1); //初始化PCA模式寄存器,這兩項在PWMn.h中選擇。
- CCAPM0 = 0x4D; //高速輸出模式,允許比較匹配中斷(ECCF0=1)。
- CL = 0; //清空PCA基本計數器。
- CH = 0;
- CCAP0_tmp = 0; //清空CCAP0重裝載影射寄存器。
- PWMn_SetHighReg(high); //初始化占空比數據。
- CR = 1; //啟動PCA。
- EA = 1; //允許總中斷
- }
- //========================================================================
- // 函數: void PCA_interrupt (void) interrupt 7
- // 描述: PCA中斷服務程序。
- // 參數: 無。
- // 返回: 無。
- // 版本: VER1.0
- // 日期: 2009-12-30
- // 備注:
- //========================================================================
- void PCA_interrupt (void) interrupt 7
- {
- if(CCF0 == 1) //PCA模塊0中斷
- {
- CCF0 = 0; //清PCA模塊0中斷標志
- if(CCP0 == 1) CCAP0_tmp += PWM_high; //輸出為高電平,則給影射寄存器裝載高電平時間長度
- else CCAP0_tmp += PWM_low; //輸出為低電平,則給影射寄存器裝載低電平時間長度
- CCAP0L = (unsigned char)CCAP0_tmp; //將影射寄存器寫入捕獲寄存器,先寫CCAP0L
- CCAP0H = (unsigned char)(CCAP0_tmp >> 8); //后寫CCAP0H
- }
- /*
- else if(CCF1 == 1) //PCA模塊1中斷
- {
- CCF1 = 0; //清PCA模塊1中斷標志
- }
- else if(CF == 1) //PCA溢出中斷
- {
- CF = 0; //清PCA溢出中斷標志
- }
- */
- }
復制代碼 |