Anda di halaman 1dari 9

Dto.

Tcnico EduDevices

www.edudevices.com.ar

COMENTARIO TECNICO

Generacin de retardos en la familia HC908


Por el Ing. Gabriel Dubatti www.ingdubatti.com.ar

Introduccin
Una tarea muy frecuente al programar microcontroladores es la generacin de retardos, en general, para controlar hardware perifrico o para sealar distintos tipos de eventos mediante luces o sonidos. En algunos casos puede utilizarse para generar estos tiempos el mdulo de timer incorporado en el microcontrolador, pero para muchos otros hay que buscar otras soluciones debido a los inconvenientes que se vern a continuacin. Se muestra, a modo de ejemplo, como realizar una puerta serie por software en el procesador 68HC908JL3.

Generacin de tiempos con el mdulo de TIMER


El mdulo de TIMER suele ser utilizado mediante interrupciones de la siguiente forma: Se elige un valor de prescaler (que determina el tiempo de avance del registro de 16 bits en funcin de la frecuencia de bus). Cada cuenta en el TIMER es un "tick". Modo autorecargable: Se le da un valor de mdulo al TIMER para que interrumpa por "Overflow" indicando la cantidad de "ticks" deseados (esto genera un aviso peridico). Modo libre: Se indica en uno de los canales del TIMER dentro de cuantos "ticks" queremos que Interrumpa sumando al valor actual del TIMER la cantidad de "ticks" deseados y recalculndolo manualmente en cada interrupcin.

El inconveniente de este mtodo radica en lo que se denomina latencia de las interrupciones. O sea la demora que se produce desde el evento de tiempo deseado y el momento en que realmente se ejecuta el cdigo. Esta latencia tiene la desventaja de no ser predecible ya que en la ejecucin de una interrupcin intervienen los siguientes factores: (si fuera predecible bastara con restar al tiempo deseado al de la latencia) Esperar a que se destapen las interrupciones (bit I del registro CC): Si estamos ejecutando una seccin de cdigo que tiene las interrupciones deshabilitadas, esta esperar hasta que se habiliten para poder ejecutar. Este tiempo puede ser muy difcil de estimar si estamos trabajando con varias interrupciones y no habilitamos la entrada de una interrupcin "sobre" otra. Esperar a que termine de ejecutar la instruccin en curso: Las instrucciones se procesan en forma "atmica" (o sea en forma indivisible) y por lo tanto para procesar una interrupcin debe esperarse a que esta se complete. La cantidad de ciclos que demora una instruccin en la familia HC908 est comprendida entre 1 y 9 ciclos de la frecuencia de bus.

Ing. Daniel Di Lella: - Dedicated Field Application Engineer

e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices Tiempo de salvado de registros

www.edudevices.com.ar

Cuando se logran las condiciones anteriores, el microcontrolador debe salvar el "contexto" actual de trabajo. Para ello, inserta en el stack los registros: PC,X,A,CC con una demora adicional de 9 ciclos (suponiendo que demora lo mismo que la instruccin SWI). Este tiempo al ser fijo, puede ser restado del tiempo deseado para corregirlo. La latencia hace que el mtodo de trabajo por interrupciones se utilice para generar tiempos relativamente grandes en ciclos de bus, de modo que el error obtenido sea despreciable o promediado (por ejemplo: si programamos el TIMER para generar 10 interrupciones por segundo con el modo autorecargable, a pesar de la latencia, obtendremos 10 interrupciones por segundo cada una con una pequea demora distinta, pero "no acumulativa" ). Para corregir estos efectos puede usarse el TIMER sin interrupciones. Esto es, leyndolo y esperando a que llegue al valor deseado. En este caso hay que tener cuidado con la comparacin, ya que si se hace "por igual" hay que estar seguro de que el tiempo que se demora entre lectura y lectura no haga que se pase el valor deseado "de largo" sin verlo y si se compara por "mayor o igual" hay que tener cuidado con la "circularidad" del registro (o sea, luego de $FFFF se vuelve a $0000 y lo que era mayor ahora es menor!). Cuando los tiempos a generar son muy chicos (pocos ciclos) hay que tener en cuenta la incertidumbre del prescaler del TIMER, ya que no sabemos en que valor se encuentra este divisor al iniciar el retardo. Si deseamos generar retardos de distintas duraciones, deberemos buscar una unidad de interrupcin que sea comn a todos los retardos y contar interrupciones para generar los eventos ms largos. Por ejemplo: si necesitamos retardos de 15 mseg, 50 mseg y 100 mseg, podemos usar 5 msegs de unidad y contar 3, 10 y 20 interrupciones respectivamente o bien trabajar el timer en modo libre y programar la demora en cada caso.

Generacin de retardos por demora de las instrucciones


Dado que cada instruccin del procesador requiere una determinada cantidad de ciclos de bus para ser completada, surge la posibilidad de utilizar este "efecto secundario" para generar retardos de duracin controlada. Y dado que las instrucciones demoran de 1 a 9 ciclos, pueden obtenerse retardos muy cortos o largos y muy precisos. Es de notar que para que el retardo sea de la duracin deseada: el cdigo debe ejecutarse con las interrupciones deshabilitadas ya que si se presenta una interrupcin, al tiempo transcurrido se le deber sumar todo el tiempo que tardo la interrupcin en ejecutar. Si lo que se desea es un retardo de "por lo menos" la demora dada, por ejemplo para generar un pulso de "strobe", no hay problema en tener las interrupciones habilitadas. Este mtodo tiene el atractivo de poder realizar alguna funcin til mientras se est esperando (como borrar memoria, precargar registros, etc.). La instruccin de demora por excelencia es "NOP" (no operacin) que no hace nada salvo demorar 1 ciclo la ejecucin del programa. Para generar delay ms largos podemos colocar varias instrucciones NOP seguidas, pero consultando las hojas de datos del procesador surgen variantes ms interesantes:

Ing. Daniel Di Lella: - Dedicated Field Application Engineer

e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices

www.edudevices.com.ar

Ciclos 1 2 2 2 2 2 3 3 4 5 5 5 6 7 7 1 1 1 1 1 2 1 2 2 1 3 3 2 1 3

Bytes NOP SEI CLI DAA TSX NOP NOP NSA BRN $ PSHA PULA MUL PSHA PULA NOP

Cdigo

Comentarios Fuerza I=1 Fuerza I=0 Invalida registro A Invalida registros H y X Intercambia nibbles del registro A Utiliza y libera un byte del stack Invalida registros A, X y CC (bits H y C) Utiliza y libera un byte del stack Invalida registro CC (bits V, N y Z) Usar cualquier direccin en pgina 0. Invalida registros A, X y H Utiliza y libera un byte del stack Utiliza y libera dos bytes del stack Se puede utilizar un RTS existente y ahorrar un byte. Intercambia nibbles del registro A Utiliza y libera dos bytes del stack Se puede utilizar un RTS existente y ahorrar un byte. Utiliza y libera 5 bytes del stack Se puede utilizar un RTS existente y ahorrar un byte.

MOV $80,$80 NSA NSA DIV PSHA NSA PULA BSR rutina .. rutina: RTS NSA NSA NSA JSR rutina .. rutina: RTS SWI ... vector_swi: RTI

3 (o 2)

4 (o 3)

16

2 (o 1)

En la tabla se aclara que efecto colateral tiene realizar la demora con las instrucciones indicadas. Por ejemplo: la instruccin "NSA" demora 3 ciclos pero intercambia los nibbles del registro A, por lo que tambin se indica en la tabla que usando la instruccin "BRN xx" (branch never) se obtiene una demora igual pero sin modificar ningn registro. Tambin pueden ponerse 3 "NOP"s pero a expensas de 1 byte extra y ningn beneficio.

Ing. Daniel Di Lella: - Dedicated Field Application Engineer

e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices

www.edudevices.com.ar

Si las condiciones no nos permiten usar un tem de la tabla, siempre podemos generar una demora concatenando 2 o ms tems de la tabla que s cumplan con las condiciones deseadas. Cuando las demoras a generar son de muchos ciclos es mucho ms compacto obtener dicha demora por iteracin. As surgen los siguientes ejemplos:

Ciclos 769 3

Bytes CLRA DBNZA $

Cdigo

5,8,11..770

LDA #CTE DBNZA $ LDA #CTE DBNZA $ DBNZA $ LDA #CTE loop: NOP DBNZA loop

773,776..1538

6,10,14..1026

8,14,20..1538

LDX #CTE loop: NSA DBNZX loop LDA #CTE loop: NSA NSA DBNZA loop

11,20,29..2306

