# XC8 mplab x  programacion PWM con 16f628A



## yamilongiano (May 15, 2013)

Hola quiero avisar que soy nuevo en este lenguaje estaba mirando unos codigos por la web y encontre un PWM en un microcontrolador y llamo mi atencion.

copie el codigo en mplab x y al compilarlo me crea el .hx pero sale un error en
 __delay_ms(100); aun asi logra crearlo.
aqui va el codigo


```
/*
    * File:   PWM.c
    * Author: lucas
    * Created on 15 de mayo de 2013, 13:58
    * Microcontrolador: PIC16F628A
    *
    * Utilizando PWM para dimerizar un LED
    */
    #include <xc.h> // Librería XC8
    #define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
    // PIC16F648A Configuration Bit Settings
    #pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
    #pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
    #pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
    #pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
    #pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
    #pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
    // FUNCION PRINCIPAL
    void main(void) {
       TRISB = 0;                  // Puerto B como salidas
       PORTB = 0;                  // Limpio el puerto B

    // CONFIGURANDO PWM
       CCP1CON = 0b00001100;       // Activamos el modo PWM
       PR2 = 250;                  // Frecuencia 250Hz
       T2CONbits.T2CKPS = 0b10;    // Prescaler del timer 2 en 1:16
       T2CONbits.TMR2ON = 1;       // Arranca el PWM

    // BUCLE INFINITO
       unsigned char i;           // Declaramos una variable
       while (1){
       for(i=0; i=50; i++)
       {
         CCPR1L = CCPR1L++;        // Seteando el ciclo de trabajo
         __delay_ms(100);
       }
       i=0;                       // Reiniciamos la variable para comenzar el ciclo de nuevo
       }
       }
```

dice que hay un error en el  __delay_ms(100); pero no entiendo por que seria el error.

codigo de error:


```
CLEAN SUCCESSFUL (total time: 200ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make[1]: Entering directory `C:/Users/****/Desktop/primeros pasos en C/xc8/led prende.X'
make  -f nbproject/Makefile-default.mk dist/default/production/led_prende.X.production.hex
make[2]: Entering directory `C:/Users/****/Desktop/primeros pasos en C/xc8/led prende.X'
"C:\Program Files (x86)\Microchip\xc8\v1.12\bin\xc8.exe" --pass1  --chip=16F628A -Q -G --asmlist  --double=24 --float=24 --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=free -P -N255 --warn=0 --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-osccal,-resetbits,-download,-stackcall,+clib "--errformat=%%f:%%l: error: %%s" "--warnformat=%%f:%%l: warning: %%s" "--msgformat=%%f:%%l: advisory: %%s"  -o"build/default/production/led prende.p1"  "led prende.c" 
"C:\Program Files (x86)\Microchip\xc8\v1.12\bin\xc8.exe"  --chip=16F628A -G --asmlist -mdist/default/production/led_prende.X.production.map  --double=24 --float=24 --opt=default,+asm,-asmfile,+speed,-space,-debug --addrqual=ignore --mode=free -P -N255 --warn=0 --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,-osccal,-resetbits,-download,-stackcall,+clib "--errformat=%%f:%%l: error: %%s" "--warnformat=%%f:%%l: warning: %%s" "--msgformat=%%f:%%l: advisory: %%s"   -odist/default/production/led_prende.X.production.cof  "build/default/production/led prende.p1"     
Microchip MPLAB XC8 C Compiler V1.12
Copyright (C) 2012 Microchip Technology Inc.
License type: Node Configuration

:: warning: Omniscient Code Generation not available in Free mode

Memory Summary:
    Program space        used    2Dh (    45) of   800h words   (  2.2%)
    Data space           used     5h (     5) of    E0h bytes   (  2.2%)
    EEPROM space         used     0h (     0) of    80h bytes   (  0.0%)
    Configuration bits   used     1h (     1) of     1h word    (100.0%)
    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)


Running this compiler in PRO mode, with Omniscient Code Generation enabled,
produces code which is typically 40% smaller than in Free mode.
See http://microchip.com for more information.

make[2]: Leaving directory `C:/Users/****/Desktop/primeros pasos en C/xc8/led prende.X'
make[1]: Leaving directory `C:/Users/****/Desktop/primeros pasos en C/xc8/led prende.X'

BUILD SUCCESSFUL (total time: 4s)
Loading code from C:/Users/****/Desktop/primeros pasos en C/xc8/led prende.X/dist/default/production/led_prende.X.production.hex...
Loading symbols from C:/Users/****/Desktop/primeros pasos en C/xc8/led prende.X/dist/default/production/led_prende.X.production.cof...
Loading completed
```

la instruccion esta bien escrita no se cual seria el problema si pueden ayudarme.

:: warning: Omniscient Code Generation not available in Free mode

ahora este es el demo seria la cuasa de mi problema?.

o quizas algo no esta correctamente declarado?


otra cosa la idea del PWM el tiempo T1 (tiempo encendido o high) como puedo hacer para que no comience desde cero subo una foto de osciloscopio

en realidad que comience de cero no importa pero que no lo deje totalmente encendido que T2 no llegue a 0

esto es lo que no quiero que suceda



se que se incremente por programacion pero no encuentro como a ese incremento comenzar desde aqui.



y termine aqui



no comprendo como cambiar esos valores en la programacion. para poder dominar los tiempos T1/T2 de la frecuencia.   la idea es que T2 nunca llegue a 0....por ende el led nunca debe quedar 100% encendido

quizas un if que cuando incremente a cierto valor lo reinicie o lo detenga pero no se como introducirlo en el codigo


----------



## carferper (May 17, 2013)

> copie el codigo en mplab x y al compilarlo me crea el .hx pero sale un error en
> __delay_ms(100); aun asi logra crearlo.



intenta agregando esta linea


```
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
```



> :: warning: Omniscient Code Generation not available in Free mode
> 
> ahora este es el demo seria la cuasa de mi problema?.



exactamente, la version gratuita no permite optimizaciones



> otra cosa la idea del PWM el tiempo T1 (tiempo encendido o high) como puedo hacer para que no comience desde cero subo una foto de osciloscopio
> 
> en realidad que comience de cero no importa pero que no lo deje totalmente encendido que T2 no llegue a 0



intenta algo asi:


```
/* Uso de PWM para dimerizar un LED */

#include <xc.h>
#include <stdint.h>

#define _XTAL_FREQ 4000000
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

#pragma config FOSC = INTOSCIO  /* Uso de oscilator interno, I/O en pines RA6 y RA7 */
#pragma config WDTE = OFF       /* Perro guardian deshabilitado */
#pragma config PWRTE = OFF      /* Temporizador de encendido deshabilitado */
#pragma config MCLRE = OFF      /* Master Reset deshabilitado */
#pragma config BOREN = OFF      /* Deteccion de baja tension deshabilitada */
#pragma config LVP = OFF        /* Programacion a baja tension deshabilitada, RB4 es I/O digital */
#pragma config CPD = OFF        /* Proteccion de Datos dehabilitado */
#pragma config CP = OFF         /* Proteccion de Codigo desabilitado */

#define PWM_MAX 100
#define PWM_MIN 10
#define PWM_PERIOD 200

uint8_t dir = 0b1;

void main(void) {

    /* Inicializacion */
    TRISBbits.TRISB3 = 0b0;     /* RB3 como salida */
    PORTBbits.RB3 = 0b0;        /* clear RB3 buffer */
    CCP1CON = 0b00001100;       /* Modulo CCP configurado para PWM */
    PR2 = PWM_PERIOD;           /* Establece el periodo del PWM */
    CCPR1L = PWM_MIN;           /* Establece el Duty Cycle del PWM */
    T2CONbits.T2CKPS = 0b11;    /* Pre-escala del Timer2 = 1:16 */
    T2CONbits.TMR2ON = 0b1;     /* Habilita TMR2 (PWM) */

    /* Bucle infinito */
    while (1) {
        if (dir) {              
            CCPR1L++;
            if(CCPR1L == PWM_MAX)   dir = 0b0;
        }
        else {
            CCPR1L--;
            if(CCPR1L == PWM_MIN)   dir = 0b1;
        }
        __delay_ms(100);
    }
}
```

saludos


----------



## ByAxel (May 17, 2013)

Hola.
 __delay_ms(x); 
No es necesariamente una funciòn, debes de crear una macro, lo explica la ayuda en pdf.
Por ejemplo...

#define _XTAL_FREQ 4000000   // Esto lo usa internamente para calcular el delay.
#define MyDelay10ms()   __delay_ms(10)

Donde MyDelay10ms() lo usas en el resto del programa.

Saludos.


----------



## yamilongiano (May 20, 2013)

hola muchas gracias ya esta mejorando el circuito al mirarlo en el osciloscopio

queria saber si por favor podrian explicar me paso a paso el programa por ejemplo esta instruccion

uint8_t dir = 0b1;   que hace y  el valor que esta poniendo = 0b1 es un valor hexadecimal o no
                             el rango que puedo ponerle de cuanto... segun la memoria del 628A 
                             cuanto podria variar.

__delay_ms(x);  /* ya comprendi que este maneja la velocidad en que se incrmenta o
                             decrece el t1 y t2 del PWM gracias*/ 

otra preguntita para ustedes que conocen el lenguaje:

T2CONbits.T2CKPS = 0b11;    /* Pre-escala del Timer2 = 1:16 */ 


 me pueden explicar  que hace cada instruccion por favor



```
/* Bucle infinito */
    while (1) {                    /*while (1) yo se que es el buble infinito*/
        if (dir) {          /*no se como funciona ese dir adentro*/         
            CCPR1L++;      /*este incrementa en cuanto?*/
            if(CCPR1L == PWM_MAX)   dir = 0b0;       /*cuanto es 0b0 */
        }
        else {           
            CCPR1L--;
            if(CCPR1L == PWM_MIN)   dir = 0b1;
        }
        __delay_ms(100);
    }
}
```

dir = 0b0 no hay forma de pasarlo a binario ya que no comprendo a que numero corresponde el min. 0b1 = ?   y el max dir=0b1  son de 8 bit? perdonen si mi  pregunta es muy basica.

de todo modos muchas gracias por su tiempo.


----------



## ByAxel (May 20, 2013)

El nombre "dir" debe de estar declarado como variable en algùn lado, lo debe de usar como flag (es un aviso interno que tambien se modifica en algun lado) o puede estar declarado con un #define dir, que hace referencia a algùn bit (puerto o registro).

0b1  es un valor representado como binario y se aplica solo al bit màs bajo, el resto es cero.
otro seria 0b01 se aplica a los dos bits bajos, el resto es cero, la forma clasica es representarlo como 0b00000000 (8 bits)

saludos


----------



## yamilongiano (May 20, 2013)

gracias por tu respuesta estoy mas claro...


----------



## proghenyter (Sep 3, 2013)

Para solucionar el porblema se debe editar el archivo pic.h en la carpeta donde estan las libreiras del compilador.
ir a la linea 146
y cambiar __PICCPRO_
Por solamente __PICC__
y asi estaran disponibles los delay, y serán resaltados en azul como cualquier otra funcion XD
eso lo encontré en los foros de microchip, al parecer, ese error es causado porque dicha funcion requiere optimizacion y la optimizacion solo esta disponible en las versiones pagas.


----------

