Monologos sobre PIC's

Hola amigos. Si estais aqui es porque teneis ganas de aprender y supongo que lo que andais buscando es una forma sencilla y explicada de aprender a usar los PIC's (12c508 y 16f84) para vuestros propios desarrollos. Aqui pondre una serie de articulos sobre estos jueguetes, que pueden complementar al cursillo para PIC's que teneis en este foro o que incluso, puede llegar a ser un curso completo y funcional. Tengo que rogaros que no escribais en este hilo. Si teneis alguna duda, podreis escribirlo en otro preparado al efecto
Hola a todos, supongo que algunos os preguntareis como los PIC's se apañan para cargar los juegos y como es posible que logre convertir rapidamente el codigo de un PIC a otro, teniendo en cuenta que son diferentes... La respuesta es que resulta facil, porque el 12c508 y el 16f84 comparten muchas cosas (utilizan el mismo juego de instrucciones a nivel ensamblador), pero se diferencian en el numero de patillas, memoria y sobre todo que uno (12c508) tiene un puerto con seis entradas/salidas y el otro (16f84a) tiene dos puertos: uno de 5 entradas/salidas y otro de 8

El puerto en 12c508 recibe el nombre de GPIO en el ensamblador, y se puede operar de dos formas: en la primera forma mediante la instruccion 'tris' ponemos el modo de funcionamiento de cada pata del puerto. Cada pata esta codificada por un bit y el ancho del dato que se pone en 'tris' es de 8 bits de los que solo se usan los 6 de menor peso. Si ponemos un '1' la pata que este representada por ese bit, se configura como entrada y si ponemos un '0' como salida. La forma de hacer esto seria;

movlw b'11111111' ; ponemos en W (registro), la configuracion

del puerto

tris GPIO ; configuramos el puerto con el valor en W

En este caso ponemos todo el puerto como 'entrada' (solo los 6 ultimos bits porque el PIC tiene solo 6 patas para entrada/salida
(ver imagen adjunta, donde se detallan las patas del PIC y su conexion con el registro del puerto)

Si queremos configurar la pata 6 del PIC como salida (GP1) el valor a escribir seria:

movlw b'11111101'
tris GPIO

pero antes tendriamos que saber que es lo que estamos escribiendo en el puerto. Para ello existe un registro (GPIO, claro) donde se pueden guardar los datos para la salida. Notese que tambien se puede leer en caso de estar en modo lectura el bit.


Para verlo mas claro, supongamos que queremos mandar un 1 por la patilla 6, podriamos hacerlo de dos maneras:

1)

movlw 'xxxxxx1x' ; x- representa valor indiferente
movwf GPIO ; asi cambiariamos el valor de todas las salidas
2)

bsf GPIO,1 ; asi solo cambiamos el bit que queremos


Como veis el tema es sencillo, pero ahora ¿como hacemos para leer?. Supongamos que tenemos la pata 5 (GP2) como entrada,
y queremos provocar un salto en caso de que el valor sea '0' :

btfss GPIO,2 ; comprueba el GP2 y si uno salta la sig instruccion
goto GP2ESTAAZERO ; pues eso
...... ; aqui sigue el codigo en caso de '1'
Claro que tambien podriamos querer guardar la lectura del puerto:
movf GPIO,W ; pone en W el valor leido del puerto;
movwf PUERTO ; salva en la variable PUERTO el valor de GPIO
btfss PUERTO,2
goto GP2ESTAAZERO

facil, no? (esta es la segunda forma de operar con el puerto, la primera lo configura y la segunda para leer o escribir)

Bien pues en el caso del 16f84, trabajamos igual solo que ahora tenemos dos puertos PORTA y PORTB. El primero tiene solo 5 entradas /salidas luego pasa como en el 12c508 que los bits de mayor peso, no cuentan, y el segundo puerto tiene los 8 bits disponibles por entero. Si volveis echar un vistazo a la imagen, supongamos que queremos poner las patillas 12 , 9 y 18 como salidas. la 12 y 9 pertenecen al puerto B (RB6,RB3) y la 18 al puerto A (RA1) entonces hariamos:

movlw b'10110111' ; dato en binario
tris PORTB ; patas 12 y 9 (RB6,RB3) como salidas, resto entrada
movlw b''11111101'
tris PORTA ; pata 18 (RA1) como salida, resto entrada

Si queremos mandar datos a los puertos o leer el valor de un bit o todo el puerto, procedemos como en el caso de GPIO.

NOTA: Es conveniente fijar primero el valor que se va a enviar a un puerto como salida, antes de configurar un bit como salida.

NOTA2: Como se puede leer en el dibujo. Las patas 4 del PIC12C508 y la pata 3 del PIC16f84 son las unicas que se pueden usar para el RESET de la PS2, porque cuando los PIC estan apagados las ortas patas del chip es como si estuvieran en corto para la PS2 y producen un nivel logico bajo que no permite encender la consola.

Bien una vez que hemos visto como funciona el trabajo con los puertos, os voy a mostrar una manera de poder convertir rapidamente el codigo de uno a otro PIC cuando empleamos las señales a nivel de bit. Supongamos que queremos ver si la señal de RESET de la PS2 se ha pulsado. Teniendo en cuenta que esta señal esta a 1 normalmente y cuando se pulsa se pone a '0' y que estamos obligados a usar las patillas de la NOTA2, en caso de 12c508 seria asi:

btfss GPIO,3
goto RESETPULSADO

y en el caso de 16f84:

btfss PORTA,4
goto RESETPULSADO

Si quisieramos un codigo 'universal' podriamos hacer:

btfss PS2_RESET
goto RESETPULSADO

y antes del 'org' poner esta definicion en el 12c508:

#define PS2_RESET GPIO,3

y esta otra para 16f84a

#define PS2_RESET PORTA,4


Como veis es mucho mas facil de lo que parece, solo teneis que observar la imagen que he puesto y comparar las patas de los PIC's con sus correspondientes registro.

A TENER EN CUENTA: GPIO,PORTA y PORTB, se comportan como cualquier otro registro de estos PIC's y pueden ser sumados, restados, rotados y hacer cualquier otra operacion. Por eso hay que tener cuidado con las operaciones que efectuemos con estos registros, si no queremos provocar una catastrofe XD
Supongo que algunos habreis pensado: ¿Como lo hace USB para adaptar los codigos de sus PIC's a distintas frecuencias?¿como sabe él, el numero de 'nops' que hay que poner en una rutina para ajustar el tiempo?. La respuesta es muy sencilla. Los PIC's como todos los procesadores, tienen un reloj, proporcionado bien de forma interna (12c508) o de forma externa, mediante un cristal por ejemplo, como en el caso de 16F84.

Para procesar una instruccion, los PIC's necesitan cuatro ciclos de reloj, exceptuando las instrucciones de salto, que necesitan el doble (ocho). Es decir, que si tenemos un reloj interno de 4Mhz, el reloj sera de 0,25microsegundos (us) que sale de dividir 1/4000000 (porque la frecuencia, es inversa al tiempo, como sabreis), luego si una intruccion normal necesita 4 ciclos, esta claro que consumira 1us o lo que es lo mismo, podran ejecutarse
1 millon por segundo y en el caso de ser de salto, 2us.

Un ejemplo: a 4Mhz nop, tarda lo mismo que a 12Mhz nop nop nop. Ya explicaremos, las distintas instrucciones, despues de ver el registro de estado, pero eso sera en otro momento. Hasta luego
Bueno, para aprender a manejar los PIC , nada mejor que utilizar uno que permite ser regrabado y que tiene opciones interesantes, ademas de ser relativamente, barato. Por eso utilizaremos el 16f84a del que os pongo el cuerpo de programa, que podeis usar para vuestras creaciones o que usare para ilustrar algunos ejemplos
3 respuestas