Comentarios Fuerza registro A= 0 Invalida registro CC (bits V=0, N=0 y Z=1) Fuerza registro A= 0. Invalida registro CC (V, N y Z) delay= CTE * 3 + 2 (CTE=1..256) 256 => 0 (usar CLRA: un byte menos, 769 ciclos) Fuerza registro A= 0. Invalida registro CC (V, N y Z) delay= CTE * 3 + 770 (CTE=1..256) 256 => 0 (usar CLRA: un byte menos, 1537 ciclos) Fuerza registro A= 0. Invalida registro CC (V, N y Z) delay= CTE * 4 + 2 (CTE=1..256) 256 => 0 (usar CLRA: un byte menos, 1025 ciclos) Fuerza registro X= 0. Invalida registro CC (V, N y Z) delay= CTE * 6 + 2 (CTE=1..256) 256 => 0 (usar CLRX: un byte menos, 1537 ciclos) Si CTE es impar : intercambia nibbles del registro A; si es par : mantiene A. Fuerza registro A= 0. Invalida registro CC (V, N y Z) delay= CTE * 9 + 2 (CTE=1..256) 256 => 0 (usar CLRA: un byte menos, 2305 ciclos)

La ventaja de los mtodos de demora por iteracin es que cambiando las instrucciones que estn dentro del lazo, podemos cambiar la demora de cada iteracin y por lo tanto el multiplicador en la frmula de "delay" (demora total).

Ing. Daniel Di Lella: - Dedicated Field Application Engineer

e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices Para demoras an mayores se pueden utilizar los siguientes ejemplos de cdigo:

www.edudevices.com.ar

Ciclos 7,10..197377 8

Bytes

12..589827

7,16..590593

10

14..150995714

13

Cdigo LDA #CTE1 LDX #CTE2 loop: DBNZX $ DBNZA loop LDHX #CTE loop: AIX #-1 STHX dirmem BNE loop LDA #CTE1 LDX #CTE2 loop: NSA NSA DBNZX loop DBNZA loop LDA #CTE1 LDHX #CTE2 loop: AIX #-1 STHX dirmem BNE loop DBNZA loop

Comentarios Fuerza registros A= 0, X= 0. Invalida registro CC delay= 4 + CTE2 * 3 + (CTE1-1) * (3*256+3) (CTE1/2=1..256) 256 => 0 (usar CLRA/X: uno o dos bytes menos) Fuerza registros H= 0, X= 0. Invalida registro CC delay= 3 + CTE * 9 (CTE=1..65536) "dirmem" debe estar en pgina 0 (puede ser el registro de canal de un timer que no se use) Fuerza registros A= 0, X= 0. Invalida registro CC delay= 4 + CTE2 * 9 + (CTE1-1) * (9*256+3) (CTE1/2=1..256) 256 => 0 (usar CLRA/X: uno o dos bytes menos) Fuerza registros A= 0, H= 0, X= 0. Invalida CC. delay= 5 + CTE2 * 9 + (CTE1-1) * (9*65536+3) (CTE1=1..256, CTE2=1..65536) "dirmem" debe estar en pgina 0 (puede ser el registro de canal de un timer que no se use)

Dado que no existe una instruccin "TSTHX" para ver si el registro HX, lleg a 0, en el cdigo mostrado se graba el valor de los registros H y X en una direccin de memoria cualquiera para que actualice el registro de condicin (en particular el bit Z) y determinar si lleg a 0. Por supuesto estas no son las nicas formas de generar demoras, sino que son algunas que utilizan muy pocos bytes de cdigo (bien siempre escaso!). Desde ya, si se le ocurre alguna forma ms compacta de generar un retardo, no dude en mandarme un e-mail para agregarla a la lista.

Ejemplos
Supongamos que tenemos que generar un retardo de 1 milisegundo con una frecuencia de bus de 8 Mhz: 1. Cada ciclo de bus corresponde a: 1 / 8 Mhz = 0.125 microsegundos. 2. Por lo tanto la demora es de: 1 milisegundo / 0.125 microsegundos = 8000 ciclos de bus. 3. Elegimos de la tabla el menor cdigo para este delay: LDA #CTE1 LDX #CTE2 loop: DBNZX $ DBNZA loop

Ing. Daniel Di Lella: - Dedicated Field Application Engineer

e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices ;o en formato MacAsm: lda #CTE1 ldx #CTE2 do{ do{ }while( --x != 0 ) }while( --a != 0 )

www.edudevices.com.ar

