Club153 Programacion PIC

Nº DE COLECCIÓN 153 - Rep. Argentina: $99,99 - México: $120 M/N - Otros Países: u$s 8 Creatronica 349.qxd:Maquetación

Views 33 Downloads 0 File size 4MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

Nº DE COLECCIÓN 153 - Rep. Argentina: $99,99 - México: $120 M/N - Otros Países: u$s 8

Creatronica 349.qxd:Maquetación 1 21/4/16 12:11 p.m. p Página 1

4ª forros.qxd:Maquetación 1 15/10/13 10:37 Página 1

M I C RO C O N T RO L A D O R E S

PIC

PROGRAMACIÓN BÁSICA

M. en C. Ismael Cervantes de Anda Ing. Alberto Jesús Alcántara Méndez Docentes de la Escuela Superior de Cómputo (ESCOM) Instituto Politécnico Nacional (IPN) México

CONTENIDO

CONTENIDO ........................................................................................................................ 2 CAPÍTULO I. RUTINAS BÁSICAS..................................................................................... 3 1.1 CONFIGURACIÓN DE LOS PUERTOS COMO ENTRADA O SALIDA ...................... 3 1.2 LECTURA DE DATOS DE UN PUERTO ........................................................................... 5 1.3 ESCRITURA DE DATOS EN UN PUERTO ..................................................................... 11 1.4 ASIGNACIÓN DE DATOS A UN REGISTRO ................................................................. 16 1.5 INCREMENTO Y DECREMENTO DE DATOS DE LOS REGISTROS ...................... 23

1.5.1 Incremento o Decremento del dato de un registro en una unidad ....................................................23 1.5.2 Incremento o Decremento del dato de un registro en valores diferentes a la unidad .......................24

1.6 DISEÑO DE UN CONTADOR ............................................................................................ 25

1.6.1 Contador Ascendente .......................................................................................................................27 1.6.2 Contador Descendente .....................................................................................................................30

1.7 DISEÑO DE UN RETARDO BÁSICO POR BUCLES ..................................................... 32 1.8 SUMA ARITMÉTICA .......................................................................................................... 40 1.9 RESTA ARITMÉTICA ........................................................................................................ 51 1.10 MULTIPLICACIÓN ARITMÉTICA ............................................................................... 64 1.11 DIVISIÓN ARITMÉTICA ................................................................................................. 68

CAPÍTULO II. RUTINAS INTERMEDIAS ...................................................................... 73 2.1 FUNCIÓN LÓGICA AND Y SUS APLICACIONES........................................................ 73 2.2 FUNCIÓN LÓGICA OR Y SUS APLICACIONES .......................................................... 77 2.3 FUNCIÓN LÓGICA XOR Y SUS APLICACIONES ....................................................... 82 2.4 FUNCIONES LÓGICAS DE COMPARACIÓN ENTRE REGISTROS (=, ) .......... 85

2.4.1 Comparación IGUAL (=) ó DIFERENTE (≠) .................................................................................86 2.4.2 Comparación MENOR QUE () ó MENOR O IGUAL QUE (≤)...................................................98

2.5 LECTURA DE UN TECLADO MATRICIAL................................................................. 103 2.6 CONFIGURACIÓN DE LAS INTERRUPCIONES ....................................................... 114 2.7 IMPLEMENTACIÓN DE UN RETARDO POR TIMER .............................................. 120

2.7.1 El TIMER de 8 bits (TMR0) ..........................................................................................................122 2.7.2 El TIMER de 16 bit s (TMR1) .......................................................................................................128

2.8 CONFIGURACIÓN DE LA USART ................................................................................ 136

2.8.1 USART en modo Transmisión (Tx) ..............................................................................................138 2.8.2 USART en modo Recepción (Rx) .................................................................................................146

2

CAPÍTULO I. RUTINAS BÁSICAS 1.1 CONFIGURACIÓN DE LOS PUERTOS COMO ENTRADA O SALIDA El primer ejercicio que se realiza con un microcontrolador es la de leer o escribir datos discretos (digitales) a través de sus puertos, por lo tanto, la primera actividad que tiene que realizarse, es la de configurar sus respectivos puertos ya sean como de entrada o de salida de datos. Todos los microcontroladores poseen puertos que dependiendo de su estructura física relacionada con la cantidad de terminales, pueden poseer una cantidad de puertos igual a 1 ó 2 ó 3, etc.

Figura 1 Diversos microcontroladores PIC.

3

A continuación describiremos la manera en que tienen que ser configurados los puertos de un microcontrolador PIC, y para ello, nos basaremos en 4 microcontroladores PIC de diferentes tamaños, los cuales tomaremos como modelo y a partir de estos, podremos realizar cualquier aplicación, no importando la cantidad de terminales que posean los microcontroladores, ya que lo importante es aprender a configurarlos y obtener el máximo beneficio de sus herramientas internas. Para configurar los puertos de entrada o salida de datos digital de los microcontroladores, se tiene que guardar un valor en el respectivo registro de configuración del puerto a ser empleado.

El registro de configuración debe ser

manipulado en el llamado ―tr is‖, que dependiendo del puerto se complementa el nombre del registro a ―tr isa‖ si se trata del puerto A, o ―tr isb‖ si se trata del puerto B, o ―tr isc‖ si se trata del puerto C, etc.

Normalmente la mayor cantidad de

puertos que posee un microcontrolador PIC es de 5 por lo que solo llegaría hasta el puerto E. Cabe aclarar, que los microcontroladores que cuentan con un solo puerto como es el caso del PIC12F629, el registro de configuración de su puerto correspondiente, tan solo recibe el nombre de ―tr isio‖, ya que no es necesario especificarle de que puerto se trata, por el hecho de que solo posee uno. Los

registros

de

configuración

de

los

diferentes

puertos

de

los

microcontroladores PIC, se encuentran en el banco 1 del mapa de memoria de datos, siendo las localidades específicas para cada registro de configuración las siguientes:

2

Matrícula del PIC PIC12F629 PIC16F628A PIC16F876 PIC16F877

trisa ---85h 85h 85h

Registro de Configuración trisb trisc Trisd trise trisio ------------85h 86h ------------86h 87h ---------86h 87h 88h 89h ----

Tabla 1. Ubicación de los registros de configuración de algunos microcontroladores PIC.

Todos los registros tris (configuración de puertos) de los diferentes puertos que poseen los microcontroladores PIC, se encuentran conformados por 8 bits, los cuales dependiendo del estado lógico en el que se encuentren, será la forma de como se configure su correspondiente puerto, ya sea como entrada o salida. Para que un puerto de algún microcontrolador PIC sea configurado como entrada, en su correspondiente registro tris se debe de alojar un dato el cual debe estar compuesto por 1’s lógicos.

Expresado de otra manera, sí se requiere que

todos los bits de un puerto sean configurados como entradas, entonces a cada bit del correspondiente registro tris del puerto en cuestión se le tendrá que colocar en 1 lógico.

Tal como se muestra a continuación:

Registro tris = 11111111(binario) ó tris = FF(hexadecimal) ó tris = 255(decimal) De manera contraria, para que un puerto de algún microcontrolador PIC sea configurado como salida, en su correspondiente registro tris se debe de alojar un dato el cual debe estar constituido por 0’s lógicos.

Expresando lo anterior de

otra manera, sí se requiere que todos los bits de un puerto sean configurados como salidas, entonces a cada bit del correspondiente registro tris del puerto en cuestión se le tendrá que colocar en 0 lógico.

Tal como se muestra a

continuación: Registro tris = 00000000(binario) ó tris = 00(hexadecimal) ó tris = 000(decimal) Por otra parte, no es requisito indispensable configurar los bits de todo 3

un puerto ya sea como entrada o como salida, si no dependiendo de la aplicación un mismo puerto puede ser configurado por ejemplo mitad como entrada y mitad como salida, por lo tanto el registro tris podría quedar como: Registro tris = 00001111(binario) ó al revés tris = 11110000(binario) De manera general, la cantidad de bits de entrada o salida que se pueden configurar en un puerto, depende de las necesidades de la aplicación, pero lo que si debe de tomarse en cuenta es que los puertos cuentan con máximo 8 bits, los cuales deben ser distribuidos de manera adecuada, para considerar que microcontrolador es el que debemos de adquirir. Para acceder a cualquiera de los registros tris se tiene que apuntar en primera instancia al banco 1 del mapa de memoria de datos, para ello se tienen que manipular los bits rp0 y rp1 del registro ―stat us‖.

Por otra parte suponga que se

requiere configurar al puerto A como entrada y en el puerto B el nible superior como entrada y el nible inferior como salida.

A continuación se muestra a

manera de sugerencia el código para realizar las acciones antes descritas, sobre microcontroladores que cuentan con más de un puerto. bsf bcf movlw movwf movlw movwf

status,rp0 status,rp1 b’11111111’ trisa b’11110000’ trisb

;cambia al banco 1 ;configura al puerto A como entrada ;configura al puerto B bits del 0 a 3 como salida ;bits del 4 a 7 como entrada

Para microcontroladores que solo tienen un puerto, y además necesitamos que los bits 0,1 y 2 sean configurados como entradas, y los bits 3, 4 y 5 sean configurados como salidas, tomando en cuenta que el microcontrolador de un solo puerto puede ser el PIC12F629, se presenta el fragmento de código para configurar el puerto. bsf movlw

status,rp0 b’00000111’

movwf

trisio

;cambia al banco 1 ;configura los bits del 0 al 2 como entrada, y los bits del 3 al 5 ;como salida del único puerto.

4

Aunque todos los registros de configuración tris son de 8 bits, en el PIC12F629 solo son empleados los 6 bits de más bajo peso, por lo que los bits 6 y 7 los colocamos en ―0‖ (de todas maneras son colocados en el estado lógico ―0‖ de manera automática). Para finalizar el tema de la configuración de los registros de los puertos, podemos decir que es a través de los registros de configuración tris por donde se configuran los puertos de un microcontrolador, por lo tanto, son los primeros registros que deben ser manipulados cuando se diseña un programa. 1.2 LECTURA DE DATOS DE UN PUERTO No importando la cantidad de bits que conformen a un puerto, este puede ser configurado para que pueda ―l eer‖ algún dato del exterior, para ello, una vez que se tiene el correspondiente circuito de aplicación, se graba en el microcontrolador PIC el programa por medio del cual realizara la tarea de ingresar un dato digital al microcontrolador.

5

; Programa de prueba para leer el puerto B LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= portb equ 0x06 status equ 0x83 trisb equ 0x86 temporal equ 0x20 ;============================================================= ; Declaración de bits ;============================================================= rp0 equ 0x05 rp1 equ 0x06 ;============================================================= ; Vector del reset ;============================================================= reset org 0 goto inicio ;============================================================= ; Inicio del programa principal ;============================================================= inicio bsf status,rp0 ;cambia al banco 1 bcf status,rp1 movlw b’11111111’ ;configura al puerto B como entrada movwf trisb bcf status,rp0 ;cambia al banco 0 bcf status,rp1 movf portb,0 ;el dato del puerto es cargado al registro W movwf temporal ;el valor del registro W se aloja en el registro ;temporal. goto inicio

Tabla 2. Utilización del puerto B de cualquier microcontrolador PIC para leer datos.

Para poder emplear un puerto como entrada en los microcontroladores PIC, se tiene que comenzar con la configuración del correspondiente registro ―tr is‖, colocando todos sus bits en unos ―l ógicos‖ (1’s).

Posteriormente a la

configuración del registro tris, se tiene que emplear el registro denominado ―po rt‖, llamando al puerto A como ―po rta‖, al puerto B como ― portb‖, al puerto C como ―po rtc‖ y así sucesivamente para cada uno de los puertos con que cuente el microcontrolador.

6

; Programa de prueba para leer el puerto A LIST P=PIC16F628A ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= porta equ 0x05 cmcon equ 0x1f status equ 0x83 trisa equ 0x85 temporal equ 0x20 ;============================================================= ; Declaración de bits ;============================================================= rp0 equ 0x05 rp1 equ 0x06 ;============================================================= ; Vector del reset ;============================================================= reset org 0 goto inicio ;============================================================= ; Inicio del programa principal ;============================================================= inicio bsf status,rp0 ;cambia al banco 1 bcf status,rp1 movlw b’11111111’ ;configura al puerto A como entrada movwf trisa bcf status,rp0 ;cambia al banco 0 bcf status,rp1 movlw b’00000111’ ;selecciona 0 (cero) comparadores en el movwf cmcon ;registro cmcon (deshabilita los ;comparadores) movf porta,0 ;el dato del puerto es cargado al registro W movwf temporal ;el valor del registro W se aloja en el registro ;temporal. goto inicio

; Programa de prueba para leer el puerto A LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= porta equ 0x05 status equ 0x83 trisa equ 0x85 adcon1 equ 0x9f temporal equ 0x20 ;============================================================= ; Declaración de bits ;============================================================= rp0 equ 0x05 rp1 equ 0x06 ;============================================================= ; Vector del reset ;============================================================= reset org 0 goto inicio ;============================================================= ; Inicio del programa principal ;============================================================= inicio bsf status,rp0 ;cambia al banco 1 bcf status,rp1 movlw b’11111111’ ;configura al puerto A como entrada movwf trisa movlw b’00000111’ ;selecciona 0 (cero) comparadores en el movwf adcon1 ;registro adcon1 (deshabilita los ADC) bcf status,rp0 ;cambia al banco 0 bcf status,rp1 movf porta,0 ;el dato del puerto es cargado al registro W movwf temporal ;el valor del registro W se aloja en el registro ;temporal. goto inicio

Tabla 3. Utilización del puerto A para leer datos de los microcontroladores PIC16F628A y PIC16F876.

Los registros ―po rt‖ prácticamente se comportan como un reflejo del estado lógico que se presenta en las terminales físicas del microcontrolador, siendo más específicos, diremos que el dato que alojemos en algún registro port, se transmitirá a las terminales que se encuentran relacionadas con el registro port correspondiente, recordando que el registro tris consecuente debe encontrarse configurado de tal forma que el puerto se comporte como entrada. Todos los registros port se encuentran constituidos por 8 bits, los cuales indican el estado lógico en que se encuentran las terminales físicas del puerto en cuestión del microcontrolador PIC.

Para leer todos los bits de un puerto se

puede emplear el comando de lectura de un registro, indicando en la instrucción el puerto que tendrá que ser intervenido, para una mayor referencia observe el 7

ejemplo que se ilustra en la tabla 2.

Este código es valido para todos los

puertos exceptuando al puerto A de los microcontroladores PIC, por otra parte también se indica el direccionamiento del banco donde se encuentran los registros que serán empleados, actividad que se implementa por medio de la manipulación de los bits ―r p0‖ y ―r p1‖ del registro ―stat us‖. En las terminales del puerto A de los microcontroladores PIC dependiendo de su estructura interna, pueden poseer ya sea convertidores analógico a digital (ADC), ó comparadores de voltaje, motivo por el cual como parte de la rutina de inicialización de los registros de los microcontroladores, se les tiene que indicar de manera adicional, que se van a emplear las terminales del puerto A para realizar lecturas de naturaleza digital.

Posterior a la aplicación de un reset, las

terminales del puerto A se configuran de manera predeterminada para que sean activados ya sea el ADC ó los comparadores de voltaje, por lo tanto, tendremos que recurrir al registro en donde se configura la cantidad de ADC’s o comparadores que serán empleados, pero en esta ocasión para deshabilitarlos. Para realizar la actividad de deshabilitación de ADC ó comparadores, basta con seleccionar 0 (cero) ADC’s ó 0 (cero) comparadores de voltaje, tal como se ilustra en la código del programa de la tabla. Hasta este punto hemos revisado de qué manera se leen los puertos A ó B ó C, etc., de microcontroladores que poseen más de un puerto (el PIC16F628A cuenta con 2 puertos y el PIC16F876 cuenta con 3 puertos) como entrada, pero también podemos encontrarnos con microcontroladores que posean tan solo un puerto único, por lo tanto debemos de ser capaces de poder trabajar con el microcontrolador de un solo puerto.

8

; Programa de prueba para leer el puerto de un PIC de 8 terminales LIST P=PIC12F629 ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= w equ 00h status equ 0x03 gpio equ 0x05 cmcon equ 0x19 trisio equ 0x85 osccal equ 0x90 var1 equ 0x20 ;============================================================= ; Declaración de Bits ;============================================================= c equ 0 ;carry (acarreo) z equ 2 ;bit del cero rp0 equ 5 ;registro de selección de banco ;============================================================= ; Inicio ;============================================================= reset org 0 goto inicio ;============================================================= ; programa principal ;============================================================= inicio bcf status,rp0 ;cambiar al banco 0 movlw b’00000111’ ;selecciona 0 (cero) comparadores en el movwf cmcon ;registro cmcon (deshabilita los comparadores) bsf status,rp0 ;cambiar al banco 1 movlw b'00111111' ;configura los bits 0, 1, 2 , 3, 4 y 5 del puerto GPIO movwf trisio ;como entradas (solo contiene 6 bits). movlw b'11111100' ;configura el oscilador interno en su velocidad movwf osccal ;máxima (4 Mhz). ciclo bcf status,rp0 ;cambiar al banco 0 movf gpio,w movwf var1 goto ciclo

Tabla 4. Utilización del puerto GPIO de un PIC de 8 terminales para leer datos. Dentro de los microcontroladores PIC, uno de los que cuenta con un solo puerto es el que se identifica por medio de la matricula PIC12F629, el cual posee 8 terminales de las cuales 2 son para alimentación, por lo que sobra un puerto de tan solo 6 bits.

En este caso se trata de un microcontrolador que podemos

considerar como ―e nano‖ pero no por ello restringido en su operación, por el contrario todo depende de la aplicación que queramos realizar, y si esta no

9

requiere de muchas terminales de entrada, el PIC12F629 es muy adecuado. Para emplear el puerto del microcontrolador PIC12F629 tenemos en primera instancia que configurar los bits de su correspondiente registro ―tr isio‖ de tal manera que pueda leer datos, siguiendo la misma mecánica que se realizo para los demás microcontroladores, por lo tanto se debe de colocar unos (1´s) en los respectivos bits donde se pretende que la correspondiente terminal del microcontrolador sea configurada como entrada.

Se tiene que considerar que la

terminal identificada como GP3 (refiérase a la figura 1), siempre debe ser configurada como de entrada, ya que la arquitectura del microcontrolador PIC12F629 así la tiene diseñada. En la tabla 4 se ilustra un fragmento de código para configurar al único puerto con el que cuenta un microcontrolador PIC de 8 terminales (en este caso un PIC12F629).

En el registro ―tr isio‖ se cargan 1’s en los bits 0, 1, 2, 3, 4 y 5

porque son los que se encuentran disponibles para el PIC12F629, los bits 6 y 7 no se encuentran disponibles para este PIC.

Una vez que fue configurado el

registro trisio, se procede a emplear el registro ―g pio‖ para ingresar el dato que se encuentra en las terminales del microcontrolador.

Para emplear la totalidad de

las terminales del PIC12F629, es necesario habilitar al oscilador interno del PIC, para que se puedan emplear las 2 terminales dedicadas al oscilador como entradas discretas (GP4 y GP5), además de deshabilitar la terminal del reset externo denominado MCLR, para contar con la terminal GP3 exclusivamente como entrada.

Por otra parte, cuando se habilita al oscilador interno, se tiene que

seleccionar la frecuencia de operación, por lo que en el registro ―oscca l‖ se ingresa el valor binario ―11 111100‖ que selecciona la frecuencia máxima de operación que es de 4 Mhz.

El PIC12F629 en las terminales identificadas como GP0 y GP1

cuentan a la vez con comparadores de voltaje, mismos que tienen que ser deshabilitados para emplear dichas terminales como entradas digitales, siendo mediante la carga del valor binario ―00 000111‖ en el registro ―cm con‖. Por último se tiene que recordar que

para interactuar con algún registro, se 10

tiene que direccionar al banco adecuado.

El PIC12F629 solo cuenta con 2

bancos, por lo tanto basta con manipular el bit ―r p0‖ del registro status para acceder al banco adecuado. 1.3 ESCRITURA DE DATOS EN UN PUERTO Sin tomar en cuenta la cantidad de bits que conforman a los puertos de los microcontroladores PIC, estos pueden ser configurados para que se pueda ― escribir‖ algún dato hacia el exterior del microcontrolador, para ello, una vez que se tiene el correspondiente circuito de aplicación debidamente configurado, se graba en el microcontrolador PIC el programa por medio del cual realizara la tarea de enviar un dato digital hacia el exterior del microcontrolador. Para poder utilizar cualquiera de los puertos de un microcontrolador PIC como salida, se tiene que considerar como primer paso el de la configuración del correspondiente registro ―tr is‖, colocando todos sus bits en ceros ―l ógicos‖ (0’s). Una vez que fue configurado el registro tris, se tiene que proceder con el empleo del registro denominado ―po rt‖, y de acuerdo al puerto que se tenga que emplear se podrá seleccionar desde el puerto A como ―p orta‖, al puerto B como ―po rtb‖, al puerto C como ―p ortc‖ y así sucesivamente para cada uno de los puertos con que cuente el microcontrolador. Los registros denominados ―po rt‖ prácticamente se comportan como un reflejo del estado lógico que se presenta en las terminales físicas del microcontrolador, siendo más específicos, diremos que el dato que alojemos en algún registro port, se transmitirá a las terminales que se encuentran relacionadas con el registro port correspondiente, recordando que el registro tris consecuente debe encontrarse configurado de tal forma que el puerto se comporte como salida. En los microcontroladores PIC todos los registros port se encuentran constituidos por 8 bits, los cuales indican el estado lógico en que se encuentran las terminales físicas del puerto en cuestión del microcontrolador PIC.

11

; Programa de prueba para escribir en el puerto B LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= portb equ 0x06 status equ 0x83 trisb equ 0x86 temporal equ 0x20 ;============================================================= ; Declaración de bits ;============================================================= rp0 equ 0x05 rp1 equ 0x06 ;============================================================= ; Vector del reset ;============================================================= reset org 0 goto inicio ;============================================================= ; Inicio del programa principal ;============================================================= inicio bsf status,rp0 ;cambia al banco 1 bcf status,rp1 movlw b’00000000’ ;configura al puerto B como salida movwf trisb bcf status,rp0 ;cambia al banco 0 bcf status,rp1 movf temporal,0 ;el dato del registro temporal es cargado a W movwf portb ;escribe el dato de W en el puerto B goto inicio

Tabla 5. Utilización del puerto B de cualquier microcontrolador PIC para escribir datos. Para escribir un dato en todos los bits de un puerto se puede emplear el comando de escritura sobre un registro, indicando en la instrucción el puerto que tendrá que ser intervenido, para una mayor referencia observe el ejemplo que se ilustra en la tabla 5.

El código de la tabla 5 es valido para intervenir todos los

puertos de un microcontrolador PIC exceptuando al puerto A de los PIC, por otra parte también se indica el direccionamiento del banco donde se encuentran los registros que serán empleados, por medio de la manipulación de los bits ―r p0 y rp1‖ del registro ― status‖, que de acuerdo al banco donde se ubiquen los diferentes registros de configuración, se tendrá que colocar la combinación adecuada en los bits rp0 y rp1.

12

; Programa de prueba para escribir un dato en el puerto A LIST P=PIC16F628A ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= porta equ 0x05 cmcon equ 0x1f status equ 0x83 trisa equ 0x85 temporal equ 0x20 ;============================================================= ; Declaración de bits ;============================================================= rp0 equ 0x05 rp1 equ 0x06 ;============================================================= ; Vector del reset ;============================================================= reset org 0 goto inicio ;============================================================= ; Inicio del programa principal ;============================================================= inicio bsf status,rp0 ;cambia al banco 1 bcf status,rp1 movlw b’00000000’ ;configura al puerto A como salida movwf trisa bcf status,rp0 ;cambia al banco 0 bcf status,rp1 movlw b’00000111’ ;selecciona 0 (cero) comparadores en el movwf cmcon ;registro cmcon (deshabilita los ;comparadores) movf temporal,0 ;el dato del registro temporal es cargado a W movwf porta ;escribe el dato de W en el puerto A goto inicio

; Programa de prueba para escribir un dato en el puerto A LIST P=PIC16F876 ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= porta equ 0x05 status equ 0x83 trisa equ 0x85 adcon1 equ 0x9f temporal equ 0x20 ;============================================================= ; Declaración de bits ;============================================================= rp0 equ 0x05 rp1 equ 0x06 ;============================================================= ; Vector del reset ;============================================================= reset org 0 goto inicio ;============================================================= ; Inicio del programa principal ;============================================================= inicio bsf status,rp0 ;cambia al banco 1 bcf status,rp1 movlw b’00000000’ ;configura al puerto A como salida movwf trisa movlw b’00000111’ ;selecciona 0 (cero) comparadores en el movwf adcon1 ;registro adcon1 (deshabilita los ADC) bcf status,rp0 ;cambia al banco 0 bcf status,rp1 movf temporal,0 ;el dato del registro temporal es cargado a W movwf porta ;escribe el dato de W en el puerto A goto inicio

Tabla 6. Utilización del puerto A para escribir datos en los microcontroladores PIC16F628A y PIC16F876.

Sobre las terminales del puerto A de cualquiera de los microcontroladores PIC dependiendo de su estructura interna, pueden contar con convertidores analógico a digital (ADC), ó comparadores de voltaje,

precedente para que sea

implementada la correspondiente rutina de inicialización de los registros de los microcontroladores, para que de manera adicional se le indique a las terminales del puerto que serán empleadas para realizar la escritura de datos digitales en el puerto A.

Cuando se aplica un reset, las terminales del puerto A se configuran

siempre de manera predeterminada para que estas sean habilitadas como ADC ó los comparadores de voltaje, por lo tanto, se tendrá que recurrir al registro en donde se configura la cantidad de ADC’s o comparadores que serán empleados, pero en esta ocasión se tendrán que

deshabilitar.

13

Para realizar la actividad de deshabilitación de ADC ó comparadores, basta con seleccionar 0 (cero) ADC’s ó 0 (cero) comparadores de voltaje, tal como se ilustra en los fragmentos de código de los programas de la tabla. Hemos revisado la manera de escribir datos sobre los puertos A ó B ó C, etc., de microcontroladores que cuentan con más de un puerto (el PIC16F628A cuenta con 2 puertos y el PIC16F876 cuenta con 3 puertos), pero también podemos encontrarnos con microcontroladores que poseen tan solo un puerto único, por lo tanto se debe de contar con el conocimiento de poder trabajar con algún microcontrolador de un solo puerto. Dentro de la familia de los microcontroladores PIC, uno de los que cuenta con un solo puerto es el que se identifica por medio de la matricula PIC12F629, el cual posee 8 terminales de las cuales 2 son para que sea energizado (terminales Vdd y Vss), por lo que sobra un puerto de tan solo 6 bits.

En este caso se trata de un

microcontrolador pequeño que pudiera ser considerado como restringido en cuanto a su cantidad de terminales, pero no en su operación, por el contrario todo depende de la aplicación que se tenga que realizar, ya que si esta no requiere de muchas terminales de salida, el PIC12F629 es un microcontrolador muy adecuado. Para emplear el puerto del microcontrolador PIC12F629 tenemos en primera instancia que configurar los bits de su correspondiente registro ―tr isio‖ de tal manera que se pueda escribir algún datos, siguiendo la misma mecánica que se realizo para los demás microcontroladores, por lo tanto, se debe de colocar ceros (0´s) en los respectivos bits donde se pretende que la correspondiente terminal del microcontrolador sea configurada como salida.

Se tiene que considerar que de

las terminales con que cuenta el PIC12F629, identificada como GP3 (refiérase a la figura 1), siempre tiene que ser configurada como de entrada, ya que la arquitectura del microcontrolador PIC12F629 así la tiene diseñada.

14

;Programa de prueba para escribir datos en un PIC de 8 terminales LIST P=PIC12F629 ;Aquí se coloca la matricula del microcontrolador ;que vaya a emplearse ;============================================================= ; Declaración de registros ;============================================================= w equ 00h status equ 0x03 gpio equ 0x05 cmcon equ 0x19 trisio equ 0x85 osccal equ 0x90 var1 equ 0x20 ;============================================================= ; Declaración de Bits ;============================================================= c equ 0 ;carry (acarreo) z equ 2 ;bit del cero rp0 equ 5 ;registro de selección de banco ;============================================================= ; Inicio ;============================================================= reset org 0 goto inicio ;============================================================= ; programa principal ;============================================================= inicio bcf status,rp0 ;cambiar al banco 0 movlw b’00000111’ ;selecciona 0 (cero) comparadores en el movwf cmcon ;registro cmcon (deshabilita los comparadores) bsf status,rp0 ;cambiar al banco 1 movlw b'00001000' ;configura todos los bits (con excepción del 3) del movwf trisio ;puerto como salidas (solo contiene 6 bits). movlw b'11111100' ;configura el oscilador interno en su velocidad movwf osccal ;máxima (4 Mhz). ciclo bcf status,rp0 ;cambiar al banco 0 movf var1,w movwf gpio goto ciclo

Tabla 7. Utilización del puerto GPIO de un PIC de 8 terminales para escribir datos.

En la tabla 7 se ilustra un fragmento de código para configurar al único puerto con el que cuenta un microcontrolador PIC de 8 terminales (en este caso un PIC12F629) como salida.

En el registro ―tr isio‖ se cargan 0’s en los bits 0, 1, 2,

4 y 5 porque son los que se encuentran disponibles para el PIC12F629, los bits 6 y 7 no se encuentran disponibles para este PIC. Una vez que fue configurado el

registro trisio, se procede a emplear el 15

registro ―g pio‖ para enviar hacia el exterior del microcontrolador algún dato, para que se refleje en las terminales del microcontrolador.

Para emplear la totalidad

de las terminales del PIC12F629, es necesario habilitar al oscilador interno del PIC, para que se puedan emplear las 2 terminales dedicadas al oscilador como salidas discretas (GP4 y GP5), además de deshabilitar la terminal del reset externo denominado MCLR, para contar con la terminal GP3 exclusivamente como ― entrada‖.

Por otra parte, cuando se habilita al oscilador interno, se tiene que

seleccionar la frecuencia de operación, por lo que en el registro ―oscca l‖ se ingresa el valor binario ―11 111100‖ que selecciona la frecuencia máxima de operación que es de 4 Mhz.

El PIC12F629 en las terminales identificadas como GP0 y GP1

cuentan a la vez con comparadores de voltaje, mismos que tienen que ser deshabilitados para emplear dichas terminales como salidas digitales, siendo mediante la carga del valor binario ―00 000111‖ en el registro ―cm con‖. Por último se debe de tomar en cuenta que para interactuar con algún registro, se tiene que direccionar al banco adecuado.

El PIC12F629 solo cuenta con 2

bancos, por lo tanto, basta con manipular el bit ―r p0‖ del registro status para acceder al banco adecuado. 1.4 ASIGNACIÓN DE DATOS A UN REGISTRO Una de las tareas que tiene que realizar un microcontrolador, es la de ir almacenando datos, ya sea en sus registros de configuración, o en cualquier registro de memoria RAM, que es en donde finalmente se alojan los datos que resultan de una operación, o la lectura de un puerto, etc. Si la aplicación así lo requiere, se tiene que manipular el dato de más de un registro, para ello, se tienen que distribuir todos los registros involucrados en el proyecto, para que en primera instancia se tengan que ubicar sobre los espacios de memoria RAM, que se encuentran constituidos sobre la memoria de datos, por lo tanto, se debe de conocer sobre que banco de memoria es sobre el que se alojara el dato en un registro.

16

Para comenzar a trabajar con los registros, la primera actividad a desarrollar es la que lleva por nombre ―de claración‖ de registros, o sea se le tiene que indicar al programa editor (que en el caso de los microcontroladores PIC es el MPLAB) que se va emplear por ejemplo el registro ―tr isa‖. w status trisa trisb porta portb cmcon var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 var11 var12 var13 var14 var15 var16 var17

equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ equ

00h 0x03 0x85 0x86 0x05 0x06 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30

Tabla 8. Declaración de registros, para su empleo posterior. Recordemos que se pueden clasificar de forma general en 2 conjuntos los registros

que

emplearemos,

los

cuales

conocemos

como

registros

de

configuración y registros de propósito general, estos últimos también tienen la tarea de almacenar datos ya que se trata de registros que se encuentran implementados sobre memoria RAM.

A continuación marcaremos un mayor

énfasis sobre los registros de propósito general, sin olvidar a los registros de configuración. Una vez que fueron declarados los registros con los que trabajaremos, ya los podemos emplear para escribirles o leerles el dato que contengan, por lo tanto, en el ejemplo que se muestra sobre un listado en el fragmento de programa descrito en la tabla 8, se declaran los registros

que serán empleados, resaltando de 17

una manera particular a los registros de propósito general que son los que funcionaran como localidades de memoria RAM.

De la tabla 8 se observa que

se tienen que declara una serie de registros que se denominan ―v ar1‖, ― var2‖, ―v ar3‖, etc.

Lo importante es que ocupan las localidades de los registros que

van de la 20h a la 30 h, además de que son localidades continuas.

Se debe de

tener en cuenta que si por alguna razón se requiere insertar un nuevo registro por ejemplo entre los identificados como var7 y var8, posteriormente se tienen que enumerar nuevamente las localidades recorriendo los números de registro que a cada una le corresponde de tal manera, que de nueva cuenta queden ordenadas. w equ status equ trisa equ trisb equ porta equ portb equ cmcon equ CBLOCK var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 var11 var12 var13 var14 var15 var16 var17 ENDC

00h 0x03 0x85 0x86 0x05 0x06 0x1f 0x20

;Define donde comienza la declaración de registros

;Define donde termina la declaración de registros

Tabla 9. Declaración de un bloque de registros, para asignación automática de localidades.

En la tabla 9 se muestra una manera mucho más práctica en lo correspondiente a la declaración de registros, en donde puede observarse que a partir del registro var1, nos olvidamos

de indicar por medio de la directiva 18

―eq u‖ la localidad que le corresponde a cada registro.

Tan solo tenemos que

enumerar a todos los registros que tenemos que emplear y al comienzo del bloque le colocamos el comando ―C BLOCK‖, indicándole cual será la primera localidad que tendrá que ocuparse, tal como se muestra en la ejemplo ―C BLOCK 0x20‖, tal como aparece en la tabla 9. LIST P=PIC16F628A ;========================================= ; Declaración de registros ;========================================= w equ 0x00 status equ 0x03 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 cmcon equ 0x1f CBLOCK 0x20 ;define donde comienza la declaración de registros var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 var11 var12 var13 var14 var15 var16 var17 ENDC ;define donde termina la declaración de registros ;========================================== ; Declaración de bits ;========================================== rp0 equ 0x05 rp1 equ 0x06 ;========================================== ; Vector del Reset ;========================================== org 0x00 goto inicio

;========================================== ; Programa principal ;========================================== inicio bcf status,rp1 ;direcciona el banco 1 bsf status,rp0 movlw 0xff movwf trisa ;los bits del Puerto a como entradas bcf status,rp1 ;direcciona el banco 0 bcf status,rp0 movlw 0x07 movwf cmcon ciclo bcf status,rp1 ;direcciona el banco 0 bcf status,rp0 movf porta,0 movwf var1 movwf var2 movwf var3 movwf var4 movwf var5 movwf var6 movwf var7 movwf var8 movwf var9 movwf var10 movwf var11 movwf var12 movwf var13 movwf var14 movwf var15 movwf var16 movwf var17 goto ciclo end

Tabla 10. Empleo de los registros una vez declarados.

Para indicar en donde termina la declaración de registros, se tiene que colocar el comando ―END C‖ y hasta allí termina de realizar las declaraciones, por lo tanto, si se tiene que agregar un nuevo

registro, tan solo se tiene que escribir 19

dentro del bloque y de manera automática le proporcionara una localidad. Cuando ya fueron declarados los registros, posteriormente se procede a su empleo ya sea para guardarles un dato, o para leer el dato que contengan, en la tabla 10 se muestra un ejemplo en donde se emplea una gran cantidad de registros, los cuales durante el presente ejercicio serán empleados para alojarles un dato.

El dato será leído a través del puerto A, posteriormente se guardara en

el registro de trabajo ―W ‖, y por último el dato que se encuentre en el registro W será colocado en todos los registros que van de var1 a var17, aquí es muy importante resaltar el hecho de que la declaración de los registros fue realizada mediante un bloque. En el ejemplo mostrado en la tabla 10 se observa en la sección ―prog rama principal‖ después de la etiqueta ―ci clo‖, que de manera ordenada se tienen que ir alojando valores en cada uno de los registros identificados como ―v ar‖, mediante el empleo de una instrucción para cada uno de los registros, que en este caso se trata tan solo de 17; para cada uno de los registros se esta empleando un direccionamiento directo.

Supóngase el caso en el que se requiera el manejo

de 80 registros (no solo 17), la pregunta seria ¿se pondrán a escribir 80 instrucciones para cada uno de los registros?

Seria una cuestión de nunca

acabar, por lo que mejor recurrimos al método de direccionamiento indirecto, en el cual tan solo tenemos que indicar donde comienza la localidad de los registros que serán intervenidos, y controlar mediante un contador el acceso al siguiente registro, tal como es ilustrado en el ejemplo de la tabla 11. El código del programa ilustrado en la tabla 11 es idéntico en cuanto a la actividad que realiza el programa que se muestra en la tabla 10, pero se tiene un cambio a la manera de guardar los datos en los registros, si observa detenidamente ambos programas, el que corresponde a la tabla 11, posee menos líneas de código porque se implemento en este el método de direccionamiento indirecto, para manipular a todos los registros.

20

;========================================== ; Programa principal ;========================================== inicio bcf status,rp1 ;Direcciona el banco 1 bsf status,rp0 movlw 0xff movwf trisa ;Los bits del Puerto a como entradas movlw 0x00 movwf trisb ;Los bits del Puerto b como salidas bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x07 movwf cmcon otro bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x20 ;indica la primera localidad a manipular movwf fsr ciclo movf porta,w ;lee un dato del puerto a movwf indf ;aloja el dato en el registro indirecto movlw 0x30 ;verifica si se trata del ultimo registro xorwf fsr,w btfsc status,z goto otro incf fsr,1 goto ciclo end

LIST P=PIC16F628A ;========================================= ; Declaración de registros ;========================================= w equ 0x00 indf equ 0x00 status equ 0x03 fsr equ 0x04 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 cmcon equ 0x1f CBLOCK 0x20 ;Define donde comienza la declaración de registros var1 var2 var3 var4 var5 var6 var7 var8 var9 var10 var11 var12 var13 var14 var15 var16 var17 ENDC ;Define donde termina la declaración de registros ;========================================== ; Declaración de bits ;========================================== z equ 0x02 rp0 equ 0x05 rp1 equ 0x06 ;========================================== ; Vector del Reset ;========================================== org 0x00 goto inicio

Tabla 11. Empleo de los registros mediante direccionamiento indirecto.

El direccionamiento indirecto consiste en obtener la dirección de una localidad de memoria (memoria RAM), por medio de otro registro (File Select Register ―F SR‖) que de manera intermedia es el primero que tiene que ser consultado. El direccionamiento indirecto en los microcontroladores PIC se realiza por medio del empleo de los registros denominados en primer termino como: ―F SR‖ que es el que contendrá como dato a la localidad de memoria RAM que será manipulada, e ―IND F‖ que es el registro

en el cual se encuentra la información 21

que será escrita o leída de la localidad de memoria RAM que se esta direccionando por medio del registro FRS.

Para una mejor comprensión observe

la figura 2, en la cual se muestra que con los bits del 0 al 6 del registro FSR se direcciona una localidad de memoria RAM, mientras que la combinación generada mediante los bits 7 del registro FSR y el bit IRP del registro STATUS se puede acceder a cualquiera de los 4 bancos de memoria que posee un microcontrolador PIC.

Figura 2. Direccionamiento Directo e Indirecto en un PIC. Regresando de nuevamente al ejemplo de programa mostrado en la tabla 11, revisemos el fragmento de código que a continuación se muestra: ciclo movf movwf movlw xorwf btfsc goto incf goto Para poder

porta,w ;lee un dato del puerto a indf ;aloja el dato en el registro indirecto 0x30 ;verifica si se trata del ultimo registro fsr,w status,z otro fsr,1 ciclo emplear los registros ―i ndf‖ y ― fsr‖ tuvieron que ser declarados

mediante el comando ―eq u‖ con su 22

respectiva localidad en el mapa de

memoria de registros del microcontrolador PIC, que para el registro ―i ndf‖ se trata de la localidad 00h, y para el registro ― fsr‖ de la localidad 04h. Cuando se requiere alojar un dato de manera consecutiva en los registros de memoria RAM, se emplea la instrucción ― movwf

indf‖ (previamente tuvo que ser

cargado el dato en el registro de trabajo W) tal como se muestra en el programa de la tabla 11, pero cuando se requiere realizar la operación inversa, o sea leer de manera cíclica a los registros de memoria RAM, entonces la instrucción que tiene que ser empleada es ― movf

indf,0‖ para que el dato que contenga la localidad de

memoria RAM sea colocado en el registro de trabajo W.

En cualquiera de los

casos ya sea de escritura o lectura de una localidad de memoria RAM, lo primero que tiene que hacerse es ingresar en el registro FSR la localidad a ser intervenida. 1.5 INCREMENTO Y DECREMENTO DE DATOS DE LOS REGISTROS Incrementar o decrementar los datos de los registros, es una actividad que dependiendo de la aplicación se realiza con mucha frecuencia dentro de un programa, por ello, es que se tienen que revisar las diversas maneras de manipular la información que se encuentra alojada en los registros. 1.5.1 INCREMENTO O DECREMENTO DEL DATO DE UN REGISTRO EN UNA UNIDAD Para incrementar o decrementar el dato de un registro en una unidad, se tienen las instrucciones ―i ncf‖ y ―de cf‖ respectivamente, los cuales de manera simple realizan la operación que les corresponde, normalmente cuando observamos de manera aislada a este tipo de operaciones, en muchas ocasiones las consideramos como actividades triviales, pero debemos de estar seguros que si las empleamos de manera correcta, nuestros programas serán muy eficientes, la sintaxis completa de las instrucciones ―i ncf‖ y ―de cf‖ son las siguientes:

23

a) incf

registroX,1

;Incrementa en una unidad el dato del registro X

alojando el resultado final dentro del mismo registro X1. b) decf

registroX,1

;Decrementa en una unidad el dato del registro X

alojando el resultado final dentro del mismo registro X1. Existen otras instrucciones que a parte de realizar la tarea de incrementar o decrementar en una unidad al valor del dato de algún registro, también verifican si el resultado de la operación fue cero, teniéndose la posibilidad de diseñar un contador con pocas líneas de código, y para ello se emplean las instrucciones que se muestran con su respectiva sintaxis de manera completa a continuación: a) incfsz

registroX,1

;Incrementa en una unidad el dato del registro X

alojando el resultado final dentro del mismo registro X1, y brinca si el resultado fue 0 (cero). b) decfsz

registroX,1

;Decrementa en una unidad el dato del registro X

alojando el resultado final dentro del mismo registro X1, y brinca si el resultado fue 0 (cero). En los capítulos siguientes se mostraran ejemplos a cerca del empleo de estas instrucciones, en los cuales se muestran en aplicaciones prácticas. 1.5.2 INCREMENTO O DECREMENTO DEL DATO DE UN REGISTRO EN VALORES DIFERENTES A LA UNIDAD En diversas ocasiones se necesita que se manipule el dato de un registro, para controlar una cierta variable, para lo cual los incrementos deben ser valores diferentes de la unidad, o simplemente se tiene que sumar o restar un valor de acuerdo con la aplicación que se esta implementando, pues bien, para incrementar o decrementar el dato de algún registro con valores diferentes de la 1

Refiérase a la explicación de las instrucciones que se encuentra en el capitulo ―i nstrucciones orientadas al control de registros dentro del Modulo I.

24

unidad, se tienen las instrucciones de suma o resta respectivamente, las cuales se muestran junto con su sintaxis completa: a) addwf

registroX,1

;Suma el valor alojado en el registro W con el dato

del registro X guardando el resultado final dentro del mismo registro X2. b) subwf

registroX,1

;Resta el valor alojado en el registro W al dato del

registro X guardando el resultado final dentro del mismo registro X2. 1.6 DISEÑO DE UN CONTADOR Un contador es una de las primeras aplicaciones básicas que tienen que emplearse, por lo que en el desarrollo del presente capitulo se explicara la manera en que puede ser creado el código de un programa en le cual se tenga implementado un contador básico partiendo de registros de 8 bits, en el caso de que se requieran contadores de mas de 8 bits, la metodología mostrada en el presente capitulo será valida, pero se tendrá que recurrir a la suma o resta de registros con mas de 8 bits, y cuyas explicaciones se encuentran en los respectivos capítulos llamados ―su ma aritmética‖ y ―r esta aritmética‖ que se ubican dentro del presente capítulo. La estructura de un contador se ilustra en el diagrama de flujo de la figura 3, en la cual se muestra que se tiene que guardar un dato en un registro, que será el que fungirá como el control del contador, el valor que se alojara en el registro contador dependerá de cómo se tiene que inicializar dicho contador.

Ya

inicializado el registro contador, se procede a realizar la actividad que tiene que controlar el contador, esto es, se realiza la actividad sustancial que por ejemplo puede una serie de sumas, una serie de lecturas a través de un puerto, etc. Posteriormente a la realización de la actividad que controla el contador, se tiene que incrementar el valor del dato que se encuentra en el registro contador, para contabilizar la cantidad de eventos que se han realizado. 2

Por último, se tiene

Refiérase a la explicación de las instrucciones que se encuentra en el capitulo ―i nstrucciones orientadas al control de registros dentro del Modulo I.

25

que revisar que no se haya rebasado la cantidad de eventos a realizarse, por lo que ahora, la actividad siguiente es la de comparar el valor que se encuentra dentro del registro contador, con el valor máximo de eventos que tienen que realizarse.

Si el valor que se encuentra alojado en el registro contador, aun no

alcanza el valor máximo, entonces el proceso tiene que repetirse una vez más, por lo tanto, se tendrá que realizar nuevamente el evento de la actividad que se esta controlando.

De otra manera, si el valor del registro contador es igual al valor

máximo de los eventos que tienen que realizarse, entonces el programa tendrá que realizar una actividad diferente de la que estaba controlado con el contador, dando por terminado el contador y accediendo a un nuevo proceso.

Figura 3. Diagrama de flujo de un contador. En el diagrama de flujo del contador de la figura 3, los bloques que corresponden al control del contador son resaltados, para tener presente donde se realiza el control del contador.

Los contadores pueden desarrollarse en forma

general de dos maneras, dependiendo de si el contador se configurará como un ―con tador ascendente‖ o un ―con tador

descendente‖, pero en ambos casos la 26

estructura del contador es la misma que se ha mostrado previamente, y a continuación se muestra la estructura de los distintos tipos de contador. 1.6.1 CONTADOR ASCENDENTE El contador ascendente tiene como característica principal la de llevar un conteo ascendente en el registro contador, razón por la cual el registro contador se inicializa con un valor ―pe queño‖ que puede ser inclusive 0 (cero), dicho valor tiene que ser menor al valor máximo de eventos que tiene que controlar el contador.

Figura 4. Diagrama de flujo de un contador ascendente. Después de haber realizado la actividad que corresponde al evento que se esta controlando, el registro contador tiene que ser incrementado para precisamente llevar a cabo el conteo de la cantidad de eventos que han sido efectuados, normalmente el incremento que se aplica al registro contador es de una unidad, pero en realidad se tiene que incrementar de acuerdo a la aplicación que se esta desarrollando.

27

LIST P=PIC16F628A ;========================================= ; Declaración de registros ;========================================= w equ 0x00 status equ 0x03 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 cmcon equ 0x1f contador equ 0x20 ;========================================= ; Declaración de bits ;========================================= z equ 0x02 rp0 equ 0x05 rp1 equ 0x06 ;========================================= ; Vector del Reset ;========================================= org 0x00 goto inicio ;========================================= ; Programa principal ;========================================= inicio bcf status,rp1 ;Direcciona el banco 1 bsf status,rp0 movlw 0xff movwf trisa ;Los bits del Puerto a como entradas movlw 0x00 movwf trisb ;Los bits del Puerto b como salidas bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x07 movwf cmcon otro bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x00 ;inicia el registro contador movwf contador conteo movf porta,w ;lee un dato del puerto a movwf portb incf contador,1 ;incrementa registro contador movlw 0x05 ;verifica el valor máximo del contador xorwf contador,w btfsc status,z goto otro goto conteo end

LIST P=PIC16F628A ;========================================= ; Declaración de registros ;========================================= w equ 0x00 status equ 0x03 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 cmcon equ 0x1f contador equ 0x20 ;========================================== ; Declaración de bits ;========================================== z equ 0x02 rp0 equ 0x05 rp1 equ 0x06 ;========================================== ; Vector del Reset ;========================================== org 0x00 goto inicio ;========================================== ; Programa principal ;========================================== inicio bcf status,rp1 ;Direcciona el banco 1 bsf status,rp0 movlw 0xff movwf trisa ;Los bits del Puerto a como entradas movlw 0x00 movwf trisb ;Los bits del Puerto b como salidas bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x07 movwf cmcon otro bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x00 ;inicia el registro contador movwf contador conteo movf porta,w ;lee un dato del puerto a movwf portb movlw 0x01 addwf contador,1 ;incrementa registro contador movlw 0x05 ;verifica el valor máximo del contador xorwf contador,w btfsc status,z goto otro goto conteo end

Tabla 12. Ejemplos de programa para un contador ascendente.

Una vez que se ha incrementado el valor del registro contador, se procede a comparar el valor del registro contador con el valor máximo de la cantidad de eventos que tienen que desarrollarse, este valor puede encontrarse dentro de un registro

al

que

podemos

llamar

―Va lormaximo‖.

28

Si después de

―i ncrementar‖ el dato del valor del registro contador aun no es igual al valor máximo, entonces se tiene que aplicar un nuevo incremento al registro contador, y así sucesivamente hasta que alcance su valor total. En los ejemplos de programa ilustrados en la tabla 12, se propone el empleo de un microcontrolador PIC16F628A, pero en realidad por el momento no es relevante el microcontrolador PIC que sea empleado, ya que el código para realizar el conteo es valido para cualquier PIC.

Los programas mostrados en la

tabla 12 controlan un contador ascendente, realizando ambos programas idénticas funciones, teniendo solo un cambio en cuanto a las líneas de sus respectivos códigos.

El cambio existente entre los programas radica en la instrucción que

efectúa el incremento del registro contador. instrucción ―inc f

En un programa se emplea la

contador,1‖ la cual indica que se incremente en una unidad el

valor del registro ―con tador‖ guardando el resultado en el mismo registro.

Por

otra parte en el segundo programa que también se encuentra en la tabla 12, se emplea el par de instrucciones ― movlw

0x01‖ y ―ad dwf contador,1‖, las cuales

en primer instancia cargan el registro de trabajo W con el valor al cual tendrá que ser incrementado el registro contador, siendo el valor de 01h para el presente ejemplo, mientras que por medio de la instrucción addwf, se realiza la suma del registro contador con el valor que fue cargado en el registro de trabajo W, guardando el resultado de la suma en el mismo registro contador; si fuera necesario que el incremento que será sumado al registro contador sea diferente de 01h, tan solo se tiene que cargar el valor correspondiente en el registro de trabajo W.

Posterior al incremento del registro contador se tiene que verificar si

ya se llego al valor máximo de eventos realizados, para el presente ejemplo el incremento se tiene que realizar hasta que se alcanza el valor máximo de 5 (el proceso de comparación será mostrado con detalle en el capitulo de funciones lógicas que se encuentra dentro del presente capítulo). El evento que se esta controlando es el de leer el un dato a través del puerto a, y escribir ese mismo dato en el puerto

b.

29

1.6.2 CONTADOR DESCENDENTE El contador descendente a deferencia del contador ascendente, realiza el control del contador a través de un conteo descendente, tal como es ilustrado en la figura 5.

Figura 5. Diagrama de flujo de un contador descendente. Se observa gráficamente en el diagrama de flujo de la figura 5 que cuando se inicializa el registro contador, tiene que ser con el valor del total de los eventos que tendrán que efectuarse. A continuación se realiza la actividad del evento que se esta controlando, para posteriormente realizar un decremento en el valor del registro contador, recordando que el valor inicial que se encuentra dentro del registro contador es el valor máximo de eventos.

El decremento que se realiza en el registro contador

puede ser de unidad en unidad conforme se vayan ejecutando los eventos uno a uno, por lo tanto, cuando se realice el último evento, el valor que debe encontrarse alojado en el registro contador es igual a 0 (cero). unidad en unidad, o un valor diferente

El decremento puede ser de

de 1 lo que da origen el empleo de las 30

instrucciones ―de cf‖ o ―sub wf‖ respectivamente. LIST P=PIC16F628A ;========================================= ; Declaración de registros ;========================================= w equ 0x00 status equ 0x03 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 cmcon equ 0x1f contador equ 0x20 ;========================================= ; Declaración de bits ;========================================= z equ 0x02 rp0 equ 0x05 rp1 equ 0x06 ;========================================= ; Vector del Reset ;========================================= org 0x00 goto inicio ;========================================= ; Programa principal ;========================================= inicio bcf status,rp1 ;Direcciona el banco 1 bsf status,rp0 movlw 0xff movwf trisa ;Los bits del Puerto a como entradas movlw 0x00 movwf trisb ;Los bits del Puerto b como salidas bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x07 movwf cmcon otro bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x05 ;inicia el registro contador movwf contador conteo movf porta,w ;lee un dato del puerto a movwf portb decf contador,1 ;decrementa registro contador movlw 0x00 ;verifica el valor mínimo del contador xorwf contador,w btfsc status,z goto otro goto conteo end

LIST P=PIC16F628A ;========================================= ; Declaración de registros ;========================================= w equ 0x00 status equ 0x03 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 cmcon equ 0x1f contador equ 0x20 ;========================================== ; Declaración de bits ;========================================== z equ 0x02 rp0 equ 0x05 rp1 equ 0x06 ;========================================== ; Vector del Reset ;========================================== org 0x00 goto inicio ;========================================== ; Programa principal ;========================================== inicio bcf status,rp1 ;Direcciona el banco 1 bsf status,rp0 movlw 0xff movwf trisa ;Los bits del Puerto a como entradas movlw 0x00 movwf trisb ;Los bits del Puerto b como salidas bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x07 movwf cmcon otro bcf status,rp1 ;Direcciona el banco 0 bcf status,rp0 movlw 0x05 ;inicia el registro contador movwf contador conteo movf porta,w ;lee un dato del puerto a movwf portb movlw 0x01 subwf contador,1 ;decrementa registro contador movlw 0x00 ;verifica el valor mínimo del contador xorwf contador,w btfsc status,z goto otro goto conteo end

Tabla 13. Ejemplos de programa para un contador descendente.

En la tabla 13 se muestran 2 programas que tienen implementados un contador descendente cada uno, de los cuales la diferencia radica en que en un programa el decremento se realiza

mediante 31

una

instrucción

que

decrementa unidad por unidad (decf), mientras que en el segundo programa el decremento se realiza mediante una instrucción de resta (subwf), en la cual se puede definir el valor del decremento, mediante un dato que se guarda previamente en el registro de trabajo W. 1.7 DISEÑO DE UN RETARDO BÁSICO POR BUCLES Una de las aplicaciones que se requiere implementar para controlar el tiempo de un proceso, es una rutina a base de un contador en el cual se toma en consideración el tiempo que emplea una instrucción en ejecutarse.

Figura 6. Diagrama de flujo de un retardo. La implementación de un retardo por bucles (también llamado temporizador) toma como base la estructura de un contador, por lo que en primera instancia se tiene que definir el tipo de contador que será empleado.

Normalmente se trata

de utilizar contadores descendentes, porque es más fácil definir un valor inicial a partir del cual se tendrá que ir decrementando hasta llegar a cero, en la figura 6 se ilustra el diagrama de flujo de un

contador descendente, a través del 32

cual esta implementado el retardo. La diferencia entre un temporizador y un contador es que al evento que controla el temporizador, se encuentra relacionado con la función de decrementar el dato del registro que se emplea para contabilizar el tiempo que esta transcurriendo.

La temporización se termina en el momento que el registro

decrementado llega a cero. A partir del diagrama de flujo de la figura 6, se obtiene el código que corresponde con el programa de un temporizador, el cual a su vez se muestra en la tabla 14.

Las líneas del programa que se encuentran relacionadas de

manera directa con la función del temporizador son las que se muestran en la tabla 14. movlw movwf bucle decfsz

0x02 contador

;se carga el valor de 02h en el registro de trabajo W. ;el valor W se carga en el registro ―c ontador‖.

contador,1

;decrementa el valor del registro contador en una ;unidad, y si el registro contador es igual a cero. ;Se genera un salto saliendo del ciclo del ;decremento.

goto bucle instrucciones de un proceso siguiente . . . end

Tabla 14. Estructura básica de un temporizador.

Del fragmento de programa mostrado en la tabla 14, se observa que un registro llamado ―con tador‖ es el que mantiene el control de la temporización, ya que en el programa este registro va decrementando su valor, mientras se ejecutan las instrucciones que conforman al código del temporizador.

Se observa

también que el dato que se encuentra alojado en el registro ―con tador‖, se decrementará hasta que llegue a cero.

Cuando el valor del registro

―con tador‖ llegue a cero la temporización habrá terminado, mientras esto sucede,

33

el microcontrolador se quedara cautivo realizando la actividad de controlar al temporizador. Hemos observado que la ejecución del programa que se encuentra en la tabla 14, controla el tiempo de un temporizador, pero la pregunta natural que surge a continuación es:

¿De que manera podemos controlar el tiempo en un programa

temporizador?

La respuesta es la siguiente, si echamos un vistazo al listado

de instrucciones del microcontrolador PIC, encontraremos que la ejecución de las instrucciones (cualquiera que sea) tienen implícito el consumo de un tiempo, que es el que se tarda la instrucción en llevarse a cabo (ejecutarse).

Para

determinar el tiempo que tarda una instrucción en ejecutarse, se hace referencia a un término que nos auxilia en la determinación de dicho tiempo.

El término es el

denominado ―ci clo de instrucción‖ o simplemente ―ci clo‖, este ciclo a su vez se encuentra relacionados con la frecuencia a la cual se ejecutan las instrucciones en el microcontrolador, recordando que se debe de disponer de un circuito oscilador para que el microcontrolador.

En el listado de instrucciones de los

microcontroladores PIC, se indican la cantidad de ciclos que consume la ejecución de cada una de las instrucciones que componen al listado. Los ciclos de instrucción o ciclos en un microcontrolador PIC, equivalen a la cuarta parte de la frecuencia que proporciona el circuito oscilador. En la tabla 15 se muestra el programa que controla a un temporizador, en el se observa que de acuerdo con el listado de instrucciones de un microcontrolador PIC, la cantidad de ciclos que consume cada una de las instrucciones que conforman al programa del temporizador.

Teniéndose en cuenta que casi todas

las instrucciones requieren de un solo ciclo para que la instrucción se ejecute completamente, y en algunos casos las instrucciones requieren de 2 ciclos para que estas sean ejecutadas, y en otros casos especiales, tal como es la instrucción ―de cfsz‖ requieren ya sea de 1 ó 2 ciclos, a continuación se explica la manera en como trabaja la instrucción y dependiendo de la situación la cantidad de ciclos que consume. 34

movlw 0x02 movwf contador bucle decfsz contador,1 ; 1 ó 2 ciclos. goto bucle ; 2 ciclos. instrucciones de un proceso siguiente . . . end

Tabla 15. Cantidad de ciclos que consumen las instrucciones de un temporizador.

La instrucción ―de cfsz‖ lleva a cabo el decremento del valor de un registro, y mientras no llegue a cero el valor del registro decrementado, se ejecuta la instrucción que se encuentra expresada debajo de decfsz, consumiendo esta actividad 1 ciclo.

Pero si al ejecutar la instrucción decfsz el valor del registro

decrementado alcanzo el valor de cero, se provoca un brinco, por lo tanto, el microcontrolador omitirá la ejecución de la instrucción siguiente, pasando a la que se encuentra en segundo término después de decfsz, teniéndose en esta actividad el consumo de 2 ciclos. En la tabla 15 se muestran las cantidades de ciclos que consumen cada una de las instrucciones de un temporizador, por lo tanto, en principio con estos datos se deben de contabilizar la cantidad total de ciclos, que fueron consumidos desde que se da inicio con la rutina de temporización, hasta que el valor del registro contador llega a cero, para ello refiérase a la tabla 16, en donde se muestra detalladamente la manera en que se lleva a cabo el conteo de los ciclos totales. El ejemplo mostrado en la tabla 16 nos indica que en el paso 1 las 2 primeras instrucciones que son ejecutadas, cargan en el registro ―con tador‖ el valor 02h, por lo tanto ya se tiene el valor en el registro que se encargara de controlar al temporizador; como paso siguiente se tiene la instrucción ―de cfsz contador,1‖ que al ejecutarse decrementa el valor del registro contador a la vez guarda el resultado en el mismo registro; se tiene que

35

recordar que el valor inicial del registro

―con tador‖ es 02h, por lo que después de ejecutar la instrucción, el valor que ahora se encontrara en el registro contador será el de 01h; como el resultado en el registro contador no fue cero, la ejecución de la instrucción ―d ecfsz

contador,1‖

será de 1 ciclo; posteriormente se lleva a cabo la ejecución de ―g oto

bucle‖, esta

instrucción consume 2 ciclos, y provoca que se lleve a cabo un brinco al lugar donde se encuentra la etiqueta bucle, preparando una nueva secuencia en el control del temporizador; de manera acumulada en esta etapa se tiene un total de 3 ciclos. PASO 1

PASO 2

movlw 0x02 ;contador = 02h movwf contador bucle decfsz contador,1 ; 1 ciclo. goto bucle ; 2 ciclos. instrucciones de un proceso siguiente . . . end

movlw 0x02 movwf contador bucle decfsz contador,1 ; 2 ciclos. goto bucle ; no se ejecuta instrucciones de un proceso siguiente . . . end

contador = 01h ciclos = 3

contador = 00h ciclos = 2 PASO 1 ciclos = 3 + PASO 2 ciclos = 2

Ciclos totales = 5

Tabla 16. Ejecución del programa temporizador. En el paso 2 del programa de la tabla 16, las instrucciones son ejecutadas a partir de la ubicación de la etiqueta bucle, por lo que a continuación toca el turno nuevamente de la instrucción ―d ecfsz

contador,1‖, que al ser procesada

proporcionará como resultado el decremento del valor del registro ―con tador‖, que al inicio del paso 2 se encontraba con un valor igual a 01h, y después de ejecutar la instrucción del decremento, el valor que se encontrara en el registro ―con tador‖ será igual con cero, trayendo como consecuencia que en el paso 2 la instrucción decfsz consuma 2 ciclos, además de que la instrucción ―g oto

bucle‖ no será

ejecutada, pasando a la instrucción que continua después de goto, dando por

36

terminado el proceso del temporizador; el paso 2 proporciona un total de 2 ciclos. La suma de los ciclos totales del paso 1 con los del paso 2, dan un total de 5 ciclos que son los que se consumen en el temporizador, observe la tabla 16. Para determinar el tiempo que se consumió con la ejecución de los 5 ciclos del programa temporizador, se debe calcular el tiempo que consume cada ciclo de manera independiente, para ello nos basaremos en las relaciones que son mostradas en la tabla 17. Ciclo de instrucción o ciclo =

Foscilador 4

Si la frecuencia del oscilador es de 4 MHz, entonces: Ciclo de instrucción o ciclo =

4Mhz 4

El tiempo que tarda cada ciclo de instrucción es =

El tiempo de cada ciclo es =

= 1 MHz.

1 Ciclo _ de _ instrucció n

1 1MHz

= 1 μseg.

Por lo tanto para 5 ciclos se tiene un tiempo de: (5 Ciclos) * (1 μseg) = 5 μseg.

Tabla 17. Relaciones matemáticas para calcular el tiempo.

Del cálculo que se mostrado en la tabla 17 se observa que el tiempo resultante es muy pequeño, por lo tanto, si lo que se requiere es implementar un temporizador para un valor de tiempo más amplio, se tiene que colocar un valor más grande al registro ―con tador‖, para que a su vez el número de ciclos se incremente, tal como se ilustra en el programa de la tabla 18. En el programa mostrado en la figura 18, se observa que las 2 primeras instrucciones del paso 1 se emplean para cargar el valor 16610 en el registro ―con tador‖.

Por otra parte, mientras el valor del registro contador sea mayor que

cero, cada vez que es decrementado el valor del registro ―con tador‖ mediante la instrucción decfsz, esta consume 1

ciclo, más los 2 ciclos que aporta la 37

instrucción goto.

Esto último significa que los 3 ciclos resultantes se repetirán

165 veces, porque el dato que esta guardado en el registro ― contador‖ se estará decrementando unidad por unidad, comenzando por valor de 16610 hasta llegar a 110.

En la tabla 18 se muestra en la parte correspondiente al paso 1 la

cantidad de ciclos que se acumulan mientras en valor en el registro ―con tador‖ es mayor que cero. PASO 1

PASO 2

movlw .166 ;contador = 16610 movwf contador bucle decfsz contador,1 ; 1 ciclo. goto bucle ; 2 ciclos. instrucciones de un proceso siguiente . . . end

movlw .166 movwf contador bucle decfsz contador,1 ; 2 ciclos. goto bucle ; no se ejecuta instrucciones de un proceso siguiente . . . end

Después de decrementar 165 veces el valor del contador = 00h registro ― contador‖; contador = 110 ciclos = 2 ciclos = (165) * 3 = 495 PASO 1 ciclos = 495 + PASO 2 ciclos = 2

Ciclos totales = 497

Tabla 18. Tiempo base para un temporizador de 0.5mseg

Para acceder al paso 2 en el programa de la tabla 18, el valor en el registro ―con tador‖ debe ser cero, por lo que se tendrá que la ejecución de la instrucción decfsz es de 2 ciclos.

El total de ciclos se obtiene de la suma de los generados

en el paso 1 y en el paso 2, dando un total de 497 ciclos. Para calcular el tiempo en el que se ejecutan los 497 ciclos, se hace referencia a las relaciones matemáticas de la tabla 17, por lo que supongamos que se tiene un oscilador de 4 Mhz, con el que nos arrojara un término de 1 μseg, para cada ciclo que es ejecutado, por lo tanto, los 497 ciclos son ejecutados en 497 μseg, que a su vez es un valor muy cercano a

500

38

μseg,

que

también

puede

interpretarse como 0.5 mseg.

El tiempo de 0.5 mseg lo podemos tomar como

base para a partir de este valor generar temporizadores más grandes, tal como se muestra en los ejemplos de la tabla 19. EJEMPLO 1

movlw .08 ;repite 8 veces la base de tiempo. movwf var2 ciclo_2 movlw .166 movwf var1 ciclo_1 decfsz var1,1 ;base de tiempo de 0.5 mseg. goto ciclo_1 decfsz var2,1 goto ciclo_2 ….…. otras instrucciones 0.5 mseg * 8 veces = 4 mseg

EJEMPLO 2

movlw .255 ;repite 255 veces la temporIzación movwf var3 ;de 4 mseg. ciclo_3 movlw .08 movwf var2 ciclo_2 movlw .166 movwf var1 ciclo_1 decfsz var1,1 ;base de 0.5 mseg. goto ciclo_1 decfsz var2,1 goto ciclo_2 decfsz var3,1 goto ciclo_3 ….…. otras instrucciones 4 mseg * 255 veces = 1 seg

Tabla 19. Ejemplos con distintos valores de temporización.

En los ejemplos mostrados en la tabla 19 se muestra que se puede realizar un conteo largo de tiempo, y para ello basta con generar una estructura de contadores descontentes anidados unos en otros, esto es, en el momento que un contador a llevado a cero el valor de un registro, se procede a decrementar el valor de otro registro, y así sucesivamente, hasta que todos los registros involucrados son decrementados totalmente, generando bases de tiempo como las mostradas en los ejemplos ilustrados en la tabla 19. Por último, se recomienda que para implementar una rutina con temporizador dentro de un programa, se realice por medio de la invocación de una subrutina, para que cuando esta agote el tiempo que ha sido establecido mediante el cálculo correspondiente, el programa continué con la secuencia normal en cuanto a la ejecución de las instrucciones, y cuando nuevamente requiera ser empleada la rutina del temporizador, nuevamente sea llamada mediante un servicio de subrutina.

39

LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 00h status equ 0x03 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 cmcon equ 0x1f var1 equ 0x20 var2 equ 0x21 var3 equ 0x22 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;carry (acarreo) z equ 2 ;bit del cero rp0 equ 5 ;registro de selección de banco rp1 equ 6 ; ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 movlw 0xff ;Puerto A como entradas movwf trisa movlw 0x00 ;Puerto B como salidas movwf trisb bcf status,rp0 ;cambiar al banco 0 bcf status,rp1

movlw b'00000111' movwf cmcon Ciclo bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 btfsc porta,1 goto sipresionado goto nopresionado nopresionado bcf portb,2 call temporizador goto ciclo sipresionado bsf portb,2 call temporizador goto ciclo ;--------------------------------------------;Subrutina ;--------------------------------------------temporizador ;Retardo de 1 segundo movlw .255 movwf var1 ciclo_3 movlw .08 movwf var2 ciclo_2 movlw .166 movwf var3 ciclo_1 decfsz var3,1 ;0.5 milisegundos goto ciclo_1 decfsz var2,1 goto ciclo_2 decfsz var1,1 goto ciclo_3 return end

Tabla 20. Programa con un temporizador de 1 segundo.

En la tabla 20 se muestra el programa que emplea una rutina con un temporizador de 1 segundo, que es llamado mediante una subrutina cada vez que se manipula el bit 2 del puerto B.

El temporizador es empleado para mostrar el

cambio que se manifiesta en el bit 1 del puerto A.

Cabe recordar que cada vez

que es empleada la rutina temporizadora, el microcontrolador dedica toda su atención a la ejecución del temporizador, olvidándose durante ese periodo de tiempo de las demás actividades a las que tiene que controlar. 1.8 SUMA ARITMÉTICA La realización de operaciones aritméticas básicas es un factor muy importante en el desarrollo del código de un

programa para un proyecto que emplea 40

algún microcontrolador, motivo por el cual en primera instancia comenzaremos con la operación de la suma aritmética, y para ello recordaremos la manera en como aprendimos a realizarla en nuestros estudios primarios, ya que para efectos de programación en un microcontrolador se hace de la misma manera. Para comprender la forma en que se hacen las sumas en un microcontrolador, vamos a realizar un ejemplo con números decimales, tal como se ilustra en la tabla 21. EJEMPLO 1

EJEMPLO 2

2 1 Digito + 3 1 Digito ============= = 0 5 1 Digito Resultado Acarreo

5 1 Digito + 6 1 Digito ============= = 1 1 2 Dígitos Resultado Acarreo

Tabla 21. Ejemplos de una suma aritmética con números decimales. Del ejemplo 1 mostrado en la tabla 21, se observa la suma de 2 números cuya magnitud es de un digito respectivamente (2 + 3), el resultado de la suma se expresa de igual manera mediante un solo digito (5), por lo tanto se asume que al ―cab er‖ el resultado en un digito, el acarreo que se generó en la suma es igual a cero.

Ahora observemos el ejemplo 2 de la misma tabla 21, en donde de

nueva cuenta se realiza una suma de 2 números con magnitud de 1 digito en cada uno de ellos (5 + 6), el resultado en esta oportunidad es un número que ocupa 2 dígitos (11), por lo tanto, el resultado no se puede expresar en un solo digito ya que no cabe, para este caso el resultado final se descompone generando un resultado de un digito (el valor 1) y un acarreo (el valor decimal 1), para que se le de continuidad al número de dígitos que se esta empleando. De la misma manera en que se realiza una suma aritmética con números decimales, se aplica el mismo procedimiento para números binarios que son con los que trabaja el microcontrolador, por lo tanto, se debe de tomar en cuenta la cantidad de bits que componen a los

números binarios que serán operados,

41

ya que de acuerdo a las cantidades que se sumen se pueden generar acarreos, mismos que deben de tomarse en cuenta para obtener un resultado real, de otra manera seria erróneo el resultado. EJEMPLO 1

EJEMPLO 2

01101100 8 Bits + 00110111 8 Bits ====================== = 0 10100011 8 Bits Resultado Acarreo

11101100 8 Bits + 01110111 8 Bits ====================== = 1 01100011 8 Bits Resultado Acarreo

Tabla 22. Ejemplos de una suma aritmética con números binarios. En los ejemplos expresados en la tabla 22 se muestran las sumas de números binarios compuestos por 8 bits cada uno de ellos, y en cada una de las operaciones se van sumando los números bit a bit, de tal suerte que el resultado al que se llega en el ejemplo 1 el acarreo es igual con cero, lo que significa que el resultado se puede expresar mediante 8 bits.

Por otra parte, el resultado que

se muestra en el ejemplo 2 requiere de un bit de más, ya que el resultado prácticamente no puede expresarse mediante 8 bits, porque se perdería el dato final.

Para que el resultado de la suma pueda considerarse como un número

completo, a los 8 bits se les tiene que agregar un bit más que recibe el nombre de bit de acarreo. Para realizar la suma de 2 números binarios de 8 bits en un microcontrolador PIC, se pueden emplear una de dos instrucciones de acuerdo a la forma en como se requieran aplicar, las instrucciones de suma con las que cuentan los microcontroladores PIC se describen a continuación: a) addlw k.- Suma el dato que se encuentra en el registro de trabajo W con el de un valor literal dejando el resultado en el registro de trabajo W, modificando su valor con respecto del que tenia anteriormente.

El dato del registro de trabajo

W como el del valor literal son de 8 bits. b) addwf f,d.- Suma el dato que se

encuentra en el registro de trabajo W 42

con el valor de un registro f (registro de memoria RAM) dejando el resultado de la suma ya sea en el registro de trabajo W o en el registro f, dependiendo del valor que adquiera d (para una mejor referencia consulte el capitulo ―i nstrucciones orientadas al control de registros‖ e ―i nstrucciones orientadas al control de literales‖, ambos temas pertenecientes al modulo I). Cabe aclarar que siempre que se requiera sumar el dato de 2 registros de memoria RAM, en un microcontrolador PIC se tiene que hacer mediante la carga previa del valor de uno de los registros a W, ya que en un microcontrolador PIC no existe una instrucción que realice la suma de valores entre 2 registros de memoria RAM de manera directa.

Figura 7. Suma de 2 registros de 8 bits. A continuación procederemos a explicar la manera en que se realiza la suma aritmética de dos valores de 8 bits con un microcontrolador PIC, tal como se ilustra en el bloque del diagrama de flujo de la figura 7, en donde se tiene que sumar el dato del registro var1 con el dato del registro var2 y el resultado de la suma alojarlo en el registro var3, para ello en primera instancia se tiene que enviar el dato de cualquiera de los registros que se van a sumar al registro de trabajo W, para posteriormente sumar el dato del registro W con el dato del registro restante, tal como se ilustra en el fragmento de código expresado en la tabla 23. movf addwf

var1,0 var2,0

movwf

var3

;carga el dato del registro var1 al registro de trabajo W. ;suma el dato del registro var2 con el del registro W, dejando el ;resultado en el mismo registro W. ;el dato del registro W lo guarda en el registro var3.

Tabla 23. Suma de 2 registros.

43

El fragmento de código mostrado en la tabla 23 es el correspondiente al de una suma entre registros de 8 bits, pero si el resultado de la suma produce un acarreo, significa que el dato resultante de la suma fue mayor a 8 bits, por lo tanto, se debe de tomar en cuenta el bit de acarreo tal como se ilustra en el diagrama de flujo de la figura

Figura 8. Diagrama de flujo de una suma de registros de 8 bits.

44

LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 var1 equ 0x20 var2 equ 0x21 var3 equ 0x22 acarreo equ 0x23 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo z equ 2 ;bandera del cero rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,c movf var1,0 ;carga el dato del registro var1 al registro de trabajo W. addwf var2,0 ;suma el dato del registro var2 con el del registro W, dejando el ;resultado en el mismo registro W. movwf var3 ;el dato del registro W lo guarda en el registro var3. btfsc status,c goto siaca goto noaca siaca incf acarreo,1 noaca siguiente proceso . . . end

Tabla 24. Programa que suma 2 registros de 8 bits.

Después de realizar la suma que se ilustra en el diagrama de flujo de la figura 8, se tiene que revisar el estado que se genero en el bit que indica la formación de un

acarreo,

cuando

se

aplico

la

operación de la suma.

45

El bit de

acarreo se encuentra ubicado dentro del registro ―stat us‖, por lo que el bit de acarreo es una bandera que indica cualquiera de los siguientes estados: 

Si el bit de acarreo ―C ‖ es igual con 0 significa que el resultado de una suma es igual o menor a los 8 bits de los registros a sumarse.



Si el bit de acarreo ―C ‖ es igual con 1 significa que el resultado de una suma es mayor de los 8 bits de los registros a sumarse. El bit de acarreo debe tomarse en cuenta, ya que si el resultado solo es

expresado mediante los 8 bits, el resultado final no será correcto, es por ello que si al verificar el bit de acarreo este tiene un 1 lógico, se tiene que guardar el bit que rebasa a los 8 para que se tenga un resultado correcto, por lo que ahora el resultado será expresado por 2 registros de 8 bits en lugar de solo uno.

En el

diagrama de flujo de la figura 8, el registro donde se van acumulado los bits de acarreo, esta identificado como registro de ―aca rreo‖.

En el código expresado en

la tabla 24 se muestra el programa correspondiente a la suma del diagrama de flujo de la figura 8.

Figura 9. Suma entre 2 datos de 16 bits. Por otra parte, para realizan sumas con datos de registros de más de 8 bits, implica que debemos armar datos con más de un registro, por ejemplo, para realizar sumas con datos de 16 bits se necesita el espacio de 2 registros, para ello se debe de tomar en cuenta el orden de cada uno de los bits que componen a los datos, sobre todo para determinar el peso específico de cada uno de los registros, que en esta oportunidad al tratarse de un dato de 16 bits, uno de los registros será considerado

como

el

byte

menos

significativo, y el segundo registro 46

como el byte más significativo. En la figura 9 se ilustra la necesidad de realizar una suma aritmética entre 2 datos compuestos por 16 bits cada uno, por lo que tendremos que recurrir a lo expresado en la tabla 25, en donde se muestra la manera de cómo deben de ordenarse los registros de 8 bits, que están involucrados con la operación de datos de 16 bits y que pertenecen a los sumandos. Ejemplo de una suma de datos de 16 bits

Conformación de un dato de 16 bits oper1 = reg1,reg2 oper2 = reg3,reg4 oper3 = reg5,reg6 oper1 = reg1,reg2 + oper2 = reg3,reg4 =================== oper3 = reg5,reg6

10101010,01101100 + 01110001,10110111 ====================== = 1 00011100,00100011

16 Bits 16 Bits

16 Bits reg6 reg5 Acarreo

Tabla 25. Estructura de una suma con datos de 16 bits.

Los datos identificados como ―op er1‖, ―o per2‖ y ―op er3‖ se encuentran conformados por 2 registros de 8 bits cada uno de ellos, dichos registros deben de ser operados en el orden que aparecen en la tabla 25, porque cada uno de los registros contiene un peso específico.

El resultado de la operación de la suma

se guarda en los registros que para tal efecto fueron contemplados, tomando en cuenta el valor del posible acarreo. Para iniciar la adición de datos de 16 bits, primero se suman entre si los registros de menor peso de cada operando, identificados como ―r eg2‖ y ―r eg4‖. El resultado de la suma se aloja en el registro ―r eg6‖, además al resultado de esta primera suma se verifica si se origino un acarreo, si fue así, este acarreo se tiene que adicionar al registro de mayor peso (― reg1‖) del primer operando, en el diagrama de flujo de la figura 10 se ilustra una suma de 2 operandos de 16 bits. Posteriormente se realiza la adición de los registros de mayor peso de cada uno de los operandos (tomando en

cuenta el acarreo, si es que lo hubo, en 47

la suma de los registros de menor peso de los operandos), el resultado de esta segunda suma se guarda en el registro ―r eg5‖.

48

Figura 10. Diagrama de flujo de una suma entre datos de 16 bits.

49

LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 reg1 equ 0x20 reg2 equ 0x21 reg3 equ 0x22 reg4 equ 0x23 reg5 equ 0x24 reg6 equ 0x25 acarreo equ 0x26 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo z equ 2 ;bandera del cero rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,c ;limpia la bandera del acarreo. movf reg2,0 ;carga el dato del registro reg2 al registro de trabajo W. addwf reg4,0 ;suma el dato del registro reg4 con el del registro W, dejando el ;resultado en el mismo registro W. movwf reg6 ;el dato del registro W lo guarda en el registro reg6. btfsc status,c ;pregunta si existió acarreo en la suma. goto siaca1 goto noaca1 siaca1 incf reg1,1 ;sí existe acarreo se incrementa en una unidad el registro reg1. noaca1 bcf status,c ;limpia la bandera del acarreo. movf reg1,0 ;carga el dato del registro reg1 al registro de trabajo W. addwf reg3,0 ;suma el dato del registro reg3 con el del registro W, dejando el ;resultado en el mismo registro W. movwf reg5 ;pregunta si existió acarreo en la suma. btfsc status,c goto siaca2 goto noaca2 siaca2 incf acarreo,1 ;sí existe acarreo se incrementa en una unidad el registro acarreo. noaca2 siguiente proceso . . . end

Tabla 26. Programa que suma 2 datos registros de 16 bits.

Por último, para que el resultado final de la suma sea correcto, debe contemplarse además de los registros

donde se colocará el resultado (reg5 y 50

reg6), un registro más para que ahí se aloje el acarreo que se origine con la segunda adición entre los registros de mayor peso de los operandos, de otra manera, si existiera un acarreo y no se tomará en cuenta, el resultado total de la suma seria completamente erróneo, en la tabla 26 se muestra el código para un programa en donde se suman 2 datos de 16 bits. Cuando sea necesario realizar sumas con operandos de más de 8 bits, el procedimiento para realizarlas es tal como el ilustrado en la tabla 25, tomando en cuenta que la suma total se va realizando por medio de registros de 8 bits, por lo que podemos hacer sumas con datos de 16, 24, 32, …. Bits.

En todas las

sumas se debe de tomar en cuanta el acarreo que se va generando cada vez que se van sumando registros de 8 bits. En los códigos de los programas que se han ilustrado, se ha empleado un microcontrolador PIC16F628A, pero puede emplearse cualquier microcontrolador, ya que el código de las sumas no cambia. 1.9 RESTA ARITMÉTICA La resta es una de las operaciones aritméticas que pueden realizarse con un microcontrolador PIC, siendo esta operación muy útil para aplicaciones que tengan que desarrollarse, como lo son por ejemplo para una función con un convertidor analógico – digital.

En la tabla 27 se muestra una operación de resta típica con

números decimales.

EJEMPLO 1

EJEMPLO 2

6 1 Digito - 4 1 Digito ============= = + 2 1 Digito Resultado Positivo

6 1 Digito - 9 1 Digito ============= = - 3 1 Dígito Resultado Negativo

51

Tabla 27. Ejemplos de una suma aritmética con números decimales.

En un microcontrolador PIC la operación de la resta se realiza por medio de una instrucción que a su vez recurre al método de restas por complemento a 2, en la tabla 28 se ilustra un ejemplo de resta que utiliza complemento a 2 para realizar la operación. Resta de 2 números de 8 bits por complemento a 2

Resta de 2 números de 8 bits 11101100 Minuendo - 00110111 Sustraendo ====================== = + 10110101 Resultado Positivo

00110111 El sustraendo se complementa 11001000 + 1 ============= = 11001001 Sustraendo complementado a 2 11101100 Minuendo + 11001001 Sustraendo complementado a 2 ============= = 1 10110101 Resultado Acarreo

Tabla 28. Realización de una resta por complemento a 2.

Una resta por complemento a 2 se realiza a través de sumas, las cuales en primer término tiene que complementarse el operando llamado sustraendo tal como se ilustra en la tabla 28.

Para complementar al sustraendo se efectúa la

acción de cambiar los unos (1’s) por ceros (0’s) y los ceros por unos, posteriormente al complemento se le adiciona una unidad, dando como resultado el complemento a 2 del operando sustraendo.

El sustraendo (complementado

a 2) se suma al minuendo obteniendo como resultado el de la resta del minuendo menos el sustraendo. Todo el procedimiento de la resta por complemento a 2 la tiene implementada el microcontrolador PIC a través de 2 instrucciones que efectúan el mismo procedimiento, las instrucciones de resta se describen a continuación: a) sublw k.- Resta el dato que se

encuentra en el registro de trabajo W 52

con el de un valor literal dejando el resultado en el registro de trabajo W, modificando su valor con respecto del que tenia anteriormente.

El dato del

registro de trabajo W como el del valor literal son de 8 bits. b) subwf f,d.- Resta el dato que se encuentra en el registro de trabajo W al del valor de un registro f (registro de memoria RAM) dejando el resultado de la suma ya sea en el registro de trabajo W o en el registro f, dependiendo del valor que adquiera d (para una mejor referencia consulte el capitulo ―i nstrucciones orientadas al control de registros‖ e ―i nstrucciones orientadas al control de literales‖, ambos temas pertenecientes al modulo I).

Resta de 2 números de 8 bits por complemento a 2

Resta de 2 números de 8 bits -

10011100 11000111

Minuendo Sustraendo

11000111 El sustraendo se complementa 00111000 + 1 ============= = 00111001 Sustraendo complementado a 2 10011100 Minuendo + 00111001 Sustraendo complementado a 2 ============= = 0 11010101 Resultado Acarreo

53

====================== = - 00101011 Resultado Negativo

Acarreo = 0 resultado es negativo Acarreo = 1 resultado es positivo Como el acarreo fue igual con 0, el resultado 11010101 se complementa a 2. 00101010 Los 1 se cambian por 0 y los 0 por 1 + 1 Al complemento se le adiciona un 1 ========= =00101011 La magnitud es negativa

Tabla 29. Resta con resultado negativo.

Las instrucciones ―sub lw‖ y ―sub wf‖ emplean el método de restas por complemento a 2, además de que ambas instrucciones operan 2 datos de 8 bits cada una.

En cualquier microcontrolador al ejecutar las instrucciones de

restas, el resultado debe indicarse ya sea que se obtenga un valor positivo o uno negativo, para el caso de los microcontroladores PIC los números negativos y positivos se indican a través de la bandera del acarreo que se encuentra dentro del registro status.

Cuando la bandera del acarreo se coloca en 1 lógico

después de realizar una resta, significa que el resultado de la resta es positivo, y por el contrario, cuando la bandera de acarreo se coloca en 0 lógico después de realizar una resta, significa que el resultado de la resta fue negativo, y por lo tanto, el dato que se obtuvo tiene que complementarse a 2 para obtener la magnitud correcta, pero con el conocimiento de que el valor fue negativo, tal como se ilustra en la tabla 29.

Figura 11. Resta de 2 registros de 8 bits. Las restas que se realizan directamente con las instrucciones que contienen los microcontroladores PIC, se pueden

operar con datos de 8 bits, recordando 54

que la resta entre si de 2 registros de memoria RAM, no puede realizarse de manera directa, por lo que es necesario cargar uno de los datos al registro W, y después aplicar la instrucción de la resta necesaria, a manera de ejemplo se muestra una sustracción en el fragmento de diagrama de flujo de la figura 11. movf subwf

var2,0 var1,0

movwf

var3

;carga el dato del registro var2 al registro de trabajo W. ;resta el dato del registro var1 con el del registro W, dejando el ;resultado en el mismo registro W. ;el dato del registro W lo guarda en el registro var3.

Tabla 30. Resta de 2 registros.

Para emplea adecuadamente las instrucciones de resta de un microcontrolador PIC y de acuerdo con la figura 11, el dato del primer registro que debe cargarse al registro de trabajo W, es el que se encuentra identificado como var2, para posteriormente emplear la instrucción subwf, guardando el resultado de la resta en el registro de trabajo W, y por ultimo en un siguiente paso enviar el dato de W al registro var3. El código correspondiente a la descripción que se acaba de realizar se expresa por medio del fragmento del programa que se ilustra en la tabla 30.

55

Figura 12. Diagrama de flujo de una resta de registros de 8 bits. En la tabla 30 se muestra un fragmento de código para realizar una resta entre 2 datos de 8 bits, en el cual no se toma en cuenta el posible resultado negativo o positivo, motivo el cual, para que el dato que se obtenga de la resta este correcto y con la debida interpretación, se tiene que realizar el procedimiento que se muestra en el diagrama de flujo de la figura 12, en el cual se toma en cuenta si el resultado de la sustracción fue negativo o positivo, mediante la comparación del bit que indica el estado de la bandera del acarreo del registro ―stat us‖.

El bit de la

bandera del acarreo nos indica si un resultado fue positivo o negativo, después de haber ejecutado una instrucción de una resta de acuerdo a lo siguiente: a)

Si el bit de la bandera del acarreo (c) del registro status es igual con 0 (cero), el resultado de la resta fue negativo.

b)

Si el bit de la bandera del

acarreo (c) del registro status 56

es igual con 1 (uno), el resultado de la resta fue positivo. Por lo tanto, si el resultado de la resta fue positivo, no se tiene que realizar actividad alguna sobre el registro donde se encuentra el resultado de la sustracción, mientras que por otra parte, si la resta presentó un resultado negativo, entonces en el registro donde se guardo el dato resultante de la sustracción, contiene un valor complementado, por lo que a continuación se tiene que realizar el procedimiento de complementar a 2 dicho resultado negativo para obtener la magnitud del valor de la resta, y aparte en otro registro activar un valor que indique que el resultado fue negativo (para el caso del diagrama de flujo de la figura 12, el registro se llama ―ne gativo‖). En la tabla 31 se encuentra el código del programa de una resta de 2 registros cuyos datos son de 8 bits cada uno, en el programa se encuentran definidos los registros que se están empleando para realizar la sustracción, además de la correspondiente parte donde se realiza la verificación del bit que funge como bandera del acarreo, para determinar si el resultado de la resta fue negativo o positivo.

En el código del programa se muestran todas las instrucciones

relacionadas con la resta, pero para una aplicación completa se debe de cambiar el renglón que dice ―si guiente proceso‖, por las instrucciones de la parte que tenga que continuar después de haber realizado la operación de la sustracción, pero para un empleo directo para practicar con el programa, tan solo cambie el renglón ―si guiente proceso‖ por el de un ―g oto inicio‖ y también se tienen que eliminar los puntos suspensivos. Ahora procederemos a explicar el proceso que tiene que seguirse cuando se requiere realizar una resta con datos de más de 8 bits, como es el caso de una resta con datos de 16 bits, en la cual se debe de tener una metodología apropiada para que se obtenga como resultado final una magnitud además de un indicativo de que el resultado fuese positivo o negativo.

57

LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 var1 equ 0x20 var2 equ 0x21 var3 equ 0x22 negativo equ 0x23 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,c movf var2,0 ;carga el dato del registro var2 al registro de trabajo W. subwf var1,0 ;resta al dato del registro var1 el del registro W, dejando el resultado en W. movwf var3 ;el dato del registro W lo guarda en el registro var3. btfsc status,c ;verifica la bandera del acarreo para determinar si el resultado goto pos ;es positivo o negativo. goto neg pos movlw 0x00 ;limpia el registro del resultado negativo. movwf negativo goto sigproceso neg comf var3,1 ;complementa a 2 el resultado del registro var3 que es donde incf var3,1 ;se encuentra el resultado negativo de la resta. movlw 0xff ;coloca indicación de un resultado negativo, en el registro negativo. movwf negativo sigproceso siguiente proceso . . . end

Tabla 31. Programa que resta 2 registros de 8 bits.

Para realizar las restas de 16 bits se tienen que reservar dos registros de 8 bits, para cada uno de los operandos que pertenecerán a la sustracción, por lo que cada operando tendrá que acomodarse

de acuerdo con el peso específico de

58

cada uno de los bits que lo compone, en la tabla 32 se ilustra la estructura de una resta con datos de 16 bits. Conformación de datos de 16 bits oper1 = reg1,reg2 oper2 = reg3,reg4 oper3 = reg5,reg6

Minuendo Sustraendo Resultado

oper1 = reg1,reg2 Minuendo -- oper2 = reg3,reg4 Sustraendo ================= oper3 = reg5,reg6 Resultado

Ejemplo de una resta con datos de 16 bits 01010111,01101011 - 00011001,11101010 ====================== = + 00111101,10000001

16 Bits 16 Bits

16 Bits reg6 reg5 Positivo

Tabla 32. Estructura de una resta con datos de 16 bits.

De la tabla 32 observamos que los operandos se encuentran conformados de la siguiente manera; el operador minuendo identificado como oper1 esta integrado por los registros reg1 y reg2, de los cuales el que tiene el menor peso es el reg2, por lo tanto el de mayor peso es reg1.

El operador sustraendo se encuentra

identificado como oper2, y se encuentra compuesto por los registros reg3 y reg4, de los cuales el que tiene el menor peso es el reg4, y el registro de mayor peso es el reg3.

El resultado de la sustracción se guardara en el operando identificado

como oper3, el cual se encuentra integrado por los registros reg5 y reg6, de los cuales el de menor peso es el reg6, mientras que el de mayor peso es el registro reg5.

Figura 13 Resta de 2 datos de 16 bits. Cabe aclarar que los operandos oper1, oper2 y oper3, solo se consideran como una convención para considerar 59

que se trata de datos de 16 bits, por lo

tanto, estos operandos no existen en el código del programa, pero si los registros que los conforman, y por lo tanto los operandos se encuentran representados por los registros que los integran, en la figura 13 se muestra la operación de una resta aritmética con datos de 16 bits, la cual es el reflejo de la operación realizada en la tabla 32. Para comenzar con la resta de datos de 16 bits, primero se sustraen entre si los registros de menor peso de cada operando (minuendo menos el sustraendo), dichos registros se identifican como ―r eg2‖ y ―r eg4‖.

El resultado de la resta se

aloja en el registro ―r eg6‖, por otra parte, al resultado de esta primera resta se verifica si se origino un acarreo (recordando que de esta manera se sabe si el resultado fue negativo o positivo).

Sí fue originado un acarreo con un 1 lógico

en la respectiva bandera del registro status, significa que el resultado parcial fue positivo procediendo a realizar la siguiente resta entre registros de mayor peso sin ninguna operación adicional.

Pero si en la bandera del acarreo se origino un 0

lógico, significa que el resultado parcial fue negativo, por lo que se le tiene que restar una unidad al registro de mayor peso del operador minuendo, en este caso el decremento de una unidad se le tiene que aplicar al registro reg1, y después se procede a realizar la sustracción de los registros de mayor peso del minuendo y sustraendo, en el diagrama de flujo de la figura 14 se ilustra la resta de 2 operandos de 16 bits. Por último se realiza la sustracción de los registros de mayor peso de cada uno de los operandos identificados como minuendo y sustraendo (tomando en cuenta el acarreo, si es que lo hubo, en la resta de los registros de menor peso de los operandos), el resultado de esta segunda resta se guarda en el registro ―r eg5‖. Basándonos en el diagrama de flujo de la figura 14, posterior al haber encontrado el resultado completo de la resta, y después de la determinación de que el resultado fue negativo, existe un bloque que dice ―comple mentar a 2 el dato completo de reg5,reg6‖, se refiere a encontrar la magnitud del resultado final, y para ello realizaremos la actividad que

se describe a continuación. 60

Figura 14. Diagrama de flujo de una resta de datos de 16 bits. Para realizar el complemento a 2 de un número de 16 bits se sigue el mismo procedimiento que se emplea para un número de 8 bits, por lo tanto en primer instancia se tienen que sustituir los 1’s por 0’s y los 0’s por 1’s, para posteriormente sumarle una unidad al

registro de 8 bits que compone la parte

61

baja del dato de 16 bits, se debe de tomar en cuenta que al sumar la unidad se puede generar un acarreo que puede afectar al registro de 8 bits que conforma la parte alta de los 16 bits (recurra al capitulo de la suma aritmética que se encuentra antes del capitulo presente), en la tabla 33 se muestra un ejemplo en donde se realiza una resta de 2 datos de 16 bits, siendo el resultado final negativo, y la aplicación del complemento a 2 del resultado final, para obtener la magnitud de la resta. Resta de 2 números de 16 bits por complemento a 2

Resta de 2 números de 16 bits 01010010,00000101 Minuendo - 10100111,11001100 Sustraendo ================= = - 01010101,11000111 Resultado Negativo

10100111,11001100 El sustraendo se complementa 01011000,00110011 + 1 ================= =01011000,00110100 Sustraendo complementado a 2 01010010,00000101 Minuendo + 01011000,00110100 Sustraendo complementado a 2 =================== =0 10101010,00111001 Resultado en 16 bits Acarreo Acarreo = 0 resultado es negativo Acarreo = 1 resultado es positivo Como el acarreo fue igual con 0, el resultado de 16 bits se complementa a 2. 10101010,00111001 Se cambian los 1’s por 0’s y los 0’s por 1’s quedando: 01010101,11000110 + 1 Al complemento se le suma un 1 ================= =01010101,11000111 Resultado final complementado a 2 para obtener la magnitud negativa.

Tabla 33. Complemento a 2 de un resultado negativo en una resta de datos de 16 bits.

Por último en cuanto a las restas de datos de 16 bits, en la tabla 34 se muestra el código del programa correspondiente, en el se encuentran identificadas por medio de comentarios todas las partes que conforman al diagrama de flujo de la figura 14.

62

LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 reg1 equ 0x20 reg2 equ 0x21 reg3 equ 0x22 reg4 equ 0x23 reg5 equ 0x24 reg6 equ 0x25 negativo equ 0x26 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,c ;limpia la bandera del acarreo. movf reg4,0 ;carga el dato del registro reg4 al ;registro de trabajo W. subwf reg2,0 ;resta al dato del registro reg2 el ;del registro W, dejando el ;resultado en W. movwf reg6 ;el dato del registro W lo guarda ;en el registro reg6. btfsc status,c ;verifica la bandera del acarreo goto sigresta ;para determinar si el resultado ;parcial es positivo o negativo.

acarreo decf sigresta bcf movf

reg1,1 status,c reg3,0

subwf

reg1,0

movwf

reg5

btfsc goto

status,c positivo

neg

;decrementa en una unidad a reg1. ;limpia la bandera del acarreo. ;carga el dato del registro reg3 al ;registro de trabajo W. ;resta al dato del registro reg1 el ;del registro W, dejando el ;resultado en W. ;el dato del registro W lo guarda ;en el registro reg6. ;verifica la bandera del acarreo ;para determinar si el resultado ;total es positivo o negativo.

comf reg5,1 ;complementa a 2 el resultado de la comf reg6,1 ;resta que se encuentra en los movlw 0x01 ;registros reg5 y reg6. movwf reg6,1 btfss status,c goto noaca incf reg5,1 noaca movlw 0xff ;coloca indicación de un resultado movwf negativo ;negativo, en el registro negativo. goto sigproceso positivo movlw 0x00 ;limpia el registro del movwf negativo ;resultado negativo. sigproceso siguiente proceso . . . end

Tabla 34. Programa que resta 2 registros de 16 bits.

El código del programa que se encuentra expresado en la tabla 34, esta completo en cuanto a la operación de la resta de números de 16 bits, pero para cargarlo en un microcontrolador PIC, se recomienda cambiar el renglón que tiene la siguiente leyenda ― siguiente proceso‖ así como los puntos, por el código que tenga que ejecutar el microcontrolador, después de realizar la resta de 16 bits. Para terminar el presente capitulo diremos que el método para realizar restas de datos con mas de 16 bits, es prácticamente el mismo que con 16 bits, ya que de requerir números más grandes, tan solo se deben de contemplar todos los registros de 8 bits, que se requieran

para 63

conformar

a

los

datos

que

intervendrán en la resta, además de también contemplar al bit de acarreo para determinar si los resultados parciales o el resultado final fue positivo o negativo. 1.10 MULTIPLICACIÓN ARITMÉTICA La operación aritmética de la multiplicación es necesaria cuando se requiere emplear herramientas que posee un microcontrolador PIC, para realizar procesos de mediana o alta complejidad.

En los microcontroladores PIC no existe una

instrucción que de manera directa realice una multiplicación de 2 números, como puede hacerla para las operaciones de las sumas y las restas. Para implementar una multiplicación de 2 datos en un microcontrolador PIC, se tiene que hacer uso de la teoría de operación de una multiplicación, que se basa en una secuencia de sumas, las cuales deben de ser contabilizadas, por lo que en general se recurre al empleo tanto de las sumas como de contadores. Vamos a explicar la manera en que se realiza una multiplicación por medio de una serie de sumas, para ello nos basaremos en el ejemplo mostrado en la tabla 35. EJEMPLO 8 Multiplicando x 4 Multiplicador ============= 32 Producto Resultado

Serie de sumas para realizar la multiplicación. 8 + 8 ===== 16 2veces se ha sumado el 8 + 8 ===== 24 3 veces se ha sumado el 8 + 8 ===== 32 4 veces se ha sumado el 8 32 es el resultado de la multiplicación

Tabla 35. Ejemplo de una multiplicación aritmética.

Del ejemplo de la multiplicación mostrado en la tabla 35, observamos que para obtener un resultado se debe de sumar

sobre si mismo el valor expresado en

64

el término multiplicando, tantas veces como el valor expuesto en el operando multiplicador. De lo anterior deducimos que la operación de la multiplicación es un proceso derivado de las operaciones de sumas, por lo que se deben de contemplar todas las características del proceso de las sumas para obtener un resultado confiable, recordando que de acuerdo a la magnitud de los operandos se puede generar un acarreo, el cual debe alojarse o sumarse en el registro correspondiente. Con respecto al ó las localidades de memoria (registros) en donde se guardara el resultado de la multiplicación, debe de reservarse la cantidad exacta de estos para que el resultado no se vea truncado, o se tengan registros desperdiciados sin utilizarse.

Para calcular la cantidad de registros que se destinaran para el

resultado, se debe conocer el tamaño en bits de los operandos (considerando que los registros cuentan con un tamaño de 8 bits cada uno), por lo tanto, el tamaño del o los registros estarán definidos también en bits.

La manera de calcular la

cantidad de bits que se emplearan para el resultado, se basa en la simple suma de todos los bits que conforman tanto al término del multiplicando como al del multiplicador; lo anterior se expresa de una manera mucho más simple a través de la siguiente formula: (# de bits para el resultado) = (# de bits del multiplicando) + (# de bits del multiplicador)

En donde el símbolo # significa número

A continuación vamos a definir por medio de un diagrama de flujo, el proceso para realizar una multiplicación de dos datos que se encuentran conformados por 8 bits (1 registro cada uno), por lo que para alojar el resultado se necesita de un total de 16 bits (equivalente a 2 registros).

En el diagrama de flujo de la figura

15 se ilustra el proceso que se sigue para la realización de una multiplicación de 2 operandos de 8 bits cada uno de ellos.

65

Figura 15 Diagrama de flujo de una multiplicación con datos de 8 bits. Del diagrama de flujo de la figura 15 se observa que los registros identificados como ―r es0‖ y ― res1‖, son lo que se encuentran destinados para alojar el resultado de la multiplicación, por lo tanto se debe definir el peso específico de cada unos ellos, quedando el registro res1 como el de mayor peso, mientras que el registro res0 es el de menor peso.

En los registros identificados como ―m ultiplicando‖y

―m ultiplicador‖ se encuentran los datos que van a ser multiplicados. registro identificado como ―co ntador‖ es

Por último el

el encargado de llevar el control del

66

número de veces que se realiza la operación de la suma.

Los registros res0,

res1 y contador deber inicializados con un valor igual con 0 (cero) al inicio de una operación de multiplicación. LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 res0 equ 0x20 res1 equ 0x21 multiplicador equ 0x22 multiplicando equ 0x23 contador equ 0x24 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1

clrf res0 clrf res1 clrf contador contmulti bcf status,c movf multiplicando,0 ;suma el multiplicando con el addwf res0,1 ;el valor de res0. btfsc status,c ;verifica si existió acarreo en incf res1,1 ; la suma. incf contador,1 movf contador,0 xorwf multiplicador,0 ;verifica si el registro contador btfsc status,z ;es igual al multiplicando. goto finmulti goto contmulti finmulti siguientes instrucciones . . . end

Tabla 36. Programa que multiplica 2 registros de 8 bits.

En el registro multiplicando se encuentra el dato que será sumado, tantas veces como lo indique el valor que se encuentra en el registro multiplicador.

La

serie de sumas se van realizando de acuerdo con el dato que se encuentra contenido dentro del registro multiplicando, por lo que se mantiene como un valor constante, siendo el registro res0 donde se va guardando el resultado de las sumas que se van efectuando.

De a cuerdo con la cantidad de bits que

conforman a los registros de los operandos que se están multiplicando, se tiene contemplado que el resultado de la multiplicación se aloje en 16 bits o sea 2 registros, por lo tanto, posterior a la

suma del valor del multiplicando se 67

tiene que verificar si el resultado genero un acarreo, porque si es así, también tiene que incrementarse una unidad al valor del registro resg1. Siempre después de realizar la suma del valor del multiplicando se incrementa en una unidad el valor del registro contador, para poder controlar el número de veces que se ha efectuado la suma, por lo tanto, en seguida que se incrementa el valor del registro contador, se realiza una comparación entre el valor del registro contador con el del registro multiplicador, cuando estos registros contengan el mismo valor, será hasta entonces cuando el proceso de la suma tenga que detenerse, ya que en ese momento la multiplicación habrá terminado, y en los registros res0 y res1 se tendrá el dato resultante. Para cualquier multiplicación se emplea el mismo procedimiento que se mostró en el diagrama de la figura 15, teniendo en cuenta el tamaño de los operandos, para determinar la cantidad de registros que tendrán que emplearse para guardar el resultado, y para ello se debe de tomar en consideración el proceso que se aplica para la realización de las sumas. 1.11 DIVISIÓN ARITMÉTICA La operación aritmética de la división debe ser implementada por medio del uso de instrucciones que nada tienen que ver con una división, ya que en un microcontrolador PIC no existe una instrucción directa por medio de la cual se realice una división entre 2 datos. Un método para efectuar una división aritmética en un PIC es emplear una serie de restas, a través de las cuales se tendrá como resultado el correspondiente residuo que va generando la división, mientras que a través del conteo del número de restas que tienen que hacerse, se obtiene el resultado final de una división, en la tabla 37 se muestra el ejemplo de una división aritmética, en la cual se recurre al concepto básico por medio del cual se realizan las divisiones.

68

EJEMPLO

4.2 Divisor

5 21 10 0

Serie de restas para realizar la división.

Cociente Dividendo Residuo

21 - 5 ==== 16 1 - 5 ==== 11 2 - 5 ==== 06 3 - 5 ==== 01 4

vez se ha restado el 5 veces se ha restado el 5 veces se ha restado el 5

Se multiplica el residuo por 10 01 x 10 ==== 10 Se toma el valor de 10 para Continuar con la serie de restas. 10 - 5 ==== 05 1 vez se ha restado el 5 - 5 ==== 00 2 veces se ha restado el 5

veces se ha restado el 5

4.2 Es el resultado de la división con un residuo igual con 0.

Tabla 37. Ejemplo de una división aritmética.

Cuando no existe una instrucción para realizar divisiones, tal como es el caso de un microcontrolador PIC, tenemos que recurrir a un procedimiento como el ilustrado en el ejemplo de la tabla 37, en el cual la operación básica es una resta, por lo tanto, se tiene que aplicar dicha metodología para encontrar el resultado de la operación de la división. Para comenzar una división por medio del empleo de restas, se toma el valor que se encuentra en el ―div idendo‖, al cual se le resta la magnitud que se localiza en el ―div isor‖, el resultado de la resta debe contener un valor mayor que el del divisor para que sea aplicada una nueva resta; mientras se van aplicando las restas, estas se van contabilizando.

Cuando el resultado de la resta es menor

que el valor del divisor, entonces el número de restas es igual al valor entero del ―cocien te‖ (resultado de la división), si el ― residuo‖ (resultado de la última resta) obtuvo un valor igual con cero, entonces hemos terminado con la división, pero si el residuo tiene un valor diferente de cero pero menor que el del divisor, entonces se considera que se coloca un punto decimal en el cociente, por lo que se toma el valor que se encuentra en el residuo para multiplicarlo por 10 (equivale a bajar un cero, tal como se ilustra en el ejemplo de la tabla 37), posteriormente el resultado de la multiplicación es asignado nuevamente al termino dividendo, para que se reanude la aplicación de las restas,

tomando el divisor como el valor que 69

será restado al nuevo dividendo.

Este procedimiento se repetirá tantas veces

como decimales se quieran obtener, solo que para encontrar el siguiente decimal, el residuo tendrá que multiplicarse por 100, y después por 1000 y así sucesivamente.

Figura 16. Diagrama de flujo de una división. Lo importante para realizar una división aritmética con un microcontrolador PIC, es considerar la cantidad de decimales que conformaran al cociente, para destinar los registros que habrán de utilizarse para expresar el resultado de la división.

Por otra parte, el resultado de la división se expresara por medio de

varios registros, los cuales deben ser tomados en cuenta para interpretar de manera adecuada el resultado final de la división.

70

LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 divisor equ 0x20 dividendo equ 0x21 cociente_ent equ 0x22 cociente_dec equ 0x23 residuo equ 0x24 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,c clrf cociente_ent clrf cociente_dec clrf residuo division movf divisor,w ;realiza la resta del subwf dividendo,1 ;dividendo menos el ;divisor. btfss status,c goto fraccion incf cociente_ent,1 goto division

fraccion movf divisor,w ;reintegra el valor que addwf dividendo,w ; fue sustraído en la movwf dividendo ;última resta. movwf dividendo_dec ;prepara la movlw 0x10 ; multiplicación movwf multiplicador movlw 0x01 movwf contador multiplica ;realiza la multiplicación movf dividendo,w ;del residuo por 10. addwf dividendo_dec,1 incf contador,1 movf contador,w xorwf multiplicador,w btfss status,z goto multiplica movf dividendo_dec,w movwf dividendo bcf status,c division_1 ;repite el proceso de las restas movf divisor,w ;para encontrar el valor subwf dividendo,1 ;después del punto btfss status,c ; decimal. goto fraccion_1 incf cociente_dec,1 goto division_1 fraccion_1 movf divisor,w addwf dividendo,w movwf residuo siguientes instrucciones . . . end

Tabla 38. Programa que realiza divisiones.

En el diagrama de flujo de la figura 16 se ilustra el proceso para realizar una división aritmética, en la cual la operación principal es la resta entre los registros dividendo menos el divisor, guardando el resultado de la resta en mismo registro dividendo, por lo tanto, este dato se actualizara mientras se estén realizando las restas.

Del proceso de la resta es importante verificar el estado de la bandera

del ―aca rreo‖ (C), recordando que esta

bandera 71

se

encuentra

dentro

del

registro ―stat us‖.

La importancia de la bandera radica en el hecho de saber si

un resultado después de realizar una resta es igual con menor que el divisor (si el resultado de la resta, es menor que el divisor significa que ha terminado una fase de la división).

Mientras el resultado de la resta sea mayor que el divisor, se

contabilizan las restas que se vayan realizando, pasando este dato a ser parte del valor del cociente. Cuando en el resultado de la resta se identifica que el valor es menor que el del divisor, se procede a reponer el valor que fue sustraído durante la última resta, para posteriormente multiplicarlo por el valor de 10 (lo que equivale a bajar un cero en el proceso que realizamos de una división hecha a mano), y se repite nuevamente todo el desarrollo de realización de restas para obtener ahora la parte del cociente que se encuentra después del punto decimal. En la tabla 38 se muestra el código que corresponde al programa de una división, en el cual esta identificada la parte en la que se realizan las restas para obtener el resultado entero del cociente.

Por otra parte, también se muestra la

ejecución del código que se refiere a la multiplicación para posteriormente continuar con las restas, y así obtener la parte decimal del cociente. La parte de la multiplicación se recomienda que se realice a través de una subrutina, para que no se duplique con una gran extensión el código, en el programa mostrado en la tabla 38 el código no se encuentra expresado por medio de subrutinas, por lo que tan solo tiene que adecuarse el programa para que pueda ser empleada la subrutina.

72

CAPÍTULO II. RUTINAS INTERMEDIAS 2.1 FUNCIÓN LÓGICA AND Y SUS APLICACIONES Las funciones lógicas aportan una aplicación muy importante cuando se programan los microcontroladores, sobre todo cuando se efectúan tareas de control de procesos industriales, teniéndose en general la misión de generar ―m ascaras‖ para el filtrado de datos, además también se utilizan para fijar un determinado valor en uno o varios de los bits de un registro (recordar que los registros son de 8 bits) sin alterar a los demás bits. Para implementar las funciones lógicas en los microcontroladores PIC, tan solo se tiene que hacer uso de sus respectivas instrucciones, teniendo en cuenta las posibilidades existentes en cuanto a la manipulación de los datos, esto es, los diferentes tipos de operandos que pueden emplearse. La función lógica Y (AND en inglés) tiene una aplicación como una máscara, dejando pasar los estados lógicos de los bits que nos interesan de un registro, colocando los restantes bits en estado lógico ―0‖, independientemente del valor que tuvieran antes de realizar la operación. FUNCIÓN LÓGICA AND Dato 1 Dato 2 Resultado 0 0 0 0 1 0 1 0 0 1 1 1

Tabla 39. Tabla de verdad de la función lógica AND.

Para comprender la forma en que se aplica la función lógica AND, tenemos que hacer uso de su correspondiente tabla de verdad la cual se muestra en la tabla 39.

En la tabla de verdad se

observan los diferentes valores que 73

pueden adquirir los términos identificados como ―D ato 1‖ y ― Dato 2‖, generándose en total 4 diferentes combinaciones de estos, teniendo como factor común que en cualquiera de los datos de ingreso que se tenga un ―0‖ lógico, el resultado será ―0‖ (cero).

Mientras que cuando ambos datos de entrada adquieren el valor de ―1‖

lógico, el resultado será ―1‖ (uno), siendo este el motivo del nombre que posee esta función lógica, ya que para generar un ―1‖ lógico se requiere que el Dato 1 ―Y ‖ el Dato 2 se encuentren en estado lógico de ― 1‖. Partiendo de la tabla de verdad de la función lógica AND, procederemos a explicar como se realiza la función lógica en un microcontrolador, y para ello vamos a desarrollar un ejemplo empleando registros de 8 bits, tal como se ilustra en la tabla 40. EJEMPLO DE LA FUNCIÓN LÓGICA AND b7 b6 b5 b4 b3 b2 b1 b0 0 0 0 0 1 1 1 1 & (AND) 0 1 0 1 1 0 0 1 ====================== 0 0 0 0 1 0 0 1

Registro 1 Registro 2

Tabla 40. Ejemplo de aplicación entre 2 registros de la función lógica AND.

Partiendo del ejemplo ilustrado en la tabla 40, se advierte que al ejecutar la función AND (&) entre los datos alojados en ―R egistro 1‖ y ―R egistro 2‖, esta se aplica bit a bit de acuerdo con su respectiva tabla de verdad, por ejemplo, se tiene como dato un ―1‖ lógico en el bit ―b0 ‖ de ambos registros, arrojando el resultado de ―1‖ lógico.

Por otra parte, en el correspondiente bit ―b1 ‖ se encuentra un ―1‖

lógico en el registro 1 y un ―0‖ lógico en el registro 2, quedando como resultado un ―0‖ lógico; y así sucesivamente se tienen que seguir realizando las operaciones, aplicando la función lógica AND tomando los correspondientes bits de los registros en cuestión.

74

De acuerdo con el ejemplo anterior, podemos establecer un filtro de datos de acuerdo a los bits de un registro que necesitamos operar, y regresando al ejemplo si consideramos al registro 2 como el filtro, podemos decir que en los bits donde se le fijaron ceros lógicos, el resultado fue ― 0‖ lógico independientemente de los valores que tengan los bits del registro 1, mientras que si lo bits del filtro fueron establecidos como ―1‖ lógico, el resultado depende del correspondiente estado lógico del bit del registro 1. EJEMPLO DE LA FUNCIÓN LÓGICA AND

&

b7 b6 b5 b4 b3 b2 b1 b0 1 0 1 0 1 0 1 0 0 0 0 0 1 1 1 1 ====================== 0 0 0 0 1 0 1 0

Dato Filtro

Tabla 41. Aplicación de la función lógica AND como filtro.

En el ejemplo de la operación mostrada en la tabla 41, se observa que en el registro identificado como ― filtro‖ los bits que conforman al nible superior (bits b4, b5, b6 y b7) se encuentran fijos a ―0‖ lógico, mientras que los bits que componen al nible inferior del mismo registro ― filtro‖ (bits b0, b1, b2 y b3), se aprecian en estado lógico de ―1‖.

De lo analizado anteriormente, se desprende que los

datos que nos interesan se encuentran en los bits que conforman al nible inferior, mientras que los del nible superior tienen que ser colocados a ―0‖ lógico, debido a que no serán tomados en cuenta para el proceso siguiente.

Los bits

contenidos en el nible inferior del registro ―da to‖, son ― filtrados‖ tal cual se encuentren, esto es, si se tiene un ―1‖ lógico este pasara como resultado, mientras que si el dato es un ―0‖ lógico, este también pasara como resultado. Cuando aplicamos la función lógica AND como filtro, el objetivo es dejar ―pa sar‖ el estado lógico del bit que nos interesa, pero también se puede tener otra visión en cuanto a la ocupación para la

75

misma función lógica AND, siendo

esta, la de fijar de manera predeterminada un ―0‖ lógico en los bits donde sea necesario, permitiendo que en los demás bits se aloje el estado lógico que tenia antes de la aplicación de la función lógica AND.

Para una mejor comprensión

observe el ejemplo de la tabla 41, en el cual se muestra que necesitamos que los bits del nible superior del registro dato pasen a ser ―0´s‖ en el resultado, mientras que los datos contenidos en los bits del nible inferior del registro dato se trasladan de manera integra al resultado. Para ejecutar la función lógica AND entre 2 registros, en un microcontrolador PIC se pueden emplear una de dos instrucciones de acuerdo a la forma en como se requieran aplicar; las instrucciones de la función lógica AND con las que cuentan los microcontroladores PIC se describen a continuación: a) andlw k.- Función lógica AND del dato que se encuentra en el registro de trabajo W con el de un valor literal dejando el resultado en el registro de trabajo W, modificando su valor con respecto del que tenia anteriormente.

El dato del

registro de trabajo W como el del valor literal son de 8 bits. b) andwf f,d.- Función lógica AND del dato que se encuentra en el registro de trabajo W con el valor de un registro f (registro de memoria RAM) dejando el resultado de la función AND ya sea en el registro de trabajo W o en el registro f, dependiendo del valor que adquiera d (para una mejor referencia consulte el capitulo ―i nstrucciones orientadas al control de registros‖ e ―i nstrucciones orientadas al control de literales‖, ambos temas pertenecientes al modulo I). Cabe aclarar que los microcontroladores PIC ejecutaran la operación entre registros compuestos por 8 bits, y siempre que se requiera aplicar la función lógica AND sobre 2 registros de memoria RAM, en un microcontrolador PIC se tiene que hacer mediante la carga previa del valor de uno de los registros a W, ya que en un microcontrolador PIC no existe una instrucción que efectué la función lógica AND entre 2 registros de memoria RAM de forma directa. En la tabla 42 se muestra el código

de un programa que a manera de 76

ejemplo demuestra la forma en que puede ser empleada la función lógica AND. LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 var1 equ 0x20 var2 equ 0x21 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo z equ 2 ;bandera del cero rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,c movf var1,0 ;carga el dato del registro var1 al registro de trabajo W. andlw 0x0f,0 ;función AND con de W con el filtro 0F, dejando el ;resultado en el mismo registro W. movwf var2 ;el dato del registro W lo guarda en el registro var2. siguiente proceso . . . end

Tabla 42. Ejemplo de aplicación de la función lógica AND.

2.2 FUNCIÓN LÓGICA OR Y SUS APLICACIONES La función lógica O (OR en inglés) también puede emplearse para generar una máscara, solo que a diferencia de la función lógica AND, con la función lógica OR se fijan ―0´s‖ lógicos, en el o los bits que nos interesan de un registro, y por otra parte

podremos

filtrar

los

estados 77

lógicos de los bits que nos interesan de

un determinado registro, colocando los restantes bits en el estado lógico de ― 1‖, independientemente del valor que tuvieran antes de realizar la operación de la función lógica OR. FUNCIÓN LÓGICA OR Entrada 1 Entrada 2 Resultado 0 0 0 0 1 1 1 0 1 1 1 1

Tabla 43. Tabla de verdad de la función lógica AND.

Para estar en posibilidades de concebir la forma en que se aplica la función lógica OR, tenemos que recurrir al empleo uso de su correspondiente tabla de verdad la cual se ilustra en la tabla 43.

En la tabla de verdad se observan los

diferentes valores que pueden adquirir los términos identificados como ― Entrada 1‖ y ― Entrada 2‖, generándose en total 4 diferentes combinaciones de estas, teniéndose como factor común que en cualquiera de los valores de entrada que se tenga un ― 1‖ lógico, el resultado será ― 1‖ (uno).

Mientras que cuando en ambas

entradas se adquiera el valor de ― 0‖ lógico, el resultado será ― 0‖ (cero).

El

nombre de la función lógica se adquiere a partir de su operación principal, la cual reportará un ―1‖ lógico cuando en la Entrada 1 ― O‖ en la Entrada 2 se fije el estado lógico de ―1‖ (se trata de la función lógica O inclusiva ó simplemente O). Tomando como punto de partida la tabla de verdad de la función lógica OR, pasaremos a explicar la manera de como se realiza la ejecución de la función lógica en un microcontrolador, y para ello vamos a basarnos en el ejemplo que se ilustra en la tabla 44, en el cual se muestran 2 registros cuya longitud es de 8 bits, y del cual cabe aclarar que si a de emplearse la presente función lógica (inclusive la AND), para registros que contengan una mayor cantidad de bits, la función lógica tiene que irse aplicando byte a byte (o sea a cada arreglo de 8 bits), hasta encontrar el resultado final.

78

EJEMPLO DE LA FUNCIÓN LÓGICA OR b7 b6 b5 b4 b3 b2 b1 b0 1 1 1 1 0 0 0 0 | (OR) 1 0 1 0 0 1 1 0 ====================== 1 1 1 1 0 1 1 0

Registro 1 Registro 2

Tabla 44. Ejemplo de aplicación entre 2 registros de la función lógica OR.

A partir del ejemplo ilustrado en la tabla 44, nos percatamos que al ejecutar la función lógica OR ( | ) entre los datos alojados en ―R egistro 1‖ y ―R egistro 2‖, esta se aplica bit a bit de acuerdo con su respectiva tabla de verdad, por ejemplo, se tiene como dato un ― 0‖ lógico en el bit ―b 0‖ de ambos registros, arrojando el resultado de ― 0‖ lógico.

Además, en el correspondiente bit ―b 1‖ se encuentra

un ― 0‖ lógico en el registro 1 y un ― 1‖ lógico en el registro 2, quedando como resultado un ― 1‖ lógico; y así sucesivamente se tienen que seguir aplicando las operaciones, de la función lógica OR tomando los correspondientes bits de los registros en cuestión. De acuerdo con el resultado obtenido en el ejemplo mostrado en la tabla 44, podemos construir un filtro de datos de acuerdo con los bits de un registro que necesitemos operar, y nuevamente haciendo referencia al ejemplo anterior, si consideramos al registro 2 como el filtro, podemos decir que en los bits donde se le fijaron unos lógicos, el resultado fue ― 1‖ lógico independientemente de los correspondientes valores que tengan los bits del registro 1, mientras que si lo bits del filtro fueron establecidos como ― 0‖ lógico, el resultado dependerá del correspondiente estado lógico del bit del registro 1.

Para una mejor

comprensión de lo que se acaba de explicar, refiérase al ejemplo que se ilustra en la tabla 45, en la cual a la función lógica OR se le esta considerando como un filtro de datos, para que sea capaz de seleccionar a uno o más bits de un registro que contiene el dato con el que finalmente

se trabajara. 79

EJEMPLO DE LA FUNCIÓN LÓGICA OR

&

b7 b6 b5 b4 b3 b2 b1 b0 0 1 0 1 0 1 0 1 1 1 1 1 0 0 0 0 ====================== 1 1 1 1 0 1 0 1

Dato Filtro

Tabla 45. Aplicación de la función lógica OR como filtro.

En el ejemplo de la operación mostrada en la tabla 45, se observa que en el registro identificado como ― filtro‖ los bits que conforman al nible superior (bits b4, b5, b6 y b7) se encuentran fijos a ―1‖ lógico, mientras que los bits que componen al nible inferior del mismo registro ― filtro‖ (bits b0, b1, b2 y b3), se aprecian en estado lógico de ―0‖.

De lo analizado anteriormente, se desprende que los

datos que nos interesa filtrar se encuentran en los bits que conforman al nible inferior, mientras que los del nible superior tienen que ser colocados a ―1‖ lógico, debido a que no serán tomados en cuenta para el proceso siguiente.

Los bits

contenidos en el nible inferior del registro ―da to‖, son ― filtrados‖ tal cual se encuentren, esto es, si se tiene un ―1‖ lógico este pasara como resultado, mientras que si el dato es un ―0‖ lógico, este también pasara como resultado. Cuando se aplica la función lógica OR como filtro, el objetivo es dejar ―pa sar‖ el estado lógico del bit que nos interesa, pero también se puede tener otra perspectiva en cuanto al empleo de la misma función lógica OR, siendo esta, la de fijar de manera predeterminada un ― 1‖ lógico en los bits donde sea necesario, permitiendo que en los demás bits se aloje el estado lógico que tenia antes de la aplicación de la función lógica OR.

Para una mejor comprensión observe el

ejemplo de la tabla 45, en el cual se visualiza que se requiere que los bits del nible superior del registro dato pasen a ser ―1´s‖ en el resultado, mientras que los datos contenidos en los bits del nible inferior del registro dato se trasladan de manera integra al resultado.

80

Para poder hacer uso de la función lógica OR entre 2 registros en un microcontrolador PIC, se pueden emplear una de dos instrucciones de acuerdo a la forma en como se requieran aplicar; las instrucciones de la función lógica OR con las que cuentan los microcontroladores PIC se describen a continuación: a) iorlw

k.- Función lógica OR del dato que se encuentra en el registro de

trabajo W con el de un valor literal dejando el resultado en el registro de trabajo W, modificando su valor con respecto del que tenia anteriormente.

El dato del

registro de trabajo W como el del valor literal son de 8 bits. b) iorwf

f,d.- Función lógica OR del dato que se encuentra en el registro de

trabajo W con el valor de un registro f (registro de memoria RAM) dejando el resultado de la función OR ya sea en el registro de trabajo W o en el registro f, dependiendo del valor que adquiera d (para una mejor referencia consulte el capitulo ―i nstrucciones orientadas al control de registros‖ e ―i nstrucciones orientadas al control de literales‖, ambos temas pertenecientes al modulo I). Cabe aclarar que los microcontroladores PIC ejecutaran la operación entre registros compuestos por 8 bits, y siempre que se requiera aplicar la función lógica OR sobre 2 registros de memoria RAM, en un microcontrolador PIC se tiene que hacer mediante la carga previa del valor de uno de los registros a W, ya que en un microcontrolador PIC no existe una instrucción que efectué la función lógica OR entre 2 registros de memoria RAM de forma directa. Por último, en cuanto a la función lógica OR, en la tabla 46 se muestra el código de un programa que a manera de ejemplo expone la forma en que puede ser empleada la función lógica OR, tomando en cuenta la construcción de un filtro o mascara como el que fue ilustra en el ejemplo de la tabla 45, que se encargue de dejar pasar el dato del nible inferior de un registro (var1). Solo a manera de nota diremos que en el código del programa de ejemplo se esta proponiendo el empleo del microcontrolador PIC16F628A, pero también puede

emplearse

cualquier

otro

microcontrolador 81

PIC,

y

para

ello

refiérase a los capítulos ― configuración de los puertos como entrada o salida‖, ―Le ctura de datos de un puerto‖, ―escri tura de datos en un puerto‖ y ― asignación de datos a un registro‖, ambos temas pertenecientes al presente modulo II. LIST P=PIC16F628A ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 var1 equ 0x20 var2 equ 0x21 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo z equ 2 ;bandera del cero rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,c movf var1,0 ;carga el dato del registro var1 al registro de trabajo W. iorlw 0xf0,0 ;función OR con de W con el filtro F0, dejando el ;resultado en el mismo registro W. movwf var2 ;el dato del registro W lo guarda en el registro var2. siguiente proceso . . . end

Tabla 46. Ejemplo de aplicación de la función lógica OR.

2.3 FUNCIÓN LÓGICA XOR Y SUS APLICACIONES A diferencia de las funciones lógicas AND y OR, la función lógica O Exclusiva (XOR en inglés)

no tiene un empleo 82

como máscara filtradora de datos,

dejando su actividad principal en la de poder identificar el contenido de 2 registros, y reportar si estos son exactamente iguales entre si, por lo tanto, un campo de acción de la función lógica XOR se encuentra en la comparación de los datos de registros. FUNCIÓN LÓGICA XOR Entrada 1 Entrada 2 Resultado 0 0 0 0 1 1 1 0 1 1 1 0

Tabla 47. Tabla de verdad de la función lógica XOR.

En la tabla 47 se muestra la tabla de verdad de la función lógica XOR, en la cual se observan los diferentes valores que pueden adquirir los términos identificados como ― Entrada 1‖ y ― Entrada 2‖, generándose en total 4 diferentes combinaciones de estos, teniendo como funcionamiento lo siguiente. datos de entrada tienen valores distintos entre si, el resultado será ― 1‖ (uno).

Si los Por

otra parte, cuando los datos de entrada adquieren el mismo valor ya sea ―0‖ ó ―1‖ lógico, el resultado será ― 0‖ (cero).

Partiendo de este comportamiento es que

se le da el nombre de O Exclusiva, ya que para generar un ―1‖ lógico se requiere que el dato de la entrada 1 ― O‖ el dato de la entrada 2 se encuentren en estado lógico de ―1‖, pero no los 2 al mismo tiempo. Para comprender la utilidad de la función lógica XOR, nos basaremos en su correspondiente tabla de verdad y a continuación presentaremos 2 ejemplos de su aplicación, tal como se muestra en la tabla 48. Tal como sucede con las funciones lógicas AND y OR, cuando se aplica la función lógica XOR entre 2 registros, se realiza operando la función bit a bit entre los 2 registros involucrados de acuerdo con la tabla de verdad mostrada anteriormente. En el ejemplo que se muestra en la

tabla 48, se percibe que al operar la 83

función lógica XOR (^), entre los datos alojados en los registros ―R egistro 1‖ y ―R egistro 2‖ con sus correspondientes bits b0, el resultado es un ― 0‖ lógico debido a que ambos datos de entrada se encuentran en ―1‖ lógico.

Lo mismo para

cuando se aplica la función lógica XOR a los bits b1 de los registros ―R egistro 1‖ y ―R egistro 2‖, como ambos datos de entrada son iguales, la respuesta es nuevamente ―0‖ lógico, y así sucesivamente al ir aplicando la función lógica cada uno de los bits, en todos los resultados tendremos un ―0‖ lógico, salvo en los bits de entrada b3, porque el b3 del ―R egistro 1‖ se encuentra en ―0‖ lógico, y el del ―R egistro 2‖ se encuentra en ― 1‖ lógico, dando como resultado un ―1 ‖ lógico. EJEMPLO DE LA FUNCIÓN LÓGICA XOR b7 b6 b5 b4 b3 b2 b1 b0 0 1 0 1 0 1 0 1 ^ (XOR) 0 1 0 1 1 1 0 1 ====================== 0 0 0 0 1 0 0 0

Registro 1 Registro 2

Tabla 48 Ejemplo de aplicación entre 2 registros de la función lógica XOR.

Si los datos de los registros ―R egistro 1‖ y ―R egistro 2‖ hubieran sido iguales en el ejemplo de la tabla 48, el resultado después de aplicar la función lógica XOR nos entregaría ―0 ’s‖ lógicos en todos los bits del resultado, identificando son este resultado que los dato son exactamente iguales. Para aplicar la función lógica XOR entre 2 registros, recordemos que en un microcontrolador PIC, primero se debe cargar el dato de uno de ellos en el registro de trabajo W, para posteriormente poder operarlo.

En un microcontrolador PIC,

se pueden emplear una de dos instrucciones de acuerdo a la forma en como se requieran aplicar las instrucciones de la función lógica XOR, tal como a continuación se explica: a) xorlw

k.- Función lógica XOR del 84

dato que se encuentra en el registro de

trabajo W con el de un valor literal dejando el resultado en el registro de trabajo W, modificando su valor con respecto del que tenia anteriormente.

El dato del

registro de trabajo W como el del valor literal son de 8 bits. b) xorwf f,d.- Función lógica XOR del dato que se encuentra en el registro de trabajo W con el valor de un registro f (registro de memoria RAM) dejando el resultado de la función XOR ya sea en el registro de trabajo W o en el registro f, dependiendo del valor que adquiera d (para una mejor referencia consulte el capitulo ―i nstrucciones orientadas al control de registros‖ e ―i nstrucciones orientadas al control de literales‖, ambos temas pertenecientes al modulo I). Después de aplicar la función lógica XOR, se tiene que saber si el resultado fue cero (si son iguales los datos entre los registros), o diferente de cero (si son diferentes los datos entre los registros), por lo que se tiene que revisar también la bandera del cero (z) del registro ―stat us‖, por lo que les pedimos que pasen a revisar el siguiente apartado, que es en donde se muestra de manera completa y con ejemplos de la forma de realizar comparaciones entre los datos de diferentes registros. 2.4 FUNCIONES LÓGICAS DE COMPARACIÓN ENTRE REGISTROS (=, ) Existen aplicaciones en las que es necesario realizar comparaciones entre los datos de 2 registros por lo menos, y saber a partir de dicha comparación si los datos son iguales, ó uno es mayor que el otro ó uno es menor que el otro, etc. Siendo de vital importancia tener en cuenta que los datos poseen una magnitud que se encuentra en función de los bits que la componen. Las comparaciones que pueden realizarse con un microcontrolador PIC, son las que aprendimos los estudios primarios, y a las cuales llamaremos comparaciones básicas, las cuales se enumeran a continuación, indicando el además el símbolo que las caracteriza.  Igual

(=) 85

 Menor que () A partir de las comparaciones básicas podemos crear las llamadas comparaciones complementarias que prácticamente no son otra cosa que eso (de manera literal); las comparaciones complementarias se muestran a continuación.  Diferente  Mayor o igual que  Menor o igual que

(≠) (≥) (≤)

Complemento de Igual Complemento de Menor que Complemento de Mayor que

Tomando la primera de las comparaciones complementarias que es la denominada ―dife rente‖, se genera a partir de la comparación básica ―Ig ual‖, esto es, en el momento que se pregunta si un dato es igual a otro, si el resultado es no, quiere decir que entonces son diferentes.

Del mismo modo cuando se realiza la

ejecución de la comparación básica ― menor que‖ entre los valores de 2 datos, si el resultado es no, quiere decir entonces que fue ―m ayor o igual‖.

Por lo tanto, el

mismo algoritmo que se desarrolle para las comparaciones básicas es el que se emplea para las comparaciones complementarias, a continuación comenzaremos con la explicación a detalle de la primer comparación básica. 2.4.1 COMPARACIÓN IGUAL (=) Ó DIFERENTE (≠) Para

realizar

una

comparación

entre

los

datos

de

2

registros

independientemente para saber si son iguales, mayores o menores, se tiene que realizar una operación aritmética fundamental que consiste en una ―r esta‖ (para una mejor referencia sobre este tema consulte el capitulo ― resta aritmética‖, perteneciente al modulo II), y por medio de esta sabremos de manera específica si 2 magnitudes son iguales, ya que si el resultado de la resta es cero, quiere decir que los datos que fueron restados son exactamente iguales, mientras que si el resultado es diferente de cero no importando si es positivo o negativo, quiere decir que las cantidades que se restaron son diferentes entre si. En el ejemplo ilustrado en la tabla 49

se muestra la manera de emplear una

86

resta aritmética para determinar sí 2 cantidades numéricas son iguales entre ellas, obteniéndose 2 posibles resultados, uno de los resultados de la resta puede ser cero, si es que los valores de los datos fueron iguales entre si, o se puede tener un resultado diferente de cero en la resta (positivo o negativo), si los valores fueron de magnitud diferente entre si. EJEMPLO 1

EJEMPLO 2

5 Dato 1 - 5 Dato 2 =========== = 0 Resultado

5 Dato 1 - 4 Dato 2 =========== = 1 Resultado

Son ―ig uales‖ entre sí el Dato 1 con el Dato 2

Son ―di ferentes‖ entre sí el Dato 1 con el Dato 2

Tabla 49. Ejemplos de una comparación de valores realizada a partir de una resta.

Del ejemplo 1 mostrado en la tabla 49, se observa la resta de 2 números (5 5), siendo el resultado de la sustracción un valor de 0 (cero), indicando que el valor del dato 1 es igual al valor del dato 2; por otra parte, la resta que se haga pude involucrar valores de más de 1 registro de 8 bits, razón por la que recomendamos volver a repasar el correspondiente capitulo donde se abordan las restas aritméticas.

Ahora observemos el ejemplo 2 de la misma tabla 49, en

donde de nueva cuenta se realiza una resta de 2 números (5 - 4), el resultado en esta oportunidad es un 1, por lo tanto, el resultado expresa que los valores de los datos 1 y 2 son diferentes.

Se debe de tomar en cuenta que tanto para el

ejemplo 1 y 2 de la tabla 49, las restas se realizan en hexadecimal (interpretación del binario) dentro de un microcontrolador PIC. Específicamente para la implementación de una comparación entre 2 valores, y a partir de ella determinar si estos son iguales o diferentes, a parte de la resta también puede emplearse la función lógica XOR (explicada en el capitulo anterior), que en la tabla 50 se muestra un

ejemplo de su aplicación, y a partir de 87

ella determinar su 2 valores son iguales o diferentes. EJEMPLO 1

EJEMPLO 2

01010101 Dato 1 ^ 01010101 Dato 2 =========== = 00000000 Resultado

01010101 Dato 1 ^ 01110101 Dato 2 =========== = 00100000 Resultado

Son ―ig uales‖ entre si el Dato 1 con el Dato 2

Son ―di ferentes‖ entre si el Dato 1 con el Dato 2

Tabla 50. Ejemplos de una comparación de valores realizada con la función XOR.

En los ejemplos expresados en la tabla 50 se muestra la aplicación de la función lógica XOR a números binarios para una mejor comprensión, siendo el mismo caso que en los ejemplos realizados por medio de una resta, si el resultado es cero, significa que los valores de los datos 1 y 2 son iguales (ejemplo 1 de la tabla 50), mientras que cualquier otro resultado implica que los valores de los datos 1 y 2 son diferentes entre si (ejemplo 2 de la tabla 50).

Figura 17. Símbolo de la función de comparación: igual ó diferente. En la figura 17 se muestra un rombo que es el símbolo que se emplea para realizar la comparación de las magnitudes de los valores de 2 datos, dentro del rombo esta expresada la pregunta que 88

compara la magnitud de var1 con

respecto de var2, generando a su vez 2 posibles resultados, los cuales nos indican por medio de una respuesta afirmativa que las magnitudes de los datos de var1 y var2 son iguales; por otra parte, si la respuesta es ―n o‖, significa que las magnitudes de los datos de var1 y var2 son diferentes.

Figura 18. Diagrama de flujo de la comparación: Igual ó Diferente. La función de comparación de la figura 17, es desglosada para saber si los valores contenidos en 2 registros son iguales o diferentes, por lo tanto, se muestra de manera detallada en el diagrama de flujo de la figura 18, los bloques que componen el método para poder realizar la comparación, empleando en esta oportunidad como acción fundamental la operación de la resta aritmética para determinar el resultado de la comparación, pero recuerde que la operación de la resta puede ser sustituido por la función lógica XOR. Para el código que se obtendrá a

partir del diagrama de flujo de la figura 89

18, se presupone que se emplean registros de 8 bits para efectos de una mejor comprensión, pero si se quisieran comparar valores que aborden más de 8 bits en su composición, el método sigue siendo el mismo, solamente se tienen que contemplar restas con registros de más de 8 bits (16, 32, etc.). A partir del diagrama de flujo de la figura 18 se observa que para comenzar con el proceso de comparación, en primera instancia tiene que ser limpiada la bandera que indica que el resultado de la operación de la resta es cero (lo mismo se realiza si la operación es la XOR), para esta acción la bandera del cero se identifica como ―z ‖ y se encuentra dentro del registro ―stat us‖ del microcontrolador PIC.

90

LIST P=PIC16F628A ;ó P=PIC12F629 ó P=PIC16F874 ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 var1 equ 0x20 var2 equ 0x21 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo z equ 2 ;bandera del cero rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,z movf var2,w ;se carga var2 en w subwf var1,w ;resta var1 – w deja el resultado en w btfsc status,z ;pregunta por el estado de la bandera z del registro status goto igual goto diferente igual ;Código correspondiente cuando ;var1 y var2 son iguales goto siguienteproceso diferente ;Código correspondiente cuando ;var1 y var2 son diferentes goto siguienteproceso siguienteproceso end

Tabla 51. Código del programa de comparación: Igual ó Diferentes.

Posteriormente se operan los valores de los registros var1 y var2, cargando de manera primaria el valor de uno de ellos en el registro de trabajo w, para posteriormente aplicar el comando de la resta o la función XOR con el registro restante.

La aplicación de la resta ó función XOR tendrá como resultante 2

posibles valores, que es 0 (cero) ó un valor diferente de 0 (sin importar su magnitud), teniendo que revisar el estado que guarda la bandera z del registro

91

status, para saber si el resultado de la resta o función XOR fue 0 o no. La bandera z arrojara un ―1‖ lógico si el resultado de la resta ó la función XOR fue 0 (cero), por otra parte, la bandera z tendrá un ―0‖ lógico si el resultado resta ó la función XOR fue diferente de 0 (cero).

Por último, dependiendo del estado

que guarde la bandera z, se tendrán que ejecutar una secuencia de instrucciones, para cuando el resultado de la comparación entre los valores de var1 y var2 indique que fueron iguales.

Lo mismo sucederá cuando el resultado de la

comparación arroje que fueron diferentes los valores de var1 y var2. A continuación en la tabla 51 se muestra el fragmento de código por medio del cual se implementa el programa del diagrama de flujo de la figura 18. 2.4.2 COMPARACIÓN MENOR QUE () Ó MENOR O IGUAL QUE (≤) Como en los casos de las comparaciones anteriormente descritas, para realizar una comparación entre los datos contenidos en 2 registros, y saber sí uno de ellos es mayor que el otro, ú obtener el resultado complementario para determinar sí un dato es menor o igual que el otro, se tiene que realizar la operación aritmética principal para realizar comparaciones que consiste en una resta (por enésima vez lo referimos al capitulo ―r esta aritmética‖, perteneciente al presente modulo II). Siendo por medio de la aplicación de esta operación que sabremos de manera específica cual dato es mayor que el otro, ya que sí el resultado de la resta es positivo, podremos interpretar que uno de los datos que fueron restados es en magnitud mayor que el otro.

Además, si queremos obtener el complemento del

resultado ―m ayor que‖ (comparación básica), nos tenemos que referir al término ―m enor o igual‖ (comparación complementaria), y para ello se tiene que revisar el resultado de la resta, para estar en conocimiento de que se genero un resultado igual a cero ó un resultado con valor negativo, lo cual significa que uno de los valores a compararse fue menor o igual que el otro. EJEMPLO 1

EJEMPLO 2

9 Dato 1 - 5 Dato 2 =========== = 4 Resultado Positivo El Dato 1 es mayor que el Dato 2

7 Dato 1 - 9 Dato 2 =========== = - 2 Resultado Negativo ó Cero El Dato 1 es menor o igual que el Dato 2

Tabla 54 Ejemplos de una comparación “mayor que” ó “menor o igual” realizada a partir de una resta.

Para comprender de una mejor manera la explicación anterior, observe el ejemplo ilustrado en la tabla 54 en donde se muestra la manera de emplear una resta aritmética para determinar cual de las 2 cantidades numéricas es mayor, obteniéndose 2 posibles resultados, uno de los resultados de la resta puede dar un

valor positivo

(sin

importar su 98

magnitud), si es que el valor del dato 1

fue mayor que el valor del dato 2, ó se puede obtener un resultado negativo después de aplicar la operación de la resta (de nueva cuenta sin importar su magnitud), sí el valor del dato 1 resulto que es menor que el valor del dato 2, pero también pudo haber sido cero el resultado de la resta, por lo tanto, sí el resultado de la resta hubiese sido negativo ó cero se interpretara como que el dato 1 fue menor o igual que el dato 2. Del ejemplo 1 mostrado en la tabla 54, se observa la resta de 2 números (9 5), obteniéndose como resultado de la sustracción un valor igual a 4 (positivo), indicando que el valor del dato 1 es mayor que el valor del dato 2; recuerde que la resta puede realizarse con registros de más de 8 bits, razón por la cual le recordamos

de

nueva

cuenta,

que

es

recomendable

que

correspondiente capitulo donde se abordan las restas aritméticas.

repase

el

Ahora

observemos el ejemplo 2 de la misma tabla 54, en donde se realiza una resta de 2 números (7 - 9), el resultado en esta oportunidad es -2, por lo tanto, el resultado expresa que el valor del dato 1 es menor o igual que el dato 2.

Se debe de

tomar en cuenta que tanto para el ejemplo 1 como para el ejemplo 2 de la tabla 54, las restas se efectúan en formato hexadecimal por parte del microcontrolador PIC.

Figura 21. Símbolo de la función de comparación: Mayor que ó Menor o igual. En la figura 21 se muestra para la operación de una comparación un rombo, que es el símbolo de manera general se emplea para efectuar la comparación entre las magnitudes de los valores de 2 datos; dentro del rombo se esta expresando una pregunta, mediante la 99

cual se compara la magnitud de var1

con respecto de var2, generando a su vez 2 posibles resultados, los cuales nos indican por medio de una respuesta afirmativa que la magnitud del dato var1 es mayor que el dato var2; por otra parte, si la respuesta es ―no ‖, significa que la magnitud del dato var1 es menor ó igual que el dato de var2.

Figura 22. Diagrama de flujo de la comparación: Mayor que ó Menor o igual. La comparación representada en la figura 21, tiene que ser desglosada para una mejor comprensión, y de esta manera saber sí los valores contenidos en 2 registros son uno mayor que el otro ó uno es menor o igual que el otro, por lo tanto, se mostrara de manera detallada por medio del diagrama de flujo de la figura 22, los bloques que conforman el método que emplearemos para poder realizar la comparación, utilizando en

esta

100

oportunidad

como

acción

fundamental la operación de la resta aritmética para estar en posibilidades de tomar una decisión sobre el resultado final de la comparación. El código que se obtendrá a partir del diagrama de flujo de la figura 22, será representado por medio de registros de 8 bits, con el único fin de lograr una mejor comprensión en la explicación que a continuación se dará, pero si se quisieran comparar valores cuyos registros requieran de más de 8 bits en su conformación, el método seguirá siendo el mismo, solamente se tienen que contemplar restas con registros de más de 8 bits (16, 32, etc.). A partir del diagrama de flujo de la figura 22 se observa que para comenzar con el proceso de comparación, en primera instancia tiene que ser limpiada la bandera que indica que el resultado de la operación de la resta es cero, además de la bandera que indica que en el resultado de la resta se genera un acarreo, para esta acción la bandera del cero se identifica como ―z ‖ y la bandera del acarreo como ―c‖, encontrándose ambas banderas ubicadas dentro del registro ―stat us‖ del microcontrolador PIC. Posteriormente se operan por medio de la operación de la sustracción los valores de los registros var1 y var2, cargando en primer instancia el valor de var2 en el registro de trabajo w, para posteriormente aplicar el comando de la resta de var1 – w (subwf var1,w).

Después de la aplicación de la resta se preguntará sí

el posible resultado fue igual a cero, ó en su defecto sí fue diferente de cero, para lo cual se procede a revisar la bandera z que se encuentra en el registro estatus. Sí la bandera z se encuentra en estado lógico ―1‖ indica que el resultado de la resta fue cero, y por lo tanto, el contenido de var1 es igual con var2; pero si la bandera z se encuentra en estado lógico ―0‖ después de realizar la resta, significa que los datos de var1 y var2 son diferentes entre sí, siendo necesario realizar la verificación del estado que guarda la bandera del acarreo.

La bandera del

acarreo muestra sí el resultado de una resta fue positivo ó sí fue negativo, y para ello lo que tenemos que revisar es que la bandera c se encuentre en estado lógico ―1‖ para determinar que el resultado de

la resta fue positivo, ó verificar que la 101

bandera c tenga un estado ―0‖ lógico para tener en cuenta que el resultado de la resta fue negativo. LIST P=PIC16F628A ;ó P=PIC12F629 ó P=PIC16F874 ;-----------------------------------------------------------; Declaración de Registros ;-----------------------------------------------------------w equ 0x00 status equ 0x03 var1 equ 0x20 var2 equ 0x21 ;-----------------------------------------------------------; Declaración de Bits ;-----------------------------------------------------------c equ 0 ;bandera del acarreo z equ 2 ;bandera del cero rp0 equ 5 ;bit para seleccionar banco rp1 equ 6 ;bit para seleccionar banco ;-----------------------------------------------------------; Inicio ;-----------------------------------------------------------reset org 0 goto inicio ;-----------------------------------------------------------; programa principal ;-----------------------------------------------------------inicio bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf status,z bcf status,c movf var2,w ;se carga var2 en w subwf var1,w ;resta var1 – w deja el resultado en w btfsc status,z ;pregunta por el estado de la bandera z del registro status goto igualonegativo goto diferente igualonegativo ;Código correspondiente cuando ;var1 es menor o igual que var2 (var1 ≤ var2) goto siguienteproceso diferente btfsc status,c ;pregunta por el estado de la bandera c del registro status goto positivo goto igualonegativo positivo ;Código correspondiente cuando ;var1 es mayor que var2 (var1 > var2) goto siguienteproceso siguienteproceso end

Tabla 55. Código del programa de comparación: Mayor que ó Menor o igual.

102

Sí el resultado de la resta (o dicho de otra manera de la comparación) fue positivo significa que var1 es mayor que var1 (var2 > var1), y entonces como consecuencia el control del programa se tiene que dirigir a ejecutar las instrucciones conducentes con el resultado mostrado; pero sí el resultado de la resta fue negativo ó igual con cero, significa que como consecuencia de la comparación se arrojo un resultado que señala que var1 es menor o igual que var2 (var1 ≤ var2), por lo tanto, de igual manera el control del programa se tiene que desplazar para ejecutar la serie de instrucciones que corresponden a las actividades de cuando el resultado de la comparación fue var2 ≤ var1. A continuación en la tabla 55 se muestra el fragmento de código por medio del cual se implementa el programa que resulta del diagrama de flujo de la figura 22. 2.5 LECTURA DE UN TECLADO MATRICIAL Un teclado es un dispositivo por medio del cual una persona puede ―com unicarle‖ información a un microcontrolador, considerándose por lo tanto, un elemento indispensable en aquellos proyectos en donde el usuario tiene que interactuar con el microcontrolador, por ejemplo para configurar la manera de operar de la circuitería, como lo es en un horno de microondas en donde se tiene que seleccionar el tiempo de cocción de un alimento, por ejemplo. Existen 2 tipos de teclados, un tipo de teclado requiere tener disponible una terminal de entrada de un microcontrolador para cada una de las teclas, mientras que otro tipo de teclado se encuentra bajo configuración matricial, ahorrando terminales en un microcontrolador.

Para comprender este último concepto

vamos a recurrir a una situación práctica; hagamos de cuenta que necesitamos de un teclado que en total tenga 16 teclas para diferentes aplicaciones, si utilizamos el primer tipo de teclado enunciado en este apartado, necesitaríamos contar con un microcontrolador que tuviera disponible 16 terminales de entrada, lo cual hace totalmente impráctico el utilizar este tipo de teclado, a menos que multiplexemos por medio de un circuito externo al microcontrolador la información de las teclas (yo no lo haría).

En cambio con un

teclado matricial de 4 filas por 4 103

columnas es suficiente para ingresar la información al microcontrolador, y para emplear el teclado de 16 teclas solo son necesarias 8 terminales del microcontrolador (4 de entrada y 4 de salida). El teclado matricial es un circuito que nos ayuda a ingresar datos al microcontrolador, para implementarlo se requiere del uso de una serie de botones con reposición automática (push boton) conectados de tal manera que se tienen filas y columnas a través de las cuales es muy fácil identificar cual tecla fue oprimida.

El teclado matricial más común es el que posee 4 filas y 4 columnas

dando origen a un teclado con 16 teclas, pero los teclados matriciales pueden ser mucho más grandes, inclusive podemos disponer de teclados del tamaño de los empleados en las PC (102 ó 103 teclas). La forma de operación básica de cualquier teclado matricial es la siguiente: Cuando se oprime una tecla se produce la unión de una fila con una columna, provocando que para un microcontrolador sea muy sencillo identificar la tecla que fue pulsada.

Figura 23. Diagrama esquemático de un teclado matricial de 4 X 4. Se recomienda que para implementar un teclado matricial se haga uso de botones tipo push boton de cuatro

terminales, para que sea sencilla su 104

implementación en un circuito impreso de una sola cara.

Por la manera en

como se acomodaron los botones que se muestran en el diagrama esquemático de la figura 23, se generan 4 columnas y 4 filas las cuales se forman con la unión de las respectivas terminales de los botones y lo recomendable es seguir la conexión expresada en el diagrama esquemático, ya que prácticamente de ahí se obtiene el circuito impreso.

Por ejemplo enfoquemos nuestra atención hacia el

botón identificado como S5, este esta conectado en su parte izquierda con el borne identificado como ―C 1‖ que se refiere a la columna 1, y por su parte derecha al borne identificado como ―F 1‖ que se refiere a la fila 1, por lo tanto, sí es presionado este botón estaremos uniendo la fila 1 con la columna 1. Para todos los botones se tiene el mismo principio de operación, por lo que se generan combinaciones de columnas con filas, las cuales son muy fáciles de identificar de acuerdo al botón que se oprima.

