PIC18f2580 pwm CCP1

Cantafford

Member
Hello,

Using the CCP1 module of the PIC18f2580 I'm trying to send some PWM pulses on the CCP1 pin. I have put an led on it so I can check the voltage across it(simulation software not hardware).
The program is supposed to do the following:
-when no buttons are pressed no votlage across the LED
-while first is pressed 25% PWM duty cycle
-while second is pressed 50%
- third - 75%
-forth - 100%

I have wrote the following program:
Code:
/*
* File:   pwm.c
* Author: Paul
*
* Created on November 20, 2015, 1:22 PM
*/

#include <stdio.h>
#include <stdlib.h>
#include "pwm.h"

void main()
{
    OSCCON = 0b00101110; // internal freq is 250khz
    T2CON = 0b00000101; // TMR2 prescaler is 4
    PR2 = 56/100; // pr is 0.56
    // int pwm8msb = {0b00000000, 0b00000110, 0b00001100, 0b00010010, 0b00011001}; CCPR1L
    // int pwm2lsb = {0b00, 0b01, 0b10, 0b11, 0b00}; DC1B1 and DC1B0
    int i = 0, j=0;
    TRISCbits.RC2 = 0; // led is here
    TRISB = 1; // buttons are here

    // DC1B1:DC1B0 the two LSbs (bit 1 and bit 0) of the 10-bit PWM duty cycle
    CCP1M3 = 1; // CCP1 configured for PWM mode
    CCP1M2 = 1;
    CCP1M1 = 0;
    CCP1M0 = 0;


    while(1)
    {

         while(PORTBbits.RB0==1 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 1) // no voltage%
        {
          CCPR1L = 0b00000000;
          DC1B1 = 0;
          DC1B0 = 0;
        }


         while(PORTBbits.RB0==0 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 1) // 25%
        {
          CCPR1L = 0b00000110;
          DC1B1 = 0;
          DC1B0 = 1;
        }

        while(PORTBbits.RB0==1 && PORTBbits.RB1 == 0 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 1) // 50%
        {
          CCPR1L = 0b00001100;
          DC1B1 = 1;
          DC1B0 = 0;
        }

        while(PORTBbits.RB0==1 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 0 && PORTBbits.RB3 == 1) // 75%
        {
          CCPR1L = 0b00010010;
          DC1B1 = 1;
          DC1B0 = 1;
        }

         while(PORTBbits.RB0==1 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 0) // 100%
        {
          CCPR1L = 0b00011001;
          DC1B1 = 0;
          DC1B0 = 0;
        }

     }
}

This is the header file where the configuration bits are:
Code:
/*
* File:   pwm.h
* Author: Paul
*
* Created on November 20, 2015, 1:20 PM
*/

// PIC18F2580 Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>

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

// CONFIG1H
#pragma config OSC = IRCIO67    // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = BOHW     // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (VBOR set to 2.1V)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = OFF      // MCLR Pin Enable bit (RE3 input pin enabled; MCLR disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config BBSIZ = 1024     // Boot Block Size Select bit (1K words (2K bytes) boot block)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) 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)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

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

#define _XTAL_FREQ 250000




I have the following problem:
Whenever I push a button I will have some voltage across the LED but no matter what button I press the same voltage will be there. There should be 25, 50, 75 and 100% DC values but only 1 voltage is there for all the presses.
Please let me know what am I doing wrong. Thank you.
 
PR2 is zero.... PR2 can't be zero...

PR2 = 56/100; // This must be a value between 1 and 256 as it has to match the timer 2 ..
What frequency do you need...
125Khz.. prescale of 4 If the PR2 was set to 255 the PWM frequency would be 30hz PR2 = 126 then it would be 61hz..
 

Ok I have modified the PR2 value. For 61hz the led would blink too fast so I choose the following values: Oscillator Freq = 125Khz, PR2 = 2, TMR2 presc = 4. So I obtained a frequency of 2.6 KHz.
I still have the same problem: No matter what switch I press I only see one value of voltage across the LED no matter the duty cycle.
Am I doing something wrong in setting the duty cycle in the code below?

Code:
while(1)
    {

         while(PORTBbits.RB0==1 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 1) // no voltage%
        {
          CCPR1L = 0b00000000;
          DC1B1 = 0;
          DC1B0 = 0;
        }


         while(PORTBbits.RB0==0 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 1) // 25%
        {
          CCPR1L = 0b00000110;
          DC1B1 = 0;
          DC1B0 = 1;
        }

        while(PORTBbits.RB0==1 && PORTBbits.RB1 == 0 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 1) // 50%
        {
          CCPR1L = 0b00001100;
          DC1B1 = 1;
          DC1B0 = 0;
        }

        while(PORTBbits.RB0==1 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 0 && PORTBbits.RB3 == 1) // 75%
        {
          CCPR1L = 0b00010010;
          DC1B1 = 1;
          DC1B0 = 1;
        }

         while(PORTBbits.RB0==1 && PORTBbits.RB1 == 1 && PORTBbits.RB2 == 1 && PORTBbits.RB3 == 0) // 100%
        {
          CCPR1L = 0b00011001;
          DC1B1 = 0;
          DC1B0 = 0;
        }

     }
 
PR2 is the period...... You will only have 2 bit resolution..... 00 ( off) 01(33%) 10(66%) and 11( full on )..

Realistically you need PR2 as high as possible.. Make PR2 higher than 64... then timer2 has quite a count within the time period!!
 
PR2 doesn't determine blink frequency.... The frequency doesn't change only the duty cycle..

If PR2 was 255 that would give 10 bits ( using CCP1CON bits 3&4 ) the CCPR1L is the count of the high part and the rest of timer 2 until it matches PR2

If you set CCPR1L to 127 the timer would start the count and set the pin high until it matches the CCPR1H register ( Automatically loaded via CCPR1L and the other two bits ) Then sets the pin low until it matches PR2...
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…