การใช้งานโมดูล PWM ของ PIC16F877
     ไมโครคอนโทรเลอร์ PIC ได้เตรียมโมดูล CCP (Capture/Compare/PWM) สำหรับใช้ในการตรวจจับ
สัญญาณ,เปรียบเทียบข้อมูล, และสร้างสัญญาณ PWM(Pulse-width modulation) มาพร้อมใช้งาน ในที่นี้
ผมจะขอกล่าวถึงการใช้งานโมดูล PWM เพียงอย่างเดียว ซึ่งใน PIC16F877 จะมีโมดูล PWM ให้ใช้งาน
2 ชุด ได้แก่ โมดูล CCP1 และโมดูล CCP2

     โมดูล CCP(Capture/Compare/PWM) สามารถใช้กำเนิดสํญญาณและมอดูเลชั่นทางความกว้างของ พัลส์ความละเอียดขนาด 10 บิท PWM (Pulse Width Modulator) ซึ่งจะทำงานร่วมกันกับ TIMER2 เมื่อ กำหนดค่าเริ่มต้นในการทำงานให้แล้ว โมดูลนี้จะทำงานต่อไปได้เองโดยอิสระ ทำให้ MCU ไม่ต้องเสีย
เวลาวนลูปในการจัดการกับเอาต์พุต ในขณะที่โมดูลนี้ทำงาน MCU สามารถที่จะควบคุมการเปิด/ปิดสัญ ญาณผ่านทางรีจิสเตอร์ควบคุมได้

การเลือกโหมดการทำงานของโมดูล CCP ด้วยฟังก์ชั่นของ CCS
     การเลือกโหมดการทำงานของโมดูล CCP ให้ทำงานในโหมดสร้างสัญญาณ PWM สามารถทำได้ดัง
นี้
     setup_ccp1(CCP_PWM); // กำหนดให้โมดูล CCP1 ทำงานในโหมดสร้างสัญญาณ PWM
     setup_ccp2(CCP_PWM); // กำหนดให้โมดูล CCP2 ทำงานในโหมดสร้างสัญญาณ PWM

ฟังก์ชั่นกำหนดค่าดิวตี้ไซเกิลของสัญญาณ PWM
     เมื่อกำหนดโหมดให้เป็นโหมดส้างสัญญาณ PWM แล้ว สามารถที่จะกำหนดค่าดิวตี้ไซเกิลของสัญญาน
ได้ด้วยฟังก์ชั่นดังนี้
     setup_pwm1_duty(value)
     setup_pwm2_duty(value)
     
โดยที่ value คือ ค่าคงที่หรือตัวแปร 8 หรือ 16 บิต

การคำนวณค่าดิวตี้ไซเคิล

     ดิวตี้ไซเกิล = value * (1/clock) * t2div

โดยที่
     ดิวตี้ไซเกิล          ค่าเปอร์เซ็นต์ของพัลส์
     value                   ค่าที่กำหนดให้กับฟังก์ชั่น setup_pwm2_duty(value)
     clock                   ความถี่ของสัญญานนาฬิกาหลักในหน่วยเฮิรตซ์
     t2div                    ค่าปรีสเกลเลอร์ของไทเมอร์ 2

ตัวอย่างการใช้งาน
     
เป็นโปรแกรมกำเนิดความถี่ 2.4KHz ใช้โมดูล CCP1 ทำงานในโหมดสร้างสัญญาณ PWM มีดิวตี้ไซเกิล 50% ที่ความถี่ 20 MHz และปรีสเกลเลอร์ 1 : 16

ผลการทำงาน
     มีสัญญาณพัลส์ออกทางขา PORTC.2 ความถี่ 2.4 KHz

การคำนวณ
     ต้องการความถี่ 2.4 KHz ดิวตี้ไซเิกิล 50% ดังนั้นมีคาบเวลาช่วงบวกคือ 0.000416 สามารถคำนวณหาค่า value ได้ดังนี้
value = 0.000416/(16*(1/20000000)
CODE

#include <16F877.h>
#fuses HS
#fuses NOLVP
#fuses NOWDT
#fuses NOPROTECT
#use delay(clock = 20000000)

 

void main (void)
{
     setup_ccp1(CCP_PWM);
     setup_timer_2(T2_DIV_BY_16,127,1);
     set_pwm1_duty(520); // duty cycle 50%

     while(true)
     {
     ;// Statement
     }
}

กลับสู่หน้าหลัก