PIC12F1571 PWM frequency. - Page 1
Forum section: electronics / general

author: step_s
author_rank: Regular Contributor
timestamp: February 06, 2016, 04:07:55 pm
content: Hi EEV blog.I have tested some different microcontrollers lately, to learn a bit about programming them.Now I'm sitting with a PIC12F1571, and messing around with the PWM function.http://ww1.microchip.com/downloads/en/DeviceDoc/40001723D.pdfThe PWM is 16bit, and the PIC is running at 32MHz, so I'm getting (32MHz / 2^16 = 488Hz), periods just over 2ms long. So far so good.My problem is now, that i want to lower the bitrate in order to get higher frequencies, but don't know how.Setting the duty cycle is working like it should, but setting the period or the timer register makes the PWM flatline. . .This is the simple code I'm testing with.Code:OSCCON = 0b11110000; /4x PLL enable. Setting to 32MHzTRISA = 0b00000000; /Setting all to outputPWM1CLKCON = 0b00000000; /No prescaler. Clock source is FOSCPWM1DCH = 0b00100000; /Duty cycle high bitPWM1DCL = 0b00000000; /Duty cycle low bitPWM1CON = 0b11100000; /Turns on PWMHope you can help

author: dannyf
author_rank: Super Contributor
timestamp: February 06, 2016, 04:35:33 pm
content: no period register?

author: step_s
author_rank: Regular Contributor
timestamp: February 06, 2016, 05:01:14 pm
content: Hi Danny.When I write to the period register, the PWM flatlines.The period register has the PWM1PRH (High bit) and the PWM1PRL (Low bit), but writing any value to this stops the PWM completely.

author: dannyf
author_rank: Super Contributor
timestamp: February 06, 2016, 07:15:36 pm
content: QuoteReally? That would suggest the chip has bugs,Why don't you set the pwm mode into toggle, or set DC to be PR / 2.

author: Howardlong
author_rank: Super Contributor
timestamp: February 06, 2016, 08:51:50 pm
content: Here is some code I've just tested on a 12F1572 (I don't have a 12F1571 in stock, the 1572 is the same with more memory).Code:#include <xc.h>#include <stdint.h>// CONFIG1#pragma config FOSC = INTOSC // ->INTOSC oscillator; I/O function on CLKIN pin#pragma config WDTE = OFF // Watchdog Timer Enable->WDT disabled#pragma config PWRTE = OFF // Power-up Timer Enable->PWRT disabled#pragma config MCLRE = ON // MCLR Pin Function Select->MCLR/VPP pin function is MCLR#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 = ON // Clock Out Enable->CLKOUT function is enabled 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 = ON // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will 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->LPBOR is disabled#pragma config LVP = ON // Low-Voltage Programming Enable->Low-voltage programming enabled#define _XTAL_FREQ 32000000#define PWM3PERIOD (0.001024) // period in seconds#define PWM3PERIODREG ((uint16_t)((PWM3PERIOD*_XTAL_FREQ)-1))#define PWM3DUTYCYCLE (0.1) // Duty cycle as a fraction#define PWM3DUTYCYCLEREG ((uint16_t)((PWM3PERIODREG+1.0)*PWM3DUTYCYCLE)-1)void main(void){OSCCONbits.IRCF = 0b1110; // 0b1110 => 8 or 32 MHz (if PLL on or not)ANSELA = 0x00; // All pins digitalLATA=0;TRISA=0; // All outputs// Using PWM3 on RA2 so we can debug and not have to move pins around from defaults// Set the duty cyclePWM3DCH = (uint8_t)(PWM3DUTYCYCLEREG>>8);PWM3DCL = (uint8_t)PWM3DUTYCYCLEREG;// Set the periodPWM3PRH = (uint8_t)(PWM3PERIODREG>>8);PWM3PRL = (uint8_t)PWM3PERIODREG;PWM3CONbits.MODE = 0b00; // 0b00 => standard PWM modePWM3CONbits.OE = 1; // 1 => output enabledPWM3CONbits.EN = 1; // 1 => this PWM peripheral enabledwhile (1){NOP();}return;}

author: uncle_bob
author_rank: Unknown
timestamp: February 06, 2016, 09:39:12 pm
content: HiIf the only purpose is to get a higher bitrate output, look at using a timer function rather than a PWM.Bob

author: hamdi.tn
author_rank: Frequent Contributor
timestamp: February 06, 2016, 11:33:12 pm
content: i tried to check the datasheet and i think when you try to reduce the frequency by writing the period register you should also write the duty cycle register to a lower valueexample if P=10 and DC=9 it give a 90% duty-cycleif you change the period to 9 it will make period lower but it will give a 100% dc so a flat lineyou should adjust the dc register as well

author: Howardlong
author_rank: Super Contributor
timestamp: February 07, 2016, 07:43:58 am
content: Quote from: hamdi.tn on February 06, 2016, 11:33:12 pmHopefully that was demonstrated in the code I posted!

author: hamdi.tn
author_rank: Frequent Contributor
timestamp: February 07, 2016, 10:59:13 am
content: Quote from: Howardlong on February 07, 2016, 07:43:58 ami think the OP try to modify the period after initialisation been done, while the pwm module is already active The way i saw your code is that you enable pwm outputs after the module is correctly configured.on the other hand , i kind of feel that's a bit dangerous to change the pwm frequency that way ( on two steps, set the Period than the DC ) i didn't read much to verify is modified frequency or duty cycle are applied on the next period. cause if you trying to control a load with this pwm signal you will apply a full power for one period and it could be fatal for your switches. it's case dependent but i think worth taking it into consideration

author: Howardlong
author_rank: Super Contributor
timestamp: February 07, 2016, 01:46:06 pm
content: Quote from: hamdi.tn on February 07, 2016, 10:59:13 amI think you may well be right. Changing duty cycle on the fly isn't a problem if you're doing PWM, and it's exactly the way you usually want to use the PWM. For PFM you may well also want to update the PR registers on the fly. Although these registers are double buffered, because it's in two registers both need to be updated synchronously before the next reload or the possibility of a glitch exists when one half of the register set has been updated but the other one hasn't. In some PICs with peripherals like the NCO, you have to update the registers in a certain order to enable a reload. There's also a whole subsection 22.4 in the DS on PWM Reload.

author: step_s
author_rank: Regular Contributor
timestamp: February 07, 2016, 02:08:42 pm
content: Hi guys, thank you for all your answersI figured that the period should ofc be higher than the DC, but this is still not working. .By including the period register the code looks like this:Code:OSCCON = 0b11110000;TRISA = 0b00000000;PWM1CLKCON = 0b00000000;PWM1PRH = 0b11111111; /Period high bitPWM1PRL = 0b11111111; /Period low bitPWM1DCH = 0b00000001; /DC high bitPWM1DCL = 0b00000000; /DC low bitPWM1CON = 0b11100000;The period here is set to max, and it will work with changing the low bit to 0b11111000, but if I go any lower, the PWM flatlines.The DC here is set pretty low, so it should always be lower than the period.This seems pretty odd to me. .

author: hamdi.tn
author_rank: Frequent Contributor
timestamp: February 07, 2016, 02:34:29 pm
content: Don't forget about phase register, they will not be 0x00 on reset (check DS they are unkown bytes on Reset) , they could be anything, and if they are in a certain value that overpass your DC again you can get a signal that rise up but never go down. Not so sure about that though so give it a try.initialise PWMxPHH and PWMxPHL to 0x00 if you don't need them

author: step_s
author_rank: Regular Contributor
timestamp: February 07, 2016, 03:23:34 pm
content: Ah cheers Hamdi. It worked like a charmI just figured that since the datasheet said "standard mode" was a "single phase PWM" that setting the PWM to standard mode, would lock the phase.