El paso siguiente es personalizar cada uno de

los botones, por ejemplo si se tratara de una calculadora se colocarían las teclas numéricas del 0 al 9 y los botones restantes con las operaciones aritméticas básicas, ó también se personalizar los botones con letras, etc. A continuación se explicara el funcionamiento de un teclado matricial de 4X4, con un microcontrolador, por lo tanto, para que este trabaje y realice la lectura del un teclado matricial, se requiere destinar 4 de las terminales de uno de sus puertos como salidas, la cuales identificaremos por el momento como S0, S1, S2 y S3.

A cada una de las salidas por separado se le tendrá que enviar un ― 1‖

lógico, mientras el ―1‖ lógico aparece solo en una de las salidas, las 3 restantes se fijan con un estado de lógico de ―0‖.

El ―1‖ lógico se hace llegar al teclado

matricial, causando que se vaya activando una de las filas, teniendo que para activar la fila identificada como F0 se tiene que enviar un ―1‖ lógico a través de la salida S0, y ―0‖ lógicos a las salidas S1, S2 y S3.

Posteriormente se tiene que

enviar un ―1‖ lógico por la salida S1 y ―0‖ lógicos a las salidas S0, S2 y S3, para que sea activada la fila F1, y así sucesivamente hasta llegar a la fila F3 que corresponde con la salida S3.

Lo que es importante observar es el hecho de

que cuando una salida se coloca en

105

estado lógico de ―1‖, las 3 salidas

restantes se fijaran en estado lógico de ―0‖.

El ―1‖ lógico tiene que ser enviado

solo uno a la vez por la salida correspondiente, para que de esa manera se tenga el control de la fila es la que se esta activando. Una vez que un ―1‖ lógico se encuentra presente en alguna de las filas del teclado matricial, se tiene que esperar un tiempo razonable (máximo 10 milisegundos) para que sea presionada una tecla, y dependiendo de cual fue oprimida, se enviara el ―1‖ lógico a una de 4 terminales del microcontrolador que previamente tuvieron que ser configuradas como entradas, las terminales de entrada por el momento serán identificadas como E0, E1, E2 y E3, que respectivamente corresponden a las columnas C0, C1, C2 y C3. En el teclado matricial cuando es presionada una tecla, se cierra un interruptor que interconecta una fila con una columna, es por ello que solo se envía un ―1‖ lógico a la vez a la fila correspondiente, porque ese ―1‖ lógico se reflejara en una columna de acuerdo con el botón que sea oprimido.

Sí fueran enviados al

mismo tiempo a más de una fila los ―1 ’s‖ lógicos, no se podría identificar claramente a los botones que sean oprimidos.

Figura 24. Teclado matricial con sus botones identificados. En la figura 24 se muestra la imagen de un teclado matricial, con la identificación de sus teclas, para poder

ingresar los datos que se requieran, 106

en este ejemplo se esta empleando un teclado matricial de 4X4 simulando una calculadora básica.

En la tabla 56 se muestra el código ASCII (se recomienda

que se asigne código ASCII cuando se trabaja con un teclado) resultante, que será generado a partir de la combinación de fila y columna que se presente cuando una tecla sea oprimida. C0 = E0

C1 = E1

C2 = E2

C3 = E6

FO = S0

31*

32*

33*

2B*

F1 = S1

34*

35*

36*

2D*

F2 = S2

37*

38*

39*

2A*

F3 = S3

01

30*

0F

2F*

(*) Código ASCII (hexadecimal).

Tabla 56. Combinación de filas y columnas del teclado matricial.

La tabla 56 es tan solo un ejemplo que se recomienda emplear para utilizar un teclado matricial, ya que de la tabla se observa con lujo de detalle la fila y columna que se une, una vez que se presiona una tecla.

En el diagrama de bloques de la

figura 25 se muestran todas las acciones que tienen que realizarse para controlar la lectura de un teclado matricial.

A continuación se procederá a realizar la

descripción del diagrama de flujo de la figura 25, tomando en consideración que las terminales del microcontrolador que fungirán como entradas, serán las correspondientes terminales del puerto A PA0 = E0, PA1 = E1, PA2 = E2 y PA3 = E3 (estas terminales corresponden a las columnas del teclado).

Las terminales

del microcontrolador que tendrán que ser configuradas como de salida, serán las del puerto B tal como sigue PB0 = F0, PB1 = F1, PB2 = F2 y PB3 = F3 (las terminales del puerto B se conectan a las filas del teclado matricial). Tal como se explico anteriormente, para controlar la lectura de un teclado matricial, se tiene que ir activando cada 107

fila de manera independiente, por lo

tanto, se tiene que comenzar por la primera fila, o sea la identificada como F0.

Figura 25 Diagrama de flujo para controlar al teclado matricial.

Se recurre al comando ―bs f portb,0‖ para enviar un ―1‖ lógico a la salida S0 (PB0) del microcontrolador y que corresponde con la fila 0 (F0), como paso siguiente se tiene que generar un 108

retardo ó espera de cuando más 10

mseg, tiempo suficiente para minimizar el rebote que se genere en el interruptor una vez que se oprima el teclado, posteriormente cuando termina el tiempo de 10 mseg, se puede dar por hecho que sí fue oprimida una tecla, esta ya se estabilizo y por lo tanto, ahora se puede acceder al proceso para determinar la tecla que fue accionada; una vez que se activo la fila 0 del teclado, será a través de una de las 4 columnas que sabemos que tecla se oprimió. Como paso siguiente se pregunta por cual terminal de entrada del microcontrolador se recibe un ―1‖ lógico (si es que se oprimió una tecla), recordando que son 4 alternativas las que nos reporten la posible identificación de una tecla, porque al momento de activar la fila 0 se tiene abierta la identificación de las teclas ―1‖, ―2‖, ―3‖ y ―+ ‖ que corresponden con las columnas C0, C1, C2 y C3, que a su vez se conectan con las entradas PA0, PA1, PA2 y PA3 del microcontrolador.

Para reconocer la tecla que fue oprimida, se tiene que hacer

uso de comparaciones las cuales están representadas por medio del símbolo de un rombo en el diagrama de flujo de la figura 25.

Dentro de los bloques de

comparación se encuentra expresada una pregunta, por medio de la cual se verifica por cual terminal de entrada del microcontrolador se esta reflejando el ―1‖ lógico que se esta enviando por la salida S0 del microcontrolador.

Si la pregunta

se hace valida en alguna de las condiciones de comparación, como respuesta un ―si ‖ procediendo a guardar un dato en un registro de memoria RAM identificado como ―v arteclado‖. El valor del dato que será alojado en el registro varteclado depende de cual comparación fue valida, la cual a su vez esta relacionada con la tecla que ha sido presionada.

Para el caso de la fila 0 los valores que pueden ser guardados son:

31H, 32H, 33H ó 2BH, de acuerdo con la tecla que fue activada.

Pero sí ninguna

tecla de la fila 0 es accionada, entonces el resultado de las comparaciones será ―no ‖ provocando que como paso siguiente se repita nuevamente el proceso de identificar la tecla que es accionada, pero ahora en la siguiente fila que se identifica como F1 (fila 1).

109

De manera básica cuando se pasa a la activación de la fila 1, el proceso es el mismo que para la fila 0, solo que en esta oportunidad, la salida que se activará será la identificada en el microcontrolador como S1 (PB1) y que corresponde con la fila 1, haciéndose esta operación por medio del comando ―b sf portb,1‖.

De

igual manera para evitar los rebotes mecánicos de los interruptores del teclado, es utilizado un retardo de máximo 10 mseg.

Acto seguido dependiendo en que

columna se encuentra la tecla que se oprima, será por donde se reciba el correspondiente ―1‖ lógico a través de la terminal de entrada, solo que en esta ocasión las posibles teclas que pueden ser activadas con las identificadas como ― 4‖, ― 5‖, ― 6‖ ó ― -―,que corresponden con las entradas E0, E1, E2 ó E3.

Sí fue

presionada una tecla de la fila 1, se procederá a guardar un dato en el registro varteclado, que en esta oportunidad utiliza los valores 34H, 35H, 36H ó 2DH.

En

caso de que no se oprima tecla alguna de la fila 1, entonces se pasara a revisar sí en la fila 2 es en donde se presiono una tecla. La operación que se realiza para las filas 0 y 1 es la misma que se utiliza para las filas 2 y 3, pero buscando que se oprima cualquiera de las teclas ― 7‖, ― 8‖, ― 9‖ ó ―X ‖ para la fila 2, ó las teclas ―L‖, ― 0‖, ―= ‖ó― /‖ para la fila 3, todo esto de acuerdo a como se observa en el diagrama de flujo de la figura 25.

Para el presente

ejercicio de aprendizaje en la utilización del teclado, estamos condicionando al programa del microcontrolador, para que una vez que se presiona una tecla y se le asigna el valor correspondiente al registro varteclado, se proceda a realizar alguna otra actividad, mientras que si ninguna tecla se presiona, se tiene que realizar la búsqueda de alguna tecla mediante la activación de las diferentes filas, terminando con esta actividad cuando alguna tecla es presionada. En la fila 3 las teclas L e = las relacionamos con un valor hexadecimal igual con 01 y 0F respectivamente, ya que la tecla L la utilizaremos por ejemplo para limpiar el valor del registro varteclado, mientras que la tecla = la emplearemos por ejemplo para registra mostrar un resultado.

110

Figura 26. Conexión de un teclado matricial de 4 X 4. En el diagrama esquemático de la figura 26 se muestra el circuito básico para conectar el teclado matricial al microcontrolador, en el cual solo se muestran las terminales de los puertos A y B que son empleadas, pero debe de tomar en cuenta que falta la alimentación y el cristal en caso de ser requerido.

Mientras que en la

tabla 57 se muestra el programa que tiene que ser cargado al microcontrolador para que controle la lectura del teclado matricial. Por último, en el diagrama de flujo de la figura 25, y en el código del programa de las tablas 57 y 58 del teclado matricial, se hace uso de una subrutina para generar el retardo de tiempo de 10 mseg.

111

LIST P=PIC16F874 ;=============================================== ; Declaración de Registros ;=============================================== w equ 0x00 status equ 0x03 porta equ 0x05 portb equ 0x06 trisa equ 0x85 trisb equ 0x86 adcon1 equ 0x9f varteclado equ 0x20 var1 equ 0x23 var2 equ 0x24 var3 equ 0x25 ;=============================================== ; Declaración de Bits ;=============================================== c equ 0 ;carry / borrow bit rp0 equ 5 ;registrer banck select bit rp1 equ 6 ;registrer banck select bit z equ 2 ;bit cero ;=============================================== ; Inicio ;=============================================== reset org 0 goto inicio ;=============================================== ; programa principal ;=============================================== inicio bsf status,rp0 ;cambiar a banco 1 bcf status,rp1 movlw 0xff ;configurar el puerto a como entrada movwf trisa movlw 0x00 ;configurar el puerto b como salida movwf trisb movlw 0x07 movwf adcon1 bcf status,rp0 ;cambiar a banco 0 bcf status,rp1 clrf varteclado clrf portb ;=============================================== ;pregunta por las teclas 1,2,3,+ ;=============================================== fila00 bcf status,rp0 bcf status,rp1 bcf portb,3 bsf portb,0 ;envía 1 a la primera fila 0 de teclas call retardo btfsc porta,0 ;¿se trata de la tecla "1"? goto te1 btfsc porta,1 ;¿se trata de la tecla "2"? goto t e2 btfsc porta,2 ;¿se trata de la tecla "3"? goto te1 btfsc porta,3 ;¿se trata de la tecla "+"? goto temas goto fila01

te1

te2

t3

bcf bcf movlw movwf goto

status,rp0 ;escribe código ASCII de la tecla 1 status,rp1 0x31 varteclado sigproceso

bcf bcf movlw movwf goto

status,rp0 ;escribe código ASCII de la tecla 2 status,rp1 0x32 varteclado sigproceso

bcf status,rp0 ;escribe código ASCII de la tecla 3 bcf status,rp1 movlw 0x33 movwf varteclado goto sigproceso temas bcf status,rp0 ;escribe código ASCII de la tecla + bcf status,rp1 movlw 0x2b movwf varteclado goto sigproceso ;=============================================== ;pregunta por las teclas 4,5,6,;=============================================== fila01 bcf status,rp0 bcf status,rp1 bcf portb,0 bsf portb,1 ;envía 1 a la primera fila 1 de teclas call retardo btfsc porta,0 ;¿se trata de la tecla "4"? goto te4 btfsc porta,1 ;¿se trata de la tecla "5"? goto te5 btfsc porta,2 ;¿se trata de la tecla "6"? goto te6 btfsc porta,3 ;¿se trata de la tecla "-"? goto temenos goto fila02 te4 bcf status,rp0 ;escribe código ASCII de la tecla 4 bcf status,rp1 movlw 0x34 movwf varteclado goto sigproceso te5 bcf status,rp0 ;escribe código ASCII de la tecla 5 bcf status,rp1 movlw 0x35 movwf varteclado goto sigproceso te6 bcf status,rp0 ;escribe código ASCII de la tecla 6 bcf status,rp1 movlw 0x36 movwf varteclado goto sigproceso

112

Tabla 57. Código del programa de control de un teclado matricial parte 1. temenos bcf status,rp0 ;escribe código ASCII de la tecla bcf status,rp1 movlw 0x2d movwf varteclado goto sigproceso ;=============================================== ;pregunta por las teclas 7,8,9,X ;=============================================== fila02 bcf status,rp0 bcf status,rp1 bcf portb,1 bsf portb,2 ;envía 1 a la primera fila 2 de teclas call retardo btfsc porta,0 ;¿se trata de la tecla "7"? goto te7 btfsc porta,1 ;¿se trata de la tecla "8"? goto te8 btfsc porta,2 ;¿se trata de la tecla "9"? goto te9 btfsc porta,3 ;¿se trata de la tecla "X"? goto tepor goto fila03 te7 bcf status,rp0 ;escribe código ASCII de la tecla 7 bcf status,rp1 movlw 0x37 movwf varteclado goto sigproceso te8 bcf status,rp0 ;escribe código ASCII de la tecla 8 bcf status,rp1 movlw 0x38 movwf varteclado goto sigproceso te9 bcf status,rp0 ;escribe código ASCII de la tecla 9 bcf status,rp1 movlw 0x39 movwf varteclado goto sigproceso tepor bcf status,rp0 ;escribe código ASCII de la tecla X bcf status,rp1 movlw 0x2a movwf varteclado goto sigproceso ;=============================================== ;pregunta por las teclas L,0,=,/ ;=============================================== fila03 bcf status,rp0 bcf status,rp1 bcf portb,2 bsf portb,3 ;envía 1 a la primera fila 3 de teclas call retardo btfsc porta,0 ;¿se trata de la tecla "L"? goto teL btfsc porta,1 ;¿se trata de la tecla "0"? goto te0

teL

te0

btfsc goto btfsc goto goto

porta,2 teigual porta,3 tediv fila00

;¿se trata de la tecla "="?

bcf bcf movlw movwf goto

status,rp0 ;escribe código ASCII de la tecla L status,rp1 0x01 varteclado sigproceso

;¿se trata de la tecla "/"?

bcf status,rp0 ;escribe código ASCII de la tecla 0 bcf status,rp1 movlw 0x30 movwf varteclado goto sigproceso teigual bcf status,rp0 ;escribe código ASCII de la tecla = bcf status,rp1 movlw 0x0f movwf varteclado goto sigproceso tediv bcf status,rp0 ;escribe código ASCII de la tecla / bcf status,rp1 movlw 0x2f movwf varteclado goto sigproceso ;=============================================== ; rutina para desplegar los valores del teclado ;=============================================== sigproceso ;Instrucciones pertenecientes al siguiente proceso . . . ;=============================================== ; Subrutina ;=============================================== retardo bcf status,rp0 ;cambiar a pagina 0 bcf status,rp1 movlw .01 movwf var1 ciclo_3 movlw .100 movwf var2 ciclo_2 movlw .166 movwf var3 ciclo_1 decfsz var3,1 goto ciclo_1 decfsz var2,1 goto ciclo_2 decfsz var1,1 goto ciclo_3 return end

Tabla 58 Código del programa de control de un teclado matricial parte 2.

113

2.6 CONFIGURACIÓN DE LAS INTERRUPCIONES Las interrupciones en un microcontrolador son elementos muy importantes dentro de un programa, sobre todo si el microcontrolador tiene que realizar varias actividades a la vez.

Por ejemplo, existen aplicaciones en donde el

microcontrolador tiene que esperar algún dato a través de la comunicación serial asíncrona, y para esto, el microcontrolador no puede quedarse esperando hasta que llegue, porque puede pasar desde 1 milisegundo hasta 1 hora para que esto suceda, y mientras el microcontrolador tiene que procesar más información originada por diversas fuentes.

Es aquí donde la actividad de las interrupciones

cobra su importancia, porque el microcontrolador puede estar trabajando normalmente, y solo será ―i nterrumpido‖ de su actividad principal, para avisarle en el momento justo cuando tiene que poner la atención para recibir la comunicación serial.

Figura 27. Programa principal e interrupción Las interrupciones de manera general, las podemos definir como cortes que se realizan a la ejecución de un programa, para proceder a realizar la ejecución de un programa alterno, observe la imagen de la figura 27. El programa principal dentro de un

microcontrolador

114

puede

estar

en

marcha, ejecutando sus respectivas instrucciones, mientras la causa de alguna interrupción que haya sido habilitada no se haga presente.

Cuando una

interrupción es activada, el microcontrolador deja de ejecutar las instrucciones del programa principal, accediendo a una región de la memoria de programa que es donde se encuentra el código de un programa que corresponde con el servicio de la interrupción solicitada. En el mismo instante que la interrupción se genera, los datos que se encuentran en el registro contador de programa (Program Counter PCL y PCLATH) se guardan en un apuntador de pila (memoria temporal también llamada Stack Pointer), por otra parte, también se aloja en el Stack Pointer el dato que este presente en el registro status.

Una vez que esta en marcha el código del

programa que se ejecuta cuando una interrupción se hace presente, el microcontrolador debe realizar las actividades pertinentes a la causa que motivo la interrupción, esto es, se debe dar paso a la gestión de la información relacionada con el trabajo que tiene que realizarse solamente cuando la interrupción es provocada.

Normalmente el código de programa que es destinado para una

interrupción, debe ser pequeño (debe contener pocas líneas) con respecto al código del programa principal, para que el microcontrolador no se quede atrapado por mucho tiempo dentro de la interrupción, y tan solo le dedique el tiempo suficiente para que se ejecute plenamente el servicio de la interrupción. Para indicarle al microcontrolador que el programa de una interrupción ha terminado, se emplea el comando ―r etfie‖ y cuando este se ejecuta, los datos que se almacenaron previamente en el Stack Pointer, regresan de manera ordenada al registro status y apuntador de programa, para que el microcontrolador continué con la marcha del programa principal, procediendo a la ejecución de la instrucción siguiente de donde fue interrumpido el programa principal por medio de la interrupción. En un microcontrolador PIC la configuración de las interrupciones, se realiza por medio del empleo del registro

llamado ―i ntcon‖ que es en donde se 115

encuentran los bits que activan a las interrupciones, para mayor referencia observe la imagen de la figura 28, en donde se describe con detalle la ubicación de los bits que componen al registro ―i ntcon‖ (para una mejor referencia consulte el capitulo ― reset interrupciones y watchdog‖ y ― descripción de los registros‖, ambos temas pertenecientes al modulo I).

De los 8 bits que contiene el registro

―i ntcon‖ solo nos interesan por el momento los que se identifican como ―GIE ‖ y ―PEI E‖.

Figura 28. Detalle del registro INTCON. Por medio del bit GIE se realiza la activación de todas las interrupciones que posee el microcontrolador PIC, por lo tanto, es el más importante que debemos de contemplar, ya que sin la activación de este ninguna interrupción surtiría efecto. Para activar el bit GIE se necesita colocarlo en estado lógico ―1 ‖. El bit PEIE sirve para activar las interrupciones del microcontrolador que son originadas por dispositivos periféricos, esto es, además de activar todas las interrupciones por medio del bit GIE, es necesario activar el bit PEIE si es que la interrupción

que

se

microcontrolador PIC.

habilitará

pertenece

a

un

dispositivo

periférico

al

Entendiéndose por dispositivos periféricos, todos aquellos

que de manera externa al microcontrolador son necesarios para que se haga llegar información al PIC, por ejemplo la comunicación serial asíncrona, la conversión por medio del ADC, etc.

Para activar el bit PEIE se necesita colocarlo

en estado lógico ―1‖. Nuevamente indicamos que el bit GIE es el primero que tiene que ser activado, para que cualquier interrupción surta efecto, y posteriormente tomar en cuenta sí la interrupción que requerimos es originada por un dispositivo periférico, o por activación interna al microcontrolador.

Sí la interrupción se genera a través de un

dispositivo periférico, entonces tiene

que

116

hacerse

uso

del

bit

PEIE,

mientras que en caso contrario (si es originada de manera interna) se tendrá que buscar cual es el bit que tiene que activarse. LIST P=PIC16F874 ;*************************************************************************************************************** ; Declaración de Registros ;*************************************************************************************************************** Aquí se colocara la declaración de los registros que serán empleados ;*************************************************************************************************************** ; Declaración de Bits ;*************************************************************************************************************** Aquí se colocara la declaración de los bits que serán empleados ;*************************************************************************************************************** ; Inicio ;*************************************************************************************************************** reset org 0 ;vector del reset goto progprin org 4 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 btfsc intcon,toif ;Pregunta si una interrupción se ha producido, a través del bit ;que hace la indicación al colocarse en estado lógico ―1 ‖ (bit bandera) goto intertempo ;Si la respuesta es afirmativa accede al código de la Interrupción retfie ;*************************************************************************************************************** ; Inicio de la interrupción por uso del TIMER ;*************************************************************************************************************** intertempo bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf intcon,gie ;desactiva al habilitador general de interrupciones. bcf intcon,toie ;desactiva el bit que habilita la interrupción específica. Aquí se colocan las líneas de código del programa de la interrupción que se tiene que ejecutar. bcf intcon,toif ;limpia el bit bandera para preparar la siguiente interrupción bsf intcon,toie ;activa el bit que habilita la interrupción específica. bsf intcon,gie ;activa al habilitador general de interrupciones. retfie ;comando que indica que el servicio de la interrupción ha terminado ;*************************************************************************************************************** ; programa principal ;*************************************************************************************************************** progprin Instrucciones generales para configurar la operación del microcontrolador ;---------------------------------------------------------------------------------------------------------------------------------;Configuración de la interrupción ;---------------------------------------------------------------------------------------------------------------------------------Instrucciones que configuran los detalles de la interrupción bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bsf intcon,gie ;activa al habilitador general de interrupciones. bsf intcon,toie ;activa el bit que habilita la interrupción específica. Demás instrucciones end

Tabla 59. Plantilla de ejemplo para configurar una interrupción.

117

En el código que muestra como ejemplo en la tabla 59, se muestra que para configurar una interrupción se hace uso de los siguientes comandos: bsf bsf

intcon,toie intcon,gie

;activa el bit que habilita la interrupción específica. ;activa al habilitador general de interrupciones.

Por medio de las instrucciones ―bs f‖ se colocan estados lógicos ―1‖ en los bits toie y gie del registro intcon, para que de esta manera sean habilitada la interrupción con la que trabajara el microcontrolador PIC.

Como paso siguiente a

la ejecución de las instrucciones de habilitación de la interrupción, el programa principal continúa ejecutándose hasta que se presentan las condiciones que provocan la interrupción, siendo este el momento en el que se interrumpe la secuencia de ejecución de las instrucciones.

Cuando una interrupción se

presenta, se coloca en estado lógico ―1‖ el bit que hace la función de indicar que la interrupción se ha generado, este bit también recibe el nombre de bandera, y existe

uno

para

cada

interrupción

que

se

encuentre

presente

en

el

microcontrolador PIC con el que estemos trabajando. Una vez que se ha suscitado una interrupción, ya mencionamos que la ejecución normal del programa se detiene, y como paso siguiente la información que se encuentra dentro de los registros apuntadores de programa, así como también el dato del registro status, se almacenan en el stack pointer, acto seguido en el apuntador de programa se coloca el valor 04, que corresponde con el vector de interrupción, y por lo tanto, el microcontrolador sabe que tiene que dirigirse a la localidad 4 de la memoria de programa, es por ello que se declara por medio de comando ―org4‖, donde se encuentra dicha localidad. Independientemente de cual haya sido el origen de la interrupción, en el apuntador de programa se coloca el valor 04, esto quiere decir que sea cual sea el motivo de la interrupción, el microcontrolador siempre se dirigirá al vector de interrupción, por lo que una vez que el apuntador de programa se encuentra sobre este vector, se tiene que preguntar de manera específica ¿cual es el origen de la interrupción?

Para ello se tiene que

preguntar por el estado lógico que 118

tenga el bit bandera de la interrupción, y si este se encuentra en estado lógico ―1‖ significa que se ha identificado el origen de la interrupción, por lo tanto, ahora el microcontrolador tiene que ejecutar el código de la rutina de interrupción.

Se

debe de tomar en cuenta que existen aplicaciones en las que se requiere activar a mas de una interrupción, y para ello tenemos que identificar perfectamente donde se encuentran los bits bandera de cada una de las interrupciones. Ya dentro del código de programa de una interrupción, normalmente lo que se tiene que hacer es desactivar todas las interrupciones, ya que de lo contrario estando dentro de una, pudiera generarse una más causando desconcierto y perdida de la secuencia del programa del microcontrolador, y por lo tanto, este se ―pe rderá‖ y comenzara a volverse loco.

Quienes tienen experiencia en la

programación de microcontroladores, pueden manejar una interrupción dentro de otra, pero se debe de considerar también que la capacidad del stack pointer es tan solo de 8 niveles, por lo que se debe de tener un manejo exacto de las interrupciones que se van generando. Después de ejecutar las instrucciones por medio de las cuales se da el servicio para atender la causa de la interrupción, se tiene que restablecer la activación nuevamente de la interrupción, y también limpiar la bandera que indica el estado de la interrupción, para que el microcontrolador este preparado para una rutina más.

La instrucción que se emplea para indicarle al microcontrolador que el

servicio de interrupción ha sido ejecutado en su totalidad es el ―r etfie‖, y cuando este se ejecuta provoca que se obtengan los datos que se habían alojado en el stack pointer, restituyéndolos a los registros status y apuntador de programa, siendo el apuntador de programa el medio a través del cual el microcontrolador regresa a la instrucción siguiente de donde iba ejecutando el programa normalmente.

Cabe hacer la mención de que se debe de contar con un código

de programa para cada una de las interrupciones que van a ser activadas, para que el microcontrolador ―sep a‖ el trabajo específico que tiene que realizar de acuerdo a la causa que género la

interrupción.

119

Por último diremos que para un microcontrolador PIC, se tienen contempladas diversas fuentes que pueden dar origen a una interrupción, por lo que se tiene que revisar el manual del microcontrolador PIC que se vaya a utilizar para determinado proyecto, las fuentes de interrupción más comunes en los microcontroladores PIC son las siguientes: • • • • • • • • • • • • • • •

Interrupción externa RB0/INT. Interrupción TMR0 Overflow. Interrupción por cambio en el estado lógico de los pines del PORTB (pines RB). Interrupción por Comparador. Interrupción por el ADC. Interrupción al emplear la EEPROM de datos. Interrupción de Tx mediante USART. Interrupción de Rx mediante USART. Interrupción CCP (Captura/Comparación/PWM). Interrupción CCP1. Interrupción CCP2. Interrupción SSP (Puerto Serial Síncrono). Interrupción PSP (Puerto Paralelo Esclavo). Interrupción TMR1 Overflow. Interrupción TMR2 Match.

2.7 IMPLEMENTACIÓN DE UN RETARDO POR TIMER El timer dentro de un microcontrolador es una herramienta muy valiosa, sobre todo para establecer una temporización con un buen nivel de exactitud. Podemos diseñar un proceso de conteo de tiempo por medio del establecimiento de bucles de retardo, pero el microcontrolador no tendría la capacidad de realizar más tareas, y solamente se dedicaría a ―pe rder‖ el tiempo, y será solo hasta que se consuma el tiempo calculado, cuando el microcontrolador podrá dedicarse a la atención de otras actividades.

Imaginen la temporización de 1 solo minuto, y

mientras también se esta leyendo la información de los signos vitales de una persona a través de los respectivos sensores, sí el microcontrolador no hace otra cosa mientras se consume el tiempo de

la temporización, ¡el paciente se nos

120

puede morir!

Es aquí donde toma importancia el empleo de los timers con los

que cuente el microcontrolador, ya que mientras se controla el conteo de tiempo, en el mismo momento el microcontrolador puede estar realizando alguna otra tarea. El timer que sea activado le avisa al microcontrolador PIC por medio de una interrupción que ha terminado con un conteo de tiempo.

Aunque de manera

rigurosa, lo que cuentan los timer son los ciclos de ejecución de las instrucciones de un programa en un microcontrolador, pero a la vez la ejecución de una instrucción consume un tiempo, el cual sabemos su valor, por lo tanto, de manera indirecta sabremos el tiempo total que se consumió al llevar a un contador desde el valor de 00H al valor de FFH. Podemos decir que un timer básicamente es un registro, que hace la función de un contador que puede estar conformado por 8 ó 16 bits, teniendo como actividad principal la de ir incrementando unidad por unidad el valor del correspondiente registro.

De manera ilustrativa explicaremos la manera en que

opera un timer, considerando en primer instancia uno de 8 bits, por lo que el correspondiente conteo en números hexadecimales comenzara en el valor 00 H, posteriormente continuara con el valor 01H, después el 02H y así sucesivamente hasta llegar al valor máximo que es FFH, pero ahí no se detiene el conteo del registro contador del timer, por lo que si se presenta un incremento mas, el número siguiente será el 00H, siendo este ― desbordamiento‖ el que genere una interrupción, avisando que en el registro contador del timer se ha llegado al conteo máximo de eventos (para un registro de 8 bits, serán 256 que van de 00 a FF en hexadecimal).

Si el timer es de 16 bits los valores del registro contador

comenzaran en el número hexadecimal 0000 H, continuaran en 0001H, después en 0002H, y así sucesivamente hasta llegar al número FFFFH (para un registro de 16 bits, se realizarán 16536 conteos que van desde 0000 a FFFF en hexadecimal), y cuando se genere un incremento mas se producirá un ―de sbordamiento‖, dejando en el registro contador del timer el valor 0000H, lo cual dará origen a que

121

acontezca una interrupción. El incremento del número alojado en el registro contador del timer, se va dando de manera automática cuando las instrucciones del programa del microcontrolador se van ejecutando una a una, para ello, previamente se tuvo que haber activado y configurando el correspondiente timer.

Cada una de las instrucciones puede

consumir de 1 a 2 ciclos de instrucción, que es el tiempo en que se ejecuta una instrucción (para mayor referencia consulte el capitulo ―con junto de instrucciones y su formato‖ perteneciente al modulo I).

Como se indicó anteriormente, el

incremento del registro contador se va dando cuando se van ejecutando las instrucciones, por lo tanto, el programa principal que va controlando las actividades del microcontrolador puede estar en operación normal realizando las actividades correspondientes al sistema de control que se implemento, y será hasta que se genere un desbordamiento cuando se produzca una interrupción, pasando a ejecutar un programa alterno que también se encuentra dentro del microcontrolador. 2.7.1 EL TIMER DE 8 BITS (TMR0) Configurar el timer de 8 bits es una de las actividades más sencillas que se pueden realizar dentro de un microcontrolador PIC, de hecho la actividad más compleja se realiza después, cuando se escribe el código del programa de la interrupción del timer, pero dejemos por el momento la explicación de este detalle, y nos concentraremos en la tarea de configurar el timer de 8 bits. El registro principal que se tiene que intervenir para configurar al timer de 8 bits también conocido como timer0 en el microcontrolador PIC, es el identificado como ―OPT ION REG‖ (option) y en el se configuran los bits que se describen a continuación: El bit 5 del registro OPTION REG se coloca en estado lógico ―0‖ ó ―1‖, de acuerdo de donde se quiera tomar la fuente que da origen al incremento del conteo que se realiza en el registro

contador 122

del

timer,

tomando

en

cuenta que la manipulación del conteo se puede dar a través del pulso que entregue

un

circuito

oscilador

externo,

conectado

a

la

terminal

del

microcontrolador identificada como RA4/T0CKI, o el conteo también se puede dar empleando el circuito de reloj interno que posee el microcontrolador.

El bit 5 del

registro OPTION REG se identifica como T0CS (Bit selector del origen del reloj del TMR0), a continuación se expresan las posibilidades de configuración del bit 5: 1 = Transición en el pin RA4/T0CKI.- Esta configuración se emplea para implementar un contador externo de eventos. 0 = Ciclo de reloj Interno (CLKOUT).- Esta configuración se emplea para implementar un temporizador. A través del bit 3 del registro OPTION REG se configura el destino del prescaler, que tiene como función la de establecer cuantos ciclos de instrucción deben de ejecutarse para que se tenga un incremento de una unidad en el registro contador del timer.

El bit 3 se identifica como PSA (Bit de asignación del

Prescaler), el cual se coloca en estado lógico ―0‖ ó ―1‖, dependiendo de las siguientes posibilidades: 1 = El Prescaler es asignado al WDT .- Esta configuración se emplea para activar al watch dog. 0 = El Prescaler es asignado al módulo Timer0 .- Esta configuración se emplea para activar al registro TMR0, que es el registro contador del timer. Los bits 2, 1 y 0 del registro OPTION REG se identifican como PS2, PS1 y PS0 (Bits selectores del rango Prescaler) respectivamente, tienen la tarea de fijar el número de ciclos de instrucción que se deben ejecutar para que se incremente en una unidad el valor del registro contador del timer, para ello en la tabla 60, se muestran las combinaciones binarias que pueden adquirir los bits PS2, PS1 y PS0 generando las diferentes posibilidades de configuración de las cuales se tiene que seleccionar la mas adecuada en función del valor de la temporización que sea necesario habilitar.

123

Combinación binaria PS2, PS1, PS0 000 001 010 011 100 101 110 111

Rango TMR0 1:2 1:4 1:8 1 : 16 1 : 32 1 : 64 1 : 128 1 : 256

Rango WDT 1:1 1:2 1:4 1:8 1 : 16 1 : 32 1 : 64 1 : 128

Tabla 60. Configuración del Prescaler del Timer0.

Los bits restantes del registro OPTION REG que no han sido descritos se deben de colocar en estado lógico ―0‖ para que el timer0 sea completamente configurado, por otra parte, el detalle de este registro se muestra de manera completa en la imagen de la figura 29.

Figura 29. Detalle del registro OPTION_REG. Pasando a otra parte de la configuración del timer0, se mencionará que tiene que hacerse uso del manejo de las interrupciones, cada vez que el registro ―T MR0‖ (registro contador del timer0) sufre un desbordamiento de sus datos (cuando pasa del valor FFH al 00H), este desbordamiento es causado por la ejecución de las instrucciones en el microcontrolador, que de acuerdo al prescaler seleccionado se requerirá de un cierto número de ciclos de instrucción para que se vaya incrementando de unidad en unidad el valor del registro TMR0.

Para que

sea entendible la presente explicación, emplearemos un ejemplo en donde el valor del prescaler que se ha seleccionado es de 64, equivalente a colocar los datos binarios ―1‖, ―0 ‖ y ―1‖ respectivamente en los bits PS2, PS1 y PS0 del registro OPTION REG.

124

Cada vez que se desborda el registro TMR0 se tiene que producir una interrupción para ―av isar‖ que se ha completado un ciclo de tiempo bien establecido, para lo cual en primera instancia se realizan las siguientes operaciones: Ciclo de instrucción3 =

FrecOscila dor 4MHz = = 1 MHz 4 4

Tiempo del ciclo de instrucción =

1 1 = = 1 μseg Ciclodeins trucción 1MHz

Para calcular el tiempo en el que se incrementa en una unidad el valor del registro TMR0 se hace lo siguiente: (Prescaler)*(Tiempo del ciclo de instrucción) = (64)*(1 μseg) = 64 μseg Por último, para calcular el intervalo de tiempo que se consume (también llamado Ciclo de tiempo), para generar una interrupción se efectúa la siguiente operación: Ciclo de tiempo = (64 μseg)*(256 conteos en el registro TMR0) Ciclo de tiempo = 16.38 mseg Esto quiere decir que cada 16.38 mseg se produce una interrupción, por lo que para establecer un tiempo base de 1 segundo tenemos que determinar el número de interrupciones que se requieren a través de la siguiente operación: Número de Interrupciones =

1segundo = 61.035 interrupciones 16.38mseg

LIST P=PIC16F874 ;********************************************************* 3

bsf clrf

Considerando un circuito de reloj oscilador de 4MHz.

125

intcon,gie tmr0

;limpia el registro TMR0

; Declaración de Registros ;********************************************************* w equ 0x00 tmr0 equ 0x01 status equ 0x03 portc equ 0x07 intcon equ 0x0b pir1 equ 0x0c opsion equ 0x81 trisc equ 0x87 segundo equ 0x20 ;********************************************************* ; Declaración de Bits ;********************************************************* ps0 equ 0 ps1 equ 1 z equ 2 ps2 equ 2 toif equ 2 psa equ 3 toie equ 5 tocs equ 5 rp0 equ 5 rp1 equ 6 peie equ 6 gie equ 7 ;********************************************************* ; Inicio ;********************************************************* reset org 0 goto progprin org 4 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 btfsc intcon,toif goto intertempo retfie ;********************************************************* ;Inicio de la interrupción del TIMER de 8 bits ;********************************************************* intertempo bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf intcon,gie ;desactivación de bcf intcon,toie ; interrupciones incf segundo,1 bcf intcon,toif ;limpia la bandera bsf intcon,toie ;activa las interrupciones

retfie ;********************************************************* ; programa principal ;********************************************************* progprin bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 movlw 0x00 ;configurar pines del movwf trisc ;puerto C como salida ;====================================== ;Configuración del timer ;====================================== bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 bcf opsion,tocs bcf opsion,psa bsf opsion,ps0 bcf opsion,ps1 bsf opsion,ps2 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bsf intcon,gie ;activación de bsf intcon,toie ;interrupciones clrf portc clrf tmr0 ;====================================== enciendeleds ;====================================== clrf segundo movlw 0xff movwf portc mantenerencendido movlw .61 xorwf segundo,w btfss status,z goto mantenerencendido ;====================================== apagaleds ;====================================== clrf segundo movlw 0x00 movwf portc mantenerapagado movlw .61 xorwf segundo,w btfss status,z goto mantenerapagado goto enciendeleds end

Tabla 61. Programa para controlar los bits de un puerto por medio del timer de 8 bits.

Para efectos prácticos se tomará la cantidad de 61 interrupciones, para generar un tiempo base de 1 segundo, claro que para esto estamos considerando un oscilador a cristal con un valor de 4

Mhz, dicho sea de paso este tiempo 126

no genera exactamente 1 segundo, pero es muy cercano. Una vez que hemos concluido con la realización de las operaciones, y sabemos de la cantidad de interrupciones que se tienen que efectuar para generar una temporización base de 1 segundo, en la rutina de interrupción del microcontrolador se tiene que contemplar el empleo de un contador, cuya tarea principal será registrar el número de interrupciones que se van produciendo, cuando este contador llegue a un valor de 61 quiere decir que ha transcurrido aproximadamente 1 segundo.

Ahora contamos con una base de tiempo con la

cual podemos generar el programa para implementar un reloj. La manera de activar la interrupción cuando sea detectado el desbordamiento del valor del registro TMR0, es por medio del registro identificado como ―IN TCON‖ del cual se manipulan los bits 7 y 5 de acuerdo con la siguiente explicación. El bit 7 del registro INTCON que se identifica como GIE (Habilitación Global de las Interrupciones), se debe de colocar en estado lógico ―1‖, para que sean habilitadas todas las interrupciones, mientras que si es colocado un ―0‖ lógico en el bit GIE, implicará que las interrupciones sean inhabilitadas.

A continuación se

muestra de manera resumida lo expresado. 1 = Habilita todas las interrupciones no enmascarables 0 = Deshabilita todas las interrupciones El bit 5 del registro INTCON que se identifica como T0IE (Habilita la interrupción por desbordamiento en el TMR0), se debe colocar en estado lógico ―1‖, para que la interrupción por desbordamiento en el conteo del registro TMR0 surta efecto, por otra parte, se debe de colocar en ―0‖ lógico para deshabilitarlo. 1 = Habilita la interrupción del TMR0 0 = Deshabilita la interrupción del TMR0 Los bits restantes del registro INTCON que no se emplean para el timer0, deben de permanecer en estado lógico ―0‖. muestra en la imagen de la figura 30. 127

El detalle del registro INTCON se

Figura 30. Detalle del registro INTCON. La

bandera

que

indica

que

ha

sido

activada

la

interrupción,

por

desbordamiento en el conteo del registro TMR0, esta implementada en el bit 2 del registro INTCON el cual se identifica como TOIF, siendo el estado lógico de este bit el que indica que se genero una interrupción, cuando esto suceda el bit TOIF se colocará en el estado lógico ―1‖. En la tabla 61, se muestra el código completo para programar al microcontrolador PIC, empleando el timer de 8 bits para controlar el encendido y apagado de los leds del puerto C a una frecuencia de 1 Hz aproximadamente. Por otra parte, se esta configurando un microcontrolador PIC16F874, pero exactamente el mismo procedimiento se puede realizar con cualquier otro microcontrolador PIC. 2.7.2 EL TIMER DE 16 BIT S (TMR1) El timer de 16 bits es muy similar en su forma de operar al timer de 8 bits, teniendo como diferencia principal que el timer de 16 bits, emplea 2 registros de 8 bits para realizar un conteo ya sea de eventos o de tiempo, por consiguiente, se dispone tanto de una resolución como con valores mucho mas amplios en cuanto al establecimiento de un valor de tiempo o un número de eventos a contabilizarse respectivamente. El primer registro que tiene que ser intervenido para configurar al timer de 16 bits (también conocido como timer1) en el microcontrolador PIC, es el identificado como ― T1CON‖ y en el se configuran los bits que se describen a continuación: Los bits 5 y 4 del registro T1CON se identifican como T1CKPS1 y T1CKPS0 (Bits selectores del rango Prescaler del reloj) respectivamente, se colocan ya sea en estado lógico ―0‖ ó ―1‖, de acuerdo a 128

la combinación binaria que se forma

entre los 2 bits, para generar un valor que a su vez corresponde con el número de ciclos de instrucción que se deben ejecutar para que se incremente en una unidad el valor del registro contador del timer, en la tabla 62 se muestran las 4 combinaciones binarias que se pueden formar a partir de los bits T1CKPS1 y T1CKPS0, generando las diferentes posibilidades de configuración, de las cuales se tiene que seleccionar la mas adecuada, en función del valor de la temporización o el número de eventos que sea necesario contabilizar. Combinación binaria T1CKPS1, T1CKPS0 00 01 10 11

Rango TMR1 1:1 1:2 1:4 1:8

Tabla 62.Configuración del Prescaler del Timer1.

El bit 3 del registro T1CON que se identifica como T1OSCEN (Bit de control del oscilador del timer1), tiene la función de habilitar 2 terminales del microcontrolador PIC para que a través de ellas se reciba la información de un disparo externo, que a su vez alimenta a un oscilador interno en el microcontrolador.

El oscilador

interno es empleado para sincronizar la señal externa con el proceso posterior que realiza el timer1, contribuyendo con la generación de una señal apropiada tomando en cuenta de que el disparo externo puede ser de no muy buena calidad, por lo que el oscilador interno además posee de un circuito disparador de Smith. El disparo externo puede emplearse para contabilizar tiempo o número de eventos. Las terminales que son habilitadas en el microcontrolador por medio del bit T1OSCEN, se identifican como RXX/T1OSI/XXX y RYY/T1OSO/T1CKI/XXX (los términos RXX, RYY, XXX e YYY dependen del microcontrolador que se este empleando,

por

lo

tanto

se

les

recomienda

consultar el

manual

del

microcontrolador PIC correspondiente), estas terminales quedan configuradas como entradas, por lo que los 2 bits relacionados en el registro TRIS de configuración del determinado puerto 129

son ignorados.

1 = Oscilador habilitado.- Esta configuración se emplea para configurar a las terminales T1OSI y T1OSO/T1CKI como entradas. 0 = Oscilador apagado.- Por medio de esta configuración se deshabilita al oscilador interno, quedando las terminales T1OSI y T1OSO/T1CKI para otras aplicaciones. El bit 2 del registro T1CON que se identifica como T1SYNC (Bit de control de sincronización del disparo externo), tiene la tarea de sincronizar o no el disparo externo del timer1, con el oscilador interno del microcontrolador.

Cuando se

configura el timer1 para trabajar en el modo sincronizado, el microcontrolador no se debe colocar en el modo de ahorro de energía (modo sleep), mientras que por otra parte, cuando se configura el timer1 para funcionar en el modo no sincronizado, no importa que el microcontrolador se encuentre en el modo de ahorro de energía, porque el timer seguirá trabajando y aun así producirá su respectiva interrupción, provocando que el microcontrolador se ―de spierte‖.

La

configuración del bit T1SYNC, a su vez depende del estado que se tenga en el bit TMR1CS que también se encuentra dentro del registro T1CON.

A continuación

se expresan las posibilidades de configuración del bit 2. Si el bit TMR1CS se encuentra en 1 lógico: T1SYNC = 1.- No sincroniza el reloj externo. T1SYNC = 0.- Sincroniza el reloj externo. Si el bit TMR1CS se encuentra en 0 lógico: El bit T1SYNC es ignorado, por lo tanto, el Timer1 emplea el reloj interno. El bit 1 del registro T1CON que se identifican como TMR1CS (Bit que controla la selección del origen del oscilador), tiene la tarea de seleccionar la fuente que origina la generación de la señal de reloj con la que el timer realizara su función. Se cuenta con 2 posibilidades de configuración para por medio de la señal de reloj, incrementar el valor de los registros del timer 1, estas opciones se encuentran entre el empleo del reloj interno (equivalente a dividir la frecuencia del oscilador entre 4) del microcontrolador PIC, y la utilización de un circuito oscilador externo, el cual se conectaría a la terminal identificada como …/T1OSO/T1CKI/… aclarando que con la presente configuración, el incremento de los registros del

130

timer 1 se darán cuando se presente el flanco de ascenso en la oscilación externa. 1 = Oscilador externo.- Esta configuración permite el empleo de un oscilador externo conectado en la terminal T1OSO/T1CKI. 0 = Reloj interno .- Habilitación del oscilador por medio del reloj interno (La frecuencia de oscilación se divide entre 4). El bit 0 del registro T1CON que se identifica como TMR1ON (bit que enciende la timer 1), tiene la misión de activar la operación del timer 1. 1 = Activa el Timer 1 0 = Detiene el Timer 1 Los bits 5 y 6 del registro T1CON no se emplean y siempre se mantienen en estado lógico ―0‖.

A continuación en la imagen de la figura 31 se muestra el

detalle del registro.

Figura 31. Detalle del registro T1CON. Después de configurar al timer 1, continuaremos con la explicación de su operación tomando en cuenta el empleo de la correspondiente interrupción, la cual se invocara cada vez que el dato de 16 bits alojado en los registros ―T MR1H‖ y ―T MR1L‖ (parte alta y baja del dato de 16 bits), se desborda y pasa del valor FFFFH al 0000H.

El dato de 16 bits se va incrementando de unidad en unidad, a

través de la ejecución de las instrucciones en el microcontrolador, que de acuerdo con el prescaler fijado anteriormente, se requerirá de un cierto número de ciclos de instrucción para que se vaya incrementando el valor alojado en los registros TMR1H y TMR1L.

Para que se entienda mejor lo que se ha descrito,

recurriremos al empleo de un ejemplo en el cual el valor del prescaler será de 4, para ello se requiere colocar los estados lógicos de ―1‖ y ― 0‖ respectivamente en los bits T1CKPS1 y T1CKPS0 que pertenecen al registro T1CON.

Por otra

parte, será implementada la operación del reloj interno, para generar la oscilación que tenga la misión de incrementar al

valor de 16 bits, por lo tanto, serán 131

colocados en estado lógico ―0‖ los bits identificados como T1OSCEN, T1SYNC y TMR1CS, mientras que el bit TMR1ON se debe fijar en el estado lógico ―1‖ para encender al timer 1; recuerde que estos bits se encuentran dentro del registro T1CON. A continuación mostraremos la manera de realizar unos cálculos matemáticos muy sencillos, para determinar que es lo que sucede cada vez que se desborda el valor del dato contenido en los registros TMR1H y TMR1L.

Cuando se suscita

el desbordamiento se genera una interrupción, que será la encargada de ―i ndicar‖ que se ha completado un ciclo de tiempo bien establecido, para lo cual en primera instancia se realizan las siguientes operaciones: Ciclo de instrucción4 =

FrecOscila dor 4MHz = = 1 MHz 4 4

Tiempo del ciclo de instrucción =

1 1 = = 1 μseg Ciclodeins trucción 1MHz

Para calcular el tiempo en el que se incrementa en una unidad el valor del dato contenido en los registros TMR1H y TMR1L se realiza lo siguiente: (Prescaler)*(Tiempo del ciclo de instrucción) = (4)*(1 μseg) = 4 μseg Por último, para calcular el intervalo de tiempo que se consume (también llamado Ciclo de tiempo), para generar una interrupción se efectúa la siguiente operación: Ciclo de tiempo = (4 μseg)*(65536 conteos en los registros TMR1H y TMR1L) Ciclo de tiempo = 262.14 mseg El dato obtenido en el Ciclo de tiempo, significa que cada 262.14 mseg se genera una interrupción, por lo que para determinar un tiempo base de 1 segundo 4

Considerando un circuito de reloj oscilador de 4MHz.

132

se tiene que contabilizar el número de interrupciones que son necesarias, y para calcularlas lo hacemos mediante la siguiente operación: Número de Interrupciones =

1segundo = 3.81 interrupciones 262.14mseg

El número de interrupciones es de 3.81, de las cuales se pueden contabilizar perfectamente en el microcontrolador las 3 interrupciones, pero el valor de 0.81 no se pude manejar por medio de interrupciones, y como se trata de un valor considerable porque casi se trata del valor de una interrupción (pero sin llegar a ella), se debe de considerar para que la base de tiempo que estamos diseñando sea muy cercana a 1 segundo.

Por ello, en el programa se implemento después

de contabilizar las 3 interrupciones, un comparador en el cual se revisa que se encuentre el dato CF5CH en los registros TMR1H (con el valor CFH) y TMR1L (con el valor 5CH).

El valor CF5CH equivale al 81% del valor de un conteo total

tomando en cuenta 16 bits (del 0000H al FFFFH), y se considero el 81% porque equivale al valor de 0.81 del total de las interrupciones. Para efectos prácticos generar un tiempo base de 1 segundo al considerar la cantidad de 3.81 interrupciones, se esta considerando un oscilador a cristal con un valor de 4 Mhz, y dicho sea de paso, la base de tiempo que se diseño (de 1 segundo) no genera exactamente 1 segundo, pero es muy cercano.

Cuando

hemos terminado de configurar al timer 1, además de haber calculado la cantidad de interrupciones que se tienen que generar para lograr una temporización base de 1 segundo, se tiene que agregar en el código correspondiente de la rutina de interrupción del timer 1 un registro contador, cuya misión básica es la de verificar que el número de interrupciones que se produzcan sean precisamente las que se calcularon.

El registro contador recibe el nombre de ―co ntinte‖.

133

LIST P=PIC16F874 ;********************************************************* ; Declaración de Registros ;********************************************************* w equ 0x00 tmr0 equ 0x01 status equ 0x03 portc equ 0x07 intcon equ 0x0b pir1 equ 0x0c tmr1l equ 0x0e tmr1h equ 0x0f t1con equ 0x10 rcsta equ 0x18 cmcon equ 0x1f opsion equ 0x81 trisc equ 0x87 pie1 equ 0x8c continte equ 0x20 ;********************************************************* ; Declaración de Bits ;********************************************************* c equ 0 tmr1if equ 0 tmr1ie equ 0 tmr1on equ 0 tmr1cs equ 1 z equ 2 t1sync equ 2 t1oscen equ 3 t1ckps0 equ 4 t1ckps1 equ 5 rp0 equ 5 rp1 equ 6 peie equ 6 gie equ 7 ;********************************************************* ; Inicio ;********************************************************* reset org 0 goto progprin org 4 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 btfsc pir1,tmr1if goto intertempo retfie ;********************************************************* ;Inicio de la interrupción por uso del TIMER 1 ;********************************************************* intertempo bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf intcon,gie ;desactivación general de interrupciones. bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 bcf pie1,tmr1ie ;desactiva la interrupción del timer 1 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 Inca continte,1 ;incrementa el contador de interrupciones

clrf tmr1l clrf tmr1h bcf pir1,tmr1if ;limpia la bandera que provoco la interrupción bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 bsf pie1,tmr1ie ;activa la interrupción del timer 1 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bsf intcon,gie ;activación general de interrupciones. retfie ;********************************************************* ; programa principal ;********************************************************* progprin bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 movlw 0x00 ;configurar pines del puerto movwf trisc ;C como salida ;********************************************************* ;Configuración del timer, y declaración de variables ;********************************************************* bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf t1con,t1ckps0 bsf t1con,t1ckps1 bcf t1con,t1oscen bcf t1con,t1sync bcf t1con,tmr1cs bsf t1con,tmr1on bsf intcon,gie ;activar habilitador general de interrupciones. bsf intcon,peie bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 bsf pie1,tmr1ie ;activa la interrupción del timer 1 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 clrf portc otro clrf tmr1l clrf tmr1h clrf continte verinterrup ;verifica que se efectúen 3 interrupciones movlw 0x03 xorwf continte,w btfss status,z goto verinterrup verpartealta ;verifica que en la parte alta del registro movlw 0xcf ;de 16 bits se tenga el valor CF xorwf tmr1h,w btfss status,z goto verpartealta verpartebaja ;verifica que en la parte baja del registro movlw 0x5c ;de 16 bits se tenga el valor 5C xorwf tmr1l,w btfss status,z goto verpartebaja incsegundo ;incrementa el conteo en el puerto C inca portc,1 clrf continte goto otro end

Tabla 63. Programa para controlar los bits de un puerto por medio del timer de 16 bits.

134

Para que se active la interrupción originada por el desbordamiento en el conteo del valor que se encuentra dentro de los registros TMR1H y TMR1L, es necesario que sean intervenidos los bits 7 y 6 que se encuentran contenidos en el registro identificado como ―IN TCON‖, además del bit 0 del registro ―PIE 1‖, de acuerdo con lo siguiente. El bit 7 del registro INTCON que se identifica como GIE (Bit de habilitación Global de las Interrupciones), se debe de colocar en estado lógico ―1‖, para que sean habilitadas todas las interrupciones, mientras que si un ―0‖ lógico es colocado en el bit GIE, todas las interrupciones serán inhabilitadas.

A continuación se

muestra un resumen de lo expresado. 1 = Habilita todas las interrupciones no enmascarables. 0 = Deshabilita todas las interrupciones. El bit 6 del registro INTCON que se identifica como PEIE (Bit que Habilita las interrupciones por periférico), se debe colocar en estado lógico ― 1‖, para que la interrupción por desbordamiento en el conteo de los registros TMR1H y TMR1L surta efecto, ya que el timer 1 se encuentra clasificado como elemento periférico. 1 = Habilita las interrupciones por periférico. 0 = Deshabilita las interrupciones por periférico. Los bits restantes del registro INTCON que no se emplean para el timer1, deben de permanecer en estado lógico ―0‖.

El detalle del registro INTCON se

muestra en la imagen de la figura 32.

Figura 32 Detalle del registro INTCON. El bit 0 del registro PIE1 que se identifica como TMR1IE (Bit que Habilita la interrupción por desbordamiento del timer 1), se debe colocar en estado lógico ―1‖, para que sea el encargado de generar la correspondiente interrupción por desbordamiento en el conteo de los

registros TMR1H y TMR1L. 135

El

detalle del registro PIE1 se muestra en la imagen de la figura 33. 1 = Habilita la interrupción por desbordamiento en el timer 1. 0 = Deshabilita la interrupción por desbordamiento en el timer 1.

Figura 33. Detalle del registro PIE1. El bit que hace la función de ― bandera‖, por medio de la cual se indica que ha sido activada la interrupción por efecto del timer 1, es el que se identifica como TOIF (bit 2) y se encuentra alojado en el registro INTCON.

Este bit se coloca en

estado lógico ―1‖ cuando ocurre la interrupción, por lo tanto, una vez que se accede a la ejecución del código correspondiente, antes de salir del servicio de interrupción, se tiene que limpiar el bit TOIF (colocarlo en estado lógico ―0‖). Por ultimo, En la tabla 63 se muestra el código completo para programar al microcontrolador PIC, empleando el timer de 16 bits para controlar el conteo ascendente de los leds conectados al puerto C, llevándose a cabo el conteo con una frecuencia de 1 Hz aproximadamente.

Por otra parte, como una notación

adicional, mencionaremos que se esta configurando un microcontrolador PIC16F874, pero exactamente el mismo procedimiento de programación se puede implementar en cualquier otro microcontrolador PIC. 2.8 CONFIGURACIÓN DE LA USART Los microcontroladores pueden contar con algún módulo de comunicación, para que intercambien datos ya sea con otro microcontrolador, o con un circuito electrónico conectado de manera externa, o inclusive con una PC.

El módulo

que será explicado a continuación, de manera general se considera como una Interfase de Comunicación Serial (SCI por sus siglas en ingles) que poseen algunos microcontroladores PIC. Sincrona

Asíncrona

El nombre específico de la SCI es Universal

Receptor

Transmisor (USART).

136

La USART trabaja mediante el protocolo de comunicación serial conocido como RS-232, en el cual se establece que la transmisión de datos se realiza a través de un hilo conductor, enviando un solo bit cada vez, esto quiere decir que sí el dato se encuentra conformado por 8 bits, se estará transmitiendo bit por bit hasta completar la transferencia de los 8 bits.

Figura 34. Protocolo de comunicación RS-232. La comunicación serial implementada bajo el protocolo RS-232, implica el manejo de un bit de inicio para que el dispositivo transmisor (Tx) le ―a vise‖ al receptor (Rx) que un dato va a comenzar a transferirse, este bit de inicio se forma a partir del cambio que sufre la señal en la línea de transmisión, pasando del estado lógico ―1‖ a ―0‖ (flanco de descenso), para una mejor referencia observe la imagen de la figura 34.

Cabe hacer mención que en la línea de transmisión

cuando se encuentra inactiva (sin datos viajando a través de ella), se presenta el estado lógico ―1‖, indicando que la línea se encuentra desocupada. Posteriormente al establecimiento del bit de inicio, se comienza con el envío de los bits que conforman al dato que se tiene que transferir, considerando que el protocolo RS-232 acepta que pueda ser de un tamaño ya sea de 8 bits o de 9 bits, los cuales tienen que configurarse tanto en el equipo transmisor como en el receptor. Como paso siguiente a la transmisión de los bits que conforman al dato, de manera opcional se puede configurar el envío de un bit de paridad, o prescindir de este, de acuerdo con la norma que regula al protocolo RS-232, y de igual manera si es configurado el empleo de un bit de paridad en el equipo transmisor, también tiene que agregarse al correspondiente

equipo receptor.

137

Para dar por terminada la transmisión de un dato, el equipo transmisor le ―i nforma‖ al receptor que ha terminado con el envío, por medio del empleo de un bit identificado como de paro, el cual puede estar implementado por un solo bit o por 2 de acuerdo con el protocolo RS-232. Por ejemplo cuando se tiene la configuración de 8 bits de datos, 1 bit de paro y 0 (cero) bits de paridad, en total se envía una cantidad de 10 bits, considerando al bit de inicio, más 8 bits de datos, más 1 bit de paro. El envío de esta serie de bits, consume un determinado tiempo, por lo tanto también se tiene que sincronizar al equipo transmisor con el equipo receptor, para que no exista perdida de información. Cuando se emplea un microcontrolador PIC que posea el módulo de comunicación serial USART, tan solo se tiene que configurar a este ya sea para transmitir ó recibir ó realizar ambas actividades.

Una de las ventajas del módulo

USART es que nosotros nos olvidamos de enviar el bit de inicio, el de paro y el de paridad, ya que cuando es habilitado el módulo USART, tan solo debemos cargar el dato que se tiene que transmitir, y el USART se encarga de realizar lo demás de acuerdo a la forma en como fue configurado.

A continuación se procederá a

describir la manera de configurar tanto el envío, como la recepción de datos a través de la USART. 2.8.1 USART EN MODO TRANSMISIÓN (TX) Como primer paso se debe de ubicar el lugar en donde se encuentran las terminales del microcontrolador PIC, que trabajan con el módulo de comunicación serial RS-232.

Para ello, dependiendo del microcontrolador PIC estas terminales

se pueden encontrar ya sea en el puerto B, o el puerto C, etc.

Por lo que

siempre se recomienda revisar el correspondiente manual. En la imagen de la figura 35 se muestra un ejemplo de microcontroladores PIC típicos, en los que se resalta la ubicación de las terminales que trabajan con la USART, y que podemos tomar como

modelos generales para tomarlos de 138

referencia con respecto de cualquier otro PIC.

Figura 35. Ubicación de las terminales de la USART en los PICs. Una vez que se ha definido el microcontrolador que será empleado, y a la vez ubicado la correspondiente terminal de transmisión (identificada como Tx en los microcontroladores PIC, observe la figura 35), en primer lugar se tiene que configurar el bit correspondiente del puerto donde se ubique esta terminal, como terminal de salida de datos. A continuación se muestra el correspondiente código con el cual se ejemplifica la manera en que puede ser configurado el bit que contiene la transmisión de datos; este bit tiene que ser configurado de tal manera que la información salga del microcontrolador, por lo tanto, la configuración de la terminal Tx tiene que ser como salida.

Recordando que la ubicación de la terminal Tx, depende del

microcontrolador que se este empleando.

Para el ejemplo que se describe a

continuación consideremos que se tiene un microcontrolador PIC16F87X.

139

bsf bcf movlw movwf

status,rp0 status,rp1 b'X0XXXXXX' trisc

;cambiar al banco 1 ;configura el bit 6 como salida, los demás bits no importan de momento ;enviar configuración al registro del puerto C

Cuando hemos realizado la configuración del puerto donde se encuentra la terminal de transmisión, procedemos como paso siguiente a la activación de la herramienta USART para que el microcontrolador pueda transmitir un dato de manera serial, para ello se tienen que configurar los bits que integran al registro identificado como ― TXSTA‖, de acuerdo a como se muestra a continuación. El bit 7 del registro TXSTA que se identifica como CSRC (Bit que controla el origen de la señal de reloj), tiene la tarea de seleccionar un modo de operación del microcontrolador (como maestro o esclavo), si es que su módulo USART se encuentra configurado en el modo de operación ―sí ncrona‖.

De manera contraria,

sí el modulo USART se configuro para operar de manera ―así ncrona‖, este bit tiene que ser ignorado no importando su estado lógico. Sí el módulo USART esta configurado en modo asíncrono: CSRC no importa el estado lógico en que se coloque. Sí el módulo USART esta configurado en modo síncrono: CSRC = 1.- Modo Maestro (el reloj se genera internamente del BRG). CSRC = 0.- Modo Esclavo (el reloj se toma de manera externa). El bit 6 del registro TXSTA que se identifica como TX9 (bit que habilita la transmisión de 9 bits), se debe colocar en estado lógico ―1‖, para que surta efecto el envío de 9 bits que conformarán al dato que será transmitido, mientras que al colocar el bit TX9 en estado lógico ―0‖, configura a la USART para que se transmitan datos compuestos por 8 bits. 1 = Configura la transmisión de datos de 9 bits. 0 = Configura la transmisión de datos de 8 bits. El bit 5 del registro TXSTA que se identifica como TXEN (bit que habilita la transmisión de datos), se debe colocar en estado lógico ―1‖, para que sea activada la transmisión de datos por medio del módulo USART. coloca en estado lógico ―0‖ se tiene

Cuando el bit TXEN se

como consecuencia la inhabilitación 140

de la transmisión por medio del módulo USART. 1 = Habilita la transmisión de datos. 0 = Desactiva la transmisión de datos. Por medio del bit 4 del registro TXSTA que se identifica como SYNC (bit que selecciona el modo de operación de la USART), se determina el modo de operación del módulo USART, teniéndose la posibilidad de seleccionar entre la operación síncrona o asíncrona. 1 = Modo Síncrono. 0 = Modo Asíncrono. El bit 2 del registro TXSTA que se identifica como BRGH (bit de selección de alta taza de transferencia), tiene la tarea de seleccionar entre las posibilidades de transmitir a baja o alta velocidad, si es que su módulo USART se encuentra configurado en el modo de operación ― asíncrona‖.

De manera contraria, sí el

modulo USART se configuro para operar de manera ―sí ncrona‖, este bit no se emplea, por lo que no importa su estado lógico. Sí el módulo USART esta configurado en modo asíncrono: BRGH = 1.- Alta velocidad de transmisión. BRGH = 0.- Baja velocidad de transmisión. Sí el módulo USART esta configurado en modo síncrono: BRGH no importa el estado lógico en que se coloque. El bit 1 del registro TXSTA que se identifica como TRMT (bit que configura el estado de la transmisión), se emplea para configurar la indicación de cuando un dato sea transmitido, esto es, se generara un aviso cuando el dato sea transmitido completamente (TSR vacío) o cuando el dato aun no comience a transmitirse (TSR lleno). 1 = TSR vacío. 0 = TSR lleno. El bit 0 del registro TXSTA que se identifica como TX9D (bit que conforma al noveno bit de datos o también puede

ser el bit de paridad), se utiliza 141

solamente cuando se configura al módulo USART para que transmita 9 bits de datos, o cuando se habilita el empleo del bit de paridad.

Si el modulo USART se

configura para transmitir 8 bits de datos, sin bit de paridad, el bit TX9D no se emplea y por lo general se le carga el estado lógico ―0‖. El bit 3 del registro TXSTA no se emplea por lo que debe permanecer en estado lógico ―0‖.

El detalle del registro TXSTA se muestra en la imagen de la

figura 36.

Figura 36. Detalle del registro TXSTA. Cuando el registro TXSTA ha sido configurado, procederemos a determinar el valor de la tasa de trasferencia de los datos, este termino que en ingles se escribe como ―ba ud rate‖, detalla la cantidad de bits que por segundo son transmitidos. Se trata de un término muy importante, ya que si entre el elemento transmisor y el receptor no se tiene el mismo valor, entonces se perderán bits provocando que el dato transmitido sea totalmente diferente al original. En los microcontroladores PIC, recurrimos a una serie de valores ―com erciales‖ para configurar al módulo USART, los cuales pueden ser 9600 baudios (9600 bits por segundo) ó 4800 ó 2400, etc.

Estos valores y otros más los encontramos

agrupados en tablas, como las que se encuentran identificadas con los números 64, 65 y 66.

A continuación se ilustran las diferentes tablas por medio de las

cuales se determina el valor de la tasa de transferencia de los datos.

Dentro de

las tablas se observa que existe un valor en formato decimal, que es el que tiene que cargarse al registro ―SPB RG‖, para fijar la cantidad de bits que por segundo serán transmitidos.

142

Baud Rate (k) 0.3 1.2 2.4 9.6 19.2 76.8 96 300 500 HIGH LOW

FOSC = 20 MHz KBAUD NA NA NA NA 19.53 76.92 96.15 294.1 500 5000 19.53

ERROR — — — — +1.73% +0.16% +0.16% -1.96 0 — —

SPBRG valor (decimal) — — — — 255 64 51 16 9 0 255

FOSC = 16 MHz KBAUD NA NA NA NA 19.23 76.92 95.24 307.69 500 4000 15.625

ERROR — — — — +0.16% +0.16% -0.79% +2.56% 0 — —

SPBRG valor (decimal) — — — — 207 51 41 12 7 0 255

FOSC = 10 MHz KBAUD NA NA NA 9.766 19.23 75.76 96.15 312.5 500 2500 9.766

ERROR — — — +1.73% +0.16% -1.36% +0.16% +4.17% 0 — —

SPBRG valor (decimal) — — — 255 129 32 25 7 4 0 255

Baud FOSC = 7.15909 MHz SPBRG FOSC = 5.0688 MHz SPBRG Rate valor valor (k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) 0.3 NA — — NA — — 1.2 NA — — NA — — 2.4 NA — — NA — — 9.6 9.622 +0.23% 185 9.6 0 131 19.2 19.24 +0.23% 92 19.2 0 65 76.8 77.82 +1.32 22 79.2 +3.13% 15 96 94.20 -1.88 18 97.48 +1.54% 12 300 298.3 -0.57 5 316.8 5.60% 3 500 NA — — NA — — HIGH 1789.8 — 0 1267 — 0 LOW 6.991 — 255 4.950 — 255

FOSC = 4 MHz

Baud FOSC = 3.579545 MHz SPBRG Rate valor (k) KBAUD ERROR (decimal) 0.3 NA — — 1.2 NA — — 2.4 NA — — 9.6 9.622 +0.23% 92 19.2 19.04 -0.83% 46 76.8 74.57 -2.90% 11 96 99.43 +3.57% 8 300 298.3 0.57% 2 500 NA — — HIGH 894.9 — 0 LOW 3.496 — 255

FOSC = 32.768 KHz SPBRG valor KBAUD ERROR (decimal) 0.303 +1.14% 26 1.170 -2.48% 6 NA — — NA — — NA — — NA — — NA — — NA — — NA — — 8.192 — 0 0.032 — 255

FOSC = 1 MHz KBAUD NA 1.202 2.404 9.615 19.24 83.34 NA NA NA 250 0.9766

ERROR — +0.16% +0.16% +0.16% +0.16% +8.51% — — — — —

SPBRG valor (decimal) — 207 103 25 12 2 — — — 0 255

KBAUD NA NA NA 9.615 19.231 75.923 1000 NA NA 100 3.906

ERROR — — — +0.16% +0.16% +0.16% +4.17% — — — —

SPBRG valor (decimal) — — — 103 51 12 9 — — 0 255

Tabla 64. Tasa de transferencia para el modo Síncrono. Para definir el valor que se le cargara al registro SPBRG, se debe de tomar en cuenta el valor de la tasa de transferencia (baud rate), además del valor del oscilador que se le conecte al microcontrolador (FOSC). Posteriormente tomar en cuenta

el

valor

de

la

tasa

de

transferencia real a la que serán 143

transmitidos los datos (Kbaud), y por ende el error involucrado. Baud Rate (k) 0.3 1.2 2.4 9.6 19.2 76.8 96 300 500 HIGH LOW

FOSC = 20 MHz KBAUD NA 1.221 2.404 9.469 19.53 78.13 104.2 312.5 NA 312.5 1.221

ERROR — +1.73% +0.16% -1.36% +1.73% +1.73% +8.51% +4.17% — — —

SPBRG valor (decimal) — 255 129 32 15 3 2 0 — 0 255

FOSC = 16 MHz KBAUD NA 1.202 2.404 9.615 19.23 83.33 NA NA NA 250 0.977

ERROR — +0.16% +0.16% +0.16% +0.16% +8.51% — — — — —

SPBRG valor (decimal) — 207 103 25 12 2 — — — 0 255

FOSC = 10 MHz KBAUD NA 1.202 2.404 9.766 19.53 78.13 NA NA NA 156.3 0.6104

ERROR — +0.16% +0.16% +1.73% +1.73% +1.73% — — — — —

SPBRG valor (decimal) — 129 64 15 7 1 — — — 0 255

Baud FOSC = 7.15909 MHz SPBRG FOSC = 5.0688 MHz SPBRG Rate valor valor (k) KBAUD ERROR (decimal) KBAUD ERROR (decimal) 0.3 NA — — 0.31 +3.13% 255 1.2 1.203 +0.23% 92 1.2 0 65 2.4 2.380 -0.83% 46 2.4 0 32 9.6 9.322 -2.90% 11 9.9 +3.13% 7 19.2 18.64 -2.90% 5 19.8 +3.13% 3 76.8 NA — — 79.2 +3.13% 0 96 NA — — NA — — 300 NA — — NA — — 500 NA — — NA — — HIGH 111.9 — 0 79.2 — 0 LOW 0.437 — 255 0.3094 — 255

FOSC = 4 MHz

Baud FOSC = 3.579545 MHz SPBRG Rate valor (k) KBAUD ERROR (decimal) 0.3 0.301 +0.23% 185 1.2 1.190 -0.83% 46 2.4 2.432 +1.32% 22 9.6 9.322 -2.90% 5 19.2 18.64 -2.90% 2 76.8 NA — — 96 NA — — 300 NA — — 500 NA — — HIGH 55.93 — 0 LOW 0.2185 — 255

FOSC = 32.768 KHz SPBRG valor KBAUD ERROR (decimal) 0.256 -14.67% 1 NA — — NA — — NA — — NA — — NA — — NA — — NA — — NA — — 0.512 — 0 0.0020 — 255

FOSC = 1 MHz KBAUD 0.300 1.202 2.232 NA NA NA NA NA NA 15.63 0.0610

ERROR +0.16% +0.16% -6.99% — — — — — — — —

SPBRG valor (decimal) 51 12 6 — — — — — — 0 255

KBAUD 0.3005 1.202 2.404 NA NA NA NA NA NA 62.500 3.906

ERROR -0.17% +1.67% +1.67% — — — — — — — —

SPBRG valor (decimal) 207 51 25 — — — — — — 0 255

Tabla 65. Tasa de transferencia para el modo Asíncrono cuando BRGH = 0.

144

Baud Rate (k) 9600 19200 38400 57600 115200 250000 625000 1250000

FOSC = 20 MHz

SPBRG valor KBAUD ERROR (decimal) 9.615 +0.16% 129 19.230 +0.16% 64 37.878 -1.36% 32 56.818 -1.36% 21 113.636 -1.36% 10 250 0 4 625 0 1 1250 0 0

Baud FOSC = 7.15909 MHz SPBRG Rate (k) valor KBAUD ERROR (decimal) 9600 9.520 -0.83% 46 19200 19.454 +1.32% 22 38400 37.286 -2.90% 11 57600 55.930 -2.90% 7 115200 111.860 -2.90% 3 250000 NA — — 625000 NA — — 1250000 NA — — Baud FOSC = 3.579545 MHz SPBRG Rate (k) valor KBAUD ERROR (decimal) 9600 9725.543 1.308% 22 19200 18640.63 -2.913% 11 38400 37281.25 -2.913% 5 57600 55921.88 -2.913% 3 115200 111243.8 -2.913% 1 250000 223687.5 -10.525% 0 625000 NA — — 1250000 NA — —

FOSC = 16 MHz

SPBRG valor KBAUD ERROR (decimal) 9.615 +0.16% 103 19.230 +0.16% 51 38.461 +0.16% 25 58.823 +2.12% 16 111.111 -3.55% 8 250 0 3 NA — — NA — —

FOSC = 5.0688 MHz SPBRG valor KBAUD ERROR (decimal) 9598.485 0.016% 32 18632.35 -2.956% 16 39593.75 3.109% 7 52791.67 -8.348% 5 105583.3 -8.348% 2 316750 26.700% 0 NA — — NA — — FOSC = 1 MHz

SPBRG valor KBAUD ERROR (decimal) 8.928 -6.994% 6 20833.3 8.507% 2 31250 -18.620% 1 62500 +8.507% 0 NA — — NA — — NA — — NA — —

FOSC = 10 MHz KBAUD 9.615 18.939 39.062 56.818 125 NA 625 NA

SPBRG valor ERROR (decimal) +0.16% 64 -1.36% 32 +1.7% 15 -1.36% 10 +8.51% 4 — — 0 0 — —

FOSC = 4 MHz KBAUD 9615.385 19230.77 35714.29 62500 125000 250000 NA NA

SPBRG valor ERROR (decimal) 0.160% 25 0.160% 12 -6.994% 6 8.507% 3 8.507% 1 0.000% 0 — — — —

FOSC = 32.768 KHz SPBRG valor KBAUD ERROR (decimal) NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA

Tabla 66. Tasa de transferencia para el modo Asíncrono cuando BRGH = 1. Con este último paso ha quedado configurado el módulo USART para que transmita datos, por lo que ahora se tiene que cargar el valor del dato que se quiere transmitir, en el registro llamado ―T XREG‖ (buffer de transmisión). Cuando se guarda un dato en el registro TXREG, de inmediato se comienza a transferir enviando bit a bit (obviamente de manera previa se configuro y activo la USART) hacia la terminal del microcontrolador identificada como Tx. De alguna manera, el módulo USART debe tener el conocimiento de cuando termine de realizar un envío de datos,

145

para no cometer el error de transferir

un siguiente dato cuando no ha terminado con el anterior. cuenta con 2 posibilidades de configuración.

Para esto último se

En la primera de ellas se puede

activar el aviso por medio de una interrupción, por medio de fijar el estado lógico ―1‖ en el bit TXIE que se encuentra en el registro PIE1; teniendo su respectiva bandera en el bit TXIF que se encuentra en el registro PIR1, la cual se colocara en estado lógico ―1‖ cuando el dato que se esta transmitiendo haya sido completamente transferido, o dicho de otra manera, cuando el dato que se alojo en el registro TXREG se ha enviado completamente.

La segunda manera de

indicar que un dato ha sido transmitido, es simplemente esperar a que sean enviados todos los bits que componen al dato, por medio de la instrucción ― btfss pir1,txif‖, en la cual también se puede ocupar a la bandera TXIF del registro PIR1, para saber en que momento se ha vaciado el buffer de transmisión.

En la tabla

67 se muestra una propuesta de código para configurar a la USART en el modo de transmisión asíncrona. bsf bcf movlw movwf movlw movwf bcf bcf bsf movf movwf espera btfss goto

status,rp0 status,rp1 b'00100110' txsta .25 spbrg status,rp0 status,rp1 rcsta,spen recep,w txreg

;cambiar al banco 1

pir1,txif espera

;espera a que sean transmitidos todos los bits del dato

;configura al registro TXSTA ;establece el valor de la tasa de transferencia ;cambiar al banco 0 ;configura las terminales del PIC para Tx y Rx ;carga el dato que será transmitido al registro W ;el contenido del registro W se transmite

Tabla 67 Fragmento de Programa para activar la USART en modo transmisión. 2.8.2 USART EN MODO RECEPCIÓN (RX) Una vez que han sido identificados los pines del microcontrolador que contienen las terminales de transmisión y recepción de datos mediante el modulo USART, sabremos como configurar dichos pines. figura 35 para una mejor referencia, un

Se muestra en la imagen de la

ejemplo típico de la ubicación de las

146

terminales en 3 microcontroladores PIC diferentes. Cuando ya se sabe que microcontrolador a de ser empleado, en automático de conoce la ubicación de la terminal de recepción de datos (identificada como Rx en los microcontroladores PIC, observe la figura 35), en primer instancia se tiene que configurar el bit correspondiente del puerto donde se ubique esta terminal, como terminal de entrada de datos. En seguida se muestra el fragmento de código mediante el cual se configura al bit que contiene la recepción de datos, el cual se encuentra dentro del correspondiente registro ―tr is‖.

Este bit tiene que ser configurado de tal manera

que la información pueda acceder al microcontrolador, por lo tanto, la configuración de la terminal Rx tiene que ser como entrada.

Nuevamente

recordamos que la ubicación de la terminal Rx depende del microcontrolador que se este empleando. Para el ejemplo que se describe a continuación consideremos que se tiene un microcontrolador PIC16F87X. bsf bcf movlw movwf

status,rp0 status,rp1 b'1XXXXXXX' trisc

;cambiar al banco 1 ;config el bit 7 como entrada, los demás bits no importan de momento ;enviar configuración al registro del puerto C

Cuando hemos realizado la configuración del puerto donde se encuentra la terminal de recepción, procedemos a la manipulación de registros del microcontrolador PIC para poder activar la USART, dejando al microcontrolador en la tarea de recibir datos de manera serial, para ello se tienen que configurar principalmente los bits que integran a los registros identificados como TXSTA, SPBRG, RCSTA y PIE1, de acuerdo a la explicación siguiente. Del registro TSXTA se toma principalmente el bit 7 (CSRC.-Bit que controla el origen de la señal de reloj), el bit 4 (SYNC.- bit que selecciona el modo de operación de la USART), y el bit 2 (BRGH.- bit de selección de alta taza de transferencia).

Los demás bits se emplean para configurar a la actividad de

transmisión de datos seriales, motivo

por el cual no se manipulan a menos 147

que se vaya a emplear a la USART en el modo full duplex (recepción y transmisión de datos al mismo tiempo).

La explicación del detalle de los bits CSRC, SYNC y

BRGH se encuentra en el apartado ―U SART en modo transmisión‖, y el detalle de la composición del registro TXSTA se muestra en la figura 36. Otro registro que también debe ser manipulado es el identificado como ―spb rg‖, siendo a través de este registro el medio para determinar el valor de la tasa de trasferencia de los datos (baud rate), con la cual serán recibidos por el microcontrolador PIC.

Los distintos valores de tasa de trasferencia se

encuentran indicados en las tablas 64, 65 y 66, recordando que la tasa de trasferencia en un microcontrolador PIC, depende de valor que se tenga en el circuito oscilador del PIC. A continuación para que sea completamente configurada la herramienta USART del microcontrolador PIC, tienen que ser manipulados los bits que integran al registro identificado como RCSTA, tal como se explica a continuación. El bit 7 del registro RCSTA que se identifica como SPEN (Bit que habilita al puerto serie del PIC), tiene como actividad principal la de habilitar tanto a la terminal identificada como Tx y Rx, para que realicen la función de comunicar de manera serial al microcontrolador, por lo que una vez que ha sido activado este bit, se establecen los niveles eléctricos correspondientes sobre las terminales Tx y Rx. 1 = Puerto serial Habilitado. 0 = Puerto serial Deshabilitado. El bit 6 del registro RCSTA que se identifica como RX9 (bit que habilita la recepción de 9 bits), se debe colocar en estado lógico ―1‖, para que surta efecto la recepción de 9 bits que conformarán al dato que será recepcionado, mientras que al colocar el bit TX9 en estado lógico ―0‖, configura a la USART para que se reciban datos compuestos por 8 bits.

Recuerde que se coloca la recepción de 9

bits de datos, cuando en la transmisión se tienen también 9 bits de datos, por lo tanto, el dispositivo transmisor como el 148

receptor deben estar fijos con el

mismo número de bits que conforman al dato que será intercambiado. 1 = Configura la recepción de datos de 9 bits. 0 = Configura la recepción de datos de 8 bits. El bit 5 del registro RCSTA que se identifica como SREN (bit que habilita la recepción de un solo dato), tiene la tarea de activar la recepción de un solo dato, si es que su módulo USART se encuentra configurado en el modo de operación ―sí ncrona‖.

De manera contraria, sí el modulo USART se configuro para operar

de manera ―así ncrona‖, este bit tiene que ser ignorado no importando su estado lógico. Sí el módulo USART esta configurado en modo asíncrono: SREN no importa el estado lógico en que se coloque. Sí el módulo USART esta configurado en modo síncrono como maestro: SREN = 1.- Activa la recepción de un solo dato. SREN = 0.- Desactiva la recepción de un solo dato Este bit se limpia antes de que la recepción se haya completado. Sí el módulo USART esta configurado en modo síncrono como esclavo: SREN no se emplea bajo esta variante. Por medio del bit 4 del registro RCSTA que se identifica como CREN (bit que habilita la recepción continua de datos), el modulo USART del microcontrolador PIC, tiene la tarea de recibir de manera continua todos los datos que se le envíen, aun cuando se encuentre configurado tanto en el modo asíncrono como síncrono. Sí el módulo USART esta configurado en modo asíncrono: CREN = 1.- Activa la recepción continua de datos. CREN = 0.- Desactiva la recepción continua de datos. Sí el módulo USART esta configurado en modo síncrono: CREN = 1.- Activa la recepción continua de datos, hasta que el bit CREN es limpiado (el bit CREN sobre escribe al bit SREN). CREN = 0.- Desactiva la recepción continua de datos. El bit 3 del registro RCSTA que se identifica como ADEN (bit que habilita la detección de direccionamiento), realiza la activación de la carga del dato recibido en un buffer de memoria.

Esta 149

actividad

solo

se

puede

realizar

cuando el modulo USART se encuentra en el modo de operación asíncrona. Sí el módulo USART esta configurado en modo asíncrono, y cuando RX9=1: ADEN = 1.- Activa la detección de la correspondiente dirección de memoria del buffer, cuando se reciben los datos. ADEN = 0.- Activa la detección de memoria, teniendo la recepción de todos los bits, y el noveno bit puede ser empleado como bit de paridad. Sí el módulo USART esta configurado en modo síncrono: ADEN no se emplea bajo esta variante. El bit 2 del registro RCSTA que se identifica como FERR (bit bandera que indica errores en la trama), muestra por medio del estado lógico ― 1‖ sí el dato que fue recibido no cumple con el contenido de la información real, este error se debe a un bit de la información que se encuentre erróneo, este error puede ser corregido mediante la implementación del bit de paridad. 1 = Error en la trama (Puede actualizarse leyendo el registro RCREG, y/o recibiendo el siguiente dato valido). 0 = Sin error en la trama. El bit 1 del registro RCSTA que se identifica como OERR (bit bandera que indica un sobre flujo de datos), se emplea para detectar sí en el momento que la USART se encuentra recepcionando un dato, llega otro antes de que el primero termine de recepcionarse. 1 = Error por sobre flujo de datos (puede limpiarse al limpiar el bit CREN). 0 = Sin error por sobre flujo de datos. El bit 0 del registro RCSTA que se identifica como RX9D (bit que conforma al noveno bit de datos o también puede ser el bit de paridad), se utiliza solamente cuando se configura al módulo USART para que transmita 9 bits de datos, o cuando se habilita el empleo del bit de paridad.

Si el modulo USART se

configura para transmitir 8 bits de datos, sin bit de paridad, el bit RX9D no se emplea y por lo general se le carga el estado lógico ―0‖. El detalle del registro RCSTA se

150

muestra en la imagen de la figura 37.

Figura 37. Detalle del registro RCSTA. Con la configuración del registro RCSTA paso ha quedado configurado el módulo USART para que reciba datos, por lo que ahora debemos de tomar en cuenta que la información que se reciba de manera serial se encontrará alojada en el registro llamado ―R CREG‖ (buffer de recepción).

Cada vez que se recibe un

dato por medio de la terminal Rx del microcontrolador (previa activación de la USART), se guardan en el registro RCREG, por lo que de inmediato se debe tomar el dato recepcionado y cambiarlo a otro registro para almacenarlo, porque solo existe el registro RCREG para recepcionar los datos, y si no es guardado se perderá cuando suceda una nueva recepción de datos. bsf bcf movlw movwf movlw movwf bcf bcf bsf bsf bsf bsf bsf bcf bsf

status,rp0 ;cambiar al banco 1 status,rp1 b'00100110' txsta .25 spbrg status,rp0 ;cambiar al banco 0 status,rp1 rcsta,spen ;habilitación del puerto de comunicación serial rcsta,cren ;activa la recepción continua intcon,gie ;activar habilitador general de interrupciones. intcon,peie ;activar habilitador general de interrupciones por periféricos. status,rp0 ;cambiar al banco 1 status,rp1 pie1,rcie ;activar interrupción por fin de recepción por usart.

Tabla 68. Fragmento de Programa para activar la USART en modo recepción.

Cuando el modulo USART se encuentra configurado en modo recepción, permite que el microcontrolador realice otras actividades, y solo prestara atención al dato recibido cuando por medio de una interrupción tome ―con ciencia‖ de que un dato acaba de llegar al buffer de recepción (registro RCREG). de la interrupción se realiza por medio

La configuración

de la fijación del estado lógico ―1‖ en

151

el bit RCIE que se encuentra en el registro PIE1.

El bit bandera de la

interrupción por recepción de dato se encuentra en el bit RCIF que se encuentra en el registro PIR1, esta bandera se colocara en estado lógico ―1‖ cuando el dato que se recepciono ha llegado de manera completa, o dicho de otra manera, cuando el dato que se alojo en el registro RCREG se ha recibido completamente. Una vez que se produce una interrupción, el contador de programa (program counter) se ubica en la dirección 04, por lo que allí se debe de preguntar cual dispositivo interno del microcontrolador PIC es el que ha generado la interrupción, y para esto es que se emplea la bandera RCIF, ya que sí se encuentra en estado lógico ―1‖ significa que se recibió un dato.

Como paso siguiente se tiene que

direccionar la ejecución del código del programa de la interrupción, por medio de un brinco incondicional. interserie bcf bcf bcf movf movwf bcf bsf retfie

;Interrupción por USART (Recepción) status,rp0 ;cambiar al banco 0 status,rp1 intcon,gie ;desactivación de las interrupciones rcreg,w ;recuperar el dato recibido por RS232 recep pir1,rcif ;limpia la bandera intcon,gie ;activa las interrupciones ;termina la interrupción

Tabla 69. Fragmento de Programa para configurar atender la interrupción cuando se recibió un dato mediante la USART.

Ya dentro del código del programa de la interrupción, se debe colocar la menor cantidad de instrucciones, por lo que las principales son las siguientes: Desactivar las interrupciones; pasar el dato recibido a otro registro de memoria (normalmente RAM), limpiar la bandera RCREG, volver a activar las interrupciones y por último colocar la instrucción que indica la terminación de la interrupción.

152

LIST P=PIC16F876 ;************************************************************ ; Declaración de Registros ;************************************************************ status equ 0x03 portc equ 0x07 intcon equ 0x0b pir1 equ 0x0c rcsta equ 0x18 txreg equ 0x19 rcreg equ 0x1a trisc equ 0x87 pie1 equ 0x8c txsta equ 0x98 spbrg equ 0x99 recep equ 0x25 ;************************************************************ ; Declaración de Bits ;************************************************************ adon equ 0 c equ 0 z equ 2 txif equ 4 rcif equ 5 rcie equ 5 rp0 equ 5 rp1 equ 6 peie equ 6 adif equ 6 gie equ 7 ;************************************************************ ; Inicio ;************************************************************ reset org 0 goto iniProg org 4 bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 btfsc pir1,rcif ;¿interrupción por USART? goto interserie retfie ;************************************************************ ; Interrupciones ;************************************************************ interserie ;Interrupción por USART (Recepción) bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bcf intcon,gie ;desactivación de las Inter. movf rcreg,w ;recuperar el dato recibido movwf recep bcf pir1,rcif ;limpia la bandera bsf intcon,gie ;activa las interrupciones retfie ;termina la interrupción

;************************************************************ ; Programa principal ;************************************************************ iniProg bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 movlw b'10000000' ;config el bit 7 como entrada movwf trisc ;y los demás bits como salidas ;---------------------------------------------------------------------; Activación de la USART en modo Tx ;---------------------------------------------------------------------bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 movlw b'00100110' movwf txsta movlw .25 movwf spbrg bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 bsf rcsta,spen ;habilita. del puerto serial bsf rcsta,cren ;activa la recepción continua bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 bsf pie1,rcie ;activa. Inter. por recepción ;---------------------------------------------------------------------; Retransmite el dato recibido mediante USART ;---------------------------------------------------------------------esperadato bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 movf recep,w xorlw 0x00 btfss status,z goto transmite goto esperadato transmite call subTx clrf recep goto esperadato ;************************************************************ ; Subrutinas ;************************************************************ subTx ;Subrutina para Tx un dato mediante la USART bsf status,rp0 ;cambiar al banco 1 bcf status,rp1 movlw b'00100110' movwf txsta movlw .25 movwf spbrg bcf status,rp0 ;cambiar al banco 0 bcf status,rp1 movf recep,w movwf txreg espera btfss pir1,txif goto espera return end

Tabla 70. Programa para transmitir y recibir datos mediante la USART.

En la tabla 68 se muestra el código para activar la USART del microcontrolador PIC en modo recepción, además en la 153

tabla 69 a manera de sugerencia se

muestra el código de un programa para implementar la interrupción.

Se debe

considerar que se esta empleando un microcontrolador PIC16F87X, pero si se requiere usar otro, lo único que se tiene que cambiar es la ubicación de las terminales Tx y Rx.

En la tabla 70 se muestra un programa completo, en el que

el dato que reciba el microcontrolador PIC de manera serial lo retransmitirá, también empleando la USART.

154

4ª de forros.qxd:sumario 223 21/11/13 18:13 Página 4ªFo1

Creatronica 349.qxd:Maquetación 1 21/4/16 12:11 p.m. p Página 1