4. De la formula: delay= 4 + CTE2 * 3 + (CTE1-1) * (3*256+3) (CTE1/2=1..256) despejamos el valor de las constantes: 5. CTE1= ((8000-4)/771)+1= 11.37 => CTE1= 11 CTE2= (8000-4-10*771)/3=95.33 => CTE2= 95 Delay= 4+3*95+10*771= 7999 6. En general un error de 1 en 8000 puede ser ms que tolerable, pero para lograr el delay exacto hay que agregar un "NOP" al final o aumentar CTE2 a 96 y obtener un delay de 8002 ciclos si el tiempo pedido es el mnimo deseado. Otros ejemplos los puede encontrar en las rutinas de grabacin y borrado de la FLASH para el GP32 en particular la rutina "DoDelayYStaFLCR" que realiza un delay de 3*X ciclos, setea el registro FLCR y produce un delay extra: cargando los registros A y X y con un RTS, generando el "delay TRCV" (de 1 useg.= 8 ciclos) al salir de la rutina y precargando registros para usar en otras partes del cdigo.

Puerta serie por software


A modo de ejemplo se detalla a continuacin las rutinas para realizar una puerta serie por software a 9600 bauds para frecuencias de bus de 8MHz y 4MHz en un procesador 68HC908JL3 (9600 N 8 1 = 8 bits, sin paridad y con 1 bit de stop). Para probar el siguiente cdigo deber conectarse un driver de RS232 (tipo MAX232 o similar) de la siguiente forma: PORTD.7 a driver TX (salida del micro) PORTD.6 a driver RX (entrada al micro)

Para seleccionar la frecuencia de bus se utiliza el switch BUS8MEGA (comentar la lnea que no corresponda) de modo que el cdigo funcione para ambas frecuencias de bus (si utiliza otra frecuencia, deber ajustar las constantes de los retardos). El formato serie RS232 utilizado incluye los siguientes bits a generar (TX) o leer (RX):

Ing. Daniel Di Lella: - Dedicated Field Application Engineer

e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices

www.edudevices.com.ar

Donde cada uno de los bits dura: 1 / 9600 bauds = 104.16 microsegundos que a 8MHz son 833.33 ciclos y a 4MHz son 416.66 ciclos. Transmisin: la rutina itera 10 veces para enviar los 8 bits, el "start" y el "stop". El bit de "start" es generado forzando TX a 0 antes de entrar al loop. El bit de "stop" es generado con la instruccin "sec" para que luego del 8vo bit salga el stop en "1". Las instrucciones que se ejecutan antes de entrar al lazo (psha, pshx, ldx) demoran 6 ciclos al igual que las que hay entre que se setea el bit a transmitir y se vuelve a iterar (bra o brn y dbnzx), lo cual asegura que los anchos de todos los bits sean iguales. Estos 6 ciclos ms los de las operaciones del lazo (sin contar el delay) suman 21 ciclos. Por lo tanto los delays de ajustan para que demoren 812 o 316 ciclos y obtener as los 833 o 417 ciclos totales por bit. Recepcin: la rutina espera "eternamente" a que baje RX (comienzo del bit de "start") y realiza un delay inicial de 1 bit y medio, esto es todo el bit de "start" y medio "D0", de forma de leer los bits en su centro para obtener una mayor inmunidad a las variaciones de cristal del transmisor y del procesador. La rutina luego lee los 8 bits e "ignora el stop" (esto es para utilizar ese tiempo para procesar el caracter recibido, ya que inmediatamente luego del "stop" puede venir otro "start"). La rutina presentada no es ptima desde el punto de vista del filtrado de las lecturas (slo realiza una lectura por bit). No le incorpor filtrado mediante varias lecturas para mantener el cdigo lo ms claro posible pero puede agregarlo dividiendo el tiempo de iteracin, por ejemplo, a la dcima parte, realizando 10 lecturas y determinando si es "1" o "0" segn la mayor cantidad de lecturas obtenidas. ;$SET BUS8MEGA $SETNOT BUS8MEGA ;BUS de 8 MHZ requiere cristal de 32MHZ ;BUS de 4 MHZ requiere cristal de 16MHZ

;============================================================================== ; TXByte: ; Transmite un byte por la puerta serie simulada a 9600 (como caracter) ; REQUIERE BUS de 8 MHZ. (delay= 833 ciclos x bit) ; o BUS de 4 MHZ. (delay= 416-417 ciclos x bit) ; ; Requiere: ; A= byte a enviar. (MANTIENE A,X,H) ;============================================================================== TxByte: sei ;TAPA INTS (para no arruinar tiempos) sta COPCTL ;reset COP bclr 7,PORTD ;TX=0 (START) psha ;mantiene A y X pshx ldx #!10 ;X=numero de bits a enviar do{ pshx $IF BUS8MEGA ldx #!203 ;delay= 812 + 21= 833 do{ nop }while( --x != 0 ) ;DELAY= X * 4 ciclos Ing. Daniel Di Lella: - Dedicated Field Application Engineer e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices $ELSEIF ldx #!132 do{ }while( --x != 0 ) $ENDIF pulx sec rora if( cy == 1 ){ bset 7,PORTD }else{ bclr 7,PORTD brn $ } }while( --x != 0 ) pulx pula cli sta COPCTL rts ;delay= 396 + 21= 417 ;DELAY= X * 3 ciclos

www.edudevices.com.ar

;CY=1 (STOP) ;envia bits 0,1,2... al carry ;hace TX= CY ;TX=1 ;TX=0 ;delay de 3 ciclos (igual al branch del else)

;DESTAPA INTS ;reset COP

;============================================================================== ; RXByte: ; Espera y RECIBE un byte por la puerta serie. ; Espera INFINITA. ; ; Requiere: ; OUT: A= byte recibido. (MANTIENE H,X) ;============================================================================== RXByte: pshx ;salva X sei ;TAPA INTS (para medir los bits) do{ sta COPCTL ;reset COP }while( PORTD.6 == 1 ) ;espera el START $IF BUS8MEGA ldx #!249 ;espera tiempo de 1+1/2 bit= 1251 ciclos do{ sei ;delay de 2 ciclos }while( --x != 0 ) $ELSEIF ldx #!206 ;espera tiempo de 1+1/2 bit= 625 ciclos do{ }while( --x != 0 ) $ENDIF lda #$80 ;detecta RX completa (8bits) while(1){ if( PORTD.6 == 0 ){ ;CY=DATA BIT } rora Ing. Daniel Di Lella: - Dedicated Field Application Engineer e-mail: dilella@arnet.com.ar

Dto. Tcnico EduDevices if( cy == 1 ){ cli pulx sta COPCTL rts } ;ya leyo los 8 (ignora el STOP) ;DESTAPA INTS ;mantiene X ;reset COP

www.edudevices.com.ar

$IF BUS8MEGA ldx #!205 ;espera tiempo de 1 bit= 834 ciclos do{ nop }while( --x != 0 ) ;205x4= 820 $ELSEIF ldx #!134 ;espera tiempo de 1 bit= 416 ciclos do{ }while( --x != 0 ) ;134x3= 402 $ENDIF } ;leer otro bit Puede descargar el ejemplo de la puerta serie para HC908JL3 que incluye el uso de la memoria FLASH para grabarla de a 1 byte por vez. El archivo ZIP tiene el cdigo en formato MacAsm (archivo MAS) y ya preprocesado (archivo ASM) al igual que todos los programas necesarios para usar el utilitario. El cdigo de ejemplo enva por la puerta serie: "Hola mundo!", borra una pgina de FLASH (64 bytes), graba el string "HOLA" en la FLASH y transmite lo grabado (debera ser: "HOLA"), luego se pone en modo "eco" (repite todo lo que recibe).

Conclusin
En el presente artculo se han visto distintas formas de generar retardos mediante instrucciones. La lista presentada est lejos de ser exhaustiva ya que cualquier cdigo realiza una demora al ejecutarse y dependiendo de la aplicacin particular puede que un mtodo sea mejor que otro. Por ejemplo en la nota de aplicacin AN1831 de Freescale se puede observar el cdigo de la ROM de los procesadores HC908 modelos GR8, KX8, JL3, JK3 y JB8 que para obtener los delays de grabacin y borrado de la FLASH ajustados con una nica constante a la frecuencia de bus, todos los delay se generan en base a la rutina "DELNUS" (que produce un delay de X * 12 microseg), lo cual requiere ms cdigo que ajustar las rutinas para una frecuencia de bus en particular, pero es ms flexible (opcin correcta para una ROM). Para verificar que los ciclos de las instrucciones corresponden con lo calculado, conviene activar la opcin "ver cuenta de ciclos" en el ensamblador para que genere un archivo de listado como el que se ve a continuacin (con la opcin "C" en la lnea de comandos de "CASM08Z.EXE" o marcando en WIN IDE: "Show Cycles in Listing" dentro de "Setup Environment..") : .... EC58 [04] 1F03 201 bclr 7,PORTD ;TX=0 EC5A [03] 21FE 202 brn $ ;delay de 3

Ing. Daniel Di Lella: - Dedicated Field Application Engineer

e-mail: dilella@arnet.com.ar

Anda mungkin juga menyukai