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] PIC complete discussion for all

Status
Not open for further replies.
Yes........ In the absence of PR2 timer2 is same as normal timers.... i feel you can still improve the code...

yes.. according to the definition:

Register TMR2 is used to store the “initial” count value (the value from which it begins to count).

Register PR2 is used to store the “ending” count value (the maximum value we need/want to reach). ie: using Timer2 we can determine the started count value, the final count value, and the count will be between these two values.

---------- Post added at 15:46 ---------- Previous post was at 14:31 ----------

Yes........ In the absence of PR2 timer2 is same as normal timers.... i feel you can still improve the code...

Pls tell me what is the important part to improve my code.. I mean is some scenario that I need this settings or etc.. hehe
 

I have another question.. what If I just leave the PR2 as constant e.g PR2 = 0xff;
then I will just vary the duty cycle and aslo the prescaler if needed.. what do you think? :) Im not talking for a certain application but a general application of PWM.. hehe I dont know if Im correct... lol hehe
 

Yes, there is no problem with this. In this case you have a fixed frequency determined by PR2 and you can just vary CCPRxL to vary the duty cycle (and prescaler also if needed) as you said. Of course, it depends on your application, eg. if you need a specific frequency, but for general application, this will be fine.

Hope this helps.
Tahmid.
 
Yes, there is no problem with this. In this case you have a fixed frequency determined by PR2 and you can just vary CCPRxL to vary the duty cycle (and prescaler also if needed) as you said. Of course, it depends on your application, eg. if you need a specific frequency, but for general application, this will be fine.

Hope this helps.
Tahmid.

thanks... since I have little idea with pwm it's time to move to next topic... :)

---------- Post added at 01:07 ---------- Previous post was at 00:45 ----------

before I will proceed to next topic Im thinking to combine my PWM code with my ADC code and to something fun... but before that bye for now need to attend my classes this day... :)
 

Hi,
Yes, I suggest you do that. How about try to control the duty cycle (0 to 100%) of a signal of frequency (approximately 15 kHz) by reading the value from a pot (0 to 100%).

Hope this helps.
Tahmid.
 

Yes its correct, i did a simple program to vary ADC input and see the PWM duty cycle varying to learn this concept. later to which i interfaced a motor to play with.

Yea, that's exactly what I had in mind!
 
give me hint before I will start this thing tomorrow.. :)

PR2 is 8bit register right? and my aDC output is 10bit.. so how do I manipulate all these 10bits as input in PWM.. sorry for the noob question.. just a little hint..
 

First, decide what will be the value assigned to PR2. For simplicity, let's assume it is 255. Then you can scale the ADC output to fall within 255. So, dividing each ADC value by 4 will give you a value between 0 and max 255(1023/4). Instead of dividing by 4, you can bitshift the result 2 times right (>> 2) which essentially will mean the same thing and is likely to be faster. You can then load the value to CCPRxL. I would still write some code to prevent assigning CCPRxL 0 or 255.

For other values that are multiples of 2, you can scale the value by bitshifting. But if PR2 is assigned 100, then the easier way to scale ADC result would be *100/255 (although there are more efficient methods).

Hope this helps.
Tahmid.
 
Last edited:
and how about the CCPR1L register? I will just have a fixed value for the duty cycle?

---------- Post added at 11:14 ---------- Previous post was at 11:10 ----------

that is one thing I get confused.. Im thinking weird if I can control the CCPR1L and the PR2 at the same time by the ADRES value.. I dont know.. hehe
 

No, since you want to vary the duty cycle with the variation of the ADC input, you would want the value entered into CCPR1L register to vary accordingly. The scaled result from the ADC conversion I talked about will be input to the CCPR1L register to vary the duty cycle. The value in the PR2 register will be fixed (as frequency is fixed).

Hope this helps.
Tahmid.
 
that is one thing I get confused.. Im thinking weird if I can control the CCPR1L and the PR2 at the same time by the ADRES value.. I dont know.. hehe
 

okay.. thanks for the hint I have now idea.. I was just thinking weird for varying the frequency at the same time the duty cycle
 

When you're done, post the code here so we can see. By the way, I still think you should spend a few more days on PWM and ADC and write various codes involving both these to somewhat master them. I have another thing in mind you should try afterwards: use an LM35 for the ADC input. LM35 provides a voltage of 10mV/'C temperature. Use the ADC to sense the voltage and thus "decipher" temperature and control the PWM duty cycle. If temperature > 50'C, duty cycle = 90%, if temperature < 50'C, duty cycle = 30%, in between duty cycle = 50%.

Something like that.

Remember it's no good being hasty and that practice makes perfect. :grin:

Hope this helps.
Tahmid.
 
yes, I will try that.. I can start working tomorrow evening since today is school days...

I will keep you posted here with my progress.. thanks so much...

---------- Post added at 11:52 ---------- Previous post was at 11:28 ----------

yes, I will try that.. I can start working tomorrow evening since today is school days...

I will keep you posted here with my progress.. thanks so much...
 

hi, I want to base my pwm and timer calculations in PLL style of clocking but have some doubts..

It is said in the datasheet that:
The PLL is enabled in HSPLL, XTPLL, ECPLL and
ECPIO Oscillator modes. It is designed to produce a
fixed 96 MHz reference clock from a fixed 4 MHz input.

okay, the crystal is 4 MHZ then if I have this computation/formula:

TOSC = 1/Fosc

e.g.

TOSC = 1/4Mhz (crystal frequency)

or


1/48Mhz (from PLL)

what should be the Fosc I am going to use? my crystal frequency or the PLL frequency which is 96/2 = 48Mhz ?



The actual maximum Fosc or system clock is 48MHz, due to the postscaler options of which the 1/2 is the small divisor. In other words 96MHz divided by 2 is 48MHz, the stated maximum Fosc in the devices datasheet.


Glad your power is back up.


---------- Post added at 15:15 ---------- Previous post was at 14:44 ----------

i think by looking this diagram I should use the 48Mhz if PLL is enabled.
then the formula would be:

TOSC = 1/48 Mhz
and the 4Mhz crystal frequency will not be use when using PLL..

am I correct? hehe


**broken link removed**
 
Last edited:

------------------------------------------------------------------------------------------------\


guys this is my initial code for ADC and PWM..

I will fix try to fix this code tomorrow..

pwm.c
PHP:
#include<htc.h>

void init_pwm()
{
	TRISC = 0; //set PORTC as output
	CCP1CON |= 0x0c;  //enable PWM mode
	T2CONbits.TMR2ON = 1;
	//T2CONbits.T2CKPS0 = 1; //prescaler 4
    T2CONbits.T2CKPS1 = 1; //prescaler 16


}



void pwm(unsigned char period, unsigned char duty)
{
	
	PR2 = period;
	CCPR1L = duty;
	CCP1CONbits.DC1B0 |= 0;
	CCP1CONbits.DC1B1 |= 0;


}

main.c

PHP:
#include<htc.h>
#include"pwm.h"
#include"adc.h"

void init_pwm();
void pwm(unsigned char period, unsigned char duty);

void main()
{
	unsigned char x;
	init_pwm();
	init_adc();

	while(1)
	{
		x = adc_read();  //i will fixed this part
		pwm(255,x);   
	
	}

}

aDC.c

PHP:
#include<htc.h>

void init_adc()
{
/* select channel 0, enable ADC */	
	ADCON0bits.ADON = 1; 
/* Voltage reff is VDD, configure AN0 as analog */ 
	ADCON1bits.VCFG0 = 0;
	ADCON1bits.VCFG1 = 0;
	ADCON1 |= 0b1110;

/*2 x TAD, FOSC/32 */
	ADCON2bits.ACQT0 = 1;
	ADCON2bits.ADCS1 = 1;
	TRISAbits.TRISA0 = 1; // input
	ADCON2bits.ADFM = 0;  // A/D result is left justified
}

unsigned int adc_read()
{
	unsigned int adc_result;

	ADCON0 = 0x00;
	ADCON0bits.ADON = 1; //turn on adc

	ADCON0bits.GO_DONE = 1; //start converstion

	while(GO_DONE); //wait for converstion to finish
	ADCON0bits.ADON = 0; //turn off adc
	

	adc_result = (ADRESH<<2) | (ADRESL>>6);

	return adc_result;
	


}



I got very confuse this part in the ADRESH and ADRESL.. Im using left justified.. is it correct??


PHP:
adc_result = (ADRESH<<2) | (ADRESL>>6);
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top