View Single Post
Old 05-01-2007, 03:58 PM   #10
ngohaibac
Đệ tử 9 túi
 
ngohaibac's Avatar
 
Tham gia ngày: Oct 2005
Nơi Cư Ngụ: BKHN
Bài gửi: 231
:
Send a message via Yahoo to ngohaibac
Điều chế PWM.

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 .
ngohaibac vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn