Estoy tratando de hacer que PWM funcione en PIC12F683 . De acuerdo con mis cálculos, debería obtener un PWM de 8 bits a 20 kHz en GPIO2, pero eso no sucede. En cambio, recibo una señal PWM "extraña" de 5 kHz, de modo que cuando establezco el deber de ser 255, que debería ser el máximo, obtengo este 5kHz ola . ¿Cuál podría ser el problema?
EDITAR: estoy siguiendo este procedimiento que está escrito en la hoja de datos PIC12F683, pero no estoy haciendo lo correcto o hay algo más que debo hacer.
Este es el código:
/*
* File: main.c
* Author: Calin
*
* Created on November 9, 2015, 11:10 PM
*/
#define _XTAL_FREQ 8000000
#include <xc.h>
#include <PIC12F683.h>
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
/* Prototypes *****************************************************************/
long calculatePower(void);
unsigned int readVoltage(void);
unsigned int readCurrent(void);
void PWM_setup(void);
void PWM_set_duty(int);
void interrupt ISR(void);
/******************************************************************************/
void main(void) {
// Select 8Mhz internal clock
OSCCON |= 0b01110001;
// Configure GP0 and GP1 as analog inputs
TRISIO = 0b00000011; //input
ANSEL = 0b00000011; // clock = 1 meg and analog configure
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
INTCONbits.T0IE = 1;
PIE1bits.CCP1IE = 1;
PIE1bits.TMR2IE = 1;
PWM_setup();
PWM_set_duty(255);
while (1){
//long power = calculatePower();
}
return;
}
void PWM_setup(){
TRISIO &= 0b11111011; // make sure GP2 is OUTPUT
PR2 = 0x65;
CCP1CON = 0b00001100; // active high PWM
PIR1bits.TMR2IF = 0;
T2CONbits.T2CKPS = 0x1; // set prescaler to 1
T2CONbits.TMR2ON = 1; // enable Timer 2 and therefor PWM
}
void PWM_set_duty(int duty_cycle){
// Sets the PWM duty cycle by setting
// the 2 LSB's in DCB and the 8 MSB's
// in CCPR1L. 10 bit resolution
CCP1CONbits.DC1B = duty_cycle;
CCPR1L = duty_cycle >> 2;
}
long calculatePower(){
return readVoltage()*readCurrent();
}
unsigned int readVoltage(){
/*
* Reads and returns the voltage at AN0
*/
// Select channel 0 and turn on ADC
ADCON0 = 0b10000001; // enable ADC
ADCON0 = 0b10000011; // GO
while (CHECK_BIT(ADCON0, 1)){
// wait
}
// 10 bit ADC result
unsigned int voltage = ADRESL | (ADRESH << 8);
return voltage;
}
unsigned int readCurrent(){
/*
* Reads and returns the current at AN1
*/
// Select channel 1 and turn on ADC
ADCON0 = 0b10000101; // enable ADC & select channel
ADCON0 = 0b10000111; // GO
while(CHECK_BIT(ADCON0, 1)){
// wait
}
unsigned int current = ADRESL | (ADRESH << 8);
return current;
}
void interrupt ISR(){
// Timer2 overflow => start a new PWM cycle
if(PIR1bits.TMR2IF == 1){
PIR1bits.TMR2IF = 0;
TRISIObits.TRISIO2 = 0;
}
}