Subrutinas de Tiempo

Salvador Macías Hernández

Página hecha el Lunes 01 de Mayo del 2006

 

 

INTRODUCCIÓN

 

A veces es necesario que el microprocesador espere cierto intervalo de tiempo, para realizar acciones. Ya sea que requiramos que nos prenda y apague un led cada dos segundos, o bien hagamos un pequeño semáforo, o estemos abriendo una válvula durante 15 minutos para regar el pasto, etc. Al finalizar el estudio podrás utilizar el Generador de Subrtonas de TIempo

 

 

DE LA FAMILIA MCS51 DE INTEL

 

Recordemos que en la familia de microcontroladores Mcs51 de Intel. El ciclo de Máquina está dado por 12 veces el ciclo de reloj.

 

 Por ejemplo: Si el cristal de cuarzo que se está utilizando es de 12Mhz, el ciclo de máquina será de 1mS; Si el cristal ahora es de 4Mhz, el ciclo de máquina será de 3mS.


Valor del Cristal de Cuarzo
Periódo de Oscilación del Cuarzo
Periódo del Ciclo de Máquina
1 Mhz
1 µS
12 µS
2Mhz
0.5 µS  6 µS
4 Mhz
0.25 µS 3 µS
6 Mhz
0.167 µS 2 µS
10 Mhz
0.1 µS 1.2 µS
11.0592 Mhz
0.09 µS 1.085 µS
12 MHz
0.083 µS 1 µS



 

Hay que tener en cuenta, que cada instrucción que ejecuta el microcontrolador, le lleva cierto tiempo, o ciertos ciclos de máquina. Generalmente las instrucciones utilizan de uno a dos ciclos de máquina, pero hay instrucciones que consumen más ciclos de reloj. Para saber cuantos ciclos de reloj (periódos de oscilador) consume  cada instrucción, debes consultar el documento MCS-51 Programmer's Guide and Instruction Set. Así por ejemplo la instrucción NOP, consume un ciclo de máquina o 12 ciclos de reloj. A continuación vemos una tabla con las instrucciónes más utilizadas para hacer subrutinas de tiempo:

 

Instrucción Descripción Ciclos de Reloj Ciclos de Máquina
ACALL Llamado a Subrutina Absoluto 24 2
DJNZ Rn, REL Decrementa y salta si no es cero 24 2
MOV Rn, inmediate Mueve un dato al registro Rn 12 1
NOP No Operes 12 1

 

 

SUBRUTINAS DE TIEMPO SIMPLES

 

Entonces, por ejemplo:

El siguiente segmento de programa consume 3 Ciclos de Máquina, o lo que es lo mismo 36 ciclos de reloj. Si suponemos que el cristal es de 12 Mhz. El segmento de este programa consumiría 3*(12/12Mhz) = 3 micro segundos.

 

INSTRUCCIÓN Ciclos de Máquina (1mS) consumidos por instrucción Ciclos de reloj (1/12 mS) consumidos por instrucción
COMIENZA: 0 0
     NOP 1 12
     NOP 1 12
     NOP 1 12
FIN: 0 0

TOTAL:

3 Cic.Maq = 3mS 36 Cic.Rel. = 3mS

 

 

Este otro segmento de programa consume 10 Ciclos de Máquina, o lo que es lo mismo 120 ciclos de reloj. Si suponemos que el cristal es de 12 Mhz. El segmento de este programa consumiría 10*(12/12Mhz) = 10 micro segundos.

 

INSTRUCCIÓN Ciclos de Máquina (1mS) consumidos por instrucción Ciclos de reloj (1/12 mS) consumidos por instrucción
COMIENZA: 0 0
     NOP 1 12
     NOP 1 12
     NOP 1 12
     NOP 1 12
     NOP 1 12
     NOP 1 12
     NOP 1 12
     NOP 1 12
     NOP 1 12
     NOP 1 12
FIN: 0 0

TOTAL:

10 Cic.Maq = 10mS

120 Cic.Rel. = 10mS

 

SUBRUTINAS DE TIEMPO SIMPLES CON BUCLE SIMPLE

