Autor Tema: Retardos con precisión para dsPIC33F  (Leído 4464 veces)

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

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Retardos con precisión para dsPIC33F
« en: 17 de Diciembre de 2006, 04:46:57 »
Tras una nueva semana de pelea en plena arena, he conseguido implementar funciones para hacer retardos de microsegundos y milisegundos que son independientes de la velocidad con la que trabaja el micro.

Las funciones son las siguientes:

Código: [Seleccionar]
#define MIPS 50

/*********************************************/
/**  Función para hacer un retardo de 1 ms  **/
/**             www.elrebujito.es           **/
/**              Nocturno - 2006            **/
/**    Válida para MIPS >= 0.002 (4KHz)     **/
/*********************************************/

#define delay_1ms() asm("REPEAT #%0\n NOP\n REPEAT #%0\n NOP\n REPEAT #%0\n NOP\n REPEAT #%0\n NOP" :: "i" (MIPS*250-2))

/*********************************************/
/**  Función para hacer un retardo de 10 us **/
/**             www.elrebujito.es           **/
/**              Nocturno - 2006            **/
/**    Válida para MIPS >= 0.2 (400KHz)     **/
/*********************************************/

#define delay_10us() asm("REPEAT #%0\n NOP" :: "i" (MIPS*10-2))


/*********************************************/
/**  Función para hacer un retardo de 1 us  **/
/**             www.elrebujito.es           **/
/**              Nocturno - 2006            **/
/**     Válida para MIPS>=2 (>4MHz)         **/
/*********************************************/

#define delay_1us() asm("REPEAT #%0\n NOP" :: "i" (MIPS-2))

/*********************************************/
/**  Función para hacer un retardo de x us  **/
/**             www.elrebujito.es           **/
/**              Nocturno - 2006            **/
/**       Válida para MIPS>=16 (>32MHz)     **/
/**        Valores de x: de 0 a 65535       **/
/*********************************************/

void delay_us(unsigned int x) {
asm ("REPEAT #%0\n NOP" :: "i" (MIPS-16));
while ((x--)!=1) {
asm ("REPEAT #%0\n NOP" :: "i" (MIPS-7));
};
};

/*********************************************/
/**  Función para hacer un retardo de x ms  **/
/**             www.elrebujito.es           **/
/**              Nocturno - 2006            **/
/**      Válida para MIPS>=0.24 (>48KHz)    **/
/**        Valores de x: de 0 a 65535       **/
/*********************************************/

void delay_ms(unsigned int x)
 {
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-5));
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-5));
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-6));
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-6));
while ((x--)!=1) {
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-4));
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-3));
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-3));
asm ("REPEAT #%0\n NOP" :: "i" (MIPS*250-3));
};
 }

Como véis, al final he tenido que pasar por la piedra del ASM y pese a que he refunfuñado todo lo que podía, la precisión de los delays es sorprendente; sólo se ejecutan los ciclos que tienen que ejecutarse: ni uno más y por supuesto ni uno menos.

Otra cosa que podréis observar es que hay mucho código con #define, por lo que al compilar se realizan las sustituciones correspondientes y queda un código extremadamente pequeño y compacto.

En función de la velocidad de proceso de nuestro dsPIC33F, que como sabéis puede ir a muchas frecuencias distintas hasta un máximo de 50MIPS, podréis usar algunas funciones u otras. Esto es debido a que si trabajamos a frecuencias lentas, los ciclos de instrucción necesarios para hacer los cálculos van comiéndose el tiempo del delay, hasta que llegamos a un punto que nos hemos pasado. No obstante, he dejado delante de cada función una recomendación de la velocidad mínima a emplear y los límites del parámetro x.

La principal ventaja de estos retardos es su precisión y lo poco que ocupan, pero tienen un gran inconveniente: si durante un retardo salta una interrupción y el flujo de programa se va a ejecutarla, cuando vuelva seguirá por donde iba por lo que nuestro retardo habrá aumentado todo el tiempo que duró la interrupción.

Tengo casi acabadas y espero publicarlas en breve unas rutinas para generar retardos con el Timer, lo que nos permite generar retardos que no se vean afectados por dicho efecto.

Quedo a vuestra disposición para cualquier comentario.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Retardos con precisión para dsPIC33F
« Respuesta #1 en: 17 de Diciembre de 2006, 16:28:07 »
Bien, ya he probado y asegurado el código para la generación de retardos con el Timer.

Aquí os lo dejo para vuestro uso y disfrute:

Código: [Seleccionar]
#define MIPS 20

