Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Sine Wave of Frequency 50Hz using DAC0808

Status
Not open for further replies.

xpress_embedo

Advanced Member level 4
Advanced Member level 4
Joined
Jul 5, 2011
Messages
1,154
Helped
161
Reputation
396
Reaction score
189
Trophy points
1,353
Location
India
Activity points
10,591
Hello!! Everyone I have to generate a sine wave of frequency 50Hz using PIC16F877A and DAC0808

I have interfaced and generated the Sine Wave, but don't know how to generate a sharp sine wave of frequency 50 Hz

Can anyone help me???

Thanks in Advance

Regards


Arun Sharma
Capture.PNG

Capture.PNG
 

Arun,


You must to calculate and generate a sine map to record into a table in order to sample at DAC device.


+++
 

andre_teprom

Sorry, I don't understand what you want me to do....
Can you pls elaborate what u want to say
 

I believe Andre is referring to the generation of a lookup table of sine wave values to drive your DAC.


A table or array of the values of a sine wave is generated with a fixed time interval between sample points.

A timer and the associated interrupt service routine (ISR) can be utilized to fetch the values of the sine wave in sequential order at a set time interval and output these values to the DAC.

Example of an 8051/DAC Sine Wave generation with Lookup Table:

8051 Voice with DAC in C

Microchip Appnote concerning sine wave generation, the Resistor Ladder example utilizes a Lookup Table:

D/A Conversion Using PWM and R-2R Ladders to Generate Sine and DTMF Waveforms


BigDog
 
Thanks BigDogguru the information provided by you is always helpful to me...

But it seems to be much complicated for me right now...

my main logic for generating the sine wave is as follow:-


const unsigned char wave[181] = {128,132,137,141,146,150,155,159,163,168,172,176,180,184,188,192,196,200,203,207,210,214,217,220,223,226,229,232,234,237,239,241,243,245,247,248,250,251,252,253,254,254,255,255,255,255,255,255,255,255,254,253,252,251,250,248,247,245,243,241,239,237,234,232,229,226,223,220,217,214,210,207,203,200,196,192,188,184,180,176,172,168,163,159,155,150,146,141,137,132,128,124,119,115,110,106,101,97,93,88,84,80,76,72,68,64,60,56,53,49,46,42,39,36,33,30,27,24,22,19,17,15,13,11,9,8,6,5,4,3,2,1,1,0,0,0,0,0,1,1,2,3,4,5,6,8,9,11,13,15,17,19,22,24,27,30,33,36,39,42,46,49,53,56,60,64,68,72,76,80,84,88,93,97,101,106,110,115,119,124,128};


The above array is used to generate the Sine Wave at the Output of the DAC
and my logic for generating wave from this is as follow:

for(i=0;i<181;i++)
{
PORTD = wave;
__delay_us(70);
}

When i give 70 in the delay function it gives me a frequency of approx 50Hz

But in my project i have to provide a variable sine wave in the range 40Hz to 60Hz

This range must be selected by using potentiometer
When the know of the Potentiometer changes the Frequency of the sine wave must change...
Pls help me on this...

Its very important for me...

Thanking you
Arun Sharma
 

You could easily implement an ADC channel on the PIC to determine the position of the Pot.

You start with an initial delay to generate approximately 40Hz and add an additional value to generate a frequency range from 0Hz to 20Hz on top of the baseline 40Hz, this will in turn give you a frequency range of 40Hz to 60Hz based on the position of the Pot.

By the way, the array you have posted above, is in fact a lookup table.

BigDog
 
Thanks BigDogGuru for your help...

Whatsoever you told me i had implemented that before, but my result are not at all satisfactory,
Here is the Snapshot of What i Got
Capture.PNG
 

Thanks BigDogGuru for your help...

Whatsoever you told me i had implemented that before, but my result are not at all satisfactory,
Here is the Snapshot of What i Got
View attachment 66909

The gap between each cycle is most likely due to the use of a "for" loop, rather than a SuperLoop structure like a while(1).

Post or upload your code in its entirety, so that I can examine it further.

The benefit of using a timer in conjunction with an timer interrupt is that the interrupt structure can produce a more precise and steady waveform, as well as taking care of many of the time issues.

What compiler are you using?

BigDog
 
I am using Hi-Tech C Compiler Lite Edition and MPLAB IDE
and Using PIC16F877A micro-controller..

Actually this is my Coding faults..
Actually i am not a very good programmer and don't use my controller memory efficiently ....
Thats why i am stuck in this problem...


And yes there is a big loop thats why i am getting such huge time gaps..

Can you tell me where to insert the timer delays....
and how to generate the pure sine wave with that...
I am little bit confused of getting data using timers from my look up table..