Ahora bien, que pasaría si quisiéramos hacer una subrutina que consumiera 50mS, necesitaríamos poner 50 NOP's. O bien si en vez de 50mS requiriéramos 1mS, entonces necesitaríamos poner 1000 NOP's. Lo cual es totalmente inviable. Por eso aplicamos bucles para repetir unos cuantos NOP's un determinado número de veces.

 

Analicemos el siguiente programa:

   

INSTRUCCIÓN

Ciclos de Máquina (1mS) consumidos por instrucción Ciclos de reloj (1/12 mS) consumidos por instrucción Veces que se ejecuta la instrucción debido al bucle Total de Ciclos y tiempo por instrucción
COMIENZA: 0 0 1 0
Mov R7, #05 1 12 1 1CM = 1mS
     PrimerCiclo: 0 0 1 0
          NOP 1 12 5 5*1CM = 5mS
          NOP 1 12 5 5*1CM = 5mS
          NOP 1 12 5 5*1CM = 5mS
     djnz R7, PrimerCiclo 2 24 5 5*2CM = 10mS
FIN: 0 0 1 0

TOTAL:

26CM=26mS

Diagrama de Flujo del programa anterior

 

El programa comienza asignando el valor de 5 decimal al registro siete. Enseguida deja pasar tres ciclos de máquina (por los tres siguientes NOP) y después decrementa el registro siete (ya no va a valer 5, ahora va a valer 4), y compara si el nuevo valor de R7 (4 decimal) es igual a cero, si es igual a cero salta a la siguiente línea (fin de nuestro programita) y si no es cero, salta a la etiqueta PrimerCiclo. En este caso como el valor de R7 es 4 y no es igual a cero, el microcontrolador saltará a la etiqueta PrimerCiclo. Y una vez allí volverá a dejar pasar 3 ciclos de máquina (por los 3 NOP) y volverá a decrementar y a comparar, y como tampoco va a ser cero (por que R7 valdría 3), volverá a saltar a la etiqueta PrimerCiclo. Todo este proceso se llevará a cabo 5 veces, que es cuando R7 valdrá cero. Y para fines de nuestra subrutina de tiempo, esto nos significa que vamos a multiplicar 5 veces el tiempo de las instrucciones que se encuentran dentro del ciclo. 

 

Y si cambiásemos la primera instrucción, para que en vez de que cargue 5 en R7, cargue 100, entonces estaríamos multiplicando todo lo que hay dentro del ciclo por 100, lo que nos consumiría 501 ciclos de máquina, o 501 ms.

 

 

INSTRUCCIÓN

Ciclos de Máquina (1mS) consumidos por instrucción Ciclos de reloj (1/12 mS) consumidos por instrucción Veces que se ejecuta la instrucción debido al bucle Total de Ciclos y tiempo por instrucción
COMIENZA: 0 0 1 0
Mov R7, #100 1 12 1 1CM = 1mS
     PrimerCiclo: 0 0 1 0
          NOP 1 12 100 100*1CM = 100mS
          NOP 1 12 100 100*1CM = 100mS
          NOP 1 12 100 100*1CM = 100mS
     djnz R7, PrimerCiclo 2 24 100 100*2CM = 200mS
FIN: 0 0 1 0

TOTAL:

501CM=501mS

 

 

 

 

ESTRUCTURA DE SUBRUTINAS DE TIEMPO SIMPLES CON BUCLE SIMPLE

 

La estructura de las subrutinas de tiempo simple con bucle simple es la que se muestra en el siguiente diagrama:

 

 

Del programa anterior vamos a indicar el con color verde la instrucción de Inicialización del Contador, y con color azul las instrucciones del Bucle que consume Tiempo.

 

INSTRUCCIÓN

Ciclos de Máquina (1mS) consumidos por instrucción Ciclos de reloj (1/12 mS) consumidos por instrucción Veces que se ejecuta la instrucción debido al bucle Total de Ciclos y tiempo por instrucción
COMIENZA: 0 0 1 0
Mov R7, #100 1 12 1 1CM = 1mS
     PrimerCiclo: 0 0 1 0
          NOP 1 12 100 100*1CM = 100mS
          NOP 1 12 100 100*1CM = 100mS
          NOP 1 12 100 100*1CM = 100mS
     djnz R7, PrimerCiclo 2 24 100 100*2CM = 200mS
FIN: 0 0 1 0

TOTAL:

501CM=501mS

 

Como se puede apreciar, la parte medular de la subrutina es la del Bucle puesto que es la parte que más consume tiempo. Para el caso del anterior programa se muestra una tabla con los tiempos que aporta cada parte de la subrutina, expresado en microsegundos y también se indica el porcentaje que aporta.

 


Tiempo Porcentaje
Inic.Cont 1 0.2%
Bucle 500 99.8%
Total 501 100%

 

 

DISEÑO DE SUBRUTINAS DE TIEMPO SIMPLES CON BUCLE SIMPLE

 

Para hacer una subrutina que consuma un tiempo determinado, hay que realizar los siguientes cálculos:

 

 

 

   Dónde:

               CM= Ciclo de Máquina y está dando en microsegundos

               Frec.Osc= Frecuencia del Oscilador (cristal de cuarzo) y está dado en Mega Hertz

 

 

 

 

   Dónde:

               R7= Es el valor del Registro Siete, éste valor tiene que ser entero

               TiempoEsperado= Es el tiempo que debe de consumir nuestra subrutina, en microsegundos

               NumNops= Es el número de instrucciones NOP que tendrá el bucle

 

 

 

 

   Dónde:

               TiempoReal= Es el tiempo que la subrutina va a consumir en la realidad

               TiempoEsperado= Es el tiempo que debe de consumir nuestra subrutina, en microsegundos

               NumNops= Es el número de instrucciones NOP que tendrá el bucle

 

 


 

Ejemplo:

      Se desea diseñar una subrutina simple de bucle simple que consuma 100 microsegundos, en un microcontrolador de la familia MCS51 y que tiene un cuarzo de 12Mhz

 

Frec.Osc=12;                       TiempoEsperado=100

 

Usando las Fórmulas anteriores se deduce que:

CM= 1

 

 

Si elegimos arbitrariamente el valor de NumNops igual a 1, tenemos:

 

R7 = 33

 

Entonces el programa quedaría así:

 

INSTRUCCIÓN

Ciclos de Máquina (1mS) consumidos por instrucción Ciclos de reloj (1/12 mS) consumidos por instrucción Veces que se ejecuta la instrucción debido al bucle Total de Ciclos y tiempo por instrucción
COMIENZA: 0 0 1 0
Mov R7, #33 1 12 1 1CM = 1mS
     PrimerCiclo: 0 0 1 0
          NOP 1 12 33 33*1CM = 33mS
     djnz R7, PrimerCiclo 2 24 33 33*2CM = 66mS
FIN: 0 0 1 0

TOTAL:

100CM=100mS

 

 

Hay que fijarnos que R7 siempre debe de ser entero, por eso se aplica la función Round, que lo que hace es redondear el resultado de la división al número entero más próximo, es decir: si la división te da 32.8, hay que redondearlo a 33 y si te da 32.2 hay que redondearlo a 32. Al hacer ese redondeo, generamos un error, que es la diferencia entre el TiempoReal y el TiempoEsperado

 

Error = TiempoReal - TiempoEsperado

 

Para este caso en particular tenemos que el error es cero.

 

TiempoReal=R7(2+NumNops)+1= 33 (2 + 1) +1= 100

 

Error= 100 - 100 = 0

 

Cuando nuestro error es cero, como en este caso, se dice que tenemos una solución ideal. Cuando el error es el mínimo, se dice que tenemos la solución óptima. Para conseguir la solución ideal o la óptima, es necesario hacer estos cálculos con diferentes valores para ver cual es el que requerimos. Para hacer más simple este proceso, se hizo una hoja de calculo en Microsoft Excell  2003: SubTimeBucleSimple.xls en el cual solo tienes que ingresar el valor del cristal (Frecuencia del Oscilador) y el Tiempo Requerido, y automáticamente te saldrá una tabla con los valores de Número de NOP's y el Valor de R7, así como la Gráfica de Valores y de Error

 

Imagen de la Hoja de Excel SubTimeBucleSimple.xls

 

Gráfica de R7 contra el Número de NOP que debe tener el bucle

 

Grafica del Error contra el Número de NOP que deberá tener el bucle

 


 

 

SUBRUTINAS DE TIEMPO COMPLEJA CON BUCLE SIMPLE

 

      Como podemos ver las subrutinas de tiempo pueden tener un error implícito, una manera de reducir ese error es insertar un módulo de ajuste, que es una serie de NOP al final de la subrutina simple (formando una subrutina compleja), de forma tal que consuman el error. La estructura de la subrutina queda:

 

 

Para este tipo de subrutina, el valor de R7 se define como:

 

 

Donde la función Trunc, es la función truncar que no redondea el cociente, sino que únicamente toma el valor entero del mismo. Es decir, si es el cociente es: 33.89 la función resulta en: 33, si el cociente es: 33.2 la función resulta en: 33.

 

Para calcular el número de NOP's que integrarán el Módulo de Ajuste de Error se utiliza la siguiente fórmula:

 

 

Para calcular el Tiempo Real que consumirá esta subrutina, hay que usar la siguiente identidad:

 

 

 


 

Por ejemplo:

  Si deseamos hacer una subrutina de tiempo de 150uS y con 5 NOP's, el valor de R7 sería:

 

 

R7 = 21

El número de NOP's que integrarán el módulo de ajuste es:

 

 

ModAjuste = 150-21(2+5)+1= 2

 

Entonces la subrutina quedaría de la siguiente manera:

 

INSTRUCCIÓN

Ciclos de Máquina (1mS) consumidos por instrucción Ciclos de reloj (1/12 mS) consumidos por instrucción Veces que se ejecuta la instrucción debido al bucle Total de Ciclos y tiempo por instrucción
COMIENZA: 0 0 1 0
Mov R7, #21 1 12 1 1CM = 1mS
     PrimerCiclo: 0 0 1 0
          NOP 1 12 21 21*1CM = 21mS
          NOP 1 12 21 21*1CM = 21mS
          NOP 1 12 21 21*1CM = 21mS
          NOP 1 12 21 21*1CM = 21mS
          NOP 1 12 21 21*1CM = 21mS
     djnz R7, PrimerCiclo 2 24 100 21*2CM = 42mS
          NOP 1 12 1 1*1CM = 1mS
          NOP 1 12 1 1*1CM = 1mS
FIN: 0 0 1 0

TOTAL:

150CM=150mS

 

El tiempo real que consume esta subrutina sería:

 

TiempoReal=R7(2+NumNops)+ModAjuste+1= 150 CM

 

Como podemos ver, el tiempo real y el tiempo esperado es el mismo, ya que se ajustó con el último módulo, por lo que ya no es necesario calcular el error. Al igual que la subrutina anterior, se elaboró una hoja de Excel para obtener los valores mucho más rápidos: SubTimeComplBucleSimple.xls

 

Ahora bien una desventaja del método que acabamos de aprender es que tiene un máximo de tiempo, que es cuando R7 vale 255.No podremos hacer una subrutina de tiempo que dure una hora con esta metodología. Es por esto que surgen las subrutinas de bucle anidado.

 

 

SUBRUTINAS DE TIEMPO COMPLEJA CON BUCLE ANIDADO

 

Las subrutinas de bucle anidado, lo que hace es meter un bucle dentro de otro,  en el diagrama de flujo que se muestra a continuación, tenemos tres bucles anidados, estos tres bucles anidados lo que hacen es multiplicar el tiempo que consume el bucle interior (R7). Por lo que con esta estrategia podemos hacer una subrutina de tiempo tan grande como deseemos

 

 



Generador de Subrutinas de tiempo

 

 

Bibliografía

[1]     Intel;  MCS-51 Programmer's Guide and Instruction Set