# Does this code produce 60Hz sine wave? - 8051

#### Anirban Raha

Joined Dec 4, 2013
70
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)

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:

#### Anirban Raha

Joined Dec 4, 2013
70
Hi,
The Proteus Demo version is not working for 8051...some "invalid customer key" error is being generated...anyone with a good simulator would be so kind as to check my code? I just want to know whether the 8051 P2.0 and P2.1 pins will produce a sinusoidal PWM signal of 60Hz (per cycle and not PWM frequency) or not with this code.