Aunque ausente en todos los manuales de referencia técnica y en todos los libros relacionados con la programación de PC, existe un método muy fácil y eficiente para temporizar, disponible en todos los ordenadores AT. Pese a no estar documentado, un programa muy usual como es el KEYB del MS-DOS (a partir de la versión 5.0 del sistema) lo utiliza sin importar el modelo de AT. Por ello, cabe suponer que seguramente los futuros equipos mantendrán la compatibilidad en este aspecto. Sucede que la salida del contador 1 del 8254, encargada del refresco de la memoria, controla de alguna manera desconocida (tal vez a través de un flip-flop) la generación de una onda cuadrada de unos 33 KHz que puede leerse a través del bit 4 del puerto 61h (no se trata de la salida OUT del contador 1: éste está programado en modo 2 y no genera precisamente una onda cuadrada). El contador 1 es programado por la BIOS en los PC con una cuenta 18, conmutando el nivel de la salida cada segundo 1193180/18 = 66287,78 veces. Para hacer un determinado retardo basta con contar las veces que el bit cambia de nivel. Para los más curiosos, decir que el bit 5 del puerto 61h es la salida OUT del contador 2 del 8254 (la línea OUT del contador 2 del 8253 de los PC/XT también puede consultarse a través del bit 5, pero del puerto 62h).
Este método es especialmente interesante en los programas
residentes que precisen retardos de precisión, para sonido u otras tareas,
tales como limitar la duración máxima de una comprobación en un bit de estado
a unos milisegundos o microsegundos (control de timeouts); la principal
ventaja es que no se modifica en absoluto la configuración de ningún chip que
pueda estar empleando el programa principal, empezando por el 8254. Además, no
requiere preparación previa alguna. En nuestro caso podemos utilizar este
método como una forma de generar por software la modulación
por anchura de pulso necesaria para el control de los servomotores.
La rutina pausa_asm
ilustra el procedimiento antedicho. El único inconveniente del método es la
alta frecuencia con que cambia el bit: esta misma rutina escrita en C podría no
ser suficientemente ágil para detectar todas las transiciones en las máquinas
AT más lentas a 6 MHz. A partir de 8 MHz sí puede ser factible, como
evidencian las pruebas realizadas, aunque hay que extremar las precauciones para
que el código compilado sea lo bastante rápido: utilizar las dos variables
registro que realmente soportan los compiladores y huir de la aritmética de 32
bits, como puede observarse en la función pausa()
del programa de ejemplo. Una mala codificación o el compilador podrían hacer
inservible el método incluso en una máquina a 16 ó 20 MHz (ya
prácticamente fuera de uso en estos momentos).
El 8253/4 es un chip
temporizador que puede ser empleado como reloj de tiempo real, contador de
sucesos, generador de ritmo programable, generador de onda cuadrada, etc. Este
integrado posee 3 contadores totalmente independientes, que pueden ser
programados de 6 formas diferentes.
Todos
los AT y PS/2 llevan
instalado un 8254 o algo
equivalente; los PC/XT
van equipados con un
8253, algo menos versátil;
los PS/2 más avanzados
tienen un temporizador
con un cuarto contador
ligado a la interrupción
no enmascarable. Todos
los contadores van
conectados a un reloj
que oscila a una
frecuencia de 1.193.180
ciclos por segundo (casi
1,2 Mhz). La dirección
base en el espacio de
E/S del ordenador
elegida por IBM cuando
diseñó el PC es la
40h. Por tanto, los tres
contadores son
accedidos,
respectivamente, a través
de los puertos 40h, 41h
y 42h; la palabra de
control se envía al
puerto 43h.
La señal GATE de los
contadores 0 y 1 está
siempre a 1; en el
contador 2 es
seleccionable el nivel
de la línea GATE a través
de bit 0 del puerto E/S
61h. La BIOS programa
por defecto el contador
0 en el modo 3
(generador de onda
cuadrada) y el contador
1 en el modo 2
(generador de ritmo); el
usuario normalmente
programa el contador 2
en el modo 2 ó 3.
La salida del contador 0
está conectada a IRQ 0
(ligado a la INT 8, que
a su vez invoca a INT
1Ch); este contador está
programado por defecto
con el valor cero
(equivalente a 65536),
por lo que la cadencia
de los pulsos es de
1.193.180/65.536 = 18,2
veces por segundo, valor
que determina la precisión
del reloj del sistema,
ciertamente demasiado
baja. Se puede modificar
el valor de recarga de
este contador en un
programa, llamando a la
vieja INT 8 cada 1/18,2
segundos para no alterar
el funcionamiento normal
del ordenador, si bien
no es conveniente
instalar programas
residentes que cambien
permanentemente esta
especificación: los
programas del usuario
esperan encontrarse el
temporizador a la
habitual y poco útil
frecuencia de 18,2
interrupciones/segundo.
La salida del
contador 1 controla el
refresco de memoria en
todas las máquinas, su
valor normal para el
divisor es 18; aumentándolo
se puede acelerar el
funcionamiento del
ordenador, con el riesgo
-eso sí- de un fallo en
la memoria, detectado
por los chips de paridad
-si los hay-, que
provoca generalmente el
bloqueo del equipo. De
todas maneras, en los
PC/XT se puede aumentar
entre 19 y 1000 sin
demasiados riesgos,
acelerándose en
ocasiones hasta casi un
10% la velocidad de
proceso del equipo. En
los AT la ganancia de
velocidad es mucho menor
y además este es un
punto demasiado sensible
que conviene no tocar
para no correr riesgos,
aunque se podría bajar
hasta un valor 2-17 para
ralentizar el sistema.
Sin embargo, no es
conveniente alterar esta
especificación porque,
como se verá más
adelante, hay un método
para realizar retardos
(empleado por la BIOS y
algunas aplicaciones)
que se vería afectado.
El contador 2 puede
estar conectado al
altavoz del ordenador
para producir sonido;
alternativamente puede
emplearse para
temporizar. Es el único
contador que queda
realmente libre para el
usuario, lo que suele
dar quebraderos de
cabeza a la hora de
producir sonido.
Los
contadores 0 y 1,
especialmente este último,
ya están ocupados por
el sistema; en la práctica
el único disponible es
el 2. Este contador ha
sido conectado con el
doble propósito de
temporizar y de generar
sonido. Para emplearlo
en las temporizaciones,
es preciso habilitar la
puerta GATE activando el
bit 0 del puerto 61h;
también hay que
asegurarse de que la
salida del contador no
está conectada al
altavoz (a menos que se
desee música mientras
se cronometra) poniendo
a 0 el bit 1 del mismo
puerto (61h):
IN AL,61h AND AL,11111101b ; borrar bit 1 (conexión contador 2 con el altavoz) OR AL,00000001b ; activar bit 0 (línea GATE del contador 2) JMP SHORT $+2 ; estado de espera para E/S OUT 61h,AL