• No results found

2.1 Defining workgroups

2.3.2 Newer forms of workgroups

Ahora vamos a echar un vistazo a un temporizador interno, llamado "Watchdog Timer" [Nota de la traducción: En castellano sería, "temporizador perro guardián"] Así que, ¿Qué es un watchdog timer?

Supón que has escrito un programa que está continuamente corriendo en un PIC. Ahora, quieres asegurarte de que el programa sigue ejecutándose siempre, y no hay manera de que se pare nunca. La primera cosa que tienes que hacer, por supuesto, es un bucle que desde el final del programa te lleve hasta el principio. Pero ten en cuenta esto. Digamos que el PIC está monitorizando una entrada. Cuando esta entrada se pone a nivel alto, salta a otra parte del programa y espera por otro pin para que se ponga a nivel alto. Si el

segundo pin no se pone a nivel alto, el PIC simplemente "se sentará a esperar". Solo saldrá de ahí si el segundo pin se pone a nivel alto.

Consideremos otro ejemplo. Supón que has escrito un programa, lo has compilado con éxito, e incluso lo has simulado una y otra vez utilizando un simulador como MPLAB. Todo parece funcionar bien. Programas el PIC y lo colocas en tu circuito. Sin embargo

después de un largo periodo el programa se atasca en algún punto y el PIC se queda enganchado en un bucle.

Lo que se necesita en ambos casos es alguna clase de reset(o reinicio) si el programa se quedó atascado. Este es el propósito del watchdog timer.

Un circuito watchdog no es nada nuevo. Muchos microprocesadores y

microcontroladores lo tienen. Pero, ¿cómo funciona? Bien, dentro del PIC hay una red resistencia-condensador. Esta proporciona un reloj único, que es independiente de cualquier reloj externo que proporciones al circuito. Ahora cuando el watchdog timer (abreviado como WDT) está habilitado, un contador comienza en 00 y se incrementa en 1 hasta que alcanza FF. Cuando pasa de FF a 00 (lo cual es FF+1) el PIC será reiniciado, independientemente de lo que esté haciendo. La única manera de evitar que el WDT reinicie el PIC es reiniciar el propio WDT poniéndolo de vuelta a 00 durante el programa. Ahora puedes ver que si tu programa se atasca por cualquier razón, entonces el WDT no será puesto a 00 nunca. Eso hará que el WDT llegue a FF y reinicie tu PIC, causando a nuestro programa que se reinicie desde el comienzo.

Para utilizar el WDT, tenemos que saber tres cosas:

La primera, cuanto tiempo tenemos antes de tener que hacer un reinicio al WDT. ■

Segundo, como lo ponemos a cero. ■

Finalmente, tenemos que decirle al software programador del PIC que habilite el WDT dentro del PIC.

Vamos a ver esto de manera separada:

Tiempos de WDT

La hoja de datos del PIC especifica que el WDT tiene un periodo desde su inicio hasta el final de 18 ms. Esto depende de varios factores, como el voltaje aplicado, la temperatura del PIC, etc... La razón de esta aproximación es debida a que el reloj del WDT es

suministrado por una red RC interna. El tiempo de carga de la red RC depende del voltaje de alimentación. También depende de los valores de los componentes, los cuales cambian ligeramente dependiendo de su temperatura. Así que por razones de simplicidad,

tomaremos los 18 ms como el tiempo de reinicio del WDT.

