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

PWM Problem on PIC16F1825

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



Joined: 11 Jan 2012
Posts: 69

View user's profile Send private message

PWM Problem on PIC16F1825
PostPosted: Sun Nov 01, 2015 12:22 am     Reply with quote

I can't switch PWM outputs from RA5 to RC0 pins.
My compiler version is 5.026
Here is my code, thanks very much for your help.
Code:

#include <16F1825.h>
#use delay(internal=8000000)
#FUSES NOCLKOUT      //I/O function on OSC2
#FUSES NOWDT         //Watch dog timer
#FUSES INTRC_IO      //Internal RC Osc
#FUSES NOPROTECT     //Code Protection
#FUSES NOBROWNOUT    //Brown-out
#FUSES NOCPD         //Data Protection
#FUSES NOFCMEN       //Fail-Safe Clock Monitor Enable Bit
#FUSES NOIESO        //Internal External Switchover bit
#FUSES NOPUT         //Power Up Timer
#FUSES NOMCLR        //Memory Clear
#FUSES NOWRT         //No Program Memory write Protected
#FUSES NOSTVREN      //No Stak full/underflow reset
#FUSES NODEBUG       // No Debug mode for ICD
#FUSES NOLVP         //No Low Voltage Programming
#FUSES NOCLKOUT    //No Clock Out on pin A4

#include <stdio.h>

//////////////////////////////////////////////////////////
//                                                      //
//                  PROTOTYPES                          //
//                                                      //
//////////////////////////////////////////////////////////
void Initialize();


//////////////////////////////////////////////////////////
//                                                      //
//                  DEFINES / VARIABLES                 //
//                                                      //
//////////////////////////////////////////////////////////

#define BUZ PIN_A5
#bit CCP2SEL = getenv("BIT:CCP2SEL")
#bit P2BSEL = getenv("BIT:P2BSEL")
#bit P1CSEL = getenv("BIT:P1CSEL")
#bit P1DSEL = getenv("BIT:P1DSEL")
#byte APFCON0=getenv("SFR:APFCON0")
#byte APFCON1=getenv("SFR:APFCON1")
//////////////////////////////////////////////////////////
//                                                      //
//                  FUNCTIONS                           //
//                                                      //
//////////////////////////////////////////////////////////

//**************************************
// Initialize
// Function to initialize uC and LCD
//**************************************
void Initialize() {
      setup_ccp1(CCP_PWM);
      P1DSEL = 1;
      output_drive(PIN_C0);
      setup_timer_2(T2_DIV_BY_1, 255, 1);
      set_pwm1_duty(128);
     
     
//clear_interrupt(INT_TIMER0);// Clear Timer 0 interrupt
clear_interrupt(INT_TIMER2);//PWM
clear_interrupt(INT_CCP1); //PWM

enable_interrupts(INT_CCP1);//PWM
enable_interrupts(INT_TIMER2);//PWM
//enable_interrupts(int_timer0);// Enable Timer 0 interrupt
enable_interrupts(GLOBAL); // enable all interrupts
} //End of Init routine




//////////////////////////////////////////////////////////
//                                                      //
//                  INTERRUPTS                          //
//                                                      //
//////////////////////////////////////////////////////////



/*********************************************************
* TIMER0_ISR
*
* Generates Beep tones
**********************************************************/

#INT_TIMER0//TIMER0 Interrup overflows
void Timer0_isr() {
   
   clear_interrupt(INT_TIMER0); //Clear Interrupt Flag
   
}

#INT_TIMER2//TIMER2 Interrup overflows
void Timer2_isr() {

   output_toggle(BUZ);
   clear_interrupt(INT_TIMER2);
}


#INT_CCP1 // CCP1 Interrupt
void CCP1_isr() {

   output_toggle(BUZ);
   clear_interrupt(INT_CCP1);//
}

//////////////////////////////////////////////////////////
//                                                      //
//                  MAIN PROGRAM                        //
//                                                      //
//////////////////////////////////////////////////////////


void main() {
   
     Initialize();
     
      int m;

      for (m=0; m<=500; m++)
      {
      set_pwm1_duty(m);
      delay_ms(50);
      }
     
    while(TRUE) {
       
        }// While loop
}// Main Loop
Ttelmah



Joined: 11 Mar 2010
Posts: 19494

View user's profile Send private message

PostPosted: Sun Nov 01, 2015 4:45 am     Reply with quote

Some comments:
1) The clear_interrupt calls in the interrupt routines are pointless. The compiler automatically clears interrupts _unless told not to, by using NOCLEAR_.
2) You really want STVREN selected. NOSTVREN, requires (to have any hope of working at all reliably if the stack does overflow), that you add code to check the stack status. Otherwise 'anything can happen in the next half hour'....
3) The actual movements you can do, are only those allowed by the chip. C0, is the default location for P1D. No re-mapping needed. However you then have to see how to get the output from P1D. The answer to this is 'pulse steering'. This is controlled by the PSTRxCON register. In CCS, this is setup in the setup_CCP function:
Code:

    setup_ccp1(CCP_PWM | CCP_PULSE_STEERING_D);

This routes the single CCP PWM output,, to it's D output.

No need to touch CCPSEL, APFCON, or any other register.
CMatic



Joined: 11 Jan 2012
Posts: 69

View user's profile Send private message

PostPosted: Sun Nov 01, 2015 7:47 am     Reply with quote

Ttelmah wrote:
Some comments:
1) The clear_interrupt calls in the interrupt routines are pointless. The compiler automatically clears interrupts _unless told not to, by using NOCLEAR_.
2) You really want STVREN selected. NOSTVREN, requires (to have any hope of working at all reliably if the stack does overflow), that you add code to check the stack status. Otherwise 'anything can happen in the next half hour'....
3) The actual movements you can do, are only those allowed by the chip. C0, is the default location for P1D. No re-mapping needed. However you then have to see how to get the output from P1D. The answer to this is 'pulse steering'. This is controlled by the PSTRxCON register. In CCS, this is setup in the setup_CCP function:
Code:

    setup_ccp1(CCP_PWM | CCP_PULSE_STEERING_D);

This routes the single CCP PWM output,, to it's D output.

No need to touch CCPSEL, APFCON, or any other register.


Thanks for the reply. Your points 1 and 2 are great and I have fixed the code for these. However, here is what I tried with my program

setup_ccp1(CCP_PWM | CCP_PULSE_STEERING_D);
output_drive(PIN_C0); //from some previous PWM posts in this forum
setup_timer_2(T2_DIV_BY_1, 255, 1);

My PWM output seems to be stuck on RA5 pin when I last configured the PWM CCP2 module using the following code lines:

setup_ccp2(CCP_PWM);
CCP2SEL = 1;
output_drive(PIN_A5);
setup_timer_2(T2_DIV_BY_1, 255, 1);
set_pwm2_duty(128);

Thanks for looking into this.
Ttelmah



Joined: 11 Mar 2010
Posts: 19494

View user's profile Send private message

PostPosted: Sun Nov 01, 2015 9:54 am     Reply with quote

Apologies. The data sheet has an error, it lists P1D, as defaulting to C0, but it defaults to C2 (it should be coming out here after it is selected).

You need to add:
Code:

#bit P1DSEL=getenv("BIT:P1DSEL")

    //and use:
   setup_ccp1(CCP_PWM | CCP_PULSE_STEERING_D); //C2
   P1DSEL=TRUE; //Now C0
   output_float(PIN_C2); //The compiler will have set this as output
   output_drive(PIN_C0); //and you need to set this as output
   setup_timer_2(T2_DIV_BY_1, 255, 1);
   set_pwm1_duty(128);


Beware also, 'm' needs to be an int16. Currently the loop will never exit....
CMatic



Joined: 11 Jan 2012
Posts: 69

View user's profile Send private message

PostPosted: Sun Nov 01, 2015 2:23 pm     Reply with quote

Ttelmah wrote:
Apologies. The data sheet has an error, it lists P1D, as defaulting to C0, but it defaults to C2 (it should be coming out here after it is selected).

You need to add:
Code:

#bit P1DSEL=getenv("BIT:P1DSEL")

    //and use:
   setup_ccp1(CCP_PWM | CCP_PULSE_STEERING_D); //C2
   P1DSEL=TRUE; //Now C0
   output_float(PIN_C2); //The compiler will have set this as output
   output_drive(PIN_C0); //and you need to set this as output
   setup_timer_2(T2_DIV_BY_1, 255, 1);
   set_pwm1_duty(128);


Beware also, 'm' needs to be an int16. Currently the loop will never exit....


Thank you so much, its now working. Ttelmah I appreciate your help very much.
Ttelmah



Joined: 11 Mar 2010
Posts: 19494

View user's profile Send private message

PostPosted: Mon Nov 02, 2015 3:34 am     Reply with quote

Good Smile
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