Hello everyone,
I am trying to implment 3 SPWM signals with PWM shifted by 60 degree and 120 degrees ( shifted carrier not the sinusiodal signal). So , I depend on the 3 channels of the timer counter 2 to do this and channel zero of TC0 for time delay. The code below explains what I have done. The main problem is that the output signals are not stable and the sifted signals works for about 3 periods then keep high for 2 periods.
Are there any better whay to generate those three signals ??
int temp;
#define SinDivisions (5000) // 5000 pulse for each one period of output sine wave, switching frequency/sine wave fequency (250KHz/50 Hz)=5000
static unsigned int lookUpch1[SinDivisions];
int period=168;
int fsw=250; //250 [KHz]
int j=0;
int k=0;
void setup() {
// put your setup code here, to run once:
// Genrating the duty cycle table for sinusoidal PWM
for(int i = 0; i < SinDivisions/2; ++i){ // Generating the look up table.
temp = sin(i2M_PI/SinDivisions)*period; // the amplitude of the sine wave determine the duty cycle for each pulse
lookUpch1[i] = temp; // Round to integer.
}
// 1- Enable clocks for timer counters
PMC->PMC_PCER0 |=PMC_PCER0_PID27; // TC0 power ON - Timer Counter 0 channel 0 IS TC0 -----Enable clock for pin 2,13 (TIOA0,TIOB0)
PMC->PMC_PCER1 |=PMC_PCER1_PID33; // TC6 power ON - Timer Counter 2 channel 0 IS TC6 -----Enable clock for pin 5,4 (TIOA6,TIOB6)
PMC->PMC_PCER1 |=PMC_PCER1_PID34; // TC7 power ON - Timer Counter 2 channel 1 IS TC7 -----Enable clock for pin 3,10 (TIOA7,TIOB8)
PMC->PMC_PCER1 |=PMC_PCER1_PID35; // TC8 power ON - Timer Counter 2 channel 2 IS TC8 -----Enable clock for pin 11,12 (TIOA8,TIOB8)
// 2- Disable PIO from controling these pins and enable peripheral control of the pins
PIOB->PIO_PDR |= PIO_PDR_P25; // Dsiable pin 2
PIOB->PIO_PDR |= PIO_PDR_P27; // Disable pin 13
PIOC->PIO_PDR |= PIO_PDR_P25; // Dsiable pin 5
PIOC->PIO_PDR |= PIO_PDR_P26; // Disable pin 4
PIOC->PIO_PDR |= PIO_PDR_P28; // Dsiable pin 3
PIOC->PIO_PDR |= PIO_PDR_P29; // Disable pin 10
PIOD->PIO_PDR |= PIO_PDR_P7; // Dsiable pin 11
PIOD->PIO_PDR |= PIO_PDR_P8; // Disable pin 12
// 3- Assign pins to the peripheral function
PIOB->PIO_ABSR |= PIO_PB25B_TIOA0; // Peripheral B
PIOB->PIO_ABSR |= PIO_PB27B_TIOB0; // Peripheral B
PIOC->PIO_ABSR |= PIO_PC25B_TIOA6; // Peripheral B
PIOC->PIO_ABSR |= PIO_PC26B_TIOB6; // Peripheral B
PIOC->PIO_ABSR |= PIO_PC28B_TIOA7; // Peripheral B
PIOC->PIO_ABSR |= PIO_PC29B_TIOB7; // Peripheral B
PIOD->PIO_ABSR |= PIO_PD7B_TIOA8; // Peripheral B
PIOD->PIO_ABSR |= PIO_PD8B_TIOB8; // Peripheral B
// 4- Adjust settings for each pin
// PIN 2,13
TC0->TC_CHANNEL[0].TC_CMR= TC_CMR_TCCLKS_TIMER_CLOCK1| // Set clock as MCK/2 (84/2)MHZ= 42MHZ for pins 2,13 (TIOA0,TIOB0)
TC_CMR_WAVE| // Set the pins 2,13 is waveform mode
TC_CMR_WAVSEL_UP| // UP mode without automatic trigger on RC Compare
TC_CMR_ACPA_SET| // clear TIOA0 (pin 2) with RA compare match
TC_CMR_ACPC_CLEAR; // SET TIOA0 (pin2) with RC compare match
// PIN 5,4
TC2->TC_CHANNEL[0].TC_CMR= TC_CMR_TCCLKS_TIMER_CLOCK1| // Set clock as MCK/2 (84/2)MHZ= 42MHZ for pins 2,13 (TIOA0,TIOB0)
TC_CMR_WAVE| // Set the pins 2,13 is waveform mode
TC_CMR_WAVSEL_UP_RC| // UP mode with automatic trigger on RC Compare
TC_CMR_ACPA_SET| // clear TIOA0 (pin 2) with RA compare match
TC_CMR_ACPC_CLEAR| // SET TIOA0 (pin2) with RC compare match
TC_CMR_BCPB_SET| // clear TIOB0 (pin 13) with RA compare match
TC_CMR_BCPC_CLEAR| // SET TIOB0 (pin 13) with RC compare match
TC_CMR_EEVT_XC0;
// PIN 3,10
TC2->TC_CHANNEL[1].TC_CMR= TC_CMR_TCCLKS_TIMER_CLOCK1| // Set clock as MCK/2 (84/2)MHZ= 42MHZ for pins 2,13 (TIOA0,TIOB0)
TC_CMR_WAVE| // Set the pins 2,13 is waveform mode
TC_CMR_WAVSEL_UP| // UP mode without automatic trigger on RC Compare
TC_CMR_ACPA_SET| // clear TIOA0 (pin 2) with RA compare match
TC_CMR_ACPC_CLEAR| // SET TIOA0 (pin2) with RC compare match
TC_CMR_BCPB_SET| // clear TIOB0 (pin 13) with RA compare match
TC_CMR_BCPC_CLEAR| // SET TIOB0 (pin 13) with RC compare match
TC_CMR_EEVT_XC0;
// PIN 11,12
TC2->TC_CHANNEL[2].TC_CMR= TC_CMR_TCCLKS_TIMER_CLOCK1| // Set clock as MCK/2 (84/2)MHZ= 42MHZ for pins 2,13 (TIOA0,TIOB0)
TC_CMR_WAVE| // Set the pins 2,13 is waveform mode
TC_CMR_WAVSEL_UP| // UP mode with automatic trigger on RC Compare
TC_CMR_ACPA_SET| // clear TIOA0 (pin 2) with RA compare match
TC_CMR_ACPC_CLEAR| // SET TIOA0 (pin2) with RC compare match
TC_CMR_BCPB_SET| // clear TIOB0 (pin 13) with RA compare match
TC_CMR_BCPC_CLEAR| // SET TIOB0 (pin 13) with RC compare match
TC_CMR_EEVT_XC0;
// 5- Set the Frequency for each pin
TC0->TC_CHANNEL[0].TC_RC = 2; //set the frequency for TC0 channel 0 as 21 [MHZ]
TC2->TC_CHANNEL[0].TC_RC = period; // Set the Frequency for TC2 channel 0 as Frequency = MCK/2/TC_RC (250 KHz is this case)
TC2->TC_CHANNEL[1].TC_RC = period; // Set the Frequency for TC2 channel 1 as Frequency = MCK/2/TC_RC (250 KHz is this case)
TC2->TC_CHANNEL[2].TC_RC = period; // Set the Frequency for TC2 channel 2 as Frequency = MCK/2/TC_RC (250 KHz is this case)
//6- Set the duty cycle for each pin
TC0->TC_CHANNEL[0].TC_RA = 1; //duty cycle 50%
TC2->TC_CHANNEL[0].TC_RA = 60; // Set the intial Duty cycle for pin 5 as D = (TC_RA/TC_RC) *100
TC2->TC_CHANNEL[0].TC_RB = 30; // Set the intial duty cycle for pin 4
TC2->TC_CHANNEL[1].TC_RA = 60; // Set the intial Duty cycle for pin 3
TC2->TC_CHANNEL[1].TC_RB = 30; // Set the intial duty cycle for pin 10
TC2->TC_CHANNEL[2].TC_RA = 60; // Set the intial Duty cycle for pin 11
TC2->TC_CHANNEL[2].TC_RB = 30; // Set the intial Duty cycle for pin 12
// 7- Interrupt on RC compare match
TC2->TC_CHANNEL[0].TC_IER = TC_IER_CPCS; // Enable Interrupt on RC compare match for TC7
NVIC_EnableIRQ(TC6_IRQn);
//8- Software trigger and clock enable
TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN;
TC2->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC6 counter and enable
TC2->TC_BCR = TC_BCR_SYNC ; // synchrounize the clock of all TC2 channels
TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC7 counter and enable
TC2->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC8 counter and enable
}
void TC6_Handler() { //
TC2->TC_CHANNEL[0].TC_SR;
TC2->TC_CHANNEL[1].TC_SR;
TC2->TC_CHANNEL[2].TC_SR;
TC0->TC_CHANNEL[0].TC_SR;
TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG;
if (k<SinDivisions/2){
TC2->TC_CHANNEL[0].TC_RA = period-lookUpch1[k];
TC2->TC_CHANNEL[0].TC_RB = 0;
while((uint32_t)TC0->TC_CHANNEL[0].TC_CV<28){ // (60/360) *(42[MHZ]/250[KHZ])=28 pulses from TC0 channel 0 equals the phase shift 60 degree
}
TC2->TC_CHANNEL[1].TC_RA = period-lookUpch1[k];
TC2->TC_CHANNEL[1].TC_RB = 0;
TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG;
while((uint32_t)TC0->TC_CHANNEL[0].TC_CV<56){ // (120/360) *(42[MHZ]/250[KHZ])=56 pulses from TC0 channel 0 equals the phase shift 120 degree
}
TC2->TC_CHANNEL[2].TC_RA = period-lookUpch1[k];
TC2->TC_CHANNEL[2].TC_RB = 0;
TC2->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG;
}
if(k>=SinDivisions/2){
TC2->TC_CHANNEL[0].TC_RB = period-lookUpch1[k-SinDivisions/2];
TC2->TC_CHANNEL[0].TC_RA=0;
while((uint32_t)TC0->TC_CHANNEL[0].TC_CV<28){ // (60/360) *(42[MHZ]/250[KHZ])=28 pulses from TC0 channel 0 equals the phase shift 60 degree
}
TC2->TC_CHANNEL[1].TC_RB = period-lookUpch1[k-SinDivisions/2];
TC2->TC_CHANNEL[1].TC_RA=0;
TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG;
while((uint32_t)TC0->TC_CHANNEL[0].TC_CV<56){ // (120/360) *(42[MHZ]/250[KHZ])=56 pulses from TC0 channel 0 equals the phase shift 120 degree
}
TC2->TC_CHANNEL[2].TC_RB = period-lookUpch1[k-SinDivisions/2];
TC2->TC_CHANNEL[2].TC_RA=0;
TC2->TC_CHANNEL[2].TC_CCR = TC_CCR_SWTRG;
}
if(k>=SinDivisions){
k=0;}
++k;
}
void loop() {
// put your main code here, to run repeatedly:
}