0
votes

I am new to working with PIC microcontrollers and MPLAB. I bought myself a few PIC18F24Q10 chips and have slowly figuring out how to use some of the different functionalities. One thing that I am currently stumped on is the PWM. I have been trying to figure out how to get the PWM to work on the chip, but have had no luck. It does not owtput any kind of pwm signal. My end goal is for it to drive a servo, but for now i just have it connected to an LED to make sure it works.

I have posted my code below. If someone could be kind enough to take a quick look at it for me and let me know if anything jumps out as being wrong I would appreciate it. Like I said, I am quite new to this so i apologize in advance for my sloppy coding style. The values that i have loaded into the CCPR2 register and T2PR for the period and duty cycle are sort of just random values that I have been changing around and experimenting with. I mostly just want to get the PWM functionality to work before I dive into getting it set up to run a servo, which is my end goal.


#include <xc.h>
#include <stdlib.h>
// CONFIG1L
#pragma config FEXTOSC = ECH    // External Oscillator mode Selection bits (EC (external clock) above 8 MHz; PFM set to high power)
# pragma config RSTOSC = HFINTOSC_64MHZ// Power-up default value for COSC bits (HFINTOSC with HFFRQ = 64 MHz and CDIV = 1:1)

// CONFIG1H
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)

// CONFIG2L
#pragma config MCLRE = EXTMCLR  // Master Clear Enable bit (MCLR pin (RE3) is MCLR)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (Power up timer disabled)
#pragma config LPBOREN = OFF    // Low-power BOR enable bit (Low power BOR is disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled , SBOREN bit is ignored)

// CONFIG2H
#pragma config BORV = VBOR_190  // Brown Out Reset Voltage selection bits (Brown-out Reset Voltage (VBOR) set to 1.90V)
#pragma config ZCD = OFF        // ZCD Disable bit (ZCD disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON)
#pragma config PPS1WAY = OFF     // PPSLOCK bit One-Way Set Enable bit (PPSLOCK bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Extended Instruction Set and Indexed Addressing Mode disabled)

// CONFIG3L
#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF        // WDT operating mode (WDT always enabled)

// CONFIG3H
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC      // WDT input clock selector (Software Control)

// CONFIG4L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)

// CONFIG4H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-30000Bh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
#pragma config SCANE = ON       // Scanner Enable bit (Scanner module is available for use, SCANMD bit can control the module)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored)

// CONFIG5L
#pragma config CP = OFF         // UserNVM Program Memory Code Protection bit (UserNVM code protection disabled)
#pragma config CPD = OFF        // DataNVM Memory Code Protection bit (DataNVM code protection disabled)

// CONFIG5H

// CONFIG6L
#pragma config EBTR0 = OFF      // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)

// CONFIG6H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.




#define _XTAL_FREQ 8000000


void PWM_Init()            /* Initialize PWM */
{
   
    TRISC1=0;  // Set CCP2 pin as output for PWM out 
    T2ON=0;
    T2PR = 0xff; 
    CCP2CON = 0b00001100; 
    CCPR2 = 60; // load duty cycle value 
    TMR2IF=0;
    T2CLKCONbits.CS = 0b0001;
    T2CONbits.CKPS = 0b10; // prescale value of 1:4. 
    T2ON = 1; 
     
}

int main()
{
    
   OSCFRQbits.HFFRQ = 0b0011; // set clock to 8Mhz
    ANSELC = 0b00000000;
   PWM_Init();
   
  while(1)
  {
      
  }
  return 0;
} 

I have the LED hooked up to pin RC1, which corresponds with CCP2. The chip's RSTOSC bit is set to the 64MHz internal oscillator, which i then bring down to 8MHZ in my main function configuring the HFFRQ bit. I am wondering if the problem has something to do with the clock setup, but I honestly lack the understanding of the chip's clocking structure to know for sure.

Thanks in advance for your help, and let me know if you need any more detail.

1
You had to set the ENBit in CCP2CONalso had a look at the PPSsection in the datasheet.Mike

1 Answers

0
votes

I have an answer for you but it comes with a saga of trial and tribulation.

Your answer is that your code does not ENABLE the CCP2 function block.

The tribulation is that when the CCP2 is configured for PWM and the CCP2 enable bit is set the simulator crashes.

This code should initialize a real part:

    /*
     * Initialize CCP2 for PWM output on RC1
     * Set period to (FOSC/(4*T2_prescale*256)), (8000000/4096)= 1953.125 Hz
     * Set duty cycle to 50%
     */
    void PWM_Init(void)         /* Initialize PWM */
    {
        T2CON   = 0;            // Stop TIMER2
        CCP2CON = 0;            // Stop PWM2
        LATCbits.LATC1 = 0;
        TRISCbits.TRISC1 = 0;   // Set CCP2 pin as output for PWM out
        ANSELCbits.ANSELC1 = 0; // Make RC1 a digital GPIO
        
        T2CLKCON = 0x01;        // Select FOSC/4 as TIMER2 clock source
        T2PR     = 0xFF; 
        CCP2CON  = 0b00001100; 
        CCPR2    = 511;         // load 50% duty cycle value 
        TMR2IF   = 0;
        T2CONbits.CKPS = 0b10;  // prescale value of 1:4.
        T2ON     = 1;
        RC1PPS   = 0x06;        // Assign PWM2 output to RC1
        CCP2CONbits.CCP2EN = 1;
        Nop();  /* when the simulation stops here the simulator is broken */
    }

My problem is that I do have a PIC18F27Q10 to test this code on so my code still may have issues. I did try to initialize everything so give it a try on your controller.

The MPLAB Code Configurator(MCC) sets up the same stuff only splattered across several source files.