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 support@ccsinfo.com

PWM on 16F876

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



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PWM on 16F876
PostPosted: Thu Jan 11, 2018 9:12 am     Reply with quote

Windows 10
MPLAB 8.91.00.00
CCS PCM V5.064 xxxxx

PIC16F876 running at 4.0 MHz.

Developed some code that runs a PWM at 50% duty and 1000Hz.

This all works fine, wanted to make some code that set to other frequencies to test output with our test equipment. Below is my code snippet that sets the PWM up. I simply uncomment the line I want at that time for the test.
1000 Hz code works, others do not, the PWM channel just stays high for any frequency besides 1000Hz. Not sure what is going on as the math works for the equations or at least I think so.
Code:
if(input(MODE))  {
       PWM_MODE = 1;
    }
    else  {
       PWM_MODE = 0;
    }
   output_low(PIN_C1); // Set CCP2 output low
   output_low(PIN_C2); // Set CCP1 output low
    output_low(VISIBLE_CNTRL); // visible LED is off


  if(PWM_MODE)  {         // Set up CCP1 and CCP2
    setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
    setup_ccp2(CCP_PWM); // Configure CCP2 as a PWM

   setup_timer_2(T2_DIV_BY_4, 249, 1); // 1000 Hz
    //setup_timer_2(T2_DIV_BY_16, 124, 1); // 477 Hz
    //setup_timer_2(T2_DIV_BY_4, 124, 1);  // 2000 Hz
    //setup_timer_2(T2_DIV_BY_4, 24, 1);  // 10000 Hz
 
    enable_interrupts(INT_TIMER2);
    set_pwm1_duty(PWM_OFF); // 0% duty cycle on pin C2
    set_pwm2_duty(PWM_OFF); // 0% duty cycle on pin C1
  }

    setup_port_a(NO_ANALOGS);
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 9:14 am     Reply with quote

Just to clarify, the PWM_OFF is used to just turn the PWM off in the initialization stage. later in the code I turn it on at 50%.
temtronic



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

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 9:45 am     Reply with quote

PWM is a 10bit register, so pretty sure you have to 'cast' the number as a long
well that's my guess...
Jay
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 9:51 am     Reply with quote

I was wondering about the need for casting, not sure why it works for the 1000 Hz situation though.
temtronic



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

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 10:14 am     Reply with quote

luck of the dice ??
I can't test, but there's a LOT of 'threads' about needing longs for 10bit devices....
Unless YOU specifically set a register it may come up as anything. Now thecompiler may 'preset' some of them, the PIC may 'powerup' in a certain config..but YOU should always be in control...kinda relates to reading the datasheets.....

edit: just had a look, table 8-4 xxxx xxxx LOTS of registers are 'unkown' on powerup ! Implies YOU need to set them up.

try casting long, see what happens. This PC is net only...NOT my eng PC.

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 10:25 am     Reply with quote

Quote:
Developed some code that runs a PWM at 50% duty and 1000Hz.

Your code fragment doesn't show the setup_pwm1_duty() and
set_pwm2_duty() calls that setup the 50% duty cycle. You only show
the lines that turn it off.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 10:51 am     Reply with quote

Here is the define for my PWM_50 variable.


#DEFINE PWM_50 128 //128 is 50%


below is a sample of how I use two discreet control lines to set which PWM is on.

Code:
if((INPUT(CNTRL_A))&&(!INPUT(CNTRL_B))) {        // 265 on.  Mode 1 265 ON
   
    if(PWM_MODE) {
      set_pwm1_duty(PWM_50);
      set_pwm2_duty(PWM_OFF);
    }
    else {
        output_high(PIN_C2);
        output_low(PIN_C1);
    }
    output_low(VISIBLE_CNTRL);

}   // end mode 1 if
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 10:55 am     Reply with quote

some more setup code for the PIC:
Code:
#FUSES XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP,NODEBUG

#use delay(clock=4000000)
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 11, 2018 11:12 am     Reply with quote

The 16F876 data sheet says:
Quote:
If the PWM duty cycle value is longer than the
PWM period, the CCP1 pin will not be cleared.

The period is set by the middle number in the setup_timer2() function.
Note that your code only follows the above rule in the case of 1000 Hz.
In all other cases, your duty cycle value is higher than the middle number
and you are getting a continuous logic "1" out. That's what they mean
when they say "will not be cleared".
gaugeguy



Joined: 05 Apr 2011
Posts: 286

View user's profile Send private message

PostPosted: Fri Jan 12, 2018 7:43 am     Reply with quote

For 1000 Hz you are setting the duty cycle to 128/250 = 51.2%
For 477 Hz, 128/125 = 102.4%
For 2000 Hz, 128/125 = 102.4%
For 10000Hz, 25/128 = 512%

For any duty cycle over 100% you won't see any signal change.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Fri Jan 12, 2018 9:14 am     Reply with quote

Code:

//routine to set pwm to a particular division
//(within the hardware limitations) 1 to 4096
int1 set_pwm_to(int16 division)
{
    //feed this with the division you want.
    //obviously limited accuracy
    if (division>4096)
        return FALSE; //can't be done....
    if (division>1024)
    {
        //here we are going to have to use /16
        division/=16;
        setup_timer_2(T2_DIV_BY_16, division-1, 1);
        set_pwm1_duty(division*2);
        //using a 16 bit division so pwm counts to
        //division * 4
    }
    else
    {
        if (division > 256)
        {
            //here /4
            division/=4;
            setup_timer_2(T2_DIV_BY_4, division-1, 1);
            set_pwm1_duty(division*2); 
        }
        else
        {
            setup_timer_2(T2_DIV_BY_1, division-1, 1);
            set_pwm1_duty(division*2); 
        }
    }
    return TRUE;
}
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