http://dientuvietnam.net/forums/show...?t=1406&page=4
Bài viết số 39.
Theo datasheet PIC687XA tại trang 67,68 về PWM, chúng ta dễ dàng có thể viết được chương trình điều chế độ rộng xung (Pulse Width Modulation).
Chương trình dưới đây điều chế một xung với tần số 15KHz và có độ rộng xung tăng dần từ 0-> 100% theo bước tăng là 10% sau mỗi khoảng thời gian 1s.
Code:
PWM Period = [ PR2 +1 ] x 4 x Tosc x (TMR2 Prescaler Value)
PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x (TMR2 Prescaler Value)
=> CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
với k là độ rộng xung (%) k = 0 -> 100
Sau đây là chương trình có kèm theo mô tả phần cứng:
Code:
/*;========================================================
; Ten chuong trinh : Dieu che do rong xung
; Nguoi thuc hien : Ngo Hai Bac (NOHB)
; Ngay thuc hien : 12/04/06
; Phien ban : 1.0
; Mo ta phan cung : Dung PIC16F877A - thach anh 20MHz
; Dieu che do rong xung ra chan RC2/CCP1, chan RC2 noi voi led roi noi voi tro 220 Ohm, roi noi voi dat.
; => sau 1s thi tang do rong xung len 10%
;----------------------------------------------------------------
; Ngay hoan thanh :
; Ngay kiem tra :
; Nguoi kiem tra :
;----------------------------------------------------------------
; Chu thich : Phan chuong trinh nho cho du an lon :D
PWM dung timer2
;========================================================*/
#include<pic.h>
__CONFIG(HS & UNPROTECT & PWRTEN & BOREN & LVPDIS & WDTDIS );
//============ cac marco
//============= ham khoi tao
void init(void){
//===== init for PWM
// PWM Period = [ PR2 +1 ] x 4 x Tosc x (TMR2 Prescaler Value)
PR2 = 82; // Tan so = 15 KHz, TMR2 Prescaler Value = 4
// PWM Duty Cycle = [ CCPR1L : CCP1CON<5:4>) x Tosc x (TMR2 Prescaler Value)
// => CCPR1L : CCP1CON<5:4> = k% x (TMR2 + 1 ) x 4;
CCPR1L = 0;
TRISC2 = 0; // RC2 la output
RC2 = 1;
T2CON = 0b00000101; // Timer2 on, TMR2 Prescaler Value = 4
CCP1CON = 0b00001100; // CCP1 hoat dong trong che do PWM
//===== init cho SFR
OPTION = 0x00; // dung tro keo len PortB, TMR0 Prescaler = 2 va dung cho TMR0
TMR0 = 0x06; // khoi tao cho Timer0
T0IF = 0; // xoa co ngat timer0
T0IE = 1; // timer0 Interrupt Enable
GIE = 1; // Global Interrupt Enable
}
//============= ham ngat
void interrupt MyInt(void){
static volatile unsigned char k; // % do rong xung => 0<= k <= 100
static volatile unsigned int counter1;
int temp;
// ==== Ngat timer0
if (T0IE & T0IF ){
T0IF = 0;
TMR0 = 6;
if(++counter1 == 1000){
counter1 = 0;
temp = 4* (PR2 + 1) * k/100;
CCPR1L = temp>>2;
CCP1Y = temp - ((temp>>1)<<1);//temp%2;
CCP1X = (temp>>1)%2;
//CCPR1L = (TMR2 + 1)>>1 ;
k += 10; // tang 10%
if( k > 100) k=0;
};
};
}
//============= ham chinh Main
void main(void){
init();
while(1);
}
Chương trình đã được test bằng mạch thật. Hiện tượng: led sáng dần dần sau đó sáng rõ. Rồi lại tắt, tiếp tục sáng dần dần,..
Ngẫu hứng đêm khuya viết tí. Sáng mai dạy viết tiếp.
Chúc anh em ngủ ngon

.