Author Topic: PIC12F1571 PWM issue II  (Read 3934 times)

0 Members and 1 Guest are viewing this topic.

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
PIC12F1571 PWM issue II
« on: September 16, 2016, 07:01:02 am »
I had read previously question which post during march 2016, and it don't help me much
As this is a new PIC to me, I went to test on the 16Bit PWM which previously I never work with(previously I do CCP only). The output is connected to a MOSFET as class D amp switch a LED.
CONFIG words work fine, delay work fine.

Code: [Select]
:blah: :blah: :blah: :blah: config setting
void InitPWM(void)
{
    TRISA1 = 0;             //output
    LATA1 = 0;              //Clear output
    APFCONbits.P1SEL = 0;   //pin RA1
     
    PWM1CON = 0b11000000;   //Enable PWM, enable output
    PWM1CLKCON = 0b00000001;//no prescaler, HFINTOSC
    PWM1TMR = 0xFFFF;       //Max 65535 ,PWMxTMR is = to PWMxTMRH:PWMxTMRL
    PWM1PR = 0xFFFF;        //max 65535, PWMxPR is = to PWMxPRH:PWMxPRL
    PWM1DC = 0x3FF;         //set 10 bits, PWMxDC is = to PWMxDCH:PWMxDCL
   
    return;                 //JIC it stuck here
}
void main(void)
{
OSCCON = 0b11110000;   
   
    InitPWM();
   
while(1)
{
        for(unsigned int a = 0 ; a < 1024 ; a++)
        {
            PWM1PH = a; //PWMxPH is = to PWMxPHH:PWMxPHL
            __delay_us(20);
        }
    }
}
base on the code, im expecting the LED will slowly fall in brightness and cycle each time around 1-2 seconds.
however, the led stuck at certain duty cycle

I swear I read carefully the PWM standard mode operation on the datasheet before I wrote my code and follow the graph that shown
so im expecting, setting the PWMxPH is determine the falling state of the PWM.

 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: PIC12F1571 PWM issue II
« Reply #1 on: September 16, 2016, 07:55:46 am »
you got it wrong!!

PWMxTMR is the timer you would have used in CCPx, let's say TMR2
PWMxPR is the equivalent of PR2 so it sets the max number of steps per cycle (the number at which the timer resets)
PWMxDC is the equivalent of CCPRxL so it sets the duty cycle
---
PWMxPH sets the phase shift of the signal.. instead of having the output rise when the TMR is "0" it rises at PH
not really in this case. output is log for 0 < TMR < PH then it's high until TMR = DC then it's low until next cycle

keep PH to 0 to have CCP-like behaviour
« Last Edit: September 16, 2016, 07:58:56 am by JPortici »
 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: PIC12F1571 PWM issue II
« Reply #2 on: September 16, 2016, 09:00:06 am »
I hope I follow the instruction from you correctly, unfortunately no output from that port at all.  :'( :'(

Code: [Select]
void InitPWM(void)
{
    TRISA1 = 0;             //output
    LATA1 = 0;              //Clear output
    ANSELAbits.ANSA1 = 1;   //Digital port
    APFCONbits.P1SEL = 0;   //pin RA1
   
    PWM1CONbits.MODE = 0;   //Standard PWM
    PWM1PR = 0xFFFF;        //Period register full
    PWM1CLKCON = 0b01000001;//16 prescaler, HFINTOSC
    PWM1PH = 0x0000;        //Phase set to 0
    PWM1DC = 0x0000;
    PWM1CON = 0b11000000;   //Enable PWM, enable output
   
    return;                 //JIC it stuck here
}
void main(void)
{
OSCCON = 0b11110000;   
   
    InitPWM();
   
while(1)
{
        for(unsigned int a = 0 ; a < 65536 ; a++)
        {
            PWM1DC = a;
            __delay_us(100);
        }
    }
}

this is what I do while using CCP on PIC16F1825

Code: [Select]
void PWMA(unsigned int DutyCycle)
{
CCPR1L   = DutyCycle>>2; // Put MSB 8 bits in CCPR1L
CCP1CON &= 0xCF; // Make bit4 and 5 zero
CCP1CON |= (0x30&(DutyCycle<<4)); // Assign Last 2 LSBs to CCP1CON
}
void InitPWM(void)
{
TRISC = TRISC & 0b011111; // Set outputs of CCPs
PORTC = PORTC | 0b000000;
CCP1CON = 0b00001100; // Configure CCP1 module in PWM mode
CCP2CON = 0b00001100; // Configure CCP2 module in PWM mode
CCPTMRS = 0b00000000; // CCP use Timer2
PR2   = 0xFF; // Configure the Timer2 period
T2CON = 0b01; // Set Prescaler to be 16,
PWMA(0);
T2CON |= 0x04; // Enable the Timer2, hence enable the PWM.
}
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Re: PIC12F1571 PWM issue II
« Reply #3 on: September 16, 2016, 09:28:02 am »
ANSELAbits.ANSA1 = 1;   //Digital port
should be
ANSELAbits.ANSA1 = 0;

REGISTER 11-5: ANSELA

- One that i always forget about is the comparator. *shouldn't affect you* but writing 0x37 on CM1CON1  will disconnect the comparator inputs from RA0 and RA1

the rest seem fine :/
 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: PIC12F1571 PWM issue II
« Reply #4 on: September 16, 2016, 10:01:27 am »
Still a no. To bad and I felt so sorry to take a lot of your time D:
The CM1CON1 I tried with and w/o both give no output.
And also the PWM1TMR I try with 65535 and w/o, both still give nothing at the output.
Originally the InitPWM routine with "return", I keep and  remove it still the same

Code: [Select]
void InitPWM(void)
{
    TRISA1 = 0;             //output
    LATA1 = 0;              //Clear output
    ANSELAbits.ANSA1 = 0;   //Digital port
    APFCONbits.P1SEL = 0;   //pin RA1
   
    PWM1CONbits.MODE = 0;   //Standard PWM
    PWM1TMR = 0xFFFF;
    PWM1PR = 0xFFFF;        //Period register full
    PWM1CLKCON = 0b00000001;//0 prescaler, HFINTOSC
    PWM1PH = 0x0000;        //Phase set to 0
    PWM1DC = 0x0000;
    PWM1CON = 0b11000000;   //Enable PWM, enable output
}
void main(void)
{
OSCCON = 0b11110000;   
    CM1CON1 = 0x37;
    InitPWM();
   
    PWM1DC = 1000;
    PWM1PH = 200;
while(1)
{

    }
}

Bang my head again the wall oh~ (play in my mind) |O |O |O
 

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 627
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: PIC12F1571 PWM issue II
« Reply #5 on: September 17, 2016, 08:27:04 pm »
CONFIG words work fine,
What are your Config Word settings?
« Last Edit: September 17, 2016, 08:28:52 pm by Bruce Abbott »
 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: PIC12F1571 PWM issue II
« Reply #6 on: September 19, 2016, 02:35:12 am »
Hello, sorry for the late, the code is following.
RA5 is used to test weather the code is going though which stage.
RA1 ad PWM1 output, LED is directly connect with the output pin(I scare that transistor might have bandwidth limit)

Code: [Select]
// PIC12F1571 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1
#pragma config FOSC = INTOSC    //  (INTOSC oscillator; I/O function on CLKIN pin)
#pragma config WDTE = OFF    // Watchdog Timer Enable
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOREN = OFF    // Low Power Brown-out Reset enable bit
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

I've now success on setting PWM. However some of the time when I power up the MCU, it shows there's overflow on the PWM(example, at PWM1DC = 0, it give duty cycle about 1%, PWM65530ish it give it give 0 duty cycle)
below is how I found the problem
Code: [Select]
#include <xc.h>
#include <stdlib.h>

#define _XTAL_FREQ 32000000     //32MHz
void PWMA(unsigned int DutyCycle)
{
    PWM1CON = 0x00;
    PWM1DC = DutyCycle;

    PWM1CON = 0b11000000;
}
void InitPWM(void)
{
    TRISA1 = 0;
    LATA1 = 0;
   
    PWM1CON = 0x00;
    PWM1CLKCON = 0b00000000;
    PWM1PR = 0xFFFF;
    PWM1DC = 0x0000;

    PWM1PH = 0x0000;
    PWM1CON = 0x11100000;
   
    return;
}
void main(void)
{
    OSCCON = 0b11110000;
   
    InitPWM();
   
    TRISA5 = 0;

        for(;;)
        {
        LATA5 = 1;   
        __delay_ms(1000);
       
        LATA5 = 0;
        PWMA(0);
        __delay_ms(500);
       
        LATA5 = 1;
        PWMA(512);
        __delay_ms(500);
       
        LATA5 = 0;
        PWMA(65515);
        __delay_ms(500);
       
        LATA5 = 1;
        PWMA(65530);
        __delay_ms(500);
       
        LATA5 = 0;
        PWMA(65535);
        __delay_ms(500);
    }
}

There is also a problem that when I try to reduce the delay time to under 1ms the duty not successfully set and varies around 1-10% only. I'm also expecting the LATA5 but will toggle each time the loop is done, but unfortunately nope
Below is how to test it out on my main routine...
Code: [Select]
void main(void)
{
    OSCCON = 0b11110000;
   
    InitPWM();
   
    TRISA5 = 0;


    for(;;)
    {
        LATA5 = ~LATA5;
        for(int x = 0 ; x < 65536 ; x++)
        {
            PWMA(x);
            __delay_us(100);
        }
    }
}



 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: PIC12F1571 PWM issue II
« Reply #7 on: September 19, 2016, 02:41:01 am »
This is the first time I use PIC12F, previously I experience with PIC16F628A, PIC16F1939, PIC16F1825 and PIC16F1847.
The end project will be using the log potentiometer tie with ADC module, and the result of ADC will be input to PWM(adjust resolution to 10bits)
so success on fast varying PWM Duty Cycle is what I really concern about.
 

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 627
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: PIC12F1571 PWM issue II
« Reply #8 on: September 20, 2016, 07:56:00 am »
Please try to avoid using 'magic' numbers in your code. Apart from making it hard to follow (we have to look at the bit positions in the datasheet to find out what they do) it allows errors to slip in undetected.

In InitPWM() you have  PWM1CON = 0x11100000. This should be 0b11100000 (or 0b11000000, since bit 5 is read-only). The compiler issues a warning and truncates your hex number to 0x00, which does not enable the PWM module! As result PWM is not enabled when you call PWMA(), which I am guessing is why you had to enable it 'again' inside that function.

Replace the magic number with
Code: [Select]
    PWM1CONbits.MODE = 0;  // standard PWM
    PWM1CONbits.POL = 0;   //  active high
    PWM1CONbits.OE = 1;    // enable output
    PWM1CONbits.EN = 1;    // enable PWM
and your intentions are clearer plus it's harder to make silly mistakes.

Once the PWM module is properly enabled you should be able to change the duty cycle 'on the fly' and it will update at the start of the next cycle. So remove the PWM1CON = 0x00 and PWM1CON = 0b11000000 from PMWA(), and the duty cycle should update correctly even when the delay is less than 1ms.

 
 

Offline singlarrysongTopic starter

  • Contributor
  • Posts: 34
Re: PIC12F1571 PWM issue II
« Reply #9 on: September 20, 2016, 08:36:54 am »
Sorry making you all have to go datasheet to see the config. I do notive the hex problem after posting  but still remain same
I try the way you set but it don't work still.
Code: [Select]
void InitPWM(void)
{
    TRISA1 = 0;
    LATA1 = 0;

    PWM1CONbits.MODE = 0;  // standard PWM
    PWM1CONbits.POL = 0;   //  active high
    PWM1CONbits.OE = 1;    // enable output
    PWM1CONbits.EN = 1;    // enable PWM
    PWM1CLKCON = 0;
    PWM1PR = 0x3FF;
    PWM1PH = 0;
}
void main(void)
{
    OSCCON = 0b11110000;
   
    InitPWM();
   
    for(;;)
    {
        for(unsigned int x = 0 ; x < 1024 ; x++)
        {
            PWM1DC = x;
            __delay_ms(1);
        }
        for(signed int y = 1023 ; y > -1 ; y--)
        {
            PWM1DC = y;
            __delay_ms(1);
        }
    }
}

I had get what I wants when I change PWMxPR to 0x3FF. And the setting code remain almost same.
So basically what happening after my PWMxDC overflow 1023 and over the output will remain 100% duty cycle.
and when over 63356 it will give 0% duty cycle(as 16bits totally overflowed)
I try to reduce the PWMxCON on my PWMa() again and it don't work.

Code: [Select]
void InitPWM(void)
{
    TRISA1 = 0;
    LATA1 = 0;
   
    PWM1CLKCON = 0;
    PWM1PR = 0x3FF;
    PWM1PH = 0;
}
void PWMa(unsigned int DutyCycle)
{
    PWM1CON = 0;
    OSCCON = 0b11110000;
   
    InitPWM();
   
    for(;;)
    {
        for(unsigned int x = 0 ; x < 1024 ; x++)
        {
            PWMa(x);
            __delay_ms(1);
        }
        for(signed int y = 1023 ; y > -1 ; y--)
        {
            PWMa(y);
            __delay_ms(1);
        }
    }
}

I also notice that PWM1xPR affect the output period thus varies its frequency.

I had get what I need so far. so thanks for everyone try to help me.
and sorry for the mess xD
The minor problem is still there but we had solve the major one.  :-+
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf