I am using a PIC16F873A for generating an SPWM signal using CCP1 and timer 2. The SPWM is generated successfully but the signal is not stable. I have generated 50 Hz signal of SPWM frequency of 40 kHz, but after 1 or 2 SPWM cycles the pulse width (shape of SPWM) changes. The output on CCP1 pin is shown in the image below:
The SPWM 1, 2, 3, 4 have different shapes, although the duty cycle is same for all. The code is given below. How to solve this problem?
#include <xc.h>
#pragma config WDTE = ON
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config FOSC = HS
#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) //END CONFIG
#define _XTAL_FREQ 20000000
#include <xc.h>
unsigned char sin_table[16] = {0, 26, 50, 73, 92, 107, 118, 123, 123, 118, 107, 92, 73, 50, 26,0};
unsigned int TBL_POINTER_NEW, TBL_POINTER_OLD, TBL_POINTER_SHIFT, SET_FREQ; unsigned int TBL_temp;
unsigned char DUTY_CYCLE, FlagReg;
#define SA PORTCbits.RC3
#define SB PORTCbits.RC4
#define SC PORTCbits.RC5
#define SD PORTCbits.RC6 unsigned char Direction = 0;
void __interrupt() isr() {
if (TMR2IF == 1) {
TBL_POINTER_NEW = TBL_POINTER_OLD + SET_FREQ;
if (TBL_POINTER_NEW < TBL_POINTER_OLD) {
//CCP1CON.P1M1 = ~CCP1CON.P1M1; //Reverse direction of full-bridge
if (Direction == 0) {
SA = 0;
SD = 0;
SB = 1;
SC = 1;
Direction = 1;
}
else {
SB = 0;
SC = 0;
SA = 1;
SD = 1;
Direction = 0;
}
}
TBL_POINTER_SHIFT = TBL_POINTER_NEW >>12;
DUTY_CYCLE = TBL_POINTER_SHIFT;
CCPR1L = sin_table[DUTY_CYCLE];
TBL_POINTER_OLD = TBL_POINTER_NEW;
TMR2IF = 0;
}
}
void main() {
SET_FREQ = 162;
PORTC = 0;
TRISC = 0;
PR2 = 124; // 40kHz
CCPR1L = 0;
CCP1CON = 0x3C; //PWM mode
TRISC = 0xFF;
TMR2IF = 0;
T2CON = 0x04; //TMR2 on,
while (TMR2IF == 0);
TMR2IF = 0; //Clear TMR2IF
PORTC = 0;
TRISC = 0;
TMR2IE = 1;
GIE = 1;
PEIE = 1;
while (1);
}