Oh!! my *** i don't know what to say right now...




I will do some R&D on this Project and then inform you..

Right now i am not in a condition to do asnything

Thanks for Your Support and help..



Good Night

Regards
Arun Sharma
 
Here's a similar example for the PIC:

PIC Tone generator

The following is for an ARM LPC21XX, however it illustrates the use of timers, timer interrupts and ADC to generator a variable sine wave.

The only element missing is the lookup table, this example uses direct calculations:

Code:
/******************************************************************************/
/* BLINKY.C: LED Flasher                                                      */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools.                    */
/* Copyright (c) 2005-2006 Keil Software. All rights reserved.                */
/* This software may only be used under the terms of a valid, current,        */
/* end user licence from KEIL for a compatible version of KEIL software       */
/* development tools. Nothing else gives you the right to use this software.  */
/******************************************************************************/
                  
#include <stdio.h>                         /* standard I/O .h-file */
#include <LPC213x.H>                       /* LPC213x definitions  */
#include <math.h>

extern void init_serial (void);            /* Initialize Serial Interface     */

int volatile timeval;


/*
 * ----- Parameters and Variables for Sine Wave Generator ----- 
 */
 
unsigned long OutFreq = 480l;       /* Output Frequency (Range  1Hz - 4000Hz) */
#define OutAmpl 600                 /* Output Amplitute (Range  0 - 0.99)     */
#define PI  3.1415926
#define T0_RlFreq  8000             /* Timer 0 Reload Frequency               */

struct tone  {                      /* struct for Sine Wave Generator Signal  */
  int  cos;                         /* cosine factor                          */
  long y1;                          /* y[-1] value                            */
  int  y2;                          /* y[-2] value                            */
};                                                                            

int  NewFreq;                       /* New Frequency Setup indication         */

short tval;
signed char cval;
struct tone Tone;


/*
 * Generate Sine Wave Tone
 */
static void Generate_Sine (struct tone *t)  {
  int y;
  y     = (t->cos * (t->y1 >> 14)) - t->y2;
  t->y2 = t->y1;
  t->y1 = y;
  tval  = t->y1 >> 16;
  cval  = tval;
}


/*
 * Initialize the Sine Wave Tone Generator
 */
__inline void Init_Sine (int OutFreq) {
  Tone.cos = (cos (2*PI*((float)OutFreq/T0_RlFreq))) * 32768;
  Tone.y1  = 0;
  Tone.y2  = (sin (2*PI*((float)OutFreq/T0_RlFreq)) * OutAmpl) * 32768; 
}


/* Timer Counter 0 Interrupt executes each 10ms @ 60 MHz CPU Clock */
__irq void tc0 (void) {
  ++timeval;

  if (NewFreq)  {   /* The frequency changes when a new ADC value is measured */
    Init_Sine (NewFreq);
    NewFreq = 0;
  }

  Generate_Sine (&Tone);
  DACR = ((Tone.y1 >> 10) & 0xFFC0) + 0x8000;   
  T0IR        = 1;                             /* Clear interrupt flag        */
  VICVectAddr = 0;                             /* Acknowledge Interrupt       */  
}


/* Setup the Timer Counter 0 Interrupt */
void init_timer (void) {
  T0MR0 = 1874;                                /* 0.125uSec = 1875-1 counts   */
  T0MCR = 3;                                   /* Interrupt and Reset on MR0  */
  T0TCR = 1;                                   /* Timer0 Enable               */
  VICVectAddr0 = (unsigned long)tc0;           /* set interrupt vector in 0   */
  VICVectCntl0 = 0x20 | 4;                     /* use it for Timer0 Interrupt */
  VICIntEnable = 0x00000010;                   /* Enable Timer0 Interrupt     */
}


void delay (void) {                         /* Delay function */
  unsigned int cnt;
  unsigned int val;
  static unsigned int oldval;  
  int diff;

  AD0CR |= 0x01200000;                      /* Start A/D Conversion */
  do {
    val = AD0DR;                            /* Read A/D Data Register */
  } while ((val & 0x80000000) == 0);        /* Wait for end of A/D Conversion */
  AD0CR &= ~0x01000000;                     /* Stop A/D Conversion */
  val = (val >> 6) & 0x03FF;                /* Extract AIN0 Value */

  diff = val - oldval;
  if (diff > 10 || diff < -10)  {
    oldval = val;
    NewFreq = 1200 - val;
  }
 
  printf ("\nAIN1 Result = 0x%03X", val);   /* Output A/D Conversion Result */

  val = (val >> 2) << 12;                   /* Adjust Delay Value */
  for (cnt = 0; cnt < val; cnt++);          /* Delay */
}


