PIC12F1571 PWM issue II  - Page 1
Forum section: electronics / general

author: singlarrysong
author_rank: Contributor
timestamp: September 16, 2016, 07:01:02 am
content: I had read previously question which post during march 2016, and it don't help me muchAs 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::blah: :blah: :blah: :blah: config settingvoid InitPWM(void){TRISA1 = 0; //outputLATA1 = 0; //Clear outputAPFCONbits.P1SEL = 0; //pin RA1PWM1CON = 0b11000000; //Enable PWM, enable outputPWM1CLKCON = 0b00000001;//no prescaler, HFINTOSCPWM1TMR = 0xFFFF; //Max 65535 ,PWMxTMR is = to PWMxTMRH:PWMxTMRLPWM1PR = 0xFFFF; //max 65535, PWMxPR is = to PWMxPRH:PWMxPRLPWM1DC = 0x3FF; //set 10 bits, PWMxDC is = to PWMxDCH:PWMxDCLreturn; //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 cycleI swear I read carefully the PWM standard mode operation on the datasheet before I wrote my code and follow the graph that shownso im expecting, setting the PWMxPH is determine the falling state of the PWM.

author: JPortici
author_rank: Super Contributor
timestamp: September 16, 2016, 07:55:46 am
content: you got it wrong!!PWMxTMR is the timer you would have used in CCPx, let's say TMR2PWMxPR 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 PHnot really in this case. output is log for 0 < TMR < PH then it's high until TMR = DC then it's low until next cyclekeep PH to 0 to have CCP-like behaviour

author: singlarrysong
author_rank: Contributor
timestamp: September 16, 2016, 09:00:06 am
content: I hope I follow the instruction from you correctly, unfortunately no output from that port at all.Code:void InitPWM(void){TRISA1 = 0; //outputLATA1 = 0; //Clear outputANSELAbits.ANSA1 = 1; //Digital portAPFCONbits.P1SEL = 0; //pin RA1PWM1CONbits.MODE = 0; //Standard PWMPWM1PR = 0xFFFF; //Period register fullPWM1CLKCON = 0b01000001;//16 prescaler, HFINTOSCPWM1PH = 0x0000; //Phase set to 0PWM1DC = 0x0000;PWM1CON = 0b11000000; //Enable PWM, enable outputreturn; //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 PIC16F1825Code:void PWMA(unsigned int DutyCycle){CCPR1L = DutyCycle>>2;// Put MSB 8 bits in CCPR1LCCP1CON &= 0xCF;// Make bit4 and 5 zeroCCP1CON |= (0x30&(DutyCycle<<4));// Assign Last 2 LSBs to CCP1CON}void InitPWM(void){TRISC = TRISC & 0b011111;// Set outputs of CCPsPORTC = PORTC | 0b000000;CCP1CON = 0b00001100;// Configure CCP1 module in PWM modeCCP2CON = 0b00001100;// Configure CCP2 module in PWM modeCCPTMRS = 0b00000000;// CCP use Timer2PR2 = 0xFF;// Configure the Timer2 periodT2CON = 0b01;// Set Prescaler to be 16,PWMA(0);T2CON |= 0x04;// Enable the Timer2, hence enable the PWM.}

author: JPortici
author_rank: Super Contributor
timestamp: September 16, 2016, 09:28:02 am
content: ANSELAbits.ANSA1 = 1; //Digital portshould beANSELAbits.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 RA1the rest seem fine :/

author: singlarrysong
author_rank: Contributor
timestamp: September 16, 2016, 10:01:27 am
content: 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 sameCode:void InitPWM(void){TRISA1 = 0; //outputLATA1 = 0; //Clear outputANSELAbits.ANSA1 = 0; //Digital portAPFCONbits.P1SEL = 0; //pin RA1PWM1CONbits.MODE = 0; //Standard PWMPWM1TMR = 0xFFFF;PWM1PR = 0xFFFF; //Period register fullPWM1CLKCON = 0b00000001;//0 prescaler, HFINTOSCPWM1PH = 0x0000; //Phase set to 0PWM1DC = 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)

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: September 17, 2016, 08:27:04 pm
content: Quote from: singlarrysong on September 16, 2016, 07:01:02 amWhat are your Config Word settings?

author: singlarrysong
author_rank: Contributor
timestamp: September 19, 2016, 02:35:12 am
content: 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:// 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 problemCode:#include <xc.h>#include <stdlib.h>#define _XTAL_FREQ 32000000 //32MHzvoid 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 nopeBelow is how to test it out on my main routine...Code:void main(void){OSCCON = 0b11110000;InitPWM();TRISA5 = 0;for(;;){LATA5 = ~LATA5;for(int x = 0 ; x < 65536 ; x++){PWMA(x);__delay_us(100);}}}

author: singlarrysong
author_rank: Contributor
timestamp: September 19, 2016, 02:41:01 am
content: 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.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: September 20, 2016, 07:56:00 am
content: 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 be0b11100000(or0b11000000, since bit 5 is read-only). The compiler issues a warning and truncates your hex number to 0x00, which doesnotenable 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 withCode:PWM1CONbits.MODE = 0; // standard PWMPWM1CONbits.POL = 0; // active highPWM1CONbits.OE = 1; // enable outputPWM1CONbits.EN = 1; // enable PWMand your intentions are clearerplusit'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.

author: singlarrysong
author_rank: Contributor
timestamp: September 20, 2016, 08:36:54 am
content: Sorry making you all have to go datasheet to see the config. I do notive the hex problem after posting but still remain sameI try the way you set but it don't work still.Code:void InitPWM(void){TRISA1 = 0;LATA1 = 0;PWM1CONbits.MODE = 0; // standard PWMPWM1CONbits.POL = 0; // active highPWM1CONbits.OE = 1; // enable outputPWM1CONbits.EN = 1; // enable PWMPWM1CLKCON = 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: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 xDThe minor problem is still there but we had solve the major one.