Okada
Banned
I am using PIC18F4431 with 16 MHz Crystal and using its PCPWM module to generate 3 Phase SPWM signals but signals are not good. Please see attached Simulation Video for Signals. Also Proteus file is included.
This is the code. The only doubt that I am having is ISR code is taking more than 62.5us to execute once but even if this is true then PWM0, 1, 2, 3 should be good but they are also not good.
I see signal shifting and when signals reach PWM duty 0 it suddenly becomes pwm duty 100%.
This is the code. The only doubt that I am having is ISR code is taking more than 62.5us to execute once but even if this is true then PWM0, 1, 2, 3 should be good but they are also not good.
I see signal shifting and when signals reach PWM duty 0 it suddenly becomes pwm duty 100%.
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 /* * File: main.c * Author: Okada * * Created on March 1, 2017, 4:51 PM */ #define _XTAL_FREQ 16000000 #include <xc.h> #include <p18f4431.h> #include <stdio.h> #include <stdlib.h> #pragma config OSC = HS #pragma config FCMEN = ON #pragma config IESO = OFF #pragma config OSC = HS #pragma config DEBUG = OFF #pragma config LVP = OFF #pragma config PWRTEN = ON #pragma config WDTEN = ON #pragma config WDPS = 2048 #pragma config WINEN = OFF #pragma config MCLRE = ON #pragma config BOREN = ON #pragma config BORV = 42 #pragma config PWMPIN = OFF #pragma config LPOL = HIGH #pragma config HPOL = HIGH #pragma config T1OSCMX = OFF #pragma config STVREN = ON #pragma config CP0 = OFF #pragma config CP1 = OFF #pragma config CPB = OFF #pragma config CPD = OFF #pragma config WRT0 = OFF #pragma config WRT1 = OFF #pragma config WRTC = OFF #pragma config WRTB = OFF #pragma config WRTD = OFF #pragma config EBTR0 = OFF #pragma config EBTR1 = OFF #pragma config EBTRB = OFF /* * pwm resolution = log((1*FOSC)/Fpwm) / log(2) */ unsigned int sine_table[32] = { 0,9,37,83,144,218,302,394,490,586,678,762,836,897,943,971, 980,971,943,897,836,762,678,586,490,394,302,218,144,83,37,9 }; unsigned int TBL_POINTER_NEW[3] = {0, 0, 0}; unsigned int TBL_POINTER_OLD[3] = {0, 0, 0}; unsigned int TBL_POINTER_SHIFT[3] = {0, 0, 0}; unsigned char DUTY_CYCLE[3] = {0, 0, 0}; unsigned int SET_FREQ = 410; //Timer2 //Prescaler 1:1; Postscaler 1:1; TMR2 Preload = 249; Actual Interrupt Time : 62.5 us void InitTimer2() { T2CON = 0x04; PIE1bits.TMR2IE = 1; PR2 = 249; INTCON = 0xC0; } void interrupt isr(){ if((PIE1bits.TMR2IE) && (PIR1bits.TMR2IF)) { //Enter your code here //SET_FREQ = 65536 / (32 * 5) = 410 //Required AC Frequency = 50 Hz //PWM frequency = 16KHz //Tpwm = 1/16KHz = 62.5us (Timer2 Interrupt Period) //62.5us * 32 * 5 = 10ms (for 180 degrees) //10ms * 2 = 20ms //AC frequency = 1/20ms = 50.0Hz TBL_POINTER_NEW[0] = TBL_POINTER_OLD[0] + SET_FREQ; TBL_POINTER_SHIFT[0] = TBL_POINTER_NEW[0] >> 11; DUTY_CYCLE[0] = TBL_POINTER_SHIFT[0]; //Assign PWM duty 10 bit PDC0L = sine_table[DUTY_CYCLE[0]]; PDC0H = sine_table[DUTY_CYCLE[0]] >> 8; TBL_POINTER_OLD[0] = TBL_POINTER_NEW[0]; TBL_POINTER_NEW[1] = TBL_POINTER_OLD[1] + SET_FREQ; TBL_POINTER_SHIFT[1] = TBL_POINTER_NEW[1] >> 11; DUTY_CYCLE[1] = TBL_POINTER_SHIFT[1]; if((DUTY_CYCLE[1] + 21) < 32)DUTY_CYCLE[1] += 21; else DUTY_CYCLE[1] -= 11; //Assign PWM duty 10 bit PDC1L = (sine_table[DUTY_CYCLE[1]]); PDC1H = sine_table[DUTY_CYCLE[1]] >> 8; TBL_POINTER_OLD[1] = TBL_POINTER_NEW[1]; TBL_POINTER_NEW[2] = TBL_POINTER_OLD[2] + SET_FREQ; TBL_POINTER_SHIFT[2] = TBL_POINTER_NEW[2] >> 11; DUTY_CYCLE[2] = TBL_POINTER_SHIFT[2]; if((DUTY_CYCLE[2] + 10) < 32)DUTY_CYCLE[2] += 10; else DUTY_CYCLE[2] -= 21; //Assign PWM duty 10 bit PDC2L = (sine_table[DUTY_CYCLE[2]]); PDC2H = sine_table[DUTY_CYCLE[2]] >> 8; TBL_POINTER_OLD[2] = TBL_POINTER_NEW[2]; PIR1bits.TMR2IF = 0; } } int main(int argc, char** argv) { asm("CLRWDT"); ANSEL0 = 0x00; ANSEL1 = 0x00; TRISA = 0xC0; TRISB = 0x00; TRISC = 0x00; TRISD = 0x00; TRISE = 0x00; PORTA = 0x00; PORTB = 0x00; PORTC = 0x00; PORTD = 0x00; PORTE = 0x00; LATA = 0x00; LATB = 0x00; LATC = 0x00; LATD = 0x00; LATE = 0x00; PTCON0 = 0x20; PWMCON0 = 0x40; PWMCON1 = 0x01; DTCON = 0x84; OVDCOND = 0xFF; OVDCONS = 0xFF; FLTCONFIG = 0x00; //PTPER = ((Tpwm * Fosc/4) / PTMRPS) - 1 //PTMRPS = 1:1 = 1 //Tpwm = 62.5us, 16 KHz Fpwm //((62.5u * 16000000/4) / 1) - 1 PTMRL = 0xF9; PTMRH = 0x00; PTPERL = 0xF9; PTPERH = 0x00; SEVTCMPL = 0x00; SEVTCMPH = 0x00; InitTimer2(); PTCON1 = 0x80; while(1) { asm("CLRWDT"); } return (EXIT_SUCCESS); }