/*********************************************/
/**  Función para hacer un retardo de x us  **/
/**  utilizando el Timer e interrumpible    **/
/**  generada automáticamente por asistente **/
/**             www.elrebujito.es           **/
/**              Nocturno - 2006            **/
/**        Válida para MIPS>=1 (>2MHz)      **/
/**         Valores de x: x*MIPS-30>0       **/
/*********************************************/

void Tdelay_us(unsigned int x) {
  TMR9=-(x*MIPS-30);
  T9CON = 0x8080;
  while (IFS3bits.T9IF==0);
  IFS3bits.T9IF=0;
};

/*********************************************/
/**  Función para hacer un retardo de x ms  **/
/**  utilizando el Timer e interrumpible    **/
/**  generada automáticamente por asistente **/
/**             www.elrebujito.es           **/
/**              Nocturno - 2006            **/
/**        Válida para MIPS>=1 (>2MHz)      **/
/**              Valores de x: >1           **/
/*********************************************/

void Tdelay_ms(unsigned long x) {
  unsigned long Limite;
  Limite = x*MIPS*1000-48;
  TMR8=-(Limite);
  TMR9=(-Limite)>>16;
  T8CON = 0x8008;
  while (IFS3bits.T9IF==0);
  IFS3bits.T9IF=0;
};

He aprovechado para diseñar un nuevo asistente en El Rebujito al que sólo hay que meter los MIPS, el método a utilizar (ciclos o Timer) y elegir el nº del timer para que nos entregue el código más adecuado a cada configuración.

Podéis ver el asistente aquí:
33F - Asistente para la generación automática de retardos

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: Retardos con precisión para dsPIC33F
« Respuesta #2 en: 17 de Diciembre de 2006, 21:33:55 »
Des pues de ver el resultado de su trabajo, solo queda decir. ¡Buen trabajo! Felicitaciones y  gracias por compartirlo.

Desconectado Sispic

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 1685
    • winpic800
Re: Retardos con precisión para dsPIC33F
« Respuesta #3 en: 18 de Diciembre de 2006, 03:17:40 »
Ademas  hacia falta ... se acabó contar cada vez con los dedos los nops  para cada clock . :-)

Desconectado togarha

  • PIC12
  • **
  • Mensajes: 87
Re: Retardos con precisión para dsPIC33F
« Respuesta #4 en: 17 de Enero de 2007, 07:31:25 »
Buenas!!!

En el mismo C30 hay una funcion " __delay32(unsigned long ciclos) " escrita en ensamblador donde tienes un delay exacto tambien....

saludos

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Retardos con precisión para dsPIC33F
« Respuesta #5 en: 17 de Enero de 2007, 07:52:26 »
Pues qué guay. De haberlo sabido antes ni toco el asm :D

Desconectado togarha

  • PIC12
  • **
  • Mensajes: 87
Re: Retardos con precisión para dsPIC33F
« Respuesta #6 en: 17 de Enero de 2007, 08:49:29 »
jejejeje, no hay nada como empaparse de los foros de microchip ;)

por si a alguien le interesa y no lo encuentra esta en:

..\Microchip\MPLAB C30\src\pic30

es el archivo "delay32.s" lo incluis en el proyecto y a funcionar. Yo luego, en mi ".h" principal me creo los siguientes defines:

// External oscillator frequency with PLL enable
#define SYSCLK          8000000
#define FCY            SYSCLK*4/2


// Defines para calcular los ciclos para determinados tiempos
// Se suma uno al final para asegurarnos que tenemos el tiempo minimo deseado
// en caso de que la division no fuese exacta
#define   US_10         (1*FCY/100000)+1
#define   US_25         (25*FCY/1000000)+1
#define   US_50         (5*FCY/100000)+1
#define   US_100         (1*FCY/10000)+1
#define   US_250         (25*FCY/100000)+1
#define   US_500         (5*FCY/10000)+1

#define   MS_10         (1*FCY/100)+1
#define   MS_25         (25*FCY/1000)+1
#define   MS_50         (5*FCY/100)+1
#define   MS_100         (1*FCY/10)+1
#define   MS_250         (25*FCY/100)+1
#define   MS_500         (5*FCY/10)+1


luego ya solamente hay que hacer:

__delay32( MS_500 );

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Retardos con precisión para dsPIC33F
« Respuesta #7 en: 06 de Mayo de 2010, 07:33:23 »
Amigos, tras la migración de mi web se jodieron los scripts que ejecutan el asistente.
Acabo de repararlos y ya está otra vez operativo:
Asistente para la generación automática de retardos


 

anything