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

16F88 PWM

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
boris



Joined: 29 Nov 2007
Posts: 15
Location: Hungary

View user's profile Send private message

16F88 PWM
PostPosted: Fri Mar 14, 2008 6:10 am     Reply with quote

Hi!

I've encountered a problem with PIC16F88, and the PWM module.

I use compiler v4.068

The comiled program works fine in Proteus, but when I flash it on the real chip, it won't create a PWM.

I've set the PIN_B3 output in the code wizard.

The sample program I'm using is:

Code:

#include "main.h"


void main()
{

   setup_adc_ports(sAN2|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,99,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(200);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_8MHZ|OSC_INTRC);
   

}


The main file is:


Code:

#include <16F88.h>
#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPUT                    //No Power Up Timer
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled
#FUSES NOIESO                   //Internal External Switch Over mode disabled
#FUSES CCPB3

#use delay(clock = 8000000)



If I take out the setup_ccp1(CCP_PWM); line and add a simple program like so:
Code:

...
//setup_ccp1(CCP_PWM);
...
   while(1)
      {
      output_high(PIN_B3);
      delay_us(10);
      output_low(PIN_B3);
      delay_us(10);
      }


The PIC generates signal on PIN_B3.


I'm using a simple breadboard, the only thing I use beside the PicKit2 connector is the 4k7 resistor and a 100nF capacitor. The PIC is powered through the PicKit2.

If I check the ASM generated by the CCS the CCP1 module and the PWM module configuration seems fine.

Code:

....................    setup_ccp1(CCP_PWM);
0039:  BCF    06.3
003A:  BCF    03.5
003B:  BCF    06.3
003C:  MOVLW  0C
003D:  MOVWF  17


The compiler moves 0C to 0x17, wich is 00001100 in binary.
This seems fine according to the 16F88's datasheet, page 83, because Bit3 and Bit2 has to be 1 to enable the PWM module.

The compiler also loads the duty cycle to the CCPR1L register.
Code:

....................    set_pwm1_duty(200);
0042:  MOVLW  C8
0043:  MOVWF  15


But the timer2 setup is strange.
Code:

....................    setup_timer_2(T2_DIV_BY_1,99,1);
0032:  MOVLW  00
0033:  MOVWF  78
0034:  IORLW  04
0035:  MOVWF  12
0036:  MOVLW  63
0037:  BSF    03.5
0038:  MOVWF  12

It initializes the timer2 alright, but it doesn't assign a value to the PR2 register (0x11)

The PWM setup procedure is written in section 9.3.3 (p.87) and the first thing is: Set the PWM period by writing to the PR2 register.
I don't see the PR2 writing in the code above.


I've been using PIC's for 4 years, but I've changed to CCS about 4 mounths ago, before that I've benn using another C compiler.


Thanks for your help!
Matro
Guest







PostPosted: Fri Mar 14, 2008 7:43 am     Reply with quote

Your timer2 is configures as follow:

setup_timer_2(T2_DIV_BY_1,99,1);

So the "set_pwm1_duty" should be between 0 (= 0%) and 100 (= 100%).

All values greater than 100 (as the 200 you choose) will give a duty cycle of 100% i.e. a static high output.

Try a "set_pwm1_duty(50)" and it should generate a 50% PWM signal.

Regards,
Matro
boris



Joined: 29 Nov 2007
Posts: 15
Location: Hungary

View user's profile Send private message

PostPosted: Fri Mar 14, 2008 8:03 am     Reply with quote

HI Matro!

You ROCK!

I've would never think of it!!!
The joke is that the 200 was given by the code wizard, so I thought it was correct....

If I write 50 the PWM works like a charm!

Thanks again!
Charlie U



Joined: 09 Sep 2003
Posts: 183
Location: Somewhere under water in the Great Lakes

View user's profile Send private message

PostPosted: Fri Mar 14, 2008 11:33 am     Reply with quote

The actual value used for the period is 4x the value in the setup function. If you use an int16 for the duty cycle then 0 to 400 would be correct. To use a constant you would need to add an "L" as a suffix to the constant: set_pwm1_duty(200L);.

This gives you the full resolution of 400.

Try this and let us know if it works for you.
boris



Joined: 29 Nov 2007
Posts: 15
Location: Hungary

View user's profile Send private message

PostPosted: Mon Mar 17, 2008 1:54 am     Reply with quote

Hi Charlie U!

Thank You! The 200L works fine, and if I use int16 for the PWM value, it accepts values between 0 and 400. But where does the 400 come from? It's in the thatasheet, or in the CCS examples, or can be calculated?
Ttelmah
Guest







PostPosted: Mon Mar 17, 2008 3:19 am     Reply with quote

Basically, the timer runs off the processor clock/4, but the actual PWM generator, runs directly off the processor clock. The PWM generator, takes an extra two bits, to access this faster part of its counter. If you look at the data sheets, you will find that there is a main register (holding an 8bit value), and these extra two bits in another register. Now, the compiler, when the pwm_duty command is accessed with a normal 8bit integer, takes the 'quick' route, and writes the 8bit value directly to the 8bit PWM register, allowing counts up to the value selected for the timer (hence 0 to 100 in the example given). However if it is given a 'long' value, it realises you want to access the extra two bits, and extracts these, writing them to the extra bits in the control register, so you can then use 0 to timer*4 as a count value.

Best Wishes
Gerhard



Joined: 30 Aug 2007
Posts: 144
Location: South Africa

View user's profile Send private message Send e-mail

PostPosted: Mon Mar 17, 2008 5:49 am     Reply with quote

HI.
I am strugling to understand what part of the PWM is 4 times faster than in the setup.
If you generate a PWM signal of say 5KHZ at 50% duty cycle in the setup function of the timer, does the actual generated PWM signal equal 5KHZ or 20 KHZ. I what scenario is the actual PWM freq and duty cycle different than what is setup in the timer setup?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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