TODOPIC

Microcontroladores PIC => Primeros pasos - Iniciación a los microcontroladores => Mensaje iniciado por: alvaro2043 en 04 de Diciembre de 2013, 22:58:37

Título: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 04 de Diciembre de 2013, 22:58:37
Buenas noches la verdad no se que pasa. quiero generar una señal cuadrada de 5Khz por un pin del puerto B utilizando el timer0 realizo todo lo indicado en la hoja de datos pero no sale :(
estoy utilizando el pic18f4550 con 8Mhz de reloj (utilizando el interno)

Mi codigo es el siguiente.

Código: [Seleccionar]
#include <p18f4550.h>
#include <delays.h>

//////////////////Configuaracion de bits//////////////////////////

#pragma config PLLDIV = 4
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 1   /////En este caso no importa por que vamos a utilizar Oscilador Interno
#pragma config FOSC = INTOSC_EC  //Configurando oscilador interno
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = OFF
#pragma config BORV = 0
#pragma config VREGEN = OFF
#pragma config WDT = OFF
#pragma config WDTPS = 16384
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = ON
#pragma config CCP2MX = OFF
#pragma config STVREN = OFF
#pragma config LVP = OFF
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF,WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF,EBTR2 = OFF,EBTR3 = OFF


void main (){

    TRISBbits.RB1=0; //Definimos el pin 5 del PuertoB como salida.
    //Configuracion del timer0
    T0CONbits.T08BIT=0; //Configurado a 16bits el Timer0
    T0CONbits.T0CS=0;  //Internal Fos/4 (8Mhz/4)
    T0CONbits.PSA=1;  //No prescaler.
    //Cargando los registros TMR0H
    TMR0H=0XFF;
    TMR0L=0X38;
    INTCONbits.TMR0IF=0;
    T0CONbits.TMR0ON=1; //Iniciamos el timer0

    while(1){

        if(INTCONbits.TMR0IF)
        {
           INTCONbits.TMR0IF=0;
           TMR0H=0XFF;
           TMR0L=0X38;
           LATBbits.LATB1=!LATBbits.LATB1;
          
          
         }
     }


}

Alguien me puede decir en que estoy fallando.. muchas gracias.. Anexo imagen del osciloscopio con la señal que me genera con el codigo de arriba

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: Miquel_S en 05 de Diciembre de 2013, 03:59:54
Hola alvaro2043 debes configurar el registro TRISB como salida, por defecto esta como entrada, y tambien con ADCON1 las entradas y salidas analogicas que por defecto son analogicas.

Saludos!
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 05 de Diciembre de 2013, 09:39:24
Hola alvaro2043 debes configurar el registro TRISB como salida, por defecto esta como entrada, y tambien con ADCON1 las entradas y salidas analogicas que por defecto son analogicas.

Saludos!

He corregido lo que me ha dicho... Seleccionar los pines como digitales con el ADCON1.. Pero no he tenido buenos resultados la señal generada es de 604Hz y quiero generar una de 5Khz.. estoy hacieno mal los calculos???

Para este ejemplo quiero generar una señal cuadrada de 5khz..  osea T=1/5khz = 200us-- un Alto que dura 100us y bajo de 100us... 100us/0.5us = 200 conteo.  65536-200=65336 = FF38   eso quiere decir que TM0H=FF y TM0L=38

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 05 de Diciembre de 2013, 11:55:45
  Según el datasheet que estoy mirando, la frecuencia seteada para el oscilador interno luego de un PowerOnReset es de 1MHz, con lo cual tu frecuencia de salida debería ser aproximadamente 625Hz. Debes configurar el oscilador interno modificando el registro OSCCON.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 06 de Diciembre de 2013, 18:20:24
Si AngelGris.. tiene toda la razon.. no habia configurador el OSCILADOR A 8MHZ fue un descuido.. gracias ya esta todo solucionado

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 07 de Diciembre de 2013, 11:09:27
oK.. después de leer algunos libros ve que para generar este tipo de señales es mejor utilizar interrupciones, por lo tanto me puse en la tarea de realizar esta misma señal pero por medio de interrupciones pero esta vez utilizando una velocidad de 48Mhz.. a partir de un oscilador de cristal de 8Mhz.. Una duda que me genera es que la señal cuadrada no sale exacta, debería ser de 5khz y sale de 4.685khz utilizo el timer0 a 16bits sin prescaler y interrupcion por desbordamiento..
////////////////Calculos:

Ancho_de_pulso = TMR0*TOSC*4*TMR0PRE   .....

Ancho de pulso= 100us   ya que es una onda cuadrada de 5khz

T0SC= 1/48Mhz

TMR0PRE=1

TMR0=1200.

Eso quiere decir que para obtener esa frecuencia debo de cargar los registro TMR0H y TMR0L con 65536-1200=64336 que es lo mismo FB50  TMR0H=FB y TMR0L=50

Pero el valor esperado no es el que aparece en el osciloscopio. Lo fácil seria cuadrar a prueba y error el valor de los dos registro  TMR0H y TMR0L que es lo haría si no encuentro otra forma.. Me gustaría saber si alguien sabe la explicación del porque se genera esto.  Algo que se me viene a la cabeza es que el problema se deba algun retador por Latencia en sistema o cuando se genera la atención de la ISR. ¿Esto ocurre con todos los timer?

Anexo codigo

Código: [Seleccionar]
//Configuaracion de bits//////////////////////////

#pragma config PLLDIV = 2  //Cristal de 8Mhz lo dividimos entre 2 para tener los 4Mhz
#pragma config CPUDIV = OSC1_PLL2  //Los 96Mhz de PLL lo dividimos entre 2 para tener los 48Mhz con lo que vamos a trabajar
#pragma config USBDIV = 2  /////Tomar el reloj para USB desde el PLL- 48Mhz
#pragma config FOSC = HSPLL_HS  //Configurando oscilador interno
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = OFF
#pragma config BORV = 0
#pragma config VREGEN = OFF
#pragma config WDT = OFF
#pragma config WDTPS = 16384
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = ON
#pragma config CCP2MX = OFF
#pragma config STVREN = OFF
#pragma config LVP = OFF
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF,WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF,EBTR2 = OFF,EBTR3 = OFF

///Include////
#include <p18f4550.h>
#include <delays.h>

//Variables globales
int estado=0;
/*Prototipos de funciones*/
void Interrupt_ISR_TMR0(void);
void Change_Estado(void);

///////////////////////////////////////////////

#pragma code High_vector_Interrupt = 0x08
void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

////////////////////////////////////////////
#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
    if(INTCONbits.TMR0IF ==1 ){  //Si el timer0 se desbordo 0xFFFF a 0x0000
       INTCONbits.TMR0IF =0;     //Borramos la bandera
        Change_Estado();         //Llamamos la funcion que se realiza cuando esto ocurre.
        TMR0H=0XFB;
        TMR0L=0X50;
    }

}

void main(){

    OSCCONbits.SCS1=0;      //Configurando como Oscilador primario
    OSCCONbits.SCS0=0;

    TRISBbits.RB1=0;        //Configurando como salida el PinRB1 del puerto B
    LATBbits.LATB1=0;       //Estableciendo a un nivel bajo el PinRB1

    ADCON1=0x0F;            //Configurando todos los puerto como Digitales.

    T0CONbits.TMR0ON=0;     //Timer 0 off
    T0CONbits.T08BIT=0;     //Configurado a 16bits
    T0CONbits.T0CS=0;       //Internal
    T0CONbits.T0SE=0;
    T0CONbits.PSA=1;        //Prescaler no asignado

    TMR0H=0XFB;
    TMR0L=0X50;

    RCONbits.IPEN=1;        //Enable priority levels on Interrupts
    INTCONbits.TMR0IF=0;    //Clear TF0
    INTCONbits.GIE_GIEH=1;  //Enable Global interrupt
    INTCONbits.TMR0IE=1;    //Enable TMR0 overflow

    INTCON2bits.TMR0IP=1;   //High priority
           
    T0CONbits.TMR0ON=1;     //on Timer 0

    while(1){}


}

void Change_Estado(void){

    if(estado==0){
         LATBbits.LATB1=1;
         estado=!estado;
    }   else if (estado==1){
        LATBbits.LATB1=0;
        estado=!estado;
    }

   
}
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 07 de Diciembre de 2013, 11:57:57
El cálculo está muy bien y en general yo te diría que parece estar funcionando bien.

  Ten en cuenta que dentro de tu vector de interrupciones hay "goto" (que en código asm son dos ciclos más de instrucción) también tienes las evaluaciones de los flags y la llamada a la función "Change_Estado()" y todo lo que se incluye en dicha función hasta que cambia de estado el pin. Además de ello, es casi seguro que el compilador agregue código en la interrupción (en realidad no sé si ocurre con C18, pero sí con XC8).

  También ten en cuenta que luego de chequeado el flag (para ver si la interrupción es por el timer0) debes primeramente precargar nuevamente el timer, para no perder más tiempo.

  Todo ese código agregado generará más retardo. Observa esto...


 4.685KHz = 1/213.447uS --> es decir que tu tiempo total es 213.447uS cuando debería ser 200uS según los cálculos que realizaste.
Si dividimos el tiempo a la mitad nos da una diferencia de 106.724uS contra 100uS. Teniendo en cuenta que el ciclo de trabajo a 48MHz es de 83.333nS, la diferencia en cantidad de ciclos entre lo calculado y lo real es
100uS/83.333nS = 1200 contra 106.724uS/83.333nS = 1280, es decir que hay una diferencia aproximada de 80 ciclos de instrucción.

  Tal vez ésa sea la diferencia contando tu agregado mas lo que pueda estar agregando el compilador.

 Puedes intentar optimizar más tu código de interrupción para ver si disminuye dicha diferencia y luego quedará retocar a mano el valor necesario de la precarga del timer.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 07 de Diciembre de 2013, 14:47:31
Hola alvaro,

una pregunta: por qué intentas generar la onda cuadrada de 5kHz con el Timer0, cuando el 18F4550 tiene un par de módulos específicos para generarla mediante PWM y sin requerir absolutamente de casi nada del uso del CPU?

Saludos.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 07 de Diciembre de 2013, 21:28:44
AngelGris muchas gracias por tu explicación mas claro no puede ser me ha sacado de muchas dudas. Cuando habla de optimizar el codigo a que te refieres esa parte no me quedo claro.. Supongo que se debe eliminar la funcion void Change_Estado(void); y dejar todo sobre la interrupcion sin necesidad de hacer llamados de Funciones.. No se es la unica idea que se me viene en mente.

Hola BrunoF.. Bueno el por que esto generando señales cuadradas de 5khz si el 18f4550 cuenta con 2 modulos de PWM y uno de ECCP.. Tengo en mente controlar un puente H inversor con un tipo de modulación que se llama phase-shift  http://www.emeraldinsight.com/content_images/fig/1740250405013.png en el cual debo de generar 4 señales PWM..
Quiero arrancar desde lo mínimo que es generando señales sencillas, debido a que soy  novato con los PIC..

Gracias.. por su ayudas. a medida que vaya avanzando en esto lo ire publicando.. El paso siguiente es variar el ancho de pulso y la frecuencia por medio de dos potenciometro o 2 pulsadores, cual me recomieda que sea mejor (Pulsadores o Potenciometro)
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 12 de Diciembre de 2013, 19:21:50
Bueno sigo con otras preguntas que me surgen con respecto a la frecuencia maxima que puedo obtener con una interrupcion, estaba probando y se me dio por cargar los registros
TMR0H y TMR0L con FFFE eso quiere decir que apenas se van a realizar 2 tick.. ya que el Timer se desborda cuando llega a FFFF (Configurado a 16bits) en teoria la frecuencia debieria de ser de:

2*(1/(48Mhz/4))=166.66ns este es el ancho del pulso osea que la frecuencia seria de (1/(2*166.66ns))=3000Khz pues ese es el calculo que saco apartir de los calculos que hice para obtener los 5khz...  y la frecuencia que obtengo en mi osciloscopio es de 312Khz aprox... Que es lo que esta pasadan???' alguien me puede decir?

Nota: Solo son inquietudes que se me generan, no utilizo prescale.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 12 de Diciembre de 2013, 20:40:14
Bueno sigo con otras preguntas que me surgen con respecto a la frecuencia maxima que puedo obtener con una interrupcion, estaba probando y se me dio por cargar los registros
TMR0H y TMR0L con FFFE eso quiere decir que apenas se van a realizar 2 tick.. ya que el Timer se desborda cuando llega a FFFF (Configurado a 16bits) en teoria la frecuencia debieria de ser de:

2*(1/(48Mhz/4))=166.66ns este es el ancho del pulso osea que la frecuencia seria de (1/(2*166.66ns))=3000Khz pues ese es el calculo que saco apartir de los calculos que hice para obtener los 5khz...  y la frecuencia que obtengo en mi osciloscopio es de 312Khz aprox... Que es lo que esta pasadan???' alguien me puede decir?

Nota: Solo son inquietudes que se me generan, no utilizo prescale.

  El problema de lo que quieres intentar es que precargar el timer consume ciclos de reloj, lo mismo que volver de la interrupción. Suponiendo que puedas precargar, al retornar de la interrupción ya deberías ingresar nuevamente y así sucesivamente. Suponiendo que esté pasando éso, estás contando aproximadamente 20 ciclos.

  20 * 83.3333n * 2 = 3.333us --> 300KHz aproximadamente. O si contarás 19 daría una frecuencia de 315.79 KHz.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 12 de Diciembre de 2013, 22:47:02
Eso quiere decir que no es posible obtener una frecuencia mayor a 312Khz en C, debido a que se usan 20 ciclos de reloj (en este caso). Osea que en .ASM se puede llegar a una frecuencia superior o no?. Me nace esa inquietud porq se gasta menos ciclo de reloj en Assembler.

Perdón por hacer esas preguntas pero son conceptos que de pronto no tengo claro y que no he encontrado en ningún libro o si están no lo he entendió jejeje

Otra preguntica, con un solo timer y su interrupcion es posible generar las 4 señales que publique en la parte superior http://www.emeraldinsight.com/content_images/fig/1740250405013.png o necesitaria de otro timer? la frecuencia que tengo pensado manejar para esas señales es de 25 a 40Khz

Nota: Optimice el código como me lo recomendaron y llegue a una frecuencia de 4.96Khz.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 12 de Diciembre de 2013, 22:58:15
Eso quiere decir que no es posible obtener una frecuencia mayor a 312Khz en C, debido a que se usan 20 ciclos de reloj (en este caso).

Eso depende de muchos factores, optimizaciones del compilador en cuestión, si le metes mano tu y haces la ISR manualmente, cantidad de interrupciones, si utilizas vector de alta/baja prioridad, si guardas/restauras mas o menos registros al ingresar al vector de interrupción,etc.

Osea que en .ASM se puede llegar a una frecuencia superior o no?. Me nace esa inquietud porq se gasta menos ciclo de reloj en Assembler.

Seguramente sea más sencillo exprimir un poco más al uC en ASM, pero todo tiene su precio...

Otra preguntica, con un solo timer y su interrupcion es posible generar las 4 señales que publique en la parte superior http://www.emeraldinsight.com/content_images/fig/1740250405013.png o necesitaria de otro timer? la frecuencia que tengo pensado manejar para esas señales es de 25 a 40Khz

Cuál grupo? El de la izquierda o el de la derecha? El de la izquierda es mucho más sencillo de lograr que el de la derecha. Se puede tornar sumamente complicado hacer un phase-shift angle con un uC de estos. Hay microcontroladores, incluso de microchip, que traen módulo de phase-shift para simplificar la tarea. Acaso estás intentando hacer una fuente de corriente constante?

Saludos.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 12 de Diciembre de 2013, 23:29:14
Si tengo en mente hacer una fuente de corriente constante para ser aplicada a un calentador por inducción...

cuento con 8 modulos de este tipo y quiero ponerlo a trabajar en ese proyecto que tengo en mente..

http://www.ineltron.de/english/mitsubishi-data/IGBT/CM200DU-12F.pdf

[/quote]

Cuál grupo? El de la izquierda o el de la derecha? El de la izquierda es mucho más sencillo de lograr que el de la derecha. Se puede tornar sumamente complicado hacer un phase-shift angle con un uC de estos. Hay microcontroladores, incluso de microchip, que traen módulo de phase-shift para simplificar la tarea. Acaso estás intentando hacer una fuente de corriente constante?

[/quote]

Que Uc me puede recomendar para esa aplicacion?

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 12 de Diciembre de 2013, 23:54:08
Si tengo en mente hacer una fuente de corriente constante para ser aplicada a un calentador por inducción...

cuento con 8 modulos de este tipo y quiero ponerlo a trabajar en ese proyecto que tengo en mente..

http://www.ineltron.de/english/mitsubishi-data/IGBT/CM200DU-12F.pdf

Ok, ya me parecía debido a la necesidad del phase shifting y las frecuencias de PWM que mencionaste.

Que Uc me puede recomendar para esa aplicacion?

Modelo exácto no sabría decirte, tendría que revolver un poco porque hace un tiempo que no toco el tema. Sé que muchos dsPIC33F y PIC24H lo traen.

Acá tenés un PDF de Microchip donde lo menciona para dichas familias:

http://ww1.microchip.com/downloads/en/DeviceDoc/70323D.pdf

Saludos.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 14 de Diciembre de 2013, 16:15:25
No se que estoy cometiendo mal... Deseo hacer 30 interrupciones del Timer0 trabajando con un prescaler de 16 y oscilador de 48Mhz, no me aparece nada.. aqui pongo el codigo a ver si me puede dar una manito.

Es un codigo similar al que esta en la pagina de Redpic..pero en la pagina esta en CCS

Código: [Seleccionar]
//Configuaracion de bits//////////////////////////

#pragma config PLLDIV = 2  //Cristal de 8Mhz lo dividimos entre 2 para tener los 4Mhz
#pragma config CPUDIV = OSC1_PLL2  //Los 96Mhz de PLL lo dividimos entre 2 para tener los 48Mhz con lo que vamos a trabajar
#pragma config USBDIV = 2  /////Tomar el reloj para USB desde el PLL- 48Mhz
#pragma config FOSC = HSPLL_HS  //Configurando oscilador interno
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = OFF
#pragma config BORV = 0
#pragma config VREGEN = OFF
#pragma config WDT = OFF
#pragma config WDTPS = 16384
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = ON
#pragma config CCP2MX = OFF
#pragma config STVREN = OFF
#pragma config LVP = OFF
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF,WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF,EBTR2 = OFF,EBTR3 = OFF

///Include////
#include <p18f4550.h>
#include <delays.h>

//Variables globales

const char num_int=30;
unsigned int contador=0;
//Banderas
char flag1=0,flag2=0;
/*Prototipos de funciones*/
void Interrupt_ISR_TMR0(void);


///////////////////////////////////////////////

#pragma code High_vector_Interrupt = 0x08
void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

////////////////////////////////////////////
#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
   
    //if(INTCONbits.TMR0IF==1){  //Si se produce la interrupcion
        INTCONbits.TMR0IF==0;  //Borramos la bandera
        if(contador>num_int){  //Si es mayor a num_int
            if(flag1==0){      //Bandera que hace un cambio cada 30 interrupciones
                flag1=1;
            } else{
                flag1=0;
                 }
             contador=0;
        }       
          contador++;
     //}

    TMR0H=0X00;
    TMR0L=0X00;
  }

void main(){

   
    OSCCONbits.SCS1=0;      //Configurando como Oscilador primario
    OSCCONbits.SCS0=0;

    TRISBbits.RB1=0;        //Configurando como salida el PinRB1 del puerto B
    LATBbits.LATB1=0;       //Estableciendo a un nivel bajo el PinRB1

    ADCON1=0x0F;            //Configurando todos los puerto como Digitales.

    T0CONbits.TMR0ON=0;     //Timer 0 off
    T0CONbits.T08BIT=0;     //Configurado a 16bits
    T0CONbits.T0CS=0;       //Internal
    T0CONbits.T0SE=0;
    T0CONbits.PSA=0;        //Prescaler  asignado

    T0CONbits.T0PS2=0;      //Prescaler de 16
    T0CONbits.T0PS1=1;
    T0CONbits.T0PS0=1;
    //TMR0H=0X00;
    //TMR0L=0X00;

    RCONbits.IPEN=1;        //Enable priority levels on Interrupts
    INTCONbits.TMR0IF=0;    //Clear TF0
    INTCONbits.GIE_GIEH=1;  //Enable Global interrupt
    INTCONbits.TMR0IE=1;    //Enable TMR0 overflow

    INTCON2bits.TMR0IP=1;   //High priority

    T0CONbits.TMR0ON=1;     //on Timer 0

    do{

        if(flag1=flag2){}

        else{
            LATBbits.LATB1=!LATBbits.LATB1;
            flag2=flag1;
    }
}
    while(1);
}
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 14 de Diciembre de 2013, 16:27:30
if(flag1==flag2)
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 14 de Diciembre de 2013, 16:31:02
if(flag1==flag2)

BrunoF gracias por ese detalle, pero ya lo acabo de hacer y nada de resultados :( que mas puede ser...
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 14 de Diciembre de 2013, 17:13:22
ejejej ya encontré el error cuando estoy borrando la bandera de desbordamiento esto haciendo.
Código: [Seleccionar]
INTCONbits.TMR0IF==0; el error era ese y el de flag1==flag2
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 14 de Diciembre de 2013, 19:57:07
ejejej ya encontré el error cuando estoy borrando la bandera de desbordamiento esto haciendo.
Código: [Seleccionar]
INTCONbits.TMR0IF==0; el error era ese y el de flag1==flag2


Mirá vos. Se te habían intercambiado... :D
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 14 de Diciembre de 2013, 21:51:14
Bueno acabo de mejorar el código, el primer código me guié por uno que tenia Redpic en su pagina, yo quería ver como podía minimizar un poco el código y lo que hice fue lo siguiente:

1- Que cada vez que el contador llegue al maximo se active una bandera indicando "Un desbordamiento" y ese valor lo tomo para realizar los cambios de estado a la salida.
Código: [Seleccionar]
const int num_int=15;
unsigned int contador=0;

//Banderas
char flag1=0;
/*Prototipos de funciones*/
void Interrupt_ISR_TMR0(void);


///////////////////////////////////////////////

#pragma code High_vector_Interrupt = 0x08
void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

////////////////////////////////////////////
#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
    if(contador==num_int){
        contador=0;
        flag1=1;
      }
    ++contador;
    INTCONbits.TMR0IF=0;  //Borramos la bandera
   
    TMR0H=0X00;
    TMR0L=0X00;
    }

void main(){

   
    OSCCONbits.SCS1=0;      //Configurando como Oscilador primario
    OSCCONbits.SCS0=0;

    TRISBbits.RB1=0;        //Configurando como salida el PinRB1 del puerto B
    LATBbits.LATB1=0;       //Estableciendo a un nivel bajo el PinRB1

    ADCON1=0x0F;            //Configurando todos los puerto como Digitales.

    T0CONbits.TMR0ON=0;     //Timer 0 off
    T0CONbits.T08BIT=0;     //Configurado a 16bits
    T0CONbits.T0CS=0;       //Internal
    T0CONbits.T0SE=0;
    T0CONbits.PSA=0;        //Prescaler  asignado

    T0CONbits.T0PS2=0;      //Prescaler de 16
    T0CONbits.T0PS1=1;
    T0CONbits.T0PS0=1;
 

    RCONbits.IPEN=1;        //Enable priority levels on Interrupts
    INTCONbits.TMR0IF=0;    //Clear TF0
    INTCONbits.GIE_GIEH=1;  //Enable Global interrupt
    INTCONbits.TMR0IE=1;    //Enable TMR0 overflow

    INTCON2bits.TMR0IP=1;   //High priority

    T0CONbits.TMR0ON=1;     //on Timer 0

    while(1){

        if(flag1){
            flag1=0;
            LATBbits.LATB1=!LATBbits.LATB1;


        }

    }
}


El resultado deber ser un desbordamiento cada 1.308s (87.20ms * 15) (87.20ms por que estoy con un prescaler de 16).  ¿Que para que lo necesito?  La verdad no se, pero estoy practicando para coger destreza en esto, me imagino que ha alguien le debe de servir.

(http://imageshack.us/a/img46/6406/1pm7.jpg)

BrunoF estos son los módulos que le había dicho, estos son los que quiero poner a trabajar.

(http://imageshack.us/a/img13/7464/60qx.jpg)

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 14 de Diciembre de 2013, 22:06:11
La precarga del Timer dentro de la ISR:

    TMR0H=0X00;
    TMR0L=0X00;

provoca una demora adicional, si no necesitás ajustar el tiempo, dejalo correr libre al Timer. Ni bien se desborda vuelva cero, se levanta el flag de interr, y aún mientras la interr está ocurriendo, el Timer ya está volviendo a contar la próxima vuelta.

Lindos módulos, ojalá puedas ponerlos a trabajar pronto.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 14 de Diciembre de 2013, 22:19:49
si.. son bien bonitos jejejeje estoy ansioso por ponerlos a trabajar, por ahora decidí trabajar sin phase shift... solo voy a generar 2 señales pwm complementarias... (Se que el 18F4550 cuenta con el modulo ECCP pero quiero aprender primero hacerlo por software)  :) :)
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 15 de Diciembre de 2013, 17:55:22
una preguntilla... como puedo leer el valor del timer0. en ccs se hace con leer_timer=get_timer0();

Como lo puedo hacer en c18 sin utilizar la libreria <timer.h> leer_timer=readtimer0();

Según lo que he leído, para escribir en el Timer0 primero se carga el TMR0H y despues el TMR0L, eso es lo que vengo haciendo. Ahora para leer los valores del timer se hace el proceso contrario.. Primero se lee TMR0L y despues TMR0H.. He encontrado un ejemplo pero no entiendo la parte del 256U

Nota: No entiendo el 256U que función cumple..

 valTimer0=TMR0L;
 valTimer0|=TMR0H*256U;

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 15 de Diciembre de 2013, 19:09:41
una preguntilla... como puedo leer el valor del timer0. en ccs se hace con leer_timer=get_timer0();

Como lo puedo hacer en c18 sin utilizar la libreria <timer.h> leer_timer=readtimer0();

Según lo que he leído, para escribir en el Timer0 primero se carga el TMR0H y despues el TMR0L, eso es lo que vengo haciendo. Ahora para leer los valores del timer se hace el proceso contrario.. Primero se lee TMR0L y despues TMR0H.. He encontrado un ejemplo pero no entiendo la parte del 256U

Nota: No entiendo el 256U que función cumple..

 valTimer0=TMR0L;
 valTimer0|=TMR0H*256U;



  Multiplicar por 256 es como rotar 8 veces a la izquierda y se hace para que ocupe el byte alto en una variable de 16 bits. Por ello hace una or con el valor almacenado anteriormente.

Código: C
  1. unsigned int valor; // variable de 16 bits
  2. valor = TMR0L;      // el valor sera 0b00000000TMR0L, es decir byte alto en 0 y byte bajo el valor de TMR0L
  3. vlor |= TMR0H *256; // el valor sera 0bTMR0HTMR0L, por lo tanto valor almacenara los 16 bits del timer

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 17 de Diciembre de 2013, 14:28:11
Gracias AngelGris por la explicacion de verdad siempre me sacas de dudas  :)

BrunoF me puse en la tarea de leer el documento que me envió sobre la opción de utilizar dsPIC33f.. Para la aplicación que quiero implementar, se ve que con un dsPIC es mas trabajable obtener el tipo de control que estoy buscando ya que cuenta con modulos Phase-shift tengo en mente (a largo plazo ya para el 2014 jeejjeje ) trabajar con el dsPIC33fj32GS606, he mirado sus caracteristica y es ideal para trabajar con convertidores de potencia la cual es mi linea.. Una cosita puede alguien decirme cuales son los pasos para iniciar a utilziar estos dsPIC... ¿Que necesito? mi Pickit2 sirve para grabar en estos dsPic? el C18 sirve para programar?? Donde puedo ver un ejemplo como encender y apagar un led..

Nota: Mas adelante les consultare sobre el programa que llevo en el 18F4550 :)  lo del dspic es para hacerme una idea del 2014 que me espera jejeje
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 17 de Diciembre de 2013, 14:44:58
  Si no recuerdo mal, el sof del pickit2 trae un readme en el cual se listan los dispositivos soportados.
Supongo que para un dsPIC33 será necesario el compilador XC32... Seguramente en el sitio de microchip te dará esa información... los compiladores actuales son XC8, XC16 y XC32 y me pareció haber visto que el compilador XC32 también permite programación orientada a objetos (C++)
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 17 de Diciembre de 2013, 14:48:59
El C30 no me sirve? estoy confundido

C18-------------------------> para los PIC18

C30-----------------------> Para elo PIC24-y dspic

XC8---------------------->?

XC16-------------------->?

XC32---------------------?
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 17 de Diciembre de 2013, 15:22:32
El C30 no me sirve? estoy confundido

C18-------------------------> para los PIC18

C30-----------------------> Para elo PIC24-y dspic

XC8---------------------->?

XC16-------------------->?

XC32---------------------?

  Si no me equivoco la línea C18 y C30 no van a tener continuidad.... por ello ahora está la línea XC8, XC16 y XC32

Fijate en la opción "Design support" --> "Compilers"
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 17 de Diciembre de 2013, 17:20:18
jejej Vuelvo y repito gracias a AngelGris, BrunoF, Nocturno y todas las personas que ven y aportan ideas para solucionar algun problema me ha servido de mucha ayuda en todo este proceso de aprendizaje  :P :P :P lo de los dsPIC los dejare para el próximo año cuando me llegue el que pedí  :) Por ahora seguimos sacando jugo al timer0 y las interrupciones.. A continuación muestro unas imágenes y códigos que he hecho para hacer un PWM por software. Voy a tratar de explicar lo que hice antes de mostrar las imágenes.

Primero que todo la frecuencia de mi PWM es de 25Khz en teoría. trabajando con Timer0 - 48Mhz de crystal y prescaler de 2 y variar el ciclo de trabajo entre 50% 30% y 20% (por ahora) el máximo ciclo para esta aplicación va ser de 50% ya que es para controlar un puente H.

Que es lo que he hecho?

Rta: Aparte de leer y leer y mirar ejemplos jejeje he hecho una interrupción cada "40us" esto lo he tomado como mi periodo de la señal (1/40us)=25KHZ

Ahora para tener los 40us deberia de cargar mi TIMER0 con 65296 de tal forma que solo se cuenten 240tick teniendo en cuenta que un tick = (1/(48Mhz/4))*2 =0.166us (donde 2 es el prescaler) por lo tanto 240*0.1666uS = 40us.. que es lo deseado.. Ese resultado es en TEORIA con la ayuda del osciloscopio calibre el valor de carga del TMR0 = FF1F que es lo mismo 65311 eso es en la realidad, que con respecto a lo calculado teoricamente tenemos 15 tick de mas.. Esto fue explicado en un comentario mas arriba por AngelGris. Bueno después de esa explicación viene lo otro que hice. Ya teniendo esa interrupción cada 40us  voy variando el tiempo en que permace en high la salida.. Espero no ser tan canson con este tema, pero apenas estamos en el proceso de aprendizaje jeje . Y se que mucha gente se preguntara del porq no he utilziado los modulos PWM, la razon es una sola quiero experimentar.

Voy a generar un Switch-Case para aumentar el ciclo de trabajo o disminuir apartir de un pulsador. Por ahora solo lo estoy haciendo desde Soft.

Anexo Imagen y código si me pueden ayudar para minimizar y optimizar codigo escucho ideas.. Gracias.

La señal roja es el tiempo de interrupción y la Amarilla es el PWM

(http://sia1.subirimagenes.net/img/2013/12/17/mini_131217083307376685.jpg) (http://www.subirimagenes.net/i/131217083307376685.jpg)

(http://sim1.subirimagenes.net/img/2013/12/17//mini_131217092135118702.jpg) (http://www.subirimagenes.net/i/131217092135118702.jpg)

Código: [Seleccionar]
#include <p18f4550.h>
#include <delays.h>

#define PWM1    LATBbits.LATB1
//Variables globales

//const int periodo = 240;  //240 tick en donde un tick=0.166uS  (240x0.166us)=39.84us aprox 25.10Khz
const int duty_50 = 120;
const int duty_30 = 72;
const int duty_20 = 48;

unsigned int flag_t =0;  //Bandera que me indica cuando se genera una interrupcion
unsigned int flag_d =0;  //Bandera para el ciclo de trabajo
unsigned int contador=0;

unsigned int valTimer0;

/*Prototipos de funciones*/
void Interrupt_ISR_TMR0(void);


///////////////////////////////////////////////

#pragma code High_vector_Interrupt = 0x08
void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

////////////////////////////////////////////
#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
    if(INTCONbits.TMR0IF==1){
        INTCONbits.TMR0IF=0;   //Borramos bandera
            ++contador;       //Cada vez que se presente una interrupcion aumentamos la variable contador
            LATBbits.LATB2=!LATBbits.LATB2;
            if(contador==1){
                flag_t=1;
                contador=0;
            }
        TMR0H=0XFF;   //El timer 0 arranca desde 65311. 65536-65311=235tick*0.166uS=39.01us
        TMR0L=0X1F;
    }
  
    }


void main(){



    OSCCONbits.SCS1=0;      //Configurando como Oscilador primario
    OSCCONbits.SCS0=0;

    TRISBbits.RB1=0;        //Configurando como salida el PinRB1 del puerto B
    LATBbits.LATB1=0;       //Estableciendo a un nivel bajo el PinRB1

    TRISBbits.RB2=0;
    LATBbits.LATB2=0;

    ADCON1=0x0F;            //Configurando todos los puerto como Digitales.

    T0CONbits.TMR0ON=0;     //Timer 0 off
    T0CONbits.T08BIT=0;     //Configurado a 16bits
    T0CONbits.T0CS=0;       //Internal
    T0CONbits.T0SE=0;
    T0CONbits.PSA=0;        //Prescaler  asignado

    T0CONbits.T0PS2=0;      //Prescaler de 2
    T0CONbits.T0PS1=0;
    T0CONbits.T0PS0=0;

    

    RCONbits.IPEN=1;        //Enable priority levels on Interrupts
    INTCONbits.TMR0IF=0;    //Clear TF0
    INTCONbits.GIE_GIEH=1;  //Enable Global interrupt
    INTCONbits.TMR0IE=1;    //Enable TMR0 overflow

    INTCON2bits.TMR0IP=1;   //High priority

    T0CONbits.TMR0ON=1;     //on Timer 0

    while(1){

        //Pulso del pwm
        if(flag_t==1){  //Si se desbordo el timer activamos una bandera
            flag_t=0;   //Limpiamos la bandera
            PWM1=1;     //Activamos el pin del PWM
            flag_d=1;
        }

        //cuadrar ciclo de trabajo
        if(flag_d==1){
            valTimer0=TMR0L;    //Leemos el valor del timer0 y lo almacenamos en la variable valtimer0
            valTimer0|=TMR0H<<8;
                if(valTimer0>duty_50){
                    flag_d=0;
                    PWM1=0;

            }
        

        }

    }
}


Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 17 de Diciembre de 2013, 18:38:42
Hola,

mis sugerencias son: si pensás interrumpir en intervalos muy pequeños de tiempo, configurar el Timer0 en modo 8 bits. De esa manera te ahorras tener que escribir un registro. El código que hiciste es bastante impreciso, especialmente cuando le agregues otras fases. No me parece la mejor forma de acercarse a lo que estás intentando hacer.

Entonces, y esto es sólo mi opinión y consideración:
1) utilizar la interrupción de alta prioridad para la generación de PWM por soft. Esto siempre es importante si a futuro se llega a agregar alguna otra. Necesita ser de alta prioridad en ese caso.

2) Si es la única interr. dentro del vector elegido, NO verificar el flag TMR0IF. Es evidente que el motivo de la interr. fue ese y no otro.

3) Lo primero que haces dentro del vector de interr. es precargar el valor del Timer0. De esta manera todo el codigo que agregues debajo no afectará la frecuencia del PWM. Todo el código que se ejecute antes de la precarga, afecta a la frecuencia del PWM. Incluso la cosa empeora cuando ponés IF, WHILE, FOR, etc antes de la precarga porque puede que no siempre se ejecute la mísma cantidad de instrucciones, lo que empeora la cosa porque puede hacer variar la frecuencia incluso entre interrupciones.

4) Hay veces, como en este caso, en que la generación del PWM es mejor que ocurra DENTRO de la interrupción. Eso garantiza sincronización e incluso, para este caso particular de PWM por software, optimización de las instrucciones necesarias para lograrlo. Hay que lograr que el PWM se genere con la menor cantidad de uso del CPU posible.

5) La mejor aproximación, a mi parecer (y llevo años haciendo PWM's por software de todo tipo en desarrollos comerciales) es esta:

Suponiendo que necesitás 3 fases de PWM @ 25Khz c/u y con posibilidad de phase-shifting, con una resolución de duty y phase-shift del 10%:

Con un micro como el 18F4550 corriendo a 48Mhz (frecuencia máxima del uC ese), necesitás interrumpir cada 1000000 / 25000 / 10 = 4 uS lo que en instrucciones son 48. Está muy jugada la cosa. No sé si va a funcionar, pero podemos intentarlo. El código debajo es usando C, si usás ASM seguro te ganás unas cuántas instrucciones.

Código: C#
  1. //..
  2. #include <stdint.h>
  3. //..
  4.  
  5. //Definir los pines a usar como PWM
  6. #define PWM1    LATBbits.LATB1
  7. #define PWM2    LATBbits.LATB2
  8. #define PWM3    LATBbits.LATB3
  9.  
  10. //..
  11.  
  12. //Declarar 3 contadores, uno por PWM. No sólo decidirán el duty de cada fase sino que además, la distancia entre ellos decidirá el phase-shifting:
  13. uint8_t counter1, counter2, counter3;
  14.  
  15. //declaramos otras 3 variables, estas llevan el valor actual del PWM (en pasos de 10%, es decir, desde 0% al 100%. Son 11 valores pero el PWM se come un paso (si necesitás más explicación del por qué del paso que se come, la puedo exponer después. Por eso la división es por 10 y no por 11 en los cálculos del tiempo).
  16. uint8_t PWM1value,PWM2value,PWM3value;
  17.  
  18. //en el código de la interr:
  19.  
  20. pragma interrupt Interrupt_ISR_TMR0
  21. void  Interrupt_ISR_TMR0 (void)
  22. {
  23.         TMR0=230;         //Hay que ajustarlo. Lo elegí para que quede un poco por debajo de 25Khz. Cuando menos interrumpa el timer, más tiempo de procesador para hacer otras cosas.
  24.         INTCONbits.TMR0IF=0;   //Borramos bandera. Puede que el compilador lo haga automáticamente. Hay que verificarlo. Te podés ahorrar la instrucción en ese caso
  25.  
  26.        if(++counter1 > 10) counter1 = 1;   //nunca los hago valer 0, ese es el paso que me "como" del PWM para generar el duty del PWM fiel a lo que debe ser
  27.        if(++counter2 > 10) counter2 = 1;
  28.        if(++counter3 > 10) counter3 = 1;
  29.  
  30.        if(PWM1value >= counter1) PWM1 = 1; else PWM1 = 0;    
  31.        if(PWM2value >= counter2) PWM2 = 1; else PWM2 = 0;
  32.        if(PWM3value >= counter3) PWM3 = 1; else PWM3 = 0;  
  33.  }
  34.  
  35.  
  36. void main()
  37. {
  38.     //falta código de inicialización, etc...
  39.  
  40.      //inicializo contadores de PWM
  41.      counter1 = 1;
  42.      counter2 = 1;
  43.      counter3 = 1;
  44.      set_pwm_duty(1,4,9);    //seteo los dutys de 3 fases: 10% para la fase 1, 40% para la fase 2 y 90% para la fase 3.
  45.      set_pwm_shift(0,0);        //seteo phase-shift de 0% para la fase 2 y para la fase 3, ambas siempre con respecto a la fase 1. La fase  1 no se toca, ya que es la referencia
  46.  
  47.    //falta config interr. Tmr0, etc. similar a lo que tenías en tu código, sólo que configurando el Tmr0 a 8 bits y el prescaler a 1:2
  48.  
  49.   while(1)
  50.   {
  51.       delay_ms(2000);           //demora de 2 segundos (mucho más en realidad por todo el % de tiempo de procesador que consume la interr del Timer)
  52.       set_pwm_duty(5,5,5);    //seteo los dutys de las 3 fases al 50% para que se vea bien el phase-shift que quiero establecer justo debajo de esto
  53.       set_pwm_shift(3,7);        //seteo phase-shift de 30% para la fase 2, y 70% para la fase 3, ambas siempre con respecto a la fase 1. La fase  1 no se toca, ya que es la referencia
  54.  
  55.       delay_ms(2000);           //demora de 2 segundos (mucho más en realidad por todo el % de tiempo de procesador que consume la interr del Timer)
  56.       set_pwm_duty(1,4,9);    //seteo los dutys de 3 fases: 10% para la fase 1, 40% para la fase 2 y 90% para la fase 3.
  57.       set_pwm_shift(0,0);        //seteo phase-shift de 0% para la fase 2 y para la fase 3, ambas siempre con respecto a la fase 1. La fase  1 no se toca, ya que es la referencia
  58.   }
  59.  
  60. }
  61.  
  62. inline void set_pwm_duty(uint8_t phase1Value, uint8_t phase2Value, uint8_t phase3Value)
  63. {
  64.     PWM1value = phase1Value;
  65.     PWM2value = phase2Value;
  66.     PWM3value = phase3Value;
  67. }
  68.  
  69. void set_pwm_shift(uint8_t phase2Shift, uint8_t phase3Shift)
  70. {
  71.     uint8_t tmp;
  72.  
  73.     tmp = (counter1+ phase2Shift) % 11;
  74.     if(!tmp) tmp++;              //no dejar que valga nunca 0
  75.     counter2 = tmp;
  76.  
  77.     tmp = (counter1+ phase3Shift) % 11;
  78.     if(!tmp) tmp++;              //no dejar que valga nunca 0
  79.     counter3 = tmp;
  80. }



Entonces, lo que deberías ver es durante varios segundos las 3 fases con phase shift 0 y con un duty del 10% la 1era, 40% la segunda y 90% la tercera.
Luego, cambia durante otros cuantos segundos y debería mostrar las 3 fases con un duty del 50% pero la fase 2 despazada un 30% con respecto a la fase 1 y la fase 3 despalzada un 70% con respecto a la fase 1.

Por supuesto que podés cambiar los valores de duty y shift a gusto en cualquier momento. No he testeado el código. Sólo lo estoy escribiendo mientras respondo, por ende puede tener errores. Probalo y nos contás si funciona.

Saludos.
 


Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 17 de Diciembre de 2013, 19:48:15
BrunoF muchas gracias por esa explicación la verdad el ponerme a leer y mirar el código que escribiste he llegado a una conclusión que me  falta muchoooo camino por recorrer  :shock: :shock: para llegar al nivel que uds tiene. Me siento muy contento de que existan personas como uds que estan para ayudar. Me voy a poner a entender el codigo y a probarlo.

Tengo una preguntica cuando hablas de Necesitas interrumpir cada 1000000/25000/ 10. No entiendo de donde salen esos valores, el 10 como tu dices mas abajo es para hacer los salto de 0% a 100% con una resolución del 10% pero "1000000 y 25000" esos valores de donde salen?
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 17 de Diciembre de 2013, 19:56:20
Hola Alvaro,

lo que pasa es que tal vez hace más tiempo que estamos dando vuelta con los uC y ya nos hemos armado de mañas y truquitos que uno recuerda y reutiliza seguido. Además, conocer cómo funciona un uC a fondo lleva años. Fuera de eso, no somos más capaces ni inteligentes que el resto, al menos así me considero yo. Sólo estamos un poco más viejos en esto. :D

1 segundo = 1000000uS

Como tu frecuencia deseada es de 25Khz, necesitaríamos interrumpir 25000 veces por segundo: 1000000 / 25000 = 40uS.

Ahora, como supuse un delta duty y shift-phase del 10%, eso nos da que por cada período, podemos establecer 11 valores posibles. Como la generación de PWM se come uno, nos quedan 10. Entonces  tenemos que poder generar el ancho de duty correcto. Para ello, este método recurre a subdividir cada período en n partes (en este caso n=10) y decidir en cada momento si el PWM debe estar en alto o bajo, generando los 11 posibles valores que deseamos poder generar de duty.

Por ende, la cuenta de cada cuánto interrumpir, resulta ser:

1000000 / 25000 / 10 = 4uS.

Sé que por ahí lancé bastante código para entender, pero he visto que eres un rápido aprendiz y estoy seguro que terminarás entendiendo el funcionamiento e incluso encontrando posibles errores y mejoras.

Saludos
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 20 de Diciembre de 2013, 14:08:43
Bueno he vuelto  :) he estado un poco ocupado y ademas ya que el año se va a terminar aproveche para formatear mi PC :P jejeje  Año nuevo Virus nuevos jajaja

BrunoF gracias por esas explicaciones he mirado tu codigo muy detallado y lo he analizado, primero que todo he visto que utiliza declaraciones de variables con terminos que desconocia, como: uint8_t inline bueno he buscado sobre ellos y he visto que se trabaja orientado a la parte de c/c++. Mire en el manual de C18 y he reemplazado el Uint8_t por unsigned char "Creo que es lo mismo" el inline si no lo he utilizado por que en el manual de c18 es como una instruccion en .asm y en c/c++ creo que se utiliza  cuando se hace el llamado de la funcion se reemplace todo por el cuerpo de la funcion. NOTA: si esto diciendo cosas que nada tienen que ver me perdonan eso fue lo que he entendio.
Ahora con respecto algunas cosas del codigo tengo ciertas cosas que no entiendo.

Código: [Seleccionar]
void set_pwm_shift(uint8_t phase2Shift, uint8_t phase3Shift)
{
    uint8_t tmp;
 
    tmp = (counter1+ phase2Shift) % 11;
    if(!tmp) tmp++;              //no dejar que valga nunca 0
    counter2 = tmp;
 
    tmp = (counter1+ phase3Shift) % 11;
    if(!tmp) tmp++;              //no dejar que valga nunca 0
    counter3 = tmp;
}

no entiendo la parte del %11 el modulo ese no me queda muy claro.. si me puede explicar esa funcion te lo agradezco

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 20 de Diciembre de 2013, 14:46:58
Hola Alvaro,

BrunoF gracias por esas explicaciones he mirado tu codigo muy detallado y lo he analizado, primero que todo he visto que utiliza declaraciones de variables con terminos que desconocia, como: uint8_t inline bueno he buscado sobre ellos y he visto que se trabaja orientado a la parte de c/c++. Mire en el manual de C18 y he reemplazado el Uint8_t por unsigned char "Creo que es lo mismo" el inline si no lo he utilizado por que en el manual de c18 es como una instruccion en .asm y en c/c++ creo que se utiliza  cuando se hace el llamado de la funcion se reemplace todo por el cuerpo de la funcion. NOTA: si esto diciendo cosas que nada tienen que ver me perdonan eso fue lo que he entendio.

como había escrito en el ejemplo de código de arriba, si pones un:

#include <stdint.h>

deberías reconocerte automáticamente los tipos de variables que he utilizado en el código. Personalmente me gusta más usar este tipo de de tipos de datos, porque son mucho más fáciles y fieles de migrar a otros compiladores. Me parece una declaración mucho más explícita. Internamente el stdint.h no es mucho más que un puñado de typedefs que pueden variar de compilador en compilador. Lo importante es que utilizándolo, si quiero que el compilador actual me declare una variable sin signo de 8 bits, hago indistintamente:

uitn8_t myVar;

sin tener que preocuparme por los tipos de datos que el compilador utiliza nativamente.

Por ejemplo,

el C18 podría convertir mi uint8_t a una variable de tipo unsigned char dentro de su stdint.h
mientras que el CCS podría convertira a una variable de tipo unsigned int8 dentro de su stdint.h

Cualquiera sea el caso, yo sólo he pedido que me declaren un uint8_t y luego el compilador en su stdint.h tendrá definidas las equivalencias hacia sus tipos de datos nativos.

Ahora con respecto algunas cosas del codigo tengo ciertas cosas que no entiendo.

Código: [Seleccionar]
void set_pwm_shift(uint8_t phase2Shift, uint8_t phase3Shift)
{
    uint8_t tmp;
 
    tmp = (counter1+ phase2Shift) % 11;
    if(!tmp) tmp++;              //no dejar que valga nunca 0
    counter2 = tmp;
 
    tmp = (counter1+ phase3Shift) % 11;
    if(!tmp) tmp++;              //no dejar que valga nunca 0
    counter3 = tmp;
}

no entiendo la parte del %11 el modulo ese no me queda muy claro.. si me puede explicar esa funcion te lo agradezco

La función set_pwm_shift lo que hace es calcular el phase-shift. Los datos de entrada son los ángulos de desplazamiento (shift) que desea que tenga la fase 2 y 3 con repecto a la fase 1. El rango aceptable de los valores debería ser entre 0 y 10, siendo 0 = 0 y 10 = 2PI.

Si por ejemplo quisiese un phase-shift de 180 grados (PI) de las fases 2 y 3 con repecto a la primera, haría:

set_pwm_shift(5,5);

e internamente lo que hace la función módulo (%) es acotar el resultado del offset entre 0 y 10 (o lo que sería su equivalente en ángulos entre 0 y 2PI) ya que la función módulo devuelve el resto de la división entera. Por ende, cuando uno realiza x % y, el resultado tendrá siempre un valor dentro del intervalo [0;y-1]. En este caso al ser y = 11, el resultado será siempre acotado dentro del intervalo [0,10].

Los acoto porque los valores posibles de los contadores de cada fase son siempre entre 1 y 10 (siempre esquivo el 0, en este caso verificando si el resultado del módulo (el resto) es 0, en cuyo caso lo incremento para que valga 1). Utilizo una variable temporal (tmp) porque hasta no obtener el resultado definitivo, no quiero que suceda justo una interrupción del TMR0 y me agarre con un valor de contador incorrecto. Si hiciese esto (sin utilizar una variable temporal):

    counter2 = (counter1+ phase2Shift) % 11;
    if(!counter2) counter2++;              //no dejar que valga nunca 0


podría suceder que algunas interrupciones del Tmr0 se produjesen justo entre esas dos líneas, y en ese caso, si el resultado del módulo fuese cero, la variable counter2 ingresaría a la subrutina de interr. del Tmr0 con valor 0, que es un valor no deseado por mi, ya que produciría un error en el duty del PWM2 durante esos ciclos de PWM.

Saludos
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 20 de Diciembre de 2013, 15:46:49
Gracias de nuevo BrunoF con respecto a la directiva #include <stdint.h> creo y me arriesgo a decir esto ya que he visto el manual de C18  que en este compilador no la trae. En XC8 si viene según lo comprobé en el manual el manual.
Si estoy equivocado me lo haces saber.

Exitos :)

Lo que veo en el manual es lo siguiente

Código: [Seleccionar]
[i]An implementation that accepts any stricly conforming program that does not use complex
 types and in which the use of the features specified in the library clause (ANSI '89 Standard clause 7)
 is confined to the contents of the stadard headers <float.h> <iso646.h>.......<stdint.h>[/i]
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 20 de Diciembre de 2013, 19:22:14
Bueno ya he implementado el codigo y ha funcionado perfecto  :-/ esto me va ha servir de patron y espero que para muchos para llevar acabo mas proyectos con PWM por software. Lo que he notado es que el PWM3 no aparece nada en el PIN0 el cual lo tengo para el PWM3  el PWM2 Y PWM1 sale como en el video. 

feature=youtu.be


Código: [Seleccionar]
#pragma config PLLDIV = 2  //Cristal de 8Mhz lo dividimos entre 2 para tener los 4Mhz
#pragma config CPUDIV = OSC1_PLL2  //Los 96Mhz de PLL lo dividimos entre 2 para tener los 48Mhz con lo que vamos a trabajar
#pragma config USBDIV = 2  /////Tomar el reloj para USB desde el PLL- 48Mhz
#pragma config FOSC = HSPLL_HS  //Configurando oscilador interno
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = OFF
#pragma config BORV = 0
#pragma config VREGEN = OFF
#pragma config WDT = OFF
#pragma config WDTPS = 16384
#pragma config MCLRE = OFF
#pragma config LPT1OSC = OFF
#pragma config PBADEN = ON
#pragma config CCP2MX = OFF
#pragma config STVREN = OFF
#pragma config LVP = OFF
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#pragma config CP0 = OFF,CP1 = OFF,CP2 = OFF,CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF,WRT1 = OFF,WRT2 = OFF,WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF,EBTR2 = OFF,EBTR3 = OFF

#include <p18f4550.h>
#include <delays.h>


#define PWM1    LATBbits.LATB1
#define PWM2    LATBbits.LATB2
#define PWM3    LATBbits.LATB0

//Tres contadores uno por cada PWM

unsigned char contador1,contador2,contador3;

//Variables que llevan el valor actual del pwm
unsigned char PWM1value,PWM2value,PWM3value;

//Prototipos de Funciones

void set_pwm_duty(unsigned char phase1Value, unsigned char phase2Value, unsigned char phase3Value );
void set_pwm_shift(unsigned char phase2shift,unsigned char phase3shift);


/*-------Interrupción de Alta_Prioridad---------*/
void Interrupt_ISR_TMR0(void);
#pragma code High_vector_Interrupt = 0x08

void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
     TMR0L=238;  //Ajustado para que se genere un Interrup cada 4us
     INTCONbits.TMR0IF=0;   
     if(++contador1>10) contador1=1;
     if(++contador2>10) contador2=1;
     if(++contador3>10) contador3=1;

     if(PWM1value >= contador1) PWM1=1; else PWM1=0;
     if(PWM2value >= contador2) PWM2=1; else PWM2=0;
     if(PWM3value >= contador3) PWM3=1; else PWM3=0;
    }



void main(){

   
/*---------Configuracion Oscilador--------*/
    OSCCONbits.SCS1=0;    //Oscilador primario
    OSCCONbits.SCS0=0;

 /*-------Configuracion de pines---------*/
    TRISBbits.RB1=0;     
    LATBbits.LATB1=0;       

    TRISBbits.RB2=0;
    LATBbits.LATB2=0;

    ADCON1=0x0F;   //Todos los pines como digitales

    T0CONbits.TMR0ON=0; //Timero Off
    T0CONbits.T08BIT=1; //Configuracion a 8bits
    T0CONbits.T0CS=0;   //Internal Instruccion
    T0CONbits.T0SE=0;
    T0CONbits.PSA=0;   //Prescaler On

    T0CONbits.T0PS2=0; //Prescaler 1:2
    T0CONbits.T0PS1=0;
    T0CONbits.T0PS0=0;

    RCONbits.IPEN=1;        //Habilitamos la prioridad
    INTCONbits.TMR0IF=0;    //Interrupcion por desbordamiento
    INTCONbits.GIE_GIEH=1;
    INTCONbits.GIEH=1;      //Activamos alta_Prioridad
    INTCONbits.TMR0IE=1;   

    INTCON2bits.TMR0IP=1;  //TMR0 Alta prioridad.

    T0CONbits.TMR0ON=1;    //On Timer0

    //Inicio de contadores de PWM
    contador1=1;
    contador2=1;
    contador3=1;
    set_pwm_duty(1,4,9);
    set_pwm_shift(0,0);


    while(1){

        Delay10KTCYx(10);
        set_pwm_duty(5,5,5);
        set_pwm_shift(3,7);

        Delay10KTCYx(10);
        set_pwm_duty(1,4,9);
        set_pwm_shift(0,0);

    }
}

void set_pwm_duty(unsigned char phase1Value, unsigned char phase2Value, unsigned char phase3Value ){

    PWM1value=phase1Value;
    PWM2value=phase2Value;
    PWM3value=phase3Value;
}

void set_pwm_shift(unsigned char phase2shift,unsigned char phase3shift){

    unsigned char tmp;
    tmp=(contador1+phase2shift)%11;
    if(!tmp) tmp++;
    contador2=tmp;

    tmp=(contador1+phase3shift);
    if(!tmp) tmp++;
    contador3=tmp;

}



Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 20 de Diciembre de 2013, 21:08:39
Hola Álvaro! Me alegro que funcione. Fíjate que no configuraste como salida el pin b0.

Saludos
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 20 de Diciembre de 2013, 21:38:48
Hola Álvaro! Me alegro que funcione. Fíjate que no configuraste como salida el pin b0.


Si tienes toda la razon :P jejeje que descuido y lo de la pregunta de  la directiva #include <stdint.h> si viene en el compilador C18 ??
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 20 de Diciembre de 2013, 21:57:36
Ahora mísmo no tengo instalado el C18. Pero es tan sencillo como colocar la línea y ver si falla al compilar. Si falla es porque evidentemente no viene en el C18.

Saludos.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 30 de Diciembre de 2013, 17:01:02
Buenas tarde a todos saludos y felices fiesta he estado un poco alejado de todo esto por motivo de la llegada de amigos, familiares etc. Bueno gracias a la ayuda de BrunoF y de otros compañeros poco a poco he ido entendiendo lo que quiero hacer. En esta ocasion quiero por medio de 2 pulsadores conectado a los pines del microcontrolador variar el ancho de pulso. Como el proposito de todo esto es generar las señales para controlar un puente H el ciclo de trabajo maximo que puedo obtener es del 50% de tal forma que las señales de los 2 transistores de la misma rama no conmuten al mismo tiempo. Bueno he utilizado el programa que he hecho anteriormente con la ayuda de Bruno, el problema es que no me quiere funcionar. La logica que tengo en mente y que fue la que supuestamtne implemente es la siguiente:

1- Sabemos que el ciclo de trabajo aumenta con una resolucion del 10%  (Para esta aplicacion el maximo es de 50% Para poder controlar el punte H) por ese motivo lo limito hasta 5 pasos, desde de cumplido estos 5 pasos el siguiente debe arrancar desde 1 y asi sucesivamente.

2- He definido un pin de entrada en donde va un pulsador tambien defini otro contador el cual cumple la siguiente funcion: Cuando se oprime el pulsador el contador debe de aumenter en 1. Este contador se examina en un swicht-case y apartir del valor que tenga aumenta el ciclo de trabajo. Me cause una curiosidad ¿Como puedo solucionar en el caso que alguien tenga por mucho tiempo el pulsador activado  ya que quiero que aumente por cada cambio de estado?

Anexo el codigo.. El cual esta un poco muy prematuro.

Código: [Seleccionar]
#include <p18f4550.h>
#include <delays.h>


#define PWM1    LATBbits.LATB1
#define PWM2    LATBbits.LATB2
#define sw1     LATAbits.LATA0
//Tres contadores uno por cada PWM

unsigned char contador1,contador2,contador;

//Variables que llevan el valor actual del pwm
unsigned char PWM1value,PWM2value=1;

//Prototipos de Funciones

void set_duty(void);

/*-------Interrupción de Alta_Prioridad---------*/
void Interrupt_ISR_TMR0(void);
#pragma code High_vector_Interrupt = 0x08

void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
     TMR0L=254; 
     LATBbits.LATB0=!LATBbits.LATB0;
     INTCONbits.TMR0IF=0;
     if(++contador1>10) contador1=1;
     if(++contador2>10) contador2=1;
     

     if(PWM1value >= contador1) PWM1=1; else PWM1=0;
     if(PWM2value >= contador2) PWM2=1; else PWM2=0;
     
    }



void main(){


/*---------Configuracion Oscilador--------*/
    OSCCONbits.SCS1=0;    //Oscilador primario
    OSCCONbits.SCS0=0;

 /*-------Configuracion de pines---------*/
    /*----Salidas---*/
    TRISBbits.RB1=0;
    LATBbits.LATB1=0;

    TRISBbits.RB2=0;
    LATBbits.LATB2=0;

    TRISBbits.RB0=0;
    LATBbits.LATB0=0;

    TRISBbits.RB3=0;
    LATBbits.LATB3=0;
//-----Entradas--------//
    TRISAbits.RA0=1;  //Definido como entrada
   
   
    TRISAbits.RA1=1;  //Definido como entrada
    LATAbits.LATA1=0;
 
  //----------------------//
    ADCON1=0x0F;   //Todos los pines como digitales

   
    T0CONbits.TMR0ON=0; //Timero Off
    T0CONbits.T08BIT=1; //Configuracion a 8bits
    T0CONbits.T0CS=0;   //Internal Instruccion
    T0CONbits.T0SE=0;
    T0CONbits.PSA=0;   //Prescaler On

    T0CONbits.T0PS2=0; //Prescaler 1:2
    T0CONbits.T0PS1=0;
    T0CONbits.T0PS0=0;

    RCONbits.IPEN=1;        //Habilitamos la prioridad
    INTCONbits.TMR0IF=0;    //Interrupcion por desbordamiento
    INTCONbits.GIE_GIEH=1;
    INTCONbits.GIEH=1;      //Activamos alta_Prioridad
    INTCONbits.TMR0IE=1;

    INTCON2bits.TMR0IP=1;  //TMR0 Alta prioridad.

    T0CONbits.TMR0ON=1;    //On Timer0

    //Inicio de contadores de PWM
    contador1=1;
    contador2=1;
   
   
    while(1){

       set_duty();
           
    }
}

void set_duty(void){

    unsigned char cntduty;

    while(!sw1);
                Delay10KTCYx(10); //Retardor de 8.33ms
                cntduty++;
                switch (cntduty){

                    case 1: PWM1value=1; break; //Ciclo de trabajo del 10%
                    case 2: PWM1value=2; break; //Ciclo de trabajo del 20%
                    case 3: PWM1value=3; break; //Ciclo de trabajo del 30%
                    case 4: PWM1value=4; break; //ciclo de trabajo del 40%
                    case 5: PWM1value=5; break; //Cilco de trabajo del 50%
                    default : cntduty=0;

                }

}
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 30 de Diciembre de 2013, 17:08:18
Hola alvaro,

no te va a ejecutar nunca el código una vez que el Timer interrumpió por primera vez, porque estás precargandolo con el valor 254, que produce que el Timer se desborde inmediatamente y produce que el CPU ni bien sale de la interrupción del Timer, vuelva a ingresar sin ejecutar NUNCA código fuera del Timer.

Por el lado del pulsador, podés hacer:

Código: C#
  1. while(!sw1){
  2.                 Delay10KTCYx(10); //Retardor de 8.33ms
  3.                 cntduty++;
  4.                 switch (cntduty){
  5.  
  6.                     case 1: PWM1value=1; break; //Ciclo de trabajo del 10%
  7.                     case 2: PWM1value=2; break; //Ciclo de trabajo del 20%
  8.                     case 3: PWM1value=3; break; //Ciclo de trabajo del 30%
  9.                     case 4: PWM1value=4; break; //ciclo de trabajo del 40%
  10.                     case 5: PWM1value=5; break; //Cilco de trabajo del 50%
  11.                     default : cntduty=0;
  12.  
  13.                 }
  14.         while(!sw1);
  15.         Delay10KTCYx(10); //Retardo
  16.     }
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 30 de Diciembre de 2013, 17:22:54
Gracias Bruno osea que no es recomendable precargar el registro TMR0L a un valor cercano del desborde? si es asi aprox cual es el valor máximo que uno puede cargar el timer de tal forma que no se genere ese problema. En los anteriores codigo habiamos cargado el Timer a 238, he decido cambiar ese valor ya que quería aumentar un poco mas la frecuencia de los 25Khz a 32Khz que es lo maximo que se puede generar con esa resolucion.

He visto algo curioso cuando lo simulo en proteus sucede que cuando pulso (SW1) el cual esta conectado a GND y cuando se pulsa ve VCC se queda en VCC por un tiempo considerable y demora en retornar de nuevo a GND no se si es el simulador ya que no lo he probado en lo fisico.

Gracias.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 30 de Diciembre de 2013, 18:00:45
Gracias Bruno osea que no es recomendable precargar el registro TMR0L a un valor cercano del desborde? si es asi aprox cual es el valor máximo que uno puede cargar el timer de tal forma que no se genere ese problema. En los anteriores codigo habiamos cargado el Timer a 238, he decido cambiar ese valor ya que quería aumentar un poco mas la frecuencia de los 25Khz a 32Khz que es lo maximo que se puede generar con esa resolucion.

  Claro, no puedes dejarlo muy cercano al desborde porque más allá de tu código, hay código agregado por el compilador y por lo tanto no tienes un control preciso de la cantidad de ciclos consumidos y ademas te quedará poco tiempo (si es que sales de la interrupción y no reingresa inmediatamente) para tu programa de ejecución normal (quiero decir, todo aquello que no hagas en la interrupción).


He visto algo curioso cuando lo simulo en proteus sucede que cuando pulso (SW1) el cual esta conectado a GND y cuando se pulsa ve VCC se queda en VCC por un tiempo considerable y demora en retornar de nuevo a GND no se si es el simulador ya que no lo he probado en lo fisico.

Gracias.

  Todo dependerá de cuan cargado está el simulador. Abajo en lo que sería como una barra de estado te avisa si es que está corriendo o no en tiempo real. A su vez también te indica la carga del CPU en porcentaje.
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 02 de Enero de 2014, 18:18:17
Feliz año 2014 a todos :) que Dios los bendiga y los mejores deseos :)

Bueno todavia no he podido solucionar el problema de poder variar el ciclo de trabajo con el pulsador he probado el circuito en la protoboard y con mi osciloscopio ver los cambio.. Pero no pasa nada cuando lo oprimo Anexo el codigo. para ver que tengo mal..

Código: [Seleccionar]
#include <p18f4550.h>
#include <delays.h>

/*-----Definicion de estados--------*/

#define ciclo_10    1 //Ciclo del 10%
#define ciclo_20    2 //Ciclo del 20%
#define ciclo_30    3 //Ciclo del 30%
#define ciclo_40    4 //Ciclo del 40%
#define ciclo_50    5 //Ciclo del 50%

/*-----Definicion de pines-----------*/

#define PWM1    LATBbits.LATB0
#define button1 LATAbits.LATA0
/*-------------------------------------*/

unsigned char contador, PwmValue, estado;

/*----Prototipos de funciones----------*/

void set_pwm(unsigned char PwmValue1);
/*-------Interrupción de Alta_Prioridad---------*/
void Interrupt_ISR_TMR0(void);
#pragma code High_vector_Interrupt = 0x08

void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
    INTCONbits.TMR0IF=0;    /*Borramos bandera*/
    TMR0L=238;
    if(++contador>10) contador=1;

    if(PwmValue>=contador) PWM1=1; else PWM1=0;
}

void main(){

    estado=ciclo_10;

    TRISB=0x00;
    LATB=0x00;

    TRISAbits.RA0=1; //Como entradas
    //LATAbits.LATA0=0;

/*---------Configuracion Oscilador--------*/

    OSCCONbits.SCS1=0;    //Oscilador primario
    OSCCONbits.SCS0=0;

    ADCON1=0x0F;   //Todos los pines como digitales

    T0CONbits.TMR0ON=0; //Timero Off
    T0CONbits.T08BIT=1; //Configuracion a 8bits
    T0CONbits.T0CS=0;   //Internal Instruccion
    T0CONbits.T0SE=0;
    T0CONbits.PSA=0;   //Prescaler On

    T0CONbits.T0PS2=0; //Prescaler 1:2
    T0CONbits.T0PS1=0;
    T0CONbits.T0PS0=0;

    RCONbits.IPEN=1;        //Habilitamos la prioridad
    INTCONbits.TMR0IF=0;    //Interrupcion por desbordamiento
    INTCONbits.GIE_GIEH=1;
    INTCONbits.GIEH=1;      //Activamos alta_Prioridad
    INTCONbits.TMR0IE=1;

    INTCON2bits.TMR0IP=1;  //TMR0 Alta prioridad.

    T0CONbits.TMR0ON=1;    //On Timer0

    while(1){
        switch(estado){
        case ciclo_10 :
            PwmValue=1;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_20;
            break;
        case ciclo_20 :
            PwmValue=2;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_30;
            break;
        case ciclo_30 :
            PwmValue=3;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_40;
            break;
        case ciclo_40 :
            PwmValue=4;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_50;
        case ciclo_50:
            PwmValue=5;
            while(button1);
            Delay1KTCYx(50);
            while(!button1);
            Delay1KTCYx(50);
            estado=ciclo_10;
            break;


            }


       
    }
}

Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: AngelGris en 02 de Enero de 2014, 18:22:47
  Creo que esta mal tu definición del botón.. para leer un puerto deberías utilizar PORTAbits.RA0, o sea utilizar el registro PORT en lugar del registro LAT
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 02 de Enero de 2014, 18:29:42
como dice el chavo eso..eso..eso.. jajajaj si ese era el problema jajajaj Gracias AngelGris... Cosas mínimas que lo estancan a uno..
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: alvaro2043 en 02 de Enero de 2014, 23:14:03
Bueno ya logre algo que para uno es super sencillo que era variar el ciclo de trabajo con el pulsador. Despues de 1 mes jejejje. Unos comentarios mas arriba BrunoF me compartió un código para realizar el desafase de 2 señales a partir de una de referencia, es un código que me ayudo a entender muchas cosas ya que ese es el objetivo final pero lo tengo pensado hacer con el Dspic que mande a pedir, el cual se demora un poquito. Así que he tomado el código para poder realizar solo el desfase entre 2 señales 180 grados respecto a la otra con la misa frecuencia pero no me sale :(. Como he dicho esto lo quiero hacer para controlar un Puente H con módulos IGBT. Anexo el código que no me quiere salir y La imagen a lo que quiero llegar. Nota debo de generar un tiempo muerto para que los IGBT de la misma rama no esten activado al mismo tiempo, segun la hoja de datos del IGBT el tiene un tiempo de apagado de 350ns entonces mas o menos el tiempo muerto lo haría de 370ns..

Código: [Seleccionar]
#include <p18f4550.h>
#include <delays.h>

/*-----Definicion de estados--------*/

#define ciclo_10    1 //Ciclo del 10%
#define ciclo_20    2 //Ciclo del 20%
#define ciclo_30    3 //Ciclo del 30%
#define ciclo_40    4 //Ciclo del 40%
#define ciclo_50    5 //Ciclo del 50%

/*-----Definicion de pines-----------*/

#define PWM1    LATBbits.LATB0
#define PWM2    LATBbits.LATB2
#define button1 PORTAbits.RA0
/*-------------------------------------*/

unsigned char contador1,contador2,PwmValue,PwmValue2,estado;

/*----Prototipos de funciones----------*/

void phase_shift(void);
/*-------Interrupción de Alta_Prioridad---------*/
void Interrupt_ISR_TMR0(void);
#pragma code High_vector_Interrupt = 0x08

void High_vector(void){
     _asm goto Interrupt_ISR_TMR0 _endasm
}
#pragma code

#pragma interrupt Interrupt_ISR_TMR0
void  Interrupt_ISR_TMR0 (void)
{
    INTCONbits.TMR0IF=0;    /*Borramos bandera*/
    TMR0L=243;
    if(++contador1>10) contador1=1;
    if(++contador2>10) contador2=1;

    if(PwmValue>=contador1) PWM1=1; else PWM1=0;
    if(PwmValue2>=contador2) PWM2=1; else PWM2=0;

}

void main(){

    estado=ciclo_10;

    TRISB=0x00;
    LATB=0x00;

    TRISAbits.RA0=1; //Como entradas
    //LATAbits.LATA0=0;

/*---------Configuracion Oscilador--------*/

    OSCCONbits.SCS1=0;    //Oscilador primario
    OSCCONbits.SCS0=0;

    ADCON1=0x0F;   //Todos los pines como digitales

    T0CONbits.TMR0ON=0; //Timero Off
    T0CONbits.T08BIT=1; //Configuracion a 8bits
    T0CONbits.T0CS=0;   //Internal Instruccion
    T0CONbits.T0SE=0;
    T0CONbits.PSA=0;   //Prescaler On

    T0CONbits.T0PS2=0; //Prescaler 1:2
    T0CONbits.T0PS1=0;
    T0CONbits.T0PS0=0;

    RCONbits.IPEN=1;        //Habilitamos la prioridad
    INTCONbits.TMR0IF=0;    //Interrupcion por desbordamiento
    INTCONbits.GIE_GIEH=1;
    INTCONbits.GIEH=1;      //Activamos alta_Prioridad
    INTCONbits.TMR0IE=1;

    INTCON2bits.TMR0IP=1;  //TMR0 Alta prioridad.

    T0CONbits.TMR0ON=1;    //On Timer0

    while(1){
        switch(estado){
        case ciclo_10 :
            PwmValue=1;
            PwmValue2=1;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_20;
            break;
        case ciclo_20 :
            PwmValue=2;
            PwmValue2=2;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_30;
            break;
        case ciclo_30 :
            PwmValue=3;
            PwmValue2=3;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_40;
            break;
        case ciclo_40 :
            PwmValue=4;
            PwmValue2=4;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_50;
        case ciclo_50:
            PwmValue=5;
            PwmValue2=5;
            while(button1);
            Delay1KTCYx(10);
            while(!button1);
            Delay1KTCYx(10);
            estado=ciclo_10;
            break;
         
            }
            phase_shift();
    }
 
}


void phase_shift(void){

    unsigned char tmp;
    tmp=(contador1+6)%11;
            if(!tmp) tmp++;
    contador2=tmp;


}


(http://imageshack.us/a/img842/4375/pxj.th.png) (http://imageshack.us/photo/my-images/842/pxj.png/)
Título: Re: Timer0_PIC18F4550_No_se_que_pasa
Publicado por: BrunoF en 03 de Enero de 2014, 01:38:17
Hola,

move la linea:

phase_shift();

dentro del main pero justo antes del while().

No olvides inicializar al inicio del main() a contador1 y contador2 al valor 1.

Saludos.