PIC18F452(有兩個ccp)每個CCP(捕捉/ 比較/PWM )模塊有一個16位寄存器,它可以用作16位捕捉寄存器、16位比較寄存器或PWM 主/ 從占空比寄存器。除了特殊事件觸發器之外,CCP1的操作和CCP2相同。
捕捉/ 比較/PWM 寄存器1(CCPR1)由兩個 8 位寄存器組成:CCPR1L (低字節)和 CCPR1H(高字節)。CCP1CON 寄存器控制CCP1 的操作。
捕捉/ 比較/PWM 寄存器2(CCPR2)由兩個 8 位寄存器組成:CCPR2L (低字節)和 CCPR2H(高字節)。CCP2CON 寄存器控制CCP2 的操作。
CCP模式-定時器資源:捕捉:Timer1或Timer3;比較:Timer1或Timer3;PWM:Timer2。
給CCPRx一個值, 開定時器 TMR1計數. 定時器可以零開始計數,不斷和CCPRx的數據對比,如果相同則相應動作. (純自動的,設定好CCPRx 並開啟CCP模塊就可以, )CCPRx不能自加.
CCP1CON 寄存器/CCP2CON 寄存器。
捕捉模式:在捕捉模式下,當RC2/CCP1 引腳上有事件發生時,CCPR1H:CCPR1L即捕捉TMR1 或TMR3 寄存器的16位計數值。事件定義如下:
• 每個下降沿發生
• 每個上升沿發生
• 每4 個上升沿發生
• 每16個上升沿發生
由控制位 CCP1M3:CCP1M0(CCP1CON<3:0>)來選擇上述 4 種事件之一。當發生捕捉事件時,中斷請求標志位 CCP1IF(PIR1<2> )置 1 ;該位必須用軟件清零。如果在讀出寄存器CCPR1中的值之前發生另一個捕捉,那么之前捕捉的值將會被覆蓋。捕捉模式的改變會產生錯誤的捕捉中斷。用戶應保持
CCP1IE 位(PIE1<2> )為 0 以免發生錯誤中斷,並且應該在任何操作模式改變后清零標志位CCP1IF。
通過設置CCP1M3:CCP1M0位可以選擇四種預分頻值設置。只要CCP模塊關閉或沒有設置為捕捉模式,就可將預分頻器的計數器清零。這就意味着任何復位都可以將預分頻器計數器清零。從一個捕捉預分頻器切換到另一個捕捉預分頻器可能產生中斷。而且,預分頻器計數器不會被清零,因此第一次捕捉可能是來自一個非零的預分頻器。

1 /*CCP1輸出比較*/ 2 #include "pic.h" 3 4 void initPORTB(void); 5 void initCCP1(void); 6 void interrupt CCP1INT(void); 7 8 void main() 9 { 10 initPORTB(); 11 initCCP1(); 12 while(1) 13 { 14 } 15 } 16 17 void initCCP1() 18 { 19 TRISC=0x00; 20 T1CON=0x00; 21 CCPR1H=0x61; 22 CCPR1L=0xa8; 23 CCP1CON=0x0a; 24 CCP1IE=1; 25 PEIE=1; 26 GIE=1; 27 TMR1ON=1; 28 } 29 30 void interrupt CCP1INT(void) 31 {CCP1IF=0; 32 TMR1ON=0; 33 TMR1H=0x00; 34 TMR1L=0x00; 35 T1CON=1; 36 RB0=!RB0; 37 } 38 39 void initPORTB() 40 { 41 TRISB=0xfe; 42 PORTB=0x00; 43 } 44 45 46 47 PIC項目之CCP捕捉模塊 48 49 /*Used pic16C77, CCP捕捉*/ 50 #include "pic.h" 51 #define uint unsigned int 52 53 void initPORTB(void); 54 void initCCP1(void); 55 void interrupt CCP1INT(void); 56 void display(void); 57 58 __CONFIG(WDTDIS&XT&UNPROTECT); 59 uint counter=0; 60 61 void main() 62 { 63 initPORTB(); 64 initCCP1(); 65 while(1) 66 {display();} 67 } 68 69 void initPORTB() 70 { 71 TRISB=0x00; 72 PORTB=0x00; 73 } 74 75 void initCCP1() 76 { 77 TRISC=0x04; 78 GIE=0; 79 PEIE=0; 80 CCP1IE=0; 81 CCP1IF=0; 82 CCP1IE=1; 83 CCP1IF=1; 84 PEIE=1; 85 GIE=1; 86 CCP1CON=0x04; 87 88 } 89 90 void interrupt CCP1INT(void) 91 { 92 GIE=0; 93 CCP1IE=0; 94 CCP1IF=0; 95 counter++; 96 if(counter>9) counter=0; 97 CCP1IE=1; 98 GIE=1; 99 } 100 101 void display() 102 { 103 PORTB=counter; 104 }

1 #include<pic.h> 2 __CONFIG(0x3f3a); 3 4 #define CPPDUTY RA2 //占空比加按鍵 5 #define CPPDUTY_PULSE RA3 //占空比減按鍵 6 7 void CCP1INIT(void); 8 void INI(void); 9 void tmint(void); 10 void interrupt clkint(void) 11 12 unsigned char QC,CCP1_DUTY=0,DUTY_PULSE; 13 14 //主程序 15 16 main() 17 { 18 INI(); 19 20 tmint(); 21 while(1) 22 { 23 CCP1INIT();//CCPR1L與DC1B1與DC1B0共同組成占空比的可調范圍,以當前程序為例,則占空比為DC1B<9:0)*Tosc*TMR2預分頻 24 CCPR1L=CCP1_DUTY; 25 if((CPPDUTY==0)&&(QC==0)) 26 { 27 CCP1_DUTY++; 28 CCP1_DUTY=CCP1_DUTY>=254254:CCP1_DUTY; 29 } 30 if((CPPDUTY_PULSE==0)&&(QC==0)) 31 { 32 CCP1_DUTY--; 33 CCP1_DUTY=CCP1_DUTY<=1?1:CCP1_DUTY; 34 } 35 if(QC>255) QC=0; 36 } 37 } 38 39 void CCP1INIT() //CCP1模塊的PWM工作方式初始化子程序*/ 40 {//CCPR1L與DC1B1與DC1B0共同組成占空比的可調范圍,以當前程序為例,則占空比為DC1B<9:0)*Tosc*TMR2預分頻 41 CCP1CON=0X3C; //設置CCP1模塊為PWM工作方式,且其占它比的低兩位DC1B1與DC1B0為11 42 PR2=255; //設置PWM的工作周期,也即PWM的工作頻率 其中PWM周期=(PR2+1)*4*Tosc*TMR2預分頻比,Tosc為MCU的振盪周,以當前程序為例,則PWM的輸出頻為 1/{(156+1)*4*0.25us(4M晶體)*1}=6.3694267515923566878980891719745 43 T2CON=4; //打開TMR2,且使其前預分頻為1:1,后分頻比為1:1,但在這個程序中后分頻比用不上 44 } 45 46 void INI(void) 47 { 48 ADCON1=0B00000111; //A口全作數字IO 49 TRISA=0XFF; //全輸入 50 TRISB=0; 51 GIE=1; 52 } 53 54 55 56 void interrupt clkint(void) //定時器中斷函數 57 { 58 QC++; 59 T0IF=0x0; 60 } 61 62 63 void tmint(void) //定時初始化函數 64 { 65 T0CS=0; //T0CS是TMR0的時鍾源選擇位,當其=1時是用RA4(T0CKI)的外部輸入時鍾,當其=0時是用內部指令周期時鍾(CLKOUT) 66 PSA=0; //PSA是預分頻器分配位,當其=1預分頻器分配給WDT,當其=0時預分頻器分配給Timer0 模塊 67 PS2=0; //PS2:PS1:PS0:預分頻比選擇位 1 1 1是256分頻 68 PS1=0; 69 PS0=0; 70 T0IF=0; //T0IF是TMR0溢出中斷標志位,當其=1時TMR0 寄存器已經溢出(必須用軟件清零),當其=0時寄存器尚未發生溢出 71 T0IE=1; //T0IE是TMR0 溢出中斷允許位當其=1時允許TMR0 溢出中斷,當其=0時禁止TMR0 溢出中斷 72 }
比較模式下,16位CCPR1(CCPR2)寄存器的值隨時與TMR1 或TMR3 寄存器對的值相比較。當兩者相符時,RC2/CCP1 (RC1/CCP2 )引腳將:
• 變為高電平
• 變為低電平
• 翻轉輸出(高電平變為低電平或低電平變為高電平)
• 保持不變
引腳的狀態取決於控制位CCP1M3:CCP1M0(CCP2M3:CCP2M0)的值。同時,中斷標志位CCP1IF(CCP2IF)置1 。
用戶必須通過將相應的TRISC位清零,將CCPx 引腳配置為輸出引腳。 如果CCP模塊使用比較功能,Timer1和/ 或Timer3必須工作在定時器模式或同步計數器模式。在異步計數器模式下,可能無法進行比較操作。
當選擇了產生軟件中斷時,CCP1 引腳上的電平不受影響。CCP中斷使能時,只會產生一個CCP中斷。
在這一模式下,將產生一個內部硬件觸發信號,可用來觸發一個操作。CCP1 的特殊事件觸發器輸出使TMR1 寄存器對復位。這將使CCPR1寄存器有效地成為Timer1的16位可編程周期寄存器。CCPx 的特殊事件觸發器輸出使TMR1 或TMR3 寄存器對復位。另外,如果 A/D 模塊使能,則 CCP2 特殊事件觸發器將啟動A/D 轉換。
在脈沖寬度調制(Pulse Width Modulation,PWM)模式下,CCP1 引腳可產生分辨率高達10位的PWM 輸出。因為 CCP1 引腳與PORTC 數據鎖存器復用,所以TRISC<2>位必須清零以使CCP1引腳為輸出狀態。
PWM 周期可通過寫入PR2 寄存器來指定。可用以下公式計算PWM 周期:
PWM 周期=(PR2)+1]•4•TOSC•(TMR2 預分頻值)
PWM 頻率定義為1/[PWM 周期] 。
當TMR2 等於PR2 時,在下一遞增計數周期中將產生下面三個事件:
• 清零TMR2
• 將CCP1 引腳置1 (例外情況:如果PWM 占空比= 0%,CCP1 引腳不被置1 )
• PWM 占空比從CCPR1L 被鎖定為CCPR1H
PWM 占空比可通過向 CCPR1L 寄存器和CCP1CON<5:4> 位寫入來指定。最高分辨率可達10位。CCPR1L 包含8 位MSb,CCP1CON<5:4>包含2位LSb 。這10位值由CCPR1L:CCP1CON<5:4> 來表征。計算PWM 占空比的公式如下:
PWM 占空比= (CCPR1L:CCP1CON<5:4>) •TOSC • (TMR2 預分頻值)
可以在任何時候寫入CCPR1L 和CCP1CON<5:4>,但直到PR2 與TMR2 中的值相符(例如,當周期結束)時,占空比的值才被鎖存到CCPR1H。在PWM 模式
下,CCPR1H是只讀寄存器。CCPR1H寄存器和一個2 位的內部鎖存器用於為PWM占空比提供雙重緩沖。對於PWM 的無毛刺操作, 雙重緩沖是很必要的。
當CCPR1H和2 位鎖存器的值與附加了內部2 位Q 時鍾或2 位TMR2 預分頻器的TMR2 相符時,CCP1 引腳被清零。對於給定的PWM頻率,其最大分辨率(位)為?
設置PWM 操作通過以下步驟將CCP模塊配置為PWM 操作:
1. 寫入 PR2 寄存器以設定 PWM周期。
2. 寫入CCPR1L 寄存器和CCP1CON<5:4>位以設置PWM 占空比。
3. 將TRISC<2> 位清零以將CCP1 引腳設為輸出。
4. 寫入T2CON 以設置TMR2 預分頻值並使能Timer2。
5. 將CCP1 模塊配置為PWM 模式。