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.
 

Thread Starter

Anirban Raha

Joined Dec 4, 2013
70
Hi,
Can anyone at least suggest a good simulator that is free and has an oscilloscope with which I can check my output?
 
Top