Sin embargo, podemos hacer este tiempo mayor. Dentro del PIC hay un elemento llamado Prescaler [Nota de la Traducción: "Prescaler" se puede traducir como "etapa

previa de ajuste de escala"]. Podemos programar este prescaler para dividir el reloj

interno de la red RC. Cuanto mayor sea el factor de división, más tiempo tardará el WDT en reiniciarse.

El prescaler está localizado en el registro OPTION en la dirección 81h, los bit del 0 al 2 inclusive. Más abajo hay una tabla que muestra las asignaciones de los bits para cada ratio de división y el tiempo de reinicio del WDT:

Bit 2 Bit 1 Bit 0 Ratio Tiempo de WDT

0 0 0 1:1 18ms 0 0 1 1:2 36ms 0 1 0 1:4 72ms 0 1 1 1:8 144ms 1 0 0 1:16 288ms 1 0 1 1:32 576ms 1 1 0 1:64 1.1 Segundos 1 1 1 1:128 2.3 Segundos

Recuerda que estos tiempos son independientes de la frecuencia de tu reloj externo. Piensa en estos tiempos como en tiempo real, en lugar de como tiempos de reloj. Para ayudar a clarificar esto, vamos a suponer que queremos que el WDT reinicie nuestro PIC después de cerca de medio segundo como tiempo de seguridad ante fallo. El valor más próximo que tenemos es 576 ms o 0,576 segundos. Todo lo que hacemos es enviar b'101' a nuestro registro OPTION, tal y como sigue:

movlw b’101’ ; Esto es 0x05 en hexadecimal.

movwf 81h ; Este es el registro OPTION.

Realmente sencillo. Ahora, hay una trampa. Por defecto el prescaler está asignado a otro temporizador interno [Nota de la Traducción: Se refiere al temporizador TMR0.]. Esto significa que tenemos que cambiar el prescaler al WDT [Nota de la Traducción: Para

asignar el Prescaler al WDT hay que poner el bit 3 del registo OPTION a 1. Es decir, para poner el prescaler a 576 ms como decíamos antes y asignarlo al WDT, Hay que enviar al registro OPTION el valor b'1101]:

Primero, tenemos que reiniciar el otro contador (TMR0) y ponerlo a 0. ■

Después tenemos que cambiar al banco 1 para asignar el prescaler al WDT y configurar el tiempo.

Y después volver al banco 0. ■

El código esta aquí, donde xxx es el valor del prescaler:

bcf STATUS,0 ; Nos aseguramos de que estamos en el banco 0

clrf 01h ; Dirección del otro temporizador – TMR0. Lo ponemos a 0.

bsf STATUS,0 ; Cambiamos al banco 1switch to bank 1

clrwdt ; reiniciamos el WDT y el ''prescaler''

movlw b’1xxx’ ; Seleccionamos el valor del nuevo ''preescaler''(bits 0 al 2)

; y lo asignamos al WDT(ver bit 3 puesto a 1).

movwf OPTION ; y se lo asignamos al WDT

bcf STATUS,0 ; Vuelve al banco 0

La instrucción anterior CLRWDT es la que se utiliza para reiniciar el WDT antes de que este reinicie al PIC. Así que todo lo que tenemos que hacer es calcular donde en nuestro programa ocurrirá la finalización del tiempo del WDT, y enviar el comando CLRWDT justo antes de este punto, para que nos aseguremos de que el PIC no se reinicia. Si tu programa es largo, ten en cuenta que puede que necesites más de un CLRWDT. Por ejemplo, si utilizas el tiempo por defecto 18 ms, entonces tenemos que asegurarnos de que el programa ve un CLRWDT cada 18 ms.

Así que ahora llegamos al punto donde tenemos que trabajar en cuanto tiempo tarda nuestro código en ejecutarse, en tiempo real. El principio es muy simple, pero ¡puede que te tires de los pelos!

Temporización de las instrucciones

Como probablemente ya sabrás, el PIC toma el reloj externo y lo divide por 4. Este tiempo interno es llamado ciclo de instrucción. Como hemos dicho que conectamos un cristal de 4 Mhz a nuestro PIC, internamente el PIC irá a 1Mhz. En términos de

temporización, esto es 1/(4Mhz/4) = 1 µS. Entonces algunas instrucciones lleva ejecutarlas un solo ciclo de instrucción, p. ej. 1 µS utilizando un cristal de 4Mhz, mientras que otras emplearán 2 µS en ser ejecutadas.

La hoja de características nos dice cuantos ciclos lleva cada instrucción. La forma mas sencilla para recordarlo es muy simple. Asume que todas las instrucciones tardan 1 ciclo. Pero si una instrucción causa que el programa vaya a algún otro sitio, este se tomará 2 ciclos. Permite que te darte un par de ejemplos.

La instrucción "movwf" tarda solo 1 ciclo, porque solo mueve un dato de un lugar a otro. La instrucción "goto" tarda 2 ciclo, porque está causando que el contador de programa

(PC) vaya a otro sitio del programa. La instrucción RETURN tarda 2 ciclos, porque causa que el PC vuelva al programa principal. Al menos creemos que con esto ya puedes ver por donde va el tema.

Sin embargo, hay cuatro instrucciones que pueden tardar 1 ó 2 ciclos. Estas son

DECFSZ, INCFSZ, BTFSC y BTFSS. Estas instrucciones tienen una cosa en común. Se saltan la siguiente instrucción en caso si se cumple cierta condición. Si no se cumple la condición, entonces se lleva a cabo la siguiente instrucción. Por ejemplo, la instrucción DECFSZ decrementará en 1 el valor almacenado en el registro F. Si el resultado es 0, entonces la siguiente instrucción será ejecutada. Esta instrucción por tanto tarda 1 ciclo. Si el resultado es 0, entonces la instrucción siguiente se la salta, y la siguiente a la anterior será ejecutada. En este ejemplo la instrucción tarda 2 ciclos. La razón es que la instrucción altera el PC. Necesita 1 ciclo para ejecutar la función, y necesita otro para cambiar el PC por uno mas extra.

Para aclarar esto, vamos a mirar un código simple, y trabajaremos sobre los ciclos de instrucción que tarda:

;

movlw 02 movwf CONTADOR Bucle decfsz CONTADOR goto Bucle end

Nuestra primera instrucción simplemente mueve el valor 02 a W. Esto no causa ningún salto, por tanto es solo 1 ciclo. La siguiente instrucción es similar, mueve los contenidos del registro W a CONTADOR. De nuevo, esto tardará 1 ciclo. Ahora, la siguiente

instrucción primero decrementa CONTADOR en 1. Esto es 1 ciclo. Después hará una comprobación para ver que CONTADOR es igual a 0. En este momento no lo es, por tanto vamos a la siguiente instrucción. La siguiente instrucción es una de "goto", y por tanto tarda 2 ciclos. Volvemos a nuestra instrucción DECFSZ, la que decrementa CONTADOR en 1 de nuevo. Esto tarda otro ciclo. Hace una comprobación para ver si CONTADOR es igual a 0. Esta vez lo es, y por tanto se salta la siguiente instrucción. Para saltarse la siguiente instrucción se requiere otro ciclo. Alcanzamos el final del programa. Así que en total, con el valor de 02 para CONTADOR, este programa tarda 7 ciclos en total. Si estamos usando un cristal de 4MHz para nuestro reloj, entonces el programa tarda:

Software Programador

Dentro del PIC hay elementos llamados "Fusibles" [Nota de Traducción: En ingles

"Fuses"]. No son los mismos que puedes encontrar en los enchufes, sino que son

conmutadores electrónicos que se pueden "fundir" por el programador. Uno de estos fusibles tiene que ser 'fundido' para que el WDT pueda operar. Hay dos formas de hacerlo. Una es escribiendo un par de lineas al comienzo de tu programa para decirle al software programador del PIC que habilite o deshabilite ciertos "fusibles". La otra forma de hacerlo es decirle al software programador del PIC manualmente que fusibles

habilitar. Echaremos un vistazo a nuestro programa para instruir al software programador del capítulo pasado, cuando veamos como incluir otros ficheros y macros. El cómo

hacerlo manualmente varía dependiendo del software de programación. La

documentación que viene con el programador suele decir como hacerlo. Como estoy utilizando el [software PICALLW (http://www.picallw.com/) ], explicaremos como cambiar los "fusibles" con este programa:

Los fusibles se configuran pulsando la tecla F3, o haciendo 'click' sobre el botón de configuración. Después seleccionas el fusible que quieres habilitado, en ese caso el WDT, haciendo una marca en la caja que está junto a él.

Programa de ejemplo

Vamos a escribir un programa, donde modifiquemos el WDT, y permitamos al PIC ejecutar una función. Primero borraremos el WDT periódicamente para mostrar que el programa funciona, y después quietaremos la instrucción CLRWDT para mostrar que efectivamente el PIC se reinicia.

El programa que hemos elegido es el utilizado en el capítulo Operadores Aritméticos y Lógicos donde hacíamos que una fila de LEDs se encendiesen a un tiempo de izquierda a derecha y de derecha a izquierda. El circuito se muestra más abajo, y con los valores RC que mostramos le daremos una frecuencia de reloj de 8KHz. Esta velocidad de reloj nos permitirá realmente ver los LEDs moviéndose uno a uno. Elegimos este programa porque es suficientemente lento para que podamos jugar con el WDT, y que puedas ver

fácilmente como se reinicia el PIC. Hemos quitado los comentarios originales, y los hemos sustituido por una descripción de las lineas del WDT, y en cada linea del tiempo total desde el inicio (asumiendo 8KHz), y el número total de ciclos de reloj de cada linea.

TIEMPO equ 9FH ; Variable para el bucle de retardo.

PORTB equ 06H ; Dirección del Port B.

TRISB equ 86H ; Dirección del registro tri-estado del Port B.

PORTA equ 05H ; Dirección del Port A.

TRISA equ 85H ; Dirección del registro tri-estado del Port A.

STATUS equ 03H ; Registro para seleccionar el banco.

CONTADOR1 equ 0CH ; Registro para el bucle.

CONTADOR2 equ 0DH ; Registro para el bucle.

bsf STATUS,5 ; 1 ciclo, 0.5mS

movlw 00H ; 1 ciclo, 1.0mS

movwf TRISB ; 1 ciclo, 1.5mS

movlw 00H ; 1 ciclo, 2.0mS

movwf TRISA ; 1 ciclo, 2.5mS

bcf STATUS,5 ; 1 ciclo, 3.0mS

movlw 00H ; 1 ciclo, 3.5mS

movwf PORTA ; 1 ciclo, 4.0mS ; Comienzo del programa principal

CorreLuz

movlw 01H ; 1 ciclo, 4.5mS

movwf PORTB ; 1 ciclo, 5.0mS

call RETARDO ; 2 ciclos, 486mS

call RETARDO ; 2 ciclos, 967mS ; Mueve el bit por la izquierada del puerto B, después pausa.

rlf PORTB,1 ; 1 ciclo, 967.5mS

call RETARDO ; 2 ciclos, 1.45S

call RETARDO ; 2 ciclos, 1.93S

rlf PORTB,1 ; 1 ciclo, 1.93S

call RETARDO ; 2 ciclos, 2.41S

call RETARDO ; 2 ciclos, 2.89S

rlf PORTB,1 ; 1 ciclo, 2.89S

call RETARDO ; 2 ciclos, 3.37S

call RETARDO ; 2 ciclos, 3.85S

call RETARDO ; 2 ciclos, 4.34S

call RETARDO ; 2 ciclos, 4.82S

rlf PORTB,1 ; 1 ciclo, 4.82S

call RETARDO ; 2 ciclos, 5.30S

call RETARDO ; 2 ciclos, 5.78S

rlf PORTB,1 ; 1 ciclo, 5.78S

call RETARDO ; 2 ciclos, 6.26S

call RETARDO ; 2 ciclos, 6.74S

rlf PORTB,1 ; 1 ciclo, 6.74S

call RETARDO ; 2 ciclos, 7.22S

call RETARDO ; 2 ciclos, 7.70S

rlf PORTB,1 ; 1 ciclo, 7.70S ; Ahora mueve lo al puerto A, al bit de la izquierda.

rlf PORTA,1 ; 1 ciclo, 7.70S

call RETARDO ; 2 ciclos, 8.19S

call RETARDO ; 2 ciclos, 8.67S

rlf PORTA,1 ; 1 ciclo, 8.67S

call RETARDO ; 2 ciclos, 9.15S

call RETARDO ; 2 ciclos, 9.63S

rlf PORTA,1 ; 1 ciclo, 9.63S

call RETARDO ; 2 ciclos,10.11S

call RETARDO ; 2 ciclos,10.59S

rlf PORTA,1 ; 1 ciclo, 10.59S

call RETARDO ; 2 ciclos,11.07S

call RETARDO ; 2 ciclos,11.55S ; Mueve el bit de vuelta al puerto A.

rrf PORTA,1 ; 1 ciclo, 11.55S

call RETARDO ; 2 ciclos,12.04S

call RETARDO ; 2 ciclos,12.52S

rrf PORTA,1 ; 1 ciclo, 12.52S

call RETARDO ; 2 ciclos,12.99S

call RETARDO ; 2 ciclos,13.48S

rrf PORTA,1 ; 1 ciclo, 13.48S

call RETARDO ; 2 ciclos,13.96S

call RETARDO ; 2 ciclos,14.44S

rrf PORTA,1 ; 1 ciclo, 14.44S ; Ahora mueve el bit de vuelta al puerto B.

rrf PORTB,1 ; 1 ciclo, 14.44S

call RETARDO ; 2 ciclos,14.92S

call RETARDO ; 2 ciclos,15.40S

rrf PORTB,1 ; 1 ciclo, 15.40S

call RETARDO ; 2 ciclos,15.89S

call RETARDO ; 2 ciclos,16.37S

rrf PORTB,1 ; 1 ciclo, 16.37S

call RETARDO ; 2 ciclos,16.84S

call RETARDO ; 2 ciclos,17.33S

rrf PORTB,1 ; 1 ciclo, 17.33S

call RETARDO ; 2 ciclos,17.81S

call RETARDO ; 2 ciclos,18.29S

rrf PORTB,1 ; 1 ciclo, 18.29S

call RETARDO ; 2 ciclos,18.77S

call RETARDO ; 2 ciclos,19.25S

rrf PORTB,1 ; 1 ciclo, 19.25S

call RETARDO ; 2 ciclos,19.73S

call RETARDO ; 2 ciclos,20.22S

rrf PORTB,1 ; 1 ciclo, 20.22S

call RETARDO ; 2 ciclos,20.70S

call RETARDO ; 2 ciclos,21.18S ;

goto CorreLuz ; 2 ciclos,21.18S

; Subrutina para introducir un retardo entre los movimientos de los bits.

; Ciclos totales 957, 480mS

RETARDO

movlw TIEMPO ; 1 ciclo

movwf CONTADOR1 ; 1 ciclo

BUCLE1 ;

decfsz CONTADOR1 ; 9F x 1 ciclo + 1 ciclo = 160 ciclos

goto BUCLE1 ; 9E x 2 ciclos = 316 ciclos

movwf CONTADOR2 ; 1 ciclo

BUCLE2 ;

decfsz CONTADOR2 ; 9F x 1 ciclo + 1 ciclo = 256 ciclos

goto BUCLE2 ; 9E x 2 ciclos = 316 ciclos ;

return ; 2 ciclos

END ;

Con un reloj de 8KHz, tarda algo menos de 1 segundo en que el siguiente LED se ilumine, y tarda en total 21 segundos en ir de un extremo al otro y volver (es decir, lo que tarda le rutina en ejecutarse una vez solamente). El retardo de la subrutina es de 480ms, y la estamos llamando dos veces antes de mover el bit por los puertos. Ahora, tenemos que hacer el reinicio periódico del WDT. El mayor tiempo que podemos configurar para el WDT es de 2,3 segundos, y el siguiente en la tabla es de 1,1 segundos. Tenemos dos opciones. Podríamos hacer una llamada a la subrutina y reiniciar el WDT después de que los dos Retardos hayan terminado, o podríamos incorporar el CLRWDT dentro del retardo mismo. Hemos decidido, sin ninguna razón importante, poner el CLRWDT dentro de la subrutina de retardo. TIEMPO equ 9FH ; Variable para el bucle de retardo.

PORTB equ 06H ; Dirección del Port B.

TRISB equ 86H ; Dirección del registro tri-estado del Port B.

PORTA equ 05H ; Dirección del Port A.

TRISA equ 85H ; Dirección del registro tri-estado del Port A.

STATUS equ 03H ; Registro para seleccionar el banco.

CONTADOR1 equ 0CH ; Registro para el bucle.

CONTADOR2 equ 0DH ; Registro para el bucle.

OPT equ 81h ; Registro Option para controlar el WDT   ;************* Configura los puertos, el WDT y el preescaler****************** clrf 01h ; Pone a cero el TMR0 bsf STATUS,5 ; Cambia al banco 1 clrwdt ; reinicia el WDT y el prescaler movlw b’1101’ ; Selecciona un nuevo valor para el prescaler y movwf OPT ; se lo asigna al WDT ; movlw 00H ; Ahora configura los puertos movwf TRISB ;

movlw 00H ;

movwf TRISA ;

bcf STATUS,5 ; Vuelve al banco 0 movlw 00H ;

movwf PORTA ;

;************* Comienzo del programa principal ***************************** CorreLuz movlw 01H ;

movwf PORTB ;

call RETARDO ;

call RETARDO ;

; Mueve el bit por la izquierada del puerto B, después pausa. rlf PORTB,1 ; call RETARDO ; call RETARDO ; rlf PORTB,1 ; call RETARDO ; call RETARDO ; rlf PORTB,1 ; call RETARDO ; call RETARDO ; rlf PORTB,1 ; call RETARDO ; call RETARDO ; rlf PORTB,1 ; call RETARDO ; call RETARDO ; rlf PORTB,1 ; call RETARDO ;

call RETARDO ;

rlf PORTB,1 ;

call RETARDO ;

call RETARDO ;

rlf PORTB,1 ;

; Ahora mueve lo al puerto A, al bit de la izquierda.

rlf PORTA,1 ; call RETARDO ; call RETARDO ; rlf PORTA,1 ; call RETARDO ; call RETARDO ; rlf PORTA,1 ; call RETARDO ; call RETARDO ; rlf PORTA,1 ; call RETARDO ; call RETARDO ;

; Mueve el bit de vuelta al puerto A. rrf PORTA,1 ; call RETARDO ; call RETARDO ; rrf PORTA,1 ; call RETARDO ; call RETARDO ; rrf PORTA,1 ; call RETARDO ; call RETARDO ; rrf PORTA,1 ;

; Ahora mueve el bit de vuelta al puerto B. rrf PORTB,1 ; call RETARDO ; call RETARDO ; rrf PORTB,1 ; call RETARDO ; call RETARDO ; rrf PORTB,1 ; call RETARDO ; call RETARDO ; rrf PORTB,1 ; call RETARDO ; call RETARDO ; rrf PORTB,1 ; call RETARDO ; call RETARDO ; rrf PORTB,1 ; call RETARDO ; call RETARDO ; rrf PORTB,1 ; call RETARDO ; call RETARDO ; ; goto CorreLuz ;

; Subrutina para introducir un retardo entre los movimientos de los bits.

RETARDO

movlw TIEMPO ; 1 ciclo

movwf CONTADOR1 ; 1 ciclo

BUCLE1 ;

decfsz CONTADOR1 ; 9F x 1 ciclo + 1 ciclo = 160 ciclos

goto BUCLE1 ; 9E x 2 ciclos = 316 ciclos

movwf CONTADOR2 ; 1 ciclo

BUCLE2 ;

decfsz CONTADOR2 ; 9F x 1 ciclo + 1 ciclo = 256 ciclos

goto BUCLE2 ; 9E x 2 ciclos = 316 ciclos

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Esta parte reinicia el WDT ;;

;; Quita o comenta este comando para ver que hace el WDT. ;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clrwdt ; Esto simplemente reinicia el WDT. ; *************** Retorna desde nuestra rutina Retado*************** return ;

; END ;

Si comentas o quitas la instrucción CLRWDT, verás que el PIC no pasa de iluminar el segundo LED. Esto es debido a que el WDT hace que se reinicie el PIC. Con el

CLRWDT en su sitio, el programa funcionará como debe.

Referencias

MICROCHIP (http://www.microchip.com) ■

Microchip: El PIC 16F84 (Datasheet, Información adicional, etc...)

(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010229) ■

Microchip: El PIC 16F84A (Datasheet, Información adicional, etc...)

(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en010230) ■

Microchip: Páginas de documentación sobre MPASM (http://www.microchip.com/stellent/idcplg?

IdcService=SS_GET_PAGE&nodeId=2123&param=en022517) . ■

MPLAB IDE (Entorno Integrado de Desarrollo) (http://www.microchip.com/stellent/idcplg?

IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002) ■

MPASMWIN: Descarga de versión Windows (http://www.picbook.com/downloads.html) ■

Más Información: Lenguaje Ensamblador (en castellano). (http://perso.wanadoo.es/pictob/ensamblador.htm)

Obtenido de «http://wiki.webdearde.com/index.php?title=Tutorial:_Programaci%C3% B3n_de_PICs_en_Ensamblador&oldid=3694»

Categoría: Tutorial

Esta página fue modificada por última vez el 6 feb 2009, a las 19:32. ■

Esta página ha sido visitada 64.276 veces. ■