Mejor manera manual de programar PWM?

Buenas tardes amigos del foro, estoy haciendo un pequeño programa con un PIC16F887 en C con el compilador Hitech, quiero implementar dos PWM a aproximadamente 50 Hz y variar su ciclo de trabajo, las únicas salidas disponibles que tengo se encuentran en el puerto B.

¿Cuál es la mejor forma de realizar esto?
Hasta ahorita mi idea es hacerlo con el timer 0 y el timer 1, para un solo PWM tengo claro como lo quiero llevar a cabo, usaré el timer1 y pondré un tiempo de 20ms, cada 20 ms generaré una interrupción, después de eso al inicio de cada periodo colocaré el timer0 de acuerdo a mi ciclo de trabajo deseado, el cual irá desde 0-20ms. Cuando haya una interrupción del timer0 desactivaré la salida PWM y esta se volverá activar de nuevo hasta el overflow del timer1.

No se si me doy a entender, esta idea no la veo compatible al tener dos puertos PWM con distintos ciclos de trabajo, por lo que me pregunto si hay alguna metodología ya probada (o librería) que me pueda servir mejor o si voy por el buen camino.

Saludos. :D

P.D. Una disculpa por el título del post tan feo XD
 
Bueno por el momento estoy haciendo el PWM únicamente con el timer1 y hasta ahorita no he tenido problemas, solo estoy controlando un solo motor pero no se si será un código eficiente una vez que agregue el código para controlar dos motores al mismo tiempo ya que planeo hacerlo con un solo timer.

Código:
void interrupt timer1_int(void)
{int r;
    if (TMR1IF) // Timer1 interrupt
    {
        switch (estado)
        {
            case (1):
                RB2=1;
                TMR1L=retardo1;
                r = (retardo1>>8);
                TMR1H=r;
                estado=2;
                break;
             
            case  (2):
                RB2=0;
                TMR1L=retardo2;
                r = (retardo2>>8);
                TMR1H=r;
                estado=1;
                break;
        }
    TMR1IF = 0;             //Limpiar la interrupción
    return;
    }
}
 
void calcular_retardos (unsigned int porcentaje ){
    unsigned int registro,resta;static unsigned int multiplicador=125;
    registro=porcentaje * multiplicador;
    retardo1=65536- registro;
    resta=12500-registro;
    retardo2=65536-resta;
 
return;
}
 
Buen dia, la estructura para generar PWM por software es como sigue:

PHP:
volatile unsigned int duty_cycle_1 = 0, duty_cycle_2 = 0,;

void main (void)
{
    inicializar_puerto();
    inicializar_timers();
    inicializar_interrupciones();
 
    while(1) 
    {
        duty_cycle_1 = 100;
        duty_cycle_2 = 200;
    }  
}
 
void interrupt isr(void)
{
    static unsigned int contador = 0;
 
    T0IF = 0;
 
    if(++contador == 0) PORTB &= 0b11111100;
    if(contador == duty_cycle_1) PORTB |= 0b00000001;
    if(contador == duty_cycle_2) PORTB |= 0b00000010;
}

con este fragmento de codigo se puede obtener 256 diferentes ciclos de trabajo en cada pin. la frecuencia se determina por el timer utilizado.
 
Que tal, muchas gracias por tu respuesta, entiendo el código y lo voy a probar, pero una duda al respecto, si lo uso para frecuencias bajas, ¿me afectará esto a la hora de hacer otras tareas?, lo pregunto porque el pic estará teniendo 256 interrupciones por cada periodo o eso es lo que entiendo del código.

La verdad el código que me propones está bastante limpio y eso creo que puede ser una ventaja, ya que tras cada interrupción, le tomará al micro solo unas cuantas instrucciones para salir de la interrupción, haré la prueba y comento, muchas gracias.
 
¿me afectará esto a la hora de hacer otras tareas?

es dificil saber sin mas detalles de las otras tareas, pero si es la unica interrupcion que utilizas no hay problema.

Cambie la logica del programa para obtener exactamente 50 Hz. te adjunto un ejemplo para el 12F683 que es el unico que tengo a mano. El codigo esta en XC8 pero es basicamente lo mismo que el HiTech.
PHP:
#include <xc.h>          /* Incluye definiciones del microcontrolador */
#include <stdint.h>      /* Incluye definiciones para variables enteras */

#define _XTAL_FREQ 8000000

#pragma config FOSC = INTOSCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF, CP = OFF

/* prototipos */
void inicializar_micro(void);

/* variables globales */
volatile uint8_t duty_cycle_1 = 50, duty_cycle_2 = 150;

void main (void)
{
    inicializar_micro();

    while(1)
    {
        GPIO ^= 0b000100;
        __delay_ms(500);
    }
}

void interrupt isr(void)
{
    static uint8_t contador = 0;

    TMR0 = 118;            /* ajuste para 50Hz */
    T0IF = 0;

    if(++contador == 0) GPIO |= 0b000011;
    if(contador == duty_cycle_1) GPIO &= 0b111110;
    if(contador == duty_cycle_2) GPIO &= 0b111101;
}

void inicializar_micro(void)
{
    OSCCON  = 0b01110001;       /* osc. interno a 8 MHz */
    CMCON0 |= 0b00000111;       /* desactiva comparadores */
    ANSEL  &= 0b11110000;       /* puerto como E/S digitales */
    GPIO    = 0b000000;         /* clear latches */
    TRISIO  = 0b001000;         /* GP3 unica entrada */

    OPTION_REGbits.T0CS = 0b0;   /* selecciona Timer0 en modo timer */
    OPTION_REGbits.PSA = 0b1;    /* asigna pre-escala al WDT */
    
    INTCONbits.T0IE = 1;         /* habilita interrupciones para Timer0 */
    ei();                        /* habilita interrupciones glogales */
}

pwm.gif

saludos
 
Hola que tal, estoy probando el código que amablemente me proporcionaste, muchas gracias.

Por cierto yo uso el Hitech porque es con el que empecé hace un tiempo, no tengo mucha experiencia pero si una duda, acabo de ver en la página de microchip que los nuevos son los X como el que mencionas, XC8, como está eso?, que cambios tiene? puedo compilar los programas en Hitech con ese compilador o que cambios tendría que realizar?.

Saludos y gracias por tu tiempo.
 
Atrás
Arriba