Hi,
I have written a piece of C code for my AT89s52 to generate Sinusoidal PWM. I have taken 36 samples as you can see in the program below. Therefore, I have calulated a duty period of 230uS for each sample if the entire sinusoidal cycle (from 0 deg to 180 deg) is to be completed within (1/60 = 16.7ms). 230x36 = 8.3ms and therefore the entire cycle would be completed in 16.6ms and thus 60Hz frequency shall be achieved.
Since I'm using a 12Mhz crystal, I have calculated one clock cycle to be equal to 1us. Using this data I have started timer 0 count from 25 in order to limit duty period to 230uS.
I hope my above calculations are correct and that I haven't overlooked something. Kindly take a look at the following code and please tell me whether it produces a 60Hz sine wave signal? (P.S. I don't have access to any CRO or simulation software right now...so kindly help me out here)
I have written a piece of C code for my AT89s52 to generate Sinusoidal PWM. I have taken 36 samples as you can see in the program below. Therefore, I have calulated a duty period of 230uS for each sample if the entire sinusoidal cycle (from 0 deg to 180 deg) is to be completed within (1/60 = 16.7ms). 230x36 = 8.3ms and therefore the entire cycle would be completed in 16.6ms and thus 60Hz frequency shall be achieved.
Since I'm using a 12Mhz crystal, I have calculated one clock cycle to be equal to 1us. Using this data I have started timer 0 count from 25 in order to limit duty period to 230uS.
I hope my above calculations are correct and that I haven't overlooked something. Kindly take a look at the following code and please tell me whether it produces a 60Hz sine wave signal? (P.S. I don't have access to any CRO or simulation software right now...so kindly help me out here)
Code:
#include <REGX51.H>
//Using a 12MHz crystal. Therefore one cycle is equal to 1uS.
//Therefore to acheive a duty period of 230uS for each sine sample timer counts from 25 to 255
/* Global variables and definition */
#define PWMPIN1 P2_0
#define PWMPIN2 P2_1
unsigned char pwm_width;
bit pwm_flag = 0;
bit zcr=0;//zero-crossing indicator
int i=0;
int sin_val[36]={0,9,17,26,34,42,50,57,64,71,77,82,87,91,94,97,98,99,100,99,98,97,94,91,87,82,77,71,64,57,50,42,34,26,17,9};
void pwm_setup()
{
TMOD = 0;
EA = 1;
ET0 = 1;
TR0 = 1;
}
/* Timer 0 Interrupt service routine */
void timer0() interrupt 1
{
if(zcr==0)
{
PWMPIN2=0;
if (!pwm_flag) /* Start of High level */
{
TH0 = pwm_width; /* Load timer */
}
else /* Start of Low level */
{
TH0 = 255 - pwm_width; /* Load timer */
}
pwm_flag = ~pwm_flag;; /* Toggle flag */
PWMPIN1 = ~PWMPIN1; /* Toggle PWM o/p pin 1 */
TF0 = 0;
/* Clear interrupt flag */
}
if(zcr==1)
{
PWMPIN1=0;
if (!pwm_flag) { /* Start of High level */
TH0 = pwm_width; /* Load timer */
}
else { /* Start of Low level */
TH0 = 255 - pwm_width; /* Load timer */
}
pwm_flag = ~pwm_flag;; /* Toggle flag */
PWMPIN2 = ~PWMPIN2; /* Toggle PWM o/p pin 2 */
TF0 = 0;
/* Clear interrupt flag */
}
if(!pwm_flag) //setting next pwm_width before start of high level
{
pwm_width = 25+(sin_val[i]/100)*230;
if(i<35)
i++;
else
{
i=0;
zcr=~zcr; //[B]Edited later[/B]
}
}
}
void pwm_stop()
{
TR0 = 0; /* To disable PWM */
}
void main()
{
pwm_width = 25+(sin_val[0]/100)*230; //No. of samples = 36, Total duty period = 230uS, timer counts from 25 to 255 for 12Mhz crystal
i++;
pwm_setup();
while(1)
{
//This part is not required for the moment
}
}
Last edited: