Autor Tema: Interrupcion por desborde TIMER2 tarda mucho!  (Leído 2163 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado teban89

  • PIC10
  • *
  • Mensajes: 16
Interrupcion por desborde TIMER2 tarda mucho!
« en: 29 de Marzo de 2018, 19:55:41 »
Buenas gente, les hago una consulta a ver si me pueden dar una mano: Estoy trabajando con un 16F873a y un cristal a 20 MHz. Segun lo que estuve buscando en internet (porque en el datasheet no esta o al menos no lo encontre) dice que la interrupcion mas rapida que se puede conseguir con ese oscilador es de 0.2 uS, pero yo no logro bajar de los 13 uS. Andaria necesitando llegar a ese numero y no puedo hacerlo funcionar. Alguien sabra por que? Adjunto el codigo, el programa lo unico que hace es invertir el estado logico del pin C3:
Código: [Seleccionar]
#include <16F873A.h>

#FUSES NOWDT                  //No Watch Dog Timer
#FUSES HS                    //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES PUT                    //Power Up Timer
#FUSES NOBROWNOUT            //No brownout reset
#FUSES NOLVP                  //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use delay(clock=20000000)

#byte TRISA=0x85
#byte TRISB=0x86
#byte TRISC=0x87
#byte PORTA=0x05
#byte PORTB=0x06
#byte PORTC=0x07
#byte PR2=0x92

#bit PWM1=PORTC.3

#int_TIMER2
void  TIMER2_isr(void)
{
PWM1=!PWM1;
SET_TIMER2(t2);
}

void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //1-2-4-8 -- 65,5 ms  - 131 ms - 262 ms - 524 ms overflow
setup_timer_2(T2_DIV_BY_1,0,1); //RESOLUTION: 1-4-16 us --- Overflow 0-255, Interrupt period: 1-16
disable_interrupts(INT_TIMER0);
disable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
TRISA=0b00000000;
TRISB=0b00000000;
TRISC=0b00000000;
PORTA=PORTB=PORTC=0;
SET_TIMER2(t2);
PR2=0;

while(1)
{


}//while
}//main



Desde ya muchas gracias!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Interrupcion por desborde TIMER2 tarda mucho!
« Respuesta #1 en: 29 de Marzo de 2018, 22:55:18 »
Si.. la interrupcion puede ser de 0.2us que es lo que tarda 1 ciclo de reloj (Fosc/4). El problema surge con no conocer como funciona el micro, el datasheet lo dice pero es todo casi exceptuando los modulos

El problema es que las instrucciones tambien tardan 1 o 2 ciclos de reloj. Si pensas que:

Detectada la interrupcion, el micro debe guardar los registros y saltar al vector de interrupcion.
Dentro de la interrupcion a veces se salta al destino que corresponde que es la funcion de interrupcion ( 2 ciclos )
Guardar y reestablecer los registros STATUS y W como minimo que seran ( 8/9 ciclos mas )
Preguntar por cual interrupcion llego ahi. ( 2/3/4 mas segun)
Limpiar la bandera de interrupcion. (1 ciclos )
Recargar el Timer si es que no usas el CCP.
Ejecutar el codigo de la interrupcion (lo que hagas )
Ejecutar el RETFIE para volver  ( 2 ciclos mas )


Te vas a dar cuenta que es irrealizable lo que pedis!.
El que este demorando 13us significa que entre que se determina la interrupcion, hasta que sale (porque apenas sale entra de nuevo) pasaron 65 ciclos
Podes hacerlo mas rapido ? SI en ASM, pero no vas a ganar nada. Ademas tu micro se pasa en la interrupcion, de tal forma que ni vale la pena usarla, ya que lo del while del main jamas se va a ejecutar, entonces si lo haces en el while del main va a ser mas rapido aun. Y ni siquiera uses el Timer. Lo mas rapido que podes conseguir es:

Código: C
  1. while(1)
  2. {
  3.         output_toggle(PIN_C3);
  4. }
(Usar el FAST_IO(C) y el set_tris_c() )

Y que seguramente NO sea tan rapido como pensas, ya que le va a llevar facil unas 3 ciclos o 0.6us (1.2us periodo) como minimo (salto + XOR).
Se puede reducir aun mas si se repite output_toggle, por toda la memoria.... pero no te salvas de 0.4us de periodo, y cada tanto un estado va a quedar en alto o bajo por 0.6s por el salto.
Y esto pensandolo desde puro ASM.

Lo que vos estas buscando es si o si utilizar el PWM (del CCP) y no la interrupcion del Timer. Aun asi no creo que logres tener ese resultado, deberias tener un micro mucho mas rapido.
Si ahora necesitas muchos mas PWM independientes (Y por eso lo intentas hacer por software) a esa frecuencia entonces sugiero irte a otro integrado o buscar algun integrado aparte que haga de PWM y lo controles via SPI/i2C/etc si es que existe.

-----------

Hay micros que poseen otras ventajas, los PIC18 por ejemplo ya agregan el de guardar/restablecer los registros STATUS/W por si solos al entrar. Los PIC24 ya no ocupa 4 ciclos del oscilador para hacer una instruccion, y asi en adelante, pero lo que estas pidiendo requiere de un micro demasiado rapido e insensato hacerlo por software.

-----------

Pero la pregunta del millon es...

¿Realmente necesito esa frecuencia?
Todo esto suponiendo que es un PWM. Ya que tu codigo no es mas que dividir el reloj que es de 20Mhz por 4 y asi obtener una salida cuadrada de 5Mhz
« Última modificación: 29 de Marzo de 2018, 23:19:09 por KILLERJC »

Desconectado teban89

  • PIC10
  • *
  • Mensajes: 16
Re:Interrupcion por desborde TIMER2 tarda mucho!
« Respuesta #2 en: 30 de Marzo de 2018, 12:42:31 »
Hola KILLERJC, gracias por tomarte la molestia de darme una excelente respuesta. La idea del post era justamente justamente encontrar una respuesta a la siguiente pregunta que me habia planteado cuando lleve todo esto a la practica: ¿como puede ser que la interrupcion pueda realizarse cada 0.2 uS si ese ya es el ciclo de maquina? Obviamente que atender la interrupcion lleva muchos ciclos de maquina, entonces no entendia como podia ser que tarde 1 ciclo de maquina en atenderse. Eso era lo que me hacia pensar que en realidad no estaba teniendo un error en el codigo sino que ya era una limitacion propia del micro.

Con respuesta a la pregunta del millon, lo que yo necesito hacer es lo siguiente: necesito tener 10 salidas PWM que puedan correr "a la vez" (yo se que esto tecnicamente es imposible pero se pueden implementar algunas cosas por software para "parecer" que estan las 10 corriendo a la vez). Cada una tiene que moverse en distinto momento, pero todas a la misma velocidad y a la misma frecuencia. La salida PWM va a ir a un JFET conectado como VCR (Voltage Controlled Resistor) para controlar la ganancia de un amplificador de audio.
De estas lineas necesito manejar 10 amplificadores. De ahi viene mi necesidad de poder implementar una cuadrada con PWM y de frecuencia mayor a 20 kHz (porque si estoy dentro de la banda de audio la misma modulacion del PWM me va a actuar sobre el audio y voy a generar un efecto "tremolo").
Por eso tampoco puedo usar el modulo PWM del micro, porque me harian falta 9 mas. Entonces no me queda otra que implementarlo por software. Lo pude hacer sin problemas pero con la interrupcion consigo una frecuencia de alrededor de 4 kHz.

El metodo que utilizo es el siguiente: tengo una variable A contando hasta cierto valor (con la interrupcion del Timer2) y en el programa principal tengo otra variable "Ton" (tiempo en alto) que se compara todo el tiempo con la variable A. Si "Ton" es mayor a "A" me pone la salida en 1 y sino la pone en 0. Variando "Ton" vario el ancho del pulso. La frecuencia de la señal me la da cada cuanto desborda el Timer2 multiplicado por "hasta cuanto cuenta la variable "A" (o sea, la resolucion del PWM). Suponiendo que la interrupcion desborda cada 20 uS y la variable "A" cuenta hasta 100, el periodo total sera de 500 Hz.

Por otro lado, lo que se me ocurrio fue poner a contar la variable "A" en el bucle principal del programa y consegui una frecuencia mayor a 20 kHz (que es lo que necesito). El problema va a estar en que cuando empiece a agregar codigo esa frecuencia va a empezar a achicarse, porque la variable "A" va a tardar mas en incrementarse.

Espero no haberte mareado...

Gracias!!!!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Interrupcion por desborde TIMER2 tarda mucho!
« Respuesta #3 en: 30 de Marzo de 2018, 13:44:54 »
Te entiendo, otra pregunta es ...

Citar
De ahi viene mi necesidad De ahi viene mi necesidad de poder implementar una cuadrada con PWM y de frecuencia mayor a 20 kHz

Si o si cuadrada debe ser?, es decir no necesitas que tenga una resolucion?
Si es puramente cuadrada y no pensas tener una resolucion si podes llegar a 40Khz creo.

Suponiendo que SI necesitas resolucion digamos 32 (5bits) y suponiendo que la interrupcion le tome unos 25us agregando las 10 saldias, tendrias una frecuencia maxima de 1.25Khz, o sea muy bajo de lo que pedis.

La unica forma que se me ocurre de tener tantas salidas asi son:
- Usar varios PICs no solo 1, en el cual puedan controlar varios PWM de forma independiente. Y otro para controlarlo todo.
- Usar algun integrado que te pueda proporcionar varias salidas PWM
- O usar un potenciometro digital en ves de un FET + PWM


Desconectado nico

  • PIC16
  • ***
  • Mensajes: 180
Re:Interrupcion por desborde TIMER2 tarda mucho!
« Respuesta #4 en: 30 de Marzo de 2018, 20:02:24 »
Una consulta, si el fet va a estar como VCR y vas a controlar la ganancia, entiendo que la salida pwm luego la vas a integrar para conseguir una continua que sea proporcional al duty del pwm, no entiendo para que necesitas tan alta la frecuencia. Al menos intentaría probar a hacer las salidas por software con la mayor cantidad de bits de resolucion(que me daría la mayor cantidad de pasos en la ganancia) y luego con un buen filtro la tensión de control estara lista para atacar el gate.

Tal vez el circuito(o la parte del fet) aclararía la situación.

Salutes.


 

anything