Hello,
I'm trying to generate a sine wave that oscillates between 0V-5V at 1Hz with P12F683. So far, without paying attention to the offset I could form the wave. It's a nice sinusoidal wave. I take 50 samples for each period. I use 5 times 4ms PWM for each sample and then Timer2 interrupts; then I fetch the next sample's duty cycle from the look-up table.
However, I can't make the wave swing around 2.5V. The problem is that for 2.5V offset, some values of the look-up table goes beyond 255 which prevents me from setting CCPR1L's value directly from look-up array. So , for every value that is greater than 255, I thought designating 2 LSBs to CCP1CON.DC1B bits and 7 MSBs to CCPR1L register by doing bit shift operations would solve the problem. But it's not working well. And I can't spot the problem. I'd be grateful if you could share your opinions.
Kind Regards,
Kırlangıç
Here's the code;
I'm trying to generate a sine wave that oscillates between 0V-5V at 1Hz with P12F683. So far, without paying attention to the offset I could form the wave. It's a nice sinusoidal wave. I take 50 samples for each period. I use 5 times 4ms PWM for each sample and then Timer2 interrupts; then I fetch the next sample's duty cycle from the look-up table.
However, I can't make the wave swing around 2.5V. The problem is that for 2.5V offset, some values of the look-up table goes beyond 255 which prevents me from setting CCPR1L's value directly from look-up array. So , for every value that is greater than 255, I thought designating 2 LSBs to CCP1CON.DC1B bits and 7 MSBs to CCPR1L register by doing bit shift operations would solve the problem. But it's not working well. And I can't spot the problem. I'd be grateful if you could share your opinions.
Kind Regards,
Kırlangıç
Here's the code;
Rich (BB code):
#include <pic.h>
#include <xc.h>
#include<stdlib.h>
#pragma config FOSC = INTOSCIO, MCLRE = OFF, WDTE = OFF
#define XTAL_FREQ = 4000000
void InitPWM();
char sinval[50]={0, 31, 62, 92, 120, 147, 171, 193, 211, 226, 238, 246,
250, 250, 246, 238, 226, 211, 193, 171, 147, 120, 92, 62, 31, 0, -31,
-62, -92, -120, -147, -171, -193, -211, -226, -238, -246, -250, -250,
-246, -238, -226, -211, -193, -171, -147, -120, -92, -62, -31};
int flag = 0;
int index=0;
int main(int argc, char** argv)
{
InitPWM();
while(1)
{
if(flag==5)
{
unsigned int y_value= sinval[index]+250; //250 added due to char's limit
if(y_value>255)
{
int index_CCPR1L=y_value>>2; //get 7 MSB
int index_CCP1CON=y_value<<7;
CCPR1L = index_CCPR1L; //designate MSB's to CCPR1L
CCP1CONbits.DC1B =index_CCP1CON>>7; //designate 2 LSBs to CCP1CONbits.DC1B
}
else
{
CCPR1L=y_value;
}
index++;
if(index==50)
{index=0;
CCPR1L=index_CCPR1L;
CCP1CON =index_CCP1CON>>7;
}
flag=0;
}
}
return(EXIT_SUCCESS);
}
void InitPWM()
{
OSCCONbits.SCS=1; //Internal oscillator is used for system clock
OSCCONbits.IRCF=0b110; // Internal Oscillator Frequency 4 MHz
CCPR1L=0b00000000; // Duty Cylce %0
CCP1CON=0b00001100; // bit3-0 PWM Mode
TRISIO2=0; // CCP1 output
PR2=0b11111001; // 4 ms = (PR +1) *4 * 250ns * TMR2 Prescale value
T2CON=0b00000111; // Timer2 is on , Prescale 1:16
PIE1bits.TMR2IE=1; // Enable TMR2 PR2 match
INTCONbits.PEIE=1; // Enable Peripherial Interrupt
INTCONbits.GIE=1; // Enable Global Interrupt
}
void interrupt Interrupt()
{
if (TMR2IF)
{
flag++;
TMR2IF=0;
}
}