|
|
View previous topic :: View next topic |
Author |
Message |
yasir9909
Joined: 04 Jan 2010 Posts: 9
|
Issue with PWM DAC using built-in PWM Module of PIC16F690 |
Posted: Tue Aug 19, 2014 11:50 am |
|
|
I have searched out this help forum extensively, many of my queries regarding PWM & built-in PWM module of PIC Micro-controller have been addressed through this search, but here is an issue for which I am unable to find solution through search of this help forum.
I am trying build a simple DAC with PIC16F690 using its built-in PWM module. The PWM module is working at my desired frequency but the issue I am facing is that when I try to generate Sawtooth waveform, the PWM output stays high at 100% duty cycle for a long span of time and then starts again from zero & proceeds to upward count.
Here is my code:
Code: |
#include <16F690.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES PUT //Power Up Timer ON
#FUSES NOBROWNOUT //No brownout reset
#FUSES IESO //Internal switch over mode ON
#FUSES FCMEN //Fail safe clock monitor enabled
#FUSES NOCPD //No code protection from EE
#FUSES NOPROTECT //No code read protection
#fuses HS,
#use delay(crystal=20MHz)
#use rs232(baud=115200, xmit=PIN_B7, rcv=PIN_B5)
#define Upper_Limit 1000
unsigned int16 PWM_DC_Val = 0;
#int_TIMER2
void TIMER2_isr(void)
{
// left blank for future use
}
void main()
{
setup_timer_2(T2_DIV_BY_1,79,1);
// The cycle time will be (1/clock)*4*t2div*(period+1) = 62.5khz is
//required
setup_ccp1(CCP_PWM);
enable_interrupts(GLOBAL);
enable_interrupts(int_TIMER2);
setup_comparator(NC_NC_NC_NC);
printf("\r\nGeneration of Sawtooth Waveform using PWM Module\n\r");
while(TRUE)
{
//TODO: User Code
set_pwm1_duty(PWM_DC_Val);
if( PWM_DC_Val > Upper_Limit )
PWM_DC_Val = 0;
else
PWM_DC_Val++;
}
}
|
To implement 10-bit mode of PWM Module, I have declared the PWM Duty Cycle variable PWM_DC_Val as 16-bit unsigned so that PWM module may be set to operate in 10-bit mode through set_pwm1_duty(PWM_DC_Val) function.
As far as I have been able to understand from help files of CCS compiler, in set_pwm1_duty(PWM_DC_Val) function
0L = (unsigned int16)0=0% duty cycle
1000L =(unsigned int16)1000 =100% duty cycle
so
set_pwm1_duty((unsigned int)0) means 0% duty cycle
set_pwm1_duty((unsigned int)1000) means 100% duty cycle
I know PWM topic has been discussed in many posts on this help forum but despite thoroughly searching the forum, as much as I could, I am unable to find the solution to this issue.
The web-link to screenshot of Proteus Simulation of this code is given below:
http://www.4shared.com/download/HU3WkIbyba/pwm_q-1.jpg?lgfp=3000
In this image PWM waveform is shown in blue color at bottom, while resulting Sawtooth Waveform is shown in yellow color at the top.
regards
m.yasir |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Aug 19, 2014 12:32 pm |
|
|
Quote: | 0L = (unsigned int16)0=0% duty cycle
1000L =(unsigned int16)1000 =100% duty cycle |
That's not true. The pwm duty cycle is calculated from a formula which
is based on the middle parameter (PR2) in the setup_timer_2() function.
This thread has the formula for 10-bit PWM duty cycle:
http://www.ccsinfo.com/forum/viewtopic.php?t=42417&start=1 |
|
|
yasir9909
Joined: 04 Jan 2010 Posts: 9
|
@ PCM programmer |
Posted: Tue Aug 19, 2014 3:28 pm |
|
|
PCM programmer thank you for your reply. I have been able to deduce following the formulas from the post whose link you have shared :
1. PWM Period = 1/(Clock Frequency)*4*t2div*(Period+1)
or
PWM Frequency = (Clock Frequency)/( 4*t2div*(Period+1) )
where in function setup_timer_2(T2_DIV_BY_1,79,1);
t2div = 1,Period = 79
or
Code: |
Crystal Frequency
PWM Freq = ------------------------------------------
(PR2 + 1) * (Timer2 Prescaler) * 4
|
where in function setup_timer_2(T2_DIV_BY_1,79,1);
Timer2 Prescaler = t2div = 1, PR2=Period = 79
Here Clock Frequency=Cystal Frequency = Master Clock Frequency
of Micro-controller either internal or external
2. According to Ttelmah in the following post :
http://www.ccsinfo.com/forum/viewtopic.php?t=42417&start=1
Duty Cycle Value for the function set_pwm1_duty(Value); is given by :
Value = (%age of Duty Cycle/100) *(Period+1) *4 -1
For 50% duty cycle and Period=middle value=255 in above formula
Value will be :
Value = (50/100)*[(255+1)*4]-1 = 511
=> for 0% duty cycle Value = 0
=> for 100% Duty cycle Value = 1023
Value can't be bigger than the ((middle value+1) *4)-1.
So for a middle value of 255, maximum value is 256*4 = 1024 -1 =
1023. The '10 bit' maximum for the chip.
3. %age of Duty Cycle =[ (Value+1) /( (Period+1) *4 ) ] *100
4. So in my case with following configurations of this function:
Code: |
setup_timer_2(T2_DIV_BY_1,79,1);
|
I have following parameters:
Period or middle value = 79,t2div = Timer2 Prescaler =1,
maxium value = ((middle value+1) *4)-1
maxium value = ((79+1) *4)-1 = 319
=>
set_pwm1_duty(0L); = 0% Duty cycle
set_pwm1_duty(319L); = 100% Duty cycle
In the above posted code I have set maximum value equal to 319 by define statement as
Code: | #define Upper_Limit 319 |
This has resolved the issue of PWM duty cycle being stuck at 100% for a big span of time
I think my concepts have become clear now.
I have worked on AVR, PIC seems quite complex to me as compared with AVR. Datasheet of AVR also provides C code snippets along with assembly code that makes that task of programming different modules of AVR quite easy while Microchip provides only assembly code.
any ways thanks for your help
Last edited by yasir9909 on Wed Aug 20, 2014 9:08 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Aug 20, 2014 8:05 am |
|
|
Value = (%age of Duty Cycle/100) *(Period+1) *4 -1
You are missing one critical thing.
You are setting the Period value (PR2), to 79.
Try the formula again, with this, and understand what PCM_Programmer is telling you. |
|
|
yasir9909
Joined: 04 Jan 2010 Posts: 9
|
@Ttelmah |
Posted: Wed Aug 20, 2014 9:21 am |
|
|
I think,I have mentioned in summary of my findings regarding PWM and Timer2 settings that
PR2=Period=Middle Value = 79
Ok let me revisit the links provided by PCM Prgrammer.
Actually,I need to read analog signal through input pin of built-in analog-to-digital converter and then after mapping it to some other values saved in lookup table,I shall output it as analogue output through PWM Module and low pass filter.
Thanks for your help
regards
m.yasir |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Aug 20, 2014 10:46 am |
|
|
I'm trying to make a point about the way you are thinking.
Key to understand is that you are dealing with _embedded_ languages. You have the 'core' C functions, and then dozens of other parts that deal directly with hardware.
As such, it is the _hardware_ data that you need to look at.
Now the formula from me, that you found, is copied directly from the chip data sheet. If you look at the 16F690 data sheet, go to section 11, and look at Equation 11-2, and 11-3, you get the formulae for the pulse width, and the duty cycle. Then even a nice little table giving example periods, and how the resolution decreases as the PR2 value drops (table 11-2).
Then step back and realise that the CCS functions only set the hardware. Nothing else. If you look again at the data sheet, you see that the time for the PWM, is set by timer2. Look at timer2, and you see it has a 'prescale' setting, a period setting, and a postscale setting. Then look at the setup_timer_2 function, and the three values this takes, set the prescale, period, and postscale - the same!....
The problem is that you are working with hardware, and as such it is the hardware data you need to start with.
I posted some time ago, in another thread, the sources of data that you needed to look at when working with CCS, and a PIC. The 'C programming language' (K&R), was there, but the chip data sheet came _above_ it in the list.
Though these languages have as their core, 'C', it is an understanding of what the hardware abilities are, that has to 'lead' your use of the functions, and where you look for answers. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|