TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: PicMinor en 07 de Enero de 2021, 08:00:05
-
¡ Saludos al foro !
No se si ya se había comentado pero por si hay alguien interesado comento mi experiencia con los retardos del compilador PICC versión 5.083.
Para una aplicación he estado probando la función delay_us y he comprobado algunos resultados interesantes:
Utilizamos la función delay_us con un micro PIC16F886 con oscilador a 8 MHz y el MPLAB SIM como debugger. Probamos distintos valores y medimos el resultado en la ventana Watch.
delay_us(100); 100us
delay_us(200); 200us
delay_us(300); 300us
delay_us(400); 403.5us
delay_us(500); 503.5us
delay_us(600); 605us
delay_us(700); 702.5us
delay_us(800); 806.5us
delay_us(900); 902.5us
Y ahora utilizamos en lugar de un valor constante un variable long asignada.
Val_Ret=100 delay_us(Val_Ret); 104.5us
Val_Ret=200 delay_us(Val_Ret); 204.6us
Val_Ret=300 delay_us(Val_Ret); 306us
Val_Ret=400 delay_us(Val_Ret); 406us
Val_Ret=500 delay_us(Val_Ret); 506us
Val_Ret=600 delay_us(Val_Ret); 607.5us
Val_Ret=700 delay_us(Val_Ret); 707.5us
Val_Ret=800 delay_us(Val_Ret); 809us
Val_Ret=900 delay_us(Val_Ret); 909 us
Como se puede ver si pretendemos obtener un retardo "exacto" hay que hacer pruebas previas para saber de qué manera nos va a afectar el compilador. Luego podemos utilizar varios "trucos" si queremos dejar el retardo exacto, pero visto lo visto no se puede confiar al 100% en los retardos del compilador.
-
No es solo el compilador; también hay que tener en cuenta la frecuencia de oscilación ya que al ser valores discretos las instrucciones se ejecutan en múltiplos exactos de los clocks de reloj y eso hace que unos valores sean exactos y otros no tanto o incluso muy inexactos. Con el mismo programa, con el mismp PIC y con tan solo variar la frecuencia de reloj del mismo podríamos ver como esas tablas cambian. Y por supuesto pasando como parámetro la variable de qué periodo querenemos se desvirtúa todo al tener que tener en cuenta también las instrucciones necesarias para mover desde la RAM a los registros dichos valores y si estos son de uno o dos o tres bytes ... y por supuesto el compilador. Muchas gracias PicMinor por la prueba :mrgreen:
-
¡Saludos RedPic y gracias por la respuesta!
Estoy totalmente de acuerdo con tu respuesta, pero el objetivo de mi comentario era precisamente llamar la atención sobre la inexactitud de los compiladores a la hora de ajustar sus "prestaciones" a los requerimientos de nuestros códigos.
Creo que, tal y cómo lo he planteado, si queremos que un retardo en microsegundos se corresponda exactamente con lo que queremos que haga, hay que tener en cuenta que no se puede "confiar" en la precisión del código. Yo recomiendo, y es lo que he hecho, simular el código con el MPLAB y con los datos obtenidos decidir.
OPCION 1. Nos sirve la imprecisión del compilador. No hacemos nada.
OPCION 2. No nos sirve, pero utilizamos retardos constantes que queremos que sean lo más exactos posible. Diseñamos una rutina if-then-else o switch-case para cada caso particular ajustando los valores.
OPCION 3. No nos sirve y los retardos son variables. (Lamentablemente es mi caso). La única solución "viable" en mi problema particular, ha sido el tomar datos en todo el rango de captación y ajustarlos a los valores reales con un polinomio de regresión.
No acabo de entender como los desarrolladores de los compiladores no han contemplado este tipo de situaciones.
Creo que habría que considerar la siguiente pregunta:
¿Por qué, a la hora de diseñar un código, si yo necesito un retardo de 750us, no puedo estar seguro de que la instrucción delay_us(750) o la instrucción delay_us(Val_Retardo) con Val_Retardo=750 me de el valor correcto?
-
Muy cierto.
Yo normalmente los uso tal cual cuando el periodo no me es fundamental, cuando quiero precisión lo compongo en ASM calculando exactamente cuantas instrucciones se ejecutan y cuando demora cada una de ella para la frecuencia de uso ... todo un poema pero si quieres precisión debes hacerlo así. Ensamblador, pico y pala.
-
¿Por qué, a la hora de diseñar un código, si yo necesito un retardo de 750us, no puedo estar seguro de que la instrucción delay_us(750) o la instrucción delay_us(Val_Retardo) con Val_Retardo=750 me de el valor correcto?
Porque eso significa hacer un código de demora especifica para cada uno de esos demoras. Y eso ocupa espacio, y eso influye luego en que tan bueno es el compilador.
Por eso mismo XC8 no acepta variables en su delays, simplemente acepta constantes.
Esas constantes, luego son procesadas junto a la frecuencia del oscilador, y les da la cantidad de ciclos a esperar, nuevamente CONSTANTES, esto no va a una funcion de c, sino que esta construido en el compilador y crea la demora según el tiempo. Algo así como hacemos las demoras en ASM. Esta "función" que crea las demoras, según la cantidad de ciclos a esperar, en fin.. Nada variable. Y todo en tiempo de compilación.
Pero si pensas hacerlo variable, no podes hacerlo durante la compilación, sino que lo tenes que realizar únicamente durante el runtime, y eso muy pocas veces te va a dar justo. O podes hacer todos los calculos que si te pones a pensar la frecuencia es del orden de los millones, el periodo es de us asi que seguramente tenga que usar coma flotante, y eso termina en mas tiempo que la demora en si.
Tenes la funcion
delay_cycles (count)
En CSS pero por lo que veo es una funcion que acepta hasta 255 ciclos. no se que tan precisa será. Obviamente no podes crear una funcion delay con una llamada, sino que para que sea valido el delay, deberias ponerlo uno seguido de otro.