I. GIỚI THIỆU
Vi điều khiển PIC họ 16F877A có 2 bộ PWM dùng để điều khiển tốc độ động cơ DC.
Phần này sẽ khảo sát chi tiết khối PWM của PIC và tập lệnh lập trình C cho PWM.
II. KHẢO SÁT PWM
Vi điều khiển PIC họ 16F877A có 2 bộ PWM dùng để điều khiển tốc độ động cơ DC.
Phần này sẽ khảo sát chi tiết khối PWM của PIC và tập lệnh lập trình C cho PWM.
II. KHẢO SÁT PWM
1. SƠ ĐỒ KHỐI PWM của PIC16F877A có sơ đồ khối như hình 7-1:
Khối PWM gồm có 2 mạch so sánh: mạch so sánh 8 bit với mạch so sánh 10 bit. Mạch so sánh 8 bit sẽ so sánh giá trị đếm của timer2 với giá trị của thanh ghi PR2 (period register), giá trị trong timer2 tăng từ giá trị đặt trước cho đến khi bằng giá trị của PR2 thì mạch so sánh sẽ set flip flop RS làm ngõ ra CCPx lên mức 1. Đồng thời nạp giá trị 10 bit từ thanh ghi CCPRxL sang thanh ghi CCPRxH, timer2 bị reset và bắt đầu đếm lại cho đến khi giá trị của timer2 bằng giá trị của CCPRxH thì mạch so sánh sẽ reset flip flop RS làm ngõ ra CCPx về mức 0. Quá trình này lặp lại.Dạng sóng điều chế PWM như hình 7-2:
Chu kỳ không thay đổi, muốn thay đổi thời gian xung ở mức 1 thì ta thay đổi hệ số chu kỳ (duty cycle). Khi hệ số chu kỳ thay đổi thì điện áp hay dòng trung bình thay đổi. Hệ số chu kỳ càng lớn thì dòng trung bình càng lớn, nếu điều khiển động cơ sẽ làm thay đổi tốc độ.
2. TÍNH CHU KỲ XUNG PWM
Chu kỳ PWM của PIC16F877A được tính theo công thức:
PVTMR2 (prescale value) giá trị chia trước của timer2.
Khi giá trị của timer 2 (TMR2) bằng giá trị của thanh ghi PR2 thì 3 sự kiện theo sau sẽ xảy ra:
Hệ số chu kỳ được thiết lập bởi giá trị lưu trong thanh ghi 10 bit gồm CCPRxL 8 bit và 2 bit còn lại là bit thứ 4 và thứ 5 ở trong thanh ghi CCPxCON – kí hiệu là CCPxCON<5:4>.
Giá trị của hệ số chu kỳ là 10 bit nên có thể thay đổi từ 0 đến 1023 tạo ra 1024 cấp giá trị điều khiển. Giá trị 10 bit thì 8 bit có trọng số lớn lưu trong thanh ghi CCPRxL và 2 bit còn lại có trọng số thấp thì ở CCPxCON<5:4>.
Hệ số chu kỳ của PIC16F877A được tính theo công thức:
Chu kỳ PWM của PIC16F877A được tính theo công thức:
PERIODPWM = [(PR2) +1] * 4 * TOSC * PVTMR2
Trong đó: TOSC là chu kỳ của tụ thạch anh tạo dao động.PVTMR2 (prescale value) giá trị chia trước của timer2.
Khi giá trị của timer 2 (TMR2) bằng giá trị của thanh ghi PR2 thì 3 sự kiện theo sau sẽ xảy ra:
- · Thanh ghi TMR2 bị xóa
- · Tín hiệu ngõ ra CCPx lên mức 1, ngoại trừ hệ số chu kỳ bằng 0% thì CCPx vẫn ở mức 0.
- · Hệ số chu kỳ PWM được chuyển từ thanh ghi CCPRxL sang thanh ghi CCPRxH.
Hệ số chu kỳ được thiết lập bởi giá trị lưu trong thanh ghi 10 bit gồm CCPRxL 8 bit và 2 bit còn lại là bit thứ 4 và thứ 5 ở trong thanh ghi CCPxCON – kí hiệu là CCPxCON<5:4>.
Giá trị của hệ số chu kỳ là 10 bit nên có thể thay đổi từ 0 đến 1023 tạo ra 1024 cấp giá trị điều khiển. Giá trị 10 bit thì 8 bit có trọng số lớn lưu trong thanh ghi CCPRxL và 2 bit còn lại có trọng số thấp thì ở CCPxCON<5:4>.
Hệ số chu kỳ của PIC16F877A được tính theo công thức:
DUTY_ CYCLEPWM = (CCPRxL : CCPxCON < 5 : 4 >) * TOSC * PVTMR2
- Đây là ảnh mô phỏng protues.
- Đây là code chương trình.
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000
#include <xc.h>
#include "pwm.h"
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
unsigned int duty = 0;
void main (void)
{
PWM2_Init_Fre(1000);// tan so
PWM1_Init_Fre(1000);// tan so
while(1)
{
PWM2_Duty(127);// T(dutycycle)
PWM1_Duty(50);// T(dutycycle)
PWM2_Start();
PWM1_Start();
}
}
- Đây là cách tạo xung tuần hoàn.
unsigned int duty = 0;
void main (void)
{
PWM1_Init_Fre(1000);
while(1)
{
PWM1_Start();
PWM1_Duty(duty);
duty++;
if(duty > 127) duty = 0;
__delay_us(10);
}
}
No comments:
Post a Comment