int main (void) {
  unsigned int n;

  IODIR1  = 0x00FF0000;                     /* P1.16..23 defined as Outputs  */
  AD0CR   = 0x00200402;                     /* Setup A/D: 10-bit AIN0 @ 3MHz */
  PINSEL1 = 0x01080000;                     /* enable DAC */

  init_serial();                            /* Initialize Serial Interface   */
  init_timer ();
  
  while (1) {                               /* Loop forever */
    for (n = 0x00010000; n <= 0x00800000; n <<= 1) {
      /* Blink LED 0, 1, 2, 3, 4, 5, 6, 7 */
      IOSET1 = n;                           /* Turn on LED */
      delay();                              /* Delay */
      IOCLR1 = 0x00FF0000;                  /* Turn off LEDs */
    }
  }
}

It would be fairly straight forward to port a similar technique to the PIC.

BigDog
 

Hello!! BigDogGuru

I am using Timer-1 Interrupt in PIC16F877A to generate a frequency of 54Hz Approx.. I will adjust it later when my code will be final

Here is my code

Code:
/***This is With Interrupt***/
#include<htc.h>
#include<string.h>
#include<stdio.h>

#define _XTAL_FREQ 20000000

void T1_ISR(void);	//ISR

void interrupt Check_Interrupt(void)
{
	if(PIR1bits.TMR1IF == 1)
		T1_ISR();			//Timer-1 Interrupt Occurs
}


const unsigned char wave[181] = {128,132,137,141,146,150,155,159,163,168,172,176,180,184,188,192,196,200,203,207,210,214,217,220,223,226,229,232,234,237,239,241,243,245,247,248,250,251,252,253,254,254,255,255,255,255,255,255,255,255,254,253,252,251,250,248,247,245,243,241,239,237,234,232,229,226,223,220,217,214,210,207,203,200,196,192,188,184,180,176,172,168,163,159,155,150,146,141,137,132,128,124,119,115,110,106,101,97,93,88,84,80,76,72,68,64,60,56,53,49,46,42,39,36,33,30,27,24,22,19,17,15,13,11,9,8,6,5,4,3,2,1,1,0,0,0,0,0,1,1,2,3,4,5,6,8,9,11,13,15,17,19,22,24,27,30,33,36,39,42,46,49,53,56,60,64,68,72,76,80,84,88,93,97,101,106,110,115,119,124,128};
/*FDD5*/
unsigned int i=0;
void main()
{

	TRISD = 0x00;
	T1CON = 0x01;
	TMR1H = 0xFE;	//To Generate 111usec Pulse
	TMR1L = 0x50;
	//Enable all Interrupts
	INTCONbits.TMR0IE = 1;
	PIE1bits.TMR1IE = 1;
	INTCONbits.PEIE = 1;
	INTCONbits.GIE = 1;
	while(1)
	{
		if(i == 181)
		{	i=0;
		}
	}
}
void T1_ISR(void)
{
	PORTD = wave[i];
	i++;
	TMR1H = 0xFE;
	TMR1L = 0x50;
	PIR1bits.TMR1IF = 0;	//Clear the Timer-1 Flag Bit	
}

Now pls tell me how can i adjust the values of delay i.e TMR1H and TMR1L Register to get a Variable sine Wave...

I am not fully professional with the use of ADC.. but i can use PIC16F877A adc...
But what are the parameters by which i can control the TMR1L and TMR1H values..

Suppose i using ADC with Vref of 5V which means that 1024 steps do i require such large step size..
can you pls provide me some more details

And one more thing

As generation of the sine wave is much more important then the ADC Conversion thats why
I want to place my T1_ISR in high Priority Interrupt
But ADC_Conversion Routine Must be in Low_Priority Interrupt

How can i do that i Hi-Tech C Compiler

For High Priority i had used
void interrupt check_isr(void) //Note the Interrupt Keyword

What should i do with Low Priority Interrupt

Pls Help Me


This is my sine wave generated from the above code
Capture.PNG


Regards
Arun Sharma
 
Last edited by a moderator:
Now pls tell me how can i adjust the values of delay i.e TMR1H and TMR1L Register to get a Variable sine Wave...

I would update these values in the ADC routine.

I am not fully professional with the use of ADC.. but i can use PIC16F877A adc...
But what are the parameters by which i can control the TMR1L and TMR1H values..

Suppose i using ADC with Vref of 5V which means that 1024 steps do i require such large step size..
can you pls provide me some more details

The following is a fairly good PIC ADC Tutorial, study the tutorial along with the PIC16F877A datasheet and you should be able to implement a simple Pot ADC input.

Using Analog to Digital Converter (ADC) – PIC Microcontroller Tutorial



As generation of the sine wave is much more important then the ADC Conversion thats why
I want to place my T1_ISR in high Priority Interrupt
But ADC_Conversion Routine Must be in Low_Priority Interrupt

The PIC16F877A has only one user definable interrupt vector, for the ISR to handle the more than one interrupt condition, the flag bit of each enable interrupt must be tested to determine what interrupt condition has actually occurred.

You might consider putting the ADC conversion routine within your SuperLoop, the while(1) within main(), as it is a lower priority task. If a change in the ADC value is detected, the values in the TMR0 are updated.

BigDog
 
Thanks For your Support...

Right Now I had write a code which must vary the Frequency of Sine Wave on Changing the Knob of Potentiometer

But may be my variation is not to big or something else happens due to which i am not able to see the variation in the sine wave...

Here is my Code Hope You Understand What i write here
Code:-

Code:
/***This is With Interrupt***/
#include<htc.h>
#include<string.h>
#include<stdio.h>

#define _XTAL_FREQ 20000000



void T1_ISR(void);	//ISR for Generating Delay
void AD_ISR(void);	//ISR for A/D Conversion


void interrupt Check_Interrupt(void)
{
	if(PIR1bits.TMR1IF == 1)
		T1_ISR();			//Timer-1 Interrupt Occurs
	if(PIR1bits.ADIF == 1)	//A/D Interrupt Occurs
		AD_ISR();
}



const unsigned char wave[181] = {128,132,137,141,146,150,155,159,163,168,172,176,180,184,188,192,196,200,203,207,210,214,217,220,223,226,229,232,234,237,239,241,243,245,247,248,250,251,252,253,254,254,255,255,255,255,255,255,255,255,254,253,252,251,250,248,247,245,243,241,239,237,234,232,229,226,223,220,217,214,210,207,203,200,196,192,188,184,180,176,172,168,163,159,155,150,146,141,137,132,128,124,119,115,110,106,101,97,93,88,84,80,76,72,68,64,60,56,53,49,46,42,39,36,33,30,27,24,22,19,17,15,13,11,9,8,6,5,4,3,2,1,1,0,0,0,0,0,1,1,2,3,4,5,6,8,9,11,13,15,17,19,22,24,27,30,33,36,39,42,46,49,53,56,60,64,68,72,76,80,84,88,93,97,101,106,110,115,119,124,128};

unsigned int i=0;
unsigned char adc_data_l,adc_data_h;
void main()
{
	TRISAbits.TRISA0 = 1;	//Channel A0 as Input Port
	TRISD = 0x00;

	//Running ADC For the First Time Before Starting the Interrupt
	//So That we Can Acquire the Delay Value
	ADCON0 = 0x81;
//Fosc/64 is Selected
//Channel-0 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0xCE;
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
		__delay_ms(100);
		ADCON0bits.GO = 1;	//Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here Until Conversion Gets Over
		adc_data_l = ADRESL;	
		adc_data_h = ADRESH;	


	T1CON = 0x01;
	TMR1H = adc_data_h;
	TMR1L = adc_data_l;
	//Enable all Interrupts

	PIE1bits.TMR1IE = 1;
	PIR1bits.ADIF = 0;	//Clear A/D Flag Bit
	PIE1bits.ADIE = 1;	//Enable A/D Interrupt Bit
	INTCONbits.PEIE = 1;
	INTCONbits;GIE = 1;
	
	while(1)
	{

		if(i == 181)
		{	i=0;
		}

	}
}

void T1_ISR(void)
{
	PORTD = wave[i];
	i++;
	TMR1H = adc_data_h;
	TMR1L = adc_data_l;
	PIR1bits.TMR1IF = 0;	//Clear the Timer-1 Flag Bit	
}

//This is Interrupt Service Routine for ADC
void AD_ISR(void)
{
	adc_data_l = ADRESL;
	adc_data_h = ADRESH;
	//adc_data = adc_data | ADRESL;

	PIR1bits.ADIF = 0;	//Clears the Interrupt
}

I am not able to view the variation on the Oscilloscope...
But it must show some variation frequency according to me...
May Be my duration is so small that i will not be able to see the change

Please enclose your posted code in code tags CODE /CODE either manually or use the # button under "Advanced"
 
Last edited by a moderator:

Code:
void main()
{
	TRISAbits.TRISA0 = 1;	//Channel A0 as Input Port
	TRISD = 0x00;

	//Running ADC For the First Time Before Starting the Interrupt
	//So That we Can Acquire the Delay Value
	ADCON0 = 0x81;
//Fosc/64 is Selected
//Channel-0 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0xCE;
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
		__delay_ms(100);
[COLOR="#FF0000"]		ADCON0bits.GO = 1;	//Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here Until Conversion Gets Over[/COLOR]
		adc_data_l = ADRESL;	
		adc_data_h = ADRESH;	


	T1CON = 0x01;
	TMR1H = adc_data_h;
	TMR1L = adc_data_l;
	//Enable all Interrupts

	PIE1bits.TMR1IE = 1;
	PIR1bits.ADIF = 0;	//Clear A/D Flag Bit
	PIE1bits.ADIE = 1;	//Enable A/D Interrupt Bit
	INTCONbits.PEIE = 1;
	INTCONbits;GIE = 1;
	
	while(1)
	{

		if(i == 181)
		{	i=0;
		}

	}
}

//This is Interrupt Service Routine for ADC
void AD_ISR(void)
{
	adc_data_l = ADRESL;
	adc_data_h = ADRESH;
	//adc_data = adc_data | ADRESL;

	PIR1bits.ADIF = 0;	//Clears the Interrupt
}

It appears you are actually carrying out only one ADC at the beginning of main(). The ADC interrupt never occurs, so the timer values are never modified.

Which is why you not seeing any change in the frequency.

I would put the ADC routine within the SuperLoop, while(1) within main(). The ADC routine would constantly write the 10-bit result of the ADC to a global variable and use this ADC result to calculate the new timer value, Int40HZTMR0 + 20HZVAL*(ADCVAL/1023) = NEWTMR0. Then within the TMR0 ISR, if i=0, then the new TMR0 value is loaded into the timer, this will only start a new frequency Sine Wave when the last cycle has ended, preventing undesirable "artifacts" from occurring.

BigDog
 
Hello!!! BigDogGuru!!!

Finally i am able to Change the Frequency of the Sine Wave with the Help of the POT connected at RA0 pin of the PIC16F877A..

I am using a 10k ohm resistor along with a pot of 1k and i am tuning that pot..
As Shown Below:-

Capture.PNG


And I am programming my ADC in such a way that 1% variation in the POT will approx result in 1% increase in ADC_Data
And then storing these data in an temporary variable adc_data

and after that i am using a switch case to compare and adjust the timer-1 register values

Right now i have just tested this and its working fine...
Here is my code:

CODE:

Code:
#include<htc.h>

#define _XTAL_FREQ 20000000

void T1_ISR(void);	//ISR for Generating Delay


void interrupt Check_Interrupt(void)
{
	if(PIR1bits.TMR1IF == 1)
		T1_ISR();			//Timer-1 Interrupt Occurs
}

const unsigned char wave[181] = 

{128,132,137,141,146,150,155,159,163,168,172,176,180,184,188,192,196,200,203,207,210,214,217,220,

223,226,229,232,234,237,239,241,243,245,247,248,250,251,252,253,254,254,255,255,255,255,255,255,2

55,255,254,253,252,251,250,248,247,245,243,241,239,237,234,232,229,226,223,220,217,214,210,207,20

3,200,196,192,188,184,180,176,172,168,163,159,155,150,146,141,137,132,128,124,119,115,110,106,101

,97,93,88,84,80,76,72,68,64,60,56,53,49,46,42,39,36,33,30,27,24,22,19,17,15,13,11,9,8,6,5,4,3,2,1

,1,0,0,0,0,0,1,1,2,3,4,5,6,8,9,11,13,15,17,19,22,24,27,30,33,36,39,42,46,49,53,56,60,64,68,72,76,

80,84,88,93,97,101,106,110,115,119,124,128};

unsigned int i=0;
unsigned char adc_data;
void main()
{
	TRISAbits.TRISA0 = 1;	//Channel A0 as Input Port
	TRISB = 0x00;
	TRISC = 0x00;
	TRISD = 0x00;

	//Running ADC For the First Time Before Starting the Interrupt
	//So That we Can Acquire the Delay Value
	ADCON0 = 0x81;
//Fosc/64 is Selected
//Channel-0 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0xCE;
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
	adc_data = 0x00;
	T1CON = 0x01;
	
	TMR1H = 0xFD;	//To Generate 111usec Pulse
	TMR1L = 0xCE;	//These Values are Random

	//Enable all Interrupts

	PIE1bits.TMR1IE = 1;
	//PIR1bits.ADIF = 0;	//Clear A/D Flag Bit
	//PIE1bits.ADIE = 1;	//Enable A/D Interrupt Bit
	INTCONbits.PEIE = 1;
	INTCONbits;GIE = 1;
	while(1)
	{
		__delay_us(100);
		ADCON0bits.GO = 1;	//Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here Until Conversion Gets Over
		adc_data = ADRESL;		
	}
}


void T1_ISR(void)
{
	PORTD = wave[i];
	i++;
		switch(adc_data)
		{
			case 0x00:
					TMR1H = 0xFD;	//40Hz Frequency
					TMR1L = 0x00;
					break; 
			case 0x01:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0xA0;
					break;
			case 0x02:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
		}

	if(i == 181)
	i=0;

	PIR1bits.TMR1IF = 0;	//Clear the Timer-1 Flag Bit	
}

Its working fine for me right now,

But my problem is that...

Its very difficult to measure the frequency of the sine wave on the proteus oscilloscope for every value i loaded in the timer register..
can you tell me how to measure the frequency of the sine wave exactly in proteus by any other means...

or some particular format to generate accurate timer delays..


Regards
Arun Sharma
 

Its very difficult to measure the frequency of the sine wave on the proteus oscilloscope for every value i loaded in the timer register..
can you tell me how to measure the frequency of the sine wave exactly in proteus by any other means...

or some particular format to generate accurate timer delays..

A 40Hz Sine Wave has a period of 25ms, divided by the number of intervals in your lookup table, equals approximately 138us timer interval.

A 60Hz Sine Wave has a period of 16.7ms, divided by the number of intervals in your lookup table, equals approximately 92us timer interval.

The difference between the intervals of the 40Hz and 60Hz is 46us.

Therefore with the POT at 5V, the timer interval would be 138us, when the POT is OV, the timer interval is 92us.

At half range, the POT at 2.5v, the timer interval would need to be 115us to produce a 50hz Sine Wave or an ADC value of 127.

Therefore the formula/algorithm would be:

timer interval = 92us + 46us * (ADC Value/255)

BigDog
 
To get 138 us delay i have to load my TMRH:TMRL = FD4E
To get 111 us delay i have to load my TMRH:TMRL = FDD5
To get 94 us delay i have to load my TMRH:TMRL = FE16

But when i load these values in the Timer-Register the frequency of the sine wave is not what i wanted it to be...

But when i load FD9C in timer register i am getting the 40Hz frequency..

And Similarly FE90 is resulting in 60Hz Frequency..

But i don;t know what happens after all this...

when timer is loaded with FD9C it is giving 40Hz and after that at FE90 it is giving less than 40Hz..
I don;t know whats going on..

Pls Help me..
And My ADC is of 10-Bit


Code:
/***This is With Interrupt***/
#include<htc.h>
#include<string.h>
#include<stdio.h>

#define _XTAL_FREQ 20000000
#define LCD_DATA PORTB
#define RS PORTCbits.RC0
#define RW PORTCbits.RC1
#define EN PORTCbits.RC2

#define Second_Bit PORTCbits.RC4
void lcdcmd(unsigned char value);
void lcddata(unsigned char value);
void lcdstr(unsigned char msg[]);

void T1_ISR(void);	//ISR for Generating Delay


void interrupt Check_Interrupt(void)
{
	if(PIR1bits.TMR1IF == 1)
		T1_ISR();			//Timer-1 Interrupt Occurs
	/*if(PIR1bits.ADIF == 1)	//A/D Interrupt Occurs
		AD_ISR();*/
}


const unsigned char msg1[] = "PIC16F877A";
const unsigned char msg2[] = "MATLAB ACADEMY";
const unsigned char wave[180] = {128,132,137,141,146,150,155,159,163,168,172,176,180,184,188,192,196,200,203,207,210,214,217,220,223,226,229,232,234,237,239,241,243,245,247,248,250,251,252,253,254,254,255,255,255,255,255,255,255,255,254,253,252,251,250,248,247,245,243,241,239,237,234,232,229,226,223,220,217,214,210,207,203,200,196,192,188,184,180,176,172,168,163,159,155,150,146,141,137,132,128,124,119,115,110,106,101,97,93,88,84,80,76,72,68,64,60,56,53,49,46,42,39,36,33,30,27,24,22,19,17,15,13,11,9,8,6,5,4,3,2,1,1,0,0,0,0,0,1,1,2,3,4,5,6,8,9,11,13,15,17,19,22,24,27,30,33,36,39,42,46,49,53,56,60,64,68,72,76,80,84,88,93,97,101,106,110,115,119,124};
/*FDD5*/
unsigned int i=0;
unsigned char adc_data;
void main()
{
	TRISAbits.TRISA0 = 1;	//Channel A0 as Input Port
	TRISB = 0x00;
	TRISC = 0x00;
	TRISD = 0x00;
	EN = 0;
	lcdcmd(0x38);
	lcdcmd(0x0E);
	lcdcmd(0x01);
	lcdcmd(0x06);
	lcdcmd(0x83);
	lcdstr(msg1);
	lcdcmd(0xC1);
	lcdstr(msg2);
	lcdcmd(0x01);
//	__delay_ms(500);
	lcdcmd(0x80);
	lcdstr("Initializing....");
	lcdcmd(0xC6);
	lcdstr("DAC.......");
	lcdcmd(0x01);
	lcdcmd(0x80);
	lcdstr("See Oscilloscope");
	//Running ADC For the First Time Before Starting the Interrupt
	//So That we Can Acquire the Delay Value
	ADCON0 = 0x81;
//Fosc/64 is Selected
//Channel-0 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0xCE;
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
	/*	__delay_ms(100);
		ADCON0bits.GO = 1;	//Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here Until Conversion Gets Over
		adc_data = ADRESL;		// & 0x00FF;
		//adc_data_h = ADRESH;		 //& 0x00FF;
		/*adc_data = adc_data<<8;
		adc_data = adc_data | ADRESL;*/
	adc_data = 0x00;
	T1CON = 0x01;
	TMR1H = 0xFD;
	TMR1L = 0x9C;
	//Enable all Interrupts
	//INTCONbits.TMR0IE = 1;
	PIE1bits.TMR1IE = 1;
	//PIR1bits.ADIF = 0;	//Clear A/D Flag Bit
	//PIE1bits.ADIE = 1;	//Enable A/D Interrupt Bit
	INTCONbits.PEIE = 1;
	INTCONbits;GIE = 1;
	while(1)
	{
		__delay_us(100);
		ADCON0bits.GO = 1;	//Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here Until Conversion Gets Over
		adc_data = ADRESL;		
	}
}
void lcdcmd(unsigned char value)
{
	LCD_DATA = value;
	RS = 0;
	RW = 0;
	EN = 1;
	__delay_ms(1);
	EN = 0;
}
void lcddata(unsigned char value)
{
	LCD_DATA = value;
	RS = 1;
	RW = 0;
	EN = 1;
	__delay_ms(1);
	EN = 0;
}
void lcdstr(unsigned char msg[])
{
	unsigned int i,len;	
	len = strlen(msg);
	for(i=0;i<len;i++)
	{	
		lcddata(msg[i]);
	}
}
void T1_ISR(void)
{
	PORTD = wave[i];
	i++;
		switch(adc_data)
		{
			[I]case 0:
					TMR1H = 0xFD;	//40Hz Frequency
					TMR1L = 0x9C;
					break; [/I]
			case 1:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9F;
					break;
			case 2:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xA3;
					break;
			case 3:
					TMR1H = 0xFD;
					TMR1L = 0xA5;
					break;
			case 4:
					TMR1H = 0xFD;
					TMR1L = 0xA7;
					break;
			case 5:
					TMR1H = 0xFD;
					TMR1L = 0xA9;
					break;
			case 6:
					TMR1H = 0xFD;
					TMR1L = 0xAB;
					break; 
			case 7:
					TMR1H = 0xFD;
					TMR1L = 0xAE;
					break; 
			case 8:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0xB0;
					break;
			case 9:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 10:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 11:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 12:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 13:
					TMR1H = 0xFF;	//40Hz Frequency
					TMR1L = 0xFC;
					break; 
			case 14:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 15:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 16:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 17:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 18:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 19:
					TMR1H = 0xFF;	//40Hz Frequency
					TMR1L = 0xFC;
					break; 
			case 20:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 21:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 22:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 23:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 24:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 25:
					TMR1H = 0xFF;	//40Hz Frequency
					TMR1L = 0xFC;
					break; 
			case 26:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 27:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 28:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 29:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 30:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 31:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 32:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 33:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 34:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 29:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 30:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 31:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 32:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 33:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 34:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 29:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 30:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 31:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 32:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 33:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 34:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 35:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 36:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 37:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 38:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 39:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 40:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 41:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 42:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 43:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 44:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 45:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 46:
					TMR1H = 0xFE;
					TMR1L = 0x16;
					break;
			case 47:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 48:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 49:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			case 50:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0xFC;
					break;
			case 51:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 52:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 53:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 54:
					TMR1H = 0xFE;
					TMR1L = 0xFC;
					break;
			case 55:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x9C;
					break;
			[I]case 56:
					TMR1H = 0xFE;
					TMR1L = 0x60;
					break;[/I]
			case 57:
					TMR1H = 0xFE;
					TMR1L = 0x61;
					break;
			case 58:
					TMR1H = 0xFE;
					TMR1L = 0x62;
					break;
			case 59:
					TMR1H = 0xFE;
					TMR1L = 0x63;
					break;
			case 60:
					TMR1H = 0xFE;
					TMR1L = 0x64;
					break;
			case 61:
					TMR1H = 0xFE;
					TMR1L = 0x65;
					break;
			case 62:
					TMR1H = 0xFE;
					TMR1L = 0x66;
					break;
			case 63:
					TMR1H = 0xFE;
					TMR1L = 0x67;
					break;
			case 64:
					TMR1H = 0xFE;
					TMR1L = 0x68;
					break;
			case 65:
					TMR1H = 0xFE;
					TMR1L = 0x69;
					break;
			case 66:
					TMR1H = 0xFE;
					TMR1L = 0x6A;
					break;
			case 67:
					TMR1H = 0xFE;
					TMR1L = 0x6B;
					break;
			case 68:
					TMR1H = 0xFE;
					TMR1L = 0x6C;
					break;
			case 69:
					TMR1H = 0xFE;
					TMR1L = 0x6D;
					break;
			case 70:
					TMR1H = 0xFE;
					TMR1L = 0x6F;
					break;
			case 71:
					TMR1H = 0xFE;
					TMR1L = 0x70;
					break;
			case 72:
					TMR1H = 0xFE;
					TMR1L = 0x71;
					break;
			case 73:
					TMR1H = 0xFE;
					TMR1L = 0x72;
					break;
			case 74:
					TMR1H = 0xFE;
					TMR1L = 0x73;
					break;
			case 75:
					TMR1H = 0xFE;
					TMR1L = 0x74;
					break;
			case 76:
					TMR1H = 0xFE;
					TMR1L = 0x75;
					break;
			case 77:
					TMR1H = 0xFE;
					TMR1L = 0x77;
					break;
			case 78:
					TMR1H = 0xFE;
					TMR1L = 0x78;
					break;
			case 79:
					TMR1H = 0xFE;
					TMR1L = 0x79;
					break;
			case 80:
					TMR1H = 0xFE;
					TMR1L = 0x7A;
					break;
			case 81:
					TMR1H = 0xFE;
					TMR1L = 0x7B;
					break;
			case 82:
					TMR1H = 0xFE;
					TMR1L = 0x7C;
					break;
			case 83:
					TMR1H = 0xFE;
					TMR1L = 0x7D;
					break;
			case 84:
					TMR1H = 0xFE;
					TMR1L = 0x80;
					break;
			case 85:
					TMR1H = 0xFE;
					TMR1L = 0x81;
					break;
			case 86:
					TMR1H = 0xFE;
					TMR1L = 0x82;
					break;
			case 87:
					TMR1H = 0xFE;
					TMR1L = 0x83;
					break;
			case 88:
					TMR1H = 0xFD;	//42Hz Frequency
					TMR1L = 0x84;
					break;
			case 89:
					TMR1H = 0xFD;	//46Hz Frequency
					TMR1L = 0x85;
					break;
			case 90:
					TMR1H = 0xFE;
					TMR1L = 0x86;
					break;
			case 91:
					TMR1H = 0xFE;
					TMR1L = 0x87;
					break;
			case 92:
					TMR1H = 0xFE;
					TMR1L = 0x89;
					break;
			[I]case 93:
					TMR1H = 0xFE;
					TMR1L = 0x90;	//90.06Hz Frequency
					break;[/I]
		}
	/*TMR1H = 0xFD;	//To Generate 111usec Pulse
	TMR1L = 0xCE;*/
	if(i == 180)
	i=0;

	PIR1bits.TMR1IF = 0;	//Clear the Timer-1 Flag Bit	
}
//This is Interrupt Service Routine for ADC
/*void AD_ISR(void)
{
	adc_data_l = ADRESL;
	adc_data_h = ADRESH;
	//adc_data = adc_data | ADRESL;

	PIR1bits.ADIF = 0;	//Clears the Interrupt
}*/



Pls Help me

Here is my Circuit Diagram

Capture.PNG
 

View attachment DAC_Variable_Sine_Wave.zip

This is my project Proteus File...

Pls Consider the Switch Case 0 which is used for generating sine wave of 40Hz
Values Loaded in this case is TMR1H = 0xFD; //40Hz Frequency
TMR1L = 0x9C;

and consider the Switch Case 93 which is used for generating sine wave of 60Hz
Values Loaded in this case is TMR1H = 0xFE;
TMR1L = 0x90; //60.06Hz Frequency

for 60Hz the value of timer is greater than for 40Hz
But still it is generating the sinewave of frequency less than 40Hz
:-(
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top