Does this code produce 60Hz sine wave? - 8051

Thread Starter

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:

Thread Starter

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.
 
Top