HOW TO GENERATE SIN WAVE USING PIC MICROCONTROLLER

Here is an example that I did for a project (that I never finished and wrote up).
PicSW1.jpg

There was an RC filter attached to the output of the PWM pin (R=330 ohms and C 1.0uf) and some notes from an old post where I was asking a question about RC filters that @OBW0549 was kind enough to help me with.....

I have the PIC running at 16Mz. I have the resolution of the PWM duty at 9 bits – (PR2 register=0xFE). As an aside, you cannot get 100% duty cycle using the full 10-bit resolution and that is why I am doing it that way. Timer 2 prescaler =1.

My PWM frequency is, therefore, 15686.27451 Hz and the period is .00006375 sec (63.75 us). I have 40 duty cycle values to construct the sine wave. Thus, the frequency of the sine wave is calculated at 392.16 Hz.


C:
/******************************************************************************
PWMsine1840
Program PWM Sine Wave using a PIC12F1840
//
***  This software Is offered strictly as-is with no warranties whatsoever.
  Use it at your own risk.  ***
MPLAB X IDE V.4.05
XC-8 V.1.45
******************************************************************************/
#include <xc.h>
// set config bits
#pragma config FOSC=INTOSC, PLLEN=OFF, WDTE=OFF, MCLRE=ON,
#pragma config CLKOUTEN=OFF, IESO=OFF, FCMEN=OFF,CP=OFF, CPD=OFF,BOREN=OFF
#pragma config WRT=OFF,STVREN=ON,BORV=LO,LVP=OFF

#define _XTAL_FREQ  16000000 // used by the __delay_ms(xx) and __delay_us(xx)
//-------------------------
// globals
  volatile unsigned char Dcount =0;
  /* These are the duty cycle percentages for the sine wave
  50, 58, 65, 73, 79, 85, 90, 95, 98, 99,
  100, 99, 98, 95, 90, 85, 79, 73, 65, 58,
  50, 42, 35, 27, 21, 15, 10,  5,  2,  1,
  0,  1,  2,  5, 10, 15, 21, 27, 35, 42  */
 
  // 8 most significant bits of duty cycle
  const unsigned char DCThigh[40]=
  {
  128,148,166,186,202,217,230,242,250,252,
  255,252,250,242,230,217,202,186,166,148,
  128,107, 89, 69, 54, 38, 26, 13,  5,  2,
  0,  2,  5, 13, 26, 38, 54, 69, 89,107 
  };
  // 2 least significant bits of duty cycle
  const unsigned char DCTlow[40]=
  {
  2,0,3,1,2,3,2,1,0,2,
  0,2,0,1,2,3,2,1,3,0,
  2,0,1,3,2,1,2,3,0,2,
  0,2,0,3,2,1,2,3,1,0
  };
//-------------------------
  void main(){
  OSCCON = 0x7A; // 16 MHz with internal oscillator
  __delay_us(100);
  PR2 = 0xfe;  // PWM period register for 40 kHz 
  T2CON = 0x4; // prescaler=1 / timer on 
  CCP1CONbits.CCP1M=0x0C;  // select PWM mode for CCP module
  CCP1CONbits.P1M=0x00;    // select single output on CCP1 pin (RA2) PIN 5 
  // load  0 length duty cycle
  CCPR1L=0;
  CCP1CONbits.DC1B=0;
  PIE1bits.TMR2IE =1; // enable Timer2 interrupt 
  INTCON =0xC0;  // enable Global interrupt, peripheral interrupt 
  TRISA=0x00;
  __delay_us(10); 
  // load starting duty cycle which will be latched after first overflow
  // that overflow will also be handled by the ISR which will load
  // the next duty cycle value to be latched 
  CCPR1L=DCThigh[Dcount];
  CCP1CONbits.DC1B=DCTlow[Dcount];
  //
  // In this example we stay in a do-nothing loop, but additional
  // code could be used
  here: goto here;  // we are done so just stay put
  }
//------------------------- 
// ISR for Timer 2 
  void interrupt Timer2_ISR(void)
  {
  if (TMR2IF) {
  ++Dcount; 
  if(Dcount == 40) { // Increment counter and rollover if needed
  Dcount = 0;
  }
  // load the new duty cycle to latch on next overflow
  CCPR1L=DCThigh[Dcount];
  CCP1CONbits.DC1B=DCTlow[Dcount];
  TMR2IF = 0;
  }
  }
//-------------------------
edited: used the right code tag
 
Last edited:

danadak

Joined Mar 10, 2018
4,057
What harmonic rejection you shooting for, resolution of signal, accuracy of
signal ?

Just as an aside when you post think about posting basic info, saves you time,
same for helpers here at site. A bullet list so as to speak of specifications, some
times description of application helps as well.

Regards, Dana.
 
Last edited:

danadak

Joined Mar 10, 2018
4,057
For future reference PSOC has an on chip WavedDac. Also there is an application
where a custom component with its internal fabric was configured to do a DDS should
that be needed. A component in PSOC is an onchip resource.



Note with Wavedac component its fairly easy to do burst of N cycles, and onchip
PGA allows amplitude scaling. Or sweep it. Of course arbitrary waveform generation
can also be done. And you have a choice of Vdac or Idac output.

DDS -


DDS can drive the clock on the Wavedac, or just use Wavedac APIs to
set freq.


Regards, Dana.
 
Last edited:
Top