CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Need help with PWM on 16F15323
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
randy.shaffer



Joined: 21 Mar 2018
Posts: 51

View user's profile Send private message

Need help with PWM on 16F15323
PostPosted: Fri Sep 14, 2018 1:16 pm     Reply with quote

Code:
#include <16F15323.h>
#device ADC = 10
#device ICD = TRUE
#use delay(clock = 32MHZ, internal)
#use rs232(baud = 57600, parity = N, xmit = PIN_C4, rcv = PIN_C5, \
           bits = 8, stream = PORT1)
#PIN_SELECT CCP1OUT = PIN_A2
#include <stdio.h>
/* Function Prototypes */
void TIMER0_ISR(); // Timer 0 interrupt service routine
unsigned int16 get_ADC_channel(int8 ADC_channel);
/* Global Variables */
unsigned int16 T0_COUNT = 0;
void main()
{
 float VR = 5.0, VIN;
 unsigned int16 PWM_duty;
 unsigned int16 INDUCTOR_CURRENT = 0; // analog of inductor current
 unsigned int16 INPUT_VOLTAGE = 0; // analog of input voltage
 unsigned int16 OUTPUT_VOLTAGE = 0; // analog of output voltage
 unsigned int16 VOUT = 0, IL = 0;
 output_bit(PIN_A2, 0); // turn off high-side MOSFET
 set_tris_a(0x20); // set A5 as input, A2 as output
 set_tris_c(0x03); // set C0, C1 as inputs; C3 as output
 setup_oscillator(OSC_HFINTRC_32MHZ); // Fosc = 32 MHz
 setup_vref(VREF_ON|VREF_ADC_4v096); // Set Vref = 4.096 V for ADC
 setup_adc(ADC_CLOCK_DIV_32); // ADC clock is 32/32 = 1 MHz
 setup_adc_ports(sAN5|sAN16|sAN17, VSS_FVR); // A5, C0, & C1 are analog inputs
 set_timer0(0xFD8E); // Initialize Timer 0 for 10 ms
 setup_timer_0(T0_INTERNAL | T0_DIV_128); // clocked @15.625 kHz (Fosc/(4*128))
 enable_interrupts(INT_TIMER0); // enable Timer 0 interrupts
 enable_interrupts(global); // enable all interrupts
 setup_CCP1(CCP_PWM);
 setup_timer_2(T2_DIV_BY_1, 100, 1);
 PWM_duty = 50;
 set_PWM1_duty(PWM_duty);
 while(TRUE)
 {
.
.
.
 }

I can get the PWM to work with the #use pwm directive but waveform jitter increases with frequency. Not getting anything out of A2 with the above code.


Last edited by randy.shaffer on Fri Sep 14, 2018 1:46 pm; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 1:43 pm     Reply with quote

Some comments:
1) Use the code buttons!.... Makes the code much easier to read.
2) Your PR2 value (timer2), probably wants to be 99. Remember to give /100, you have to use 99.
3) The duty you are giving will only be 12.5% duty cycle. For 50% you would want 200. So a very small pulse. 79KHz, and a pulse width of 1.6uSec.
4) The chip will wake by default with the slew rate limit enabled on the pins. Now at your frequency, it is possible that with the slew rate limit enabled, the output would be very attenuated. Might be a problem. With the pulse width at only 1.6uSec, this could easily hardly show at all...
5) General comment, if a pin doesn't give what you expect, make sure yoiu turn off the other peripherals on the pin. ZCD etc.
6) A2 should not be set as output, till _after_ the CCP is configured. The data sheet is quite specific that it should be set as input while you configure the peripheral.
7) What compiler version?. We need to know.
randy.shaffer



Joined: 21 Mar 2018
Posts: 51

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 1:58 pm     Reply with quote

Code:
#include <16F15323.h>
#device ADC = 10
#device ICD = TRUE
#use delay(clock = 32MHZ, internal)
#use rs232(baud = 57600, parity = N, xmit = PIN_C4, rcv = PIN_C5, \
           bits = 8, stream = PORT1)
#PIN_SELECT CCP1OUT = PIN_A2
//#use pwm(PWM1, TIMER = 2, FREQUENCY = 100kHz, PWM_OFF, STREAM = PWM_OUT)
#include <stdio.h>
/* Function Prototypes */
void TIMER0_ISR(); // Timer 0 interrupt service routine
unsigned int16 get_ADC_channel(int8 ADC_channel);
/* Global Variables */
unsigned int16 T0_COUNT = 0;
void main()
{
 float VR = 5.0, VIN;
 unsigned int16 PWM_duty;
 unsigned int16 INDUCTOR_CURRENT = 0; // analog of inductor current
 unsigned int16 INPUT_VOLTAGE = 0; // analog of input voltage
 unsigned int16 OUTPUT_VOLTAGE = 0; // analog of output voltage
 unsigned int16 VOUT = 0, IL = 0;
 output_bit(PIN_A2, 0); // turn off high-side MOSFET
 setup_oscillator(OSC_HFINTRC_32MHZ); // Fosc = 32 MHz
 setup_vref(VREF_ON|VREF_ADC_4v096); // Set Vref = 4.096 V for ADC
 setup_adc(ADC_CLOCK_DIV_32); // ADC clock is 32/32 = 1 MHz
 setup_adc_ports(sAN5|sAN16|sAN17, VSS_FVR); // A5, C0, & C1 are analog inputs
 set_timer0(0xFD8E); // Initialize Timer 0 for 10 ms
 setup_timer_0(T0_INTERNAL | T0_DIV_128); // clocked @15.625 kHz (Fosc/(4*128))
 enable_interrupts(INT_TIMER0); // enable Timer 0 interrupts
 enable_interrupts(global); // enable all interrupts
 setup_CCP1(CCP_PWM);
 set_tris_a(0x20); // set A5 as input, A2 as output
 set_tris_c(0x03); // set C0, C1 as inputs; C3 as output
 setup_timer_2(T2_DIV_BY_1, 99, 1);
 PWM_duty = 200;
 set_PWM1_duty(PWM_duty);
 while(TRUE)
 {
  .
  .
  .
 }



Thank you. I am using the CCS C compiler v5.080. How do you disable the slew rate limit?
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 2:26 pm     Reply with quote

Have a look at this thread:
<http://www.ccsinfo.com/forum/viewtopic.php?t=57171&highlight=slew+rate>
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 2:27 pm     Reply with quote

Currently you have a soft UART. To make it use the hardware UART, you
need to add the two lines shown in bold below, above your #use rs232()
statement:
Quote:
#pin_select U1TX=PIN_C4
#pin_select U1RX=PIN_C5

#use rs232(baud = 57600, parity = N, xmit = PIN_C4, rcv = PIN_C5, \
bits = 8, stream = PORT1)

You can tell this by looking at the .LST file before and after making the
changes above.
randy.shaffer



Joined: 21 Mar 2018
Posts: 51

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 2:47 pm     Reply with quote

Code:
#include <16F15323.h>
#device ADC = 10
#device ICD = TRUE
#use delay(clock = 32MHZ, internal)
#pin_select U1TX = PIN_C4
#pin_select U1RX = PIN_C5
#use rs232(baud = 57600, parity = N, xmit = PIN_C4, rcv = PIN_C5, \
           bits = 8, stream = PORT1)
#PIN_SELECT CCP1OUT = PIN_A2
//#use pwm(PWM1, TIMER = 2, FREQUENCY = 100kHz, PWM_OFF, STREAM = PWM_OUT)
#include <stdio.h>
/* Function Prototypes */
void TIMER0_ISR(); // Timer 0 interrupt service routine
unsigned int16 get_ADC_channel(int8 ADC_channel);
/* Global Variables */
unsigned int16 T0_COUNT = 0;
void main()
{
 float VR = 5.0, VIN;
 unsigned int16 PWM_duty;
 unsigned int16 INDUCTOR_CURRENT = 0; // analog of inductor current
 unsigned int16 INPUT_VOLTAGE = 0; // analog of input voltage
 unsigned int16 OUTPUT_VOLTAGE = 0; // analog of output voltage
 unsigned int16 VOUT = 0, IL = 0;
 output_bit(PIN_A2, 0); // turn off high-side MOSFET
 setup_oscillator(OSC_HFINTRC_32MHZ); // Fosc = 32 MHz
 setup_vref(VREF_ON|VREF_ADC_4v096); // Set Vref = 4.096 V for ADC
 setup_adc(ADC_CLOCK_DIV_32); // ADC clock is 32/32 = 1 MHz
 setup_adc_ports(sAN5|sAN16|sAN17, VSS_FVR); // A5, C0, & C1 are analog inputs
 set_timer0(0xFD8E); // Initialize Timer 0 for 10 ms
 setup_timer_0(T0_INTERNAL | T0_DIV_128); // clocked @15.625 kHz (Fosc/(4*128))
 enable_interrupts(INT_TIMER0); // enable Timer 0 interrupts
 enable_interrupts(global); // enable all interrupts
 setup_CCP1(CCP_PWM);
 set_tris_a(0x20); // set A5 as input, A2 as output
 set_tris_c(0x03); // set C0, C1 as inputs; C3 as output
 setup_timer_2(T2_DIV_BY_1, 99, 1);
 PWM_duty = 200;
 set_PWM1_duty(PWM_duty);
 while(TRUE)
 { ...


Thank you again. Sorry but I did not see anything related to disabling the slew rate limit in that thread. Still no output on A2 with the above code.

Any ideas as to why the PWM waveform has jitter that increases with frequency with the #use pwm directive? At 80 kHz it is really, really bad.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 3:35 pm     Reply with quote

randy.shaffer wrote:

Sorry but I did not see anything related to disabling the slew rate limit in
that thread. Still no output on A2 with the above code.

See page 2 of the thread. Note the section on the SLRCON registers.
http://www.ccsinfo.com/forum/viewtopic.php?t=57171&start=15
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 3:39 pm     Reply with quote

randy.shaffer wrote:


Thank you again. Sorry but I did not see anything related to disabling the slew rate limit in that thread. Still no output on A2 with the above code.

Any ideas as to why the PWM waveform has jitter that increases with frequency with the #use pwm directive? At 80 kHz it is really, really bad.


Look at chapter 14 of the data sheet for your PIC, page 172. SLRCONx registers. They default to 1 (on). If on, any really fast events you try to generate will not appear as you expect.
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Sep 14, 2018 11:30 pm     Reply with quote

Seriously, on page 2 of the thread, I post:
Quote:

Suggestion.

Clear the SLRCON registers. SLRCONA, SLRCONB & SLRCONC. Do something like:
Code:

#byte SLRCONA=getenv("SFR:SLRCONA")
#byte SLRCONB=getenv("SFR:SLRCONB")
#byte SLRCONC=getenv("SFR:SLRCONC")

//Then in your main
SLRCONA=SLRCONB=SLRCONC=0;



These all default to '1' which implies slew rate limiting is enabled. Though the limitation should still allow the clock rates involved, it's worth trying with this off....


It turned out to fix the problem in this thread, where the poster was trying to output the CLKOUT, but was finding that it didn't work at anything faster than quite slow rates (it appeared that in this case the slew rate limit was actually slower than the data sheet figure...).
randy.shaffer



Joined: 21 Mar 2018
Posts: 51

View user's profile Send private message

PostPosted: Mon Sep 17, 2018 9:04 am     Reply with quote

Code:
#include <16F15323.h>
#device ADC = 10
#device ICD = TRUE
#use delay(clock = 32MHZ, internal)
#pin_select U1TX = PIN_C4
#pin_select U1RX = PIN_C5
#use rs232(baud = 57600, parity = N, xmit = PIN_C4, rcv = PIN_C5, \
           bits = 8, stream = PORT1)
#PIN_SELECT CCP1OUT = PIN_A2
#byte SLRCONA = getenv("SFR:SLRCONA")
#include <stdio.h>
/* Function Prototypes */
void TIMER0_ISR(); // Timer 0 interrupt service routine
unsigned int16 get_ADC_channel(int8 ADC_channel);
/* Global Variables */
unsigned int16 T0_COUNT = 0;
void main()
{
 SLRCONA = 0;
 float VR = 5.0, VIN;
 unsigned int16 PWM_duty;
 unsigned int16 INDUCTOR_CURRENT = 0; // analog of inductor current
 unsigned int16 INPUT_VOLTAGE = 0; // analog of input voltage
 unsigned int16 OUTPUT_VOLTAGE = 0; // analog of output voltage
 unsigned int16 VOUT = 0, IL = 0;
 output_bit(PIN_A2, 0); // turn off high-side MOSFET
 setup_oscillator(OSC_HFINTRC_32MHZ); // Fosc = 32 MHz
 setup_vref(VREF_ON|VREF_ADC_4v096); // Set Vref = 4.096 V for ADC
 setup_adc(ADC_CLOCK_DIV_32); // ADC clock is 32/32 = 1 MHz
 setup_adc_ports(sAN5|sAN16|sAN17, VSS_FVR); // A5, C0, & C1 are analog inputs
 set_timer0(0xFD8E); // Initialize Timer 0 for 10 ms
 setup_timer_0(T0_INTERNAL | T0_DIV_128); // clocked @15.625 kHz (Fosc/(4*128))
 enable_interrupts(INT_TIMER0); // enable Timer 0 interrupts
 enable_interrupts(global); // enable all interrupts
 setup_CCP1(CCP_PWM);
 set_tris_a(0x20); // set A5 as input, A2 as output
 set_tris_c(0x03); // set C0, C1 as inputs; C3 as output
 setup_timer_2(T2_DIV_BY_1, 99, 1);
 PWM_duty = 200;
 set_PWM1_duty(PWM_duty);
 while(TRUE)
 {...


Sorry about missing Page 2 of that post and thank you everyone for your help and suggestions. Still no output on A2 with the above code.
temtronic



Joined: 01 Jul 2010
Posts: 9246
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Sep 17, 2018 3:24 pm     Reply with quote

OK...
a silly question but...
Can you code a simple 'toggle program' and turn an LED on/off on A2 ? If not maybe there's a solder bridge grounding that pin ?
Also I see you have ICD = TRUE. Does that option 'hijack' the A2 pin for any reason ? I never use an ICD so don't know...just thought it might be posssible.

Jay
randy.shaffer



Joined: 21 Mar 2018
Posts: 51

View user's profile Send private message

PostPosted: Mon Sep 17, 2018 3:30 pm     Reply with quote

Hi Jay, I can get the PWM to work out of A2 if I use the #use pwm directive. But, the waveform has a terrible amount of jitter at the higher frequencies. It looks OK up to about 10 kHz but I want to operate at 80 - 100 kHz. I've had problems in the past with #use pwm causing some limitations and was trying a different approach without it.
temtronic



Joined: 01 Jul 2010
Posts: 9246
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Sep 17, 2018 6:00 pm     Reply with quote

OK, so it's not a basic hardware issue, rather some 'PWM setup code', sigh. I'm on my bkp xp machine cause the W7 one went 'for a walk'.....

I'd cut 2 programs, one for say 8KHz and another for 16KHz. 8 should work, 16 not so good. If so, dump the listings and check the code. Play PIC and confirm the correct registers are set properly.
Wish I could help more but all the recent CCS stuff is on, yeah the dead W7 PC.

Jay
randy.shaffer



Joined: 21 Mar 2018
Posts: 51

View user's profile Send private message

PostPosted: Wed Sep 19, 2018 11:54 am     Reply with quote

Code:
#include <16F15323.h>
#PIN_SELECT CCP1OUT = PIN_A2
void main()
{
 setup_oscillator(OSC_HFINTRC_32MHZ);
 Setup_CCP1(CCP_PWM);
 setup_timer_2(T2_DIV_BY_1 | T2_CLK_INTERNAL, 79, 1);
 set_tris_a(0xFB); // set A2 as output
 set_PWM1_duty(160);
 while(TRUE)
 {
  // ...
 }
}


Thank you, Jay. I got it to work but, sadly, the waveform still has terrible jitter. ORing T2_CLK_INTERNAL with T2_DIV_BY_1 made it work.

If anyone knows why the PWM signal has the jitters and how to fix it, I would greatly appreciate the insight.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 19, 2018 12:24 pm     Reply with quote

Can you measure the jitter on your oscilloscope ? How much is it ?

Also, you're enabling Timer0 interrupts but I don't see any Timer0
interrupt routine. Is that your entire program or did you not post all of it ?


Last edited by PCM programmer on Wed Sep 19, 2018 12:50 pm; edited 1 time in total
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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