G6 PICddd

28
 GUIA DE PRACTICA DE LABORATORIO Nº 6 1. Datos Generales 1.1 1.2 1.3 1.4 5.1 Introducción Curso : Arquitectura de Computadoras (EL-51) Sección : B-701 Semestre : 2005-1 Profesor  : Ing. Javier Barriga Hoyle 2. Título: CONTROLADOR DE INTERRUPCIONES PROGRAMABLE (PIC) & PUERTO PARALELO DE LA COMPUTADORA 3. Objetivos Aprende a configurar y programar el PIC 82C59 interno de la computadora personal. Aprende a programar el PIC para trabajar con las interrupciones IRQ0 (reloj del sistema), IRQ1 (teclado) y IRQ7 (puerto paralelo) principalmente. Comprende la utilidad de las interrupciones para la adquisición de datos en tiempo real, comunicación serial, control por puerto paralelo, etc. Realice programas utilizando más de una interrupción. Comprende cuando usar o no usar interrupciones dentro de un proceso. 4. Materiales Computadora personal con Microsoft Visual C++ 6.0. 1 Tarjeta de adquisición de datos para puerto paralelo (Tarjeta principal). 1 potenciómetro. 1 sensor de temperatura (puede ser: termistor, termocupla o pt100). Fuente de alimentación de 5 voltios. 5. Fundamento teórico Una interrupción se genera cuando se quiere que la CPU deje de ejecutar el proceso en curso y ejecute una función específica de quien produce la interrupción. Cuando se ejecuta esta función específica decimos que la CPU está atendiendo la interrupción. Podemos realizar una clasificación de las interrupciones, atendiendo a la fuente que las produce. Interrupción software, se produce cuando un usuario solicita una llamada del sistema. Se tratan de procedimientos a los que llama un programa para la ejecución de tareas ligadas, en su mayoría, al hardware de la computadora, tales como la adquisición de una tecla, enviar información a la pantalla, transmisión y recepción de datos vía un canal de comunicación con el exterior, etc.  En realidad las interrupciones por software no interrumpen nada, ya que cumplen una función muy similar a una llamada a subrutina  (por ejemplo, CALL en el caso de una PC). Interrupciones hardware, son causadas cuando un dispositivo hardware requiere la atención de la CPU para que se ejecute su manejador (rutina de interrupción). Internas: Son generadas dentro del CPU. Por ejemplo, un desbordamiento en la división, un código de operación no valido (illegal opcode), etc. Externas: Son interrupciones generadas externamente al CPU, pudiendo ser generadas  por dispositivos dentro de la placa del sistema (mainboard) o por una unidad de E/S de Laboratorio de Arquitectura de Computadoras 1

description

bbb

Transcript of G6 PICddd

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 1/28

 

GUIA DE PRACTICA DE LABORATORIO Nº 6

1. Datos Generales

1.1

1.2

1.3

1.4

5.1 Introducción

Curso : Arquitectura de Computadoras (EL-51)

Sección : B-701

Semestre : 2005-1

Profesor   : Ing. Javier Barriga Hoyle 

2. Título: CONTROLADOR DE INTERRUPCIONES PROGRAMABLE (PIC) &

PUERTO PARALELO DE LA COMPUTADORA

3. Objetivos

Aprende a configurar y programar el PIC 82C59 interno de la computadora personal.

Aprende a programar el PIC para trabajar con las interrupciones IRQ0 (reloj del sistema),

IRQ1 (teclado) y IRQ7 (puerto paralelo) principalmente.

Comprende la utilidad de las interrupciones para la adquisición de datos en tiempo real,

comunicación serial, control por puerto paralelo, etc.

Realice programas utilizando más de una interrupción.

Comprende cuando usar o no usar interrupciones dentro de un proceso.

4. Materiales

Computadora personal con Microsoft Visual C++ 6.0.

1 Tarjeta de adquisición de datos para puerto paralelo (Tarjeta principal).

1 potenciómetro.

1 sensor de temperatura (puede ser: termistor, termocupla o pt100).

Fuente de alimentación de 5 voltios.

5. Fundamento teórico

Una interrupción se genera cuando se quiere que la CPU deje de ejecutar el proceso en curso y

ejecute una función específica de quien produce la interrupción. Cuando se ejecuta esta función

específica decimos que la CPU está atendiendo la interrupción. Podemos realizar una

clasificación de las interrupciones, atendiendo a la fuente que las produce.

Interrupción software, se produce cuando un usuario solicita una llamada del sistema. Se

tratan de procedimientos a los que llama un programa para la ejecución de tareas ligadas, en

su mayoría, al hardware de la computadora, tales como la adquisición de una tecla, enviar

información a la pantalla, transmisión y recepción de datos vía un canal de comunicación con

el exterior, etc.  En realidad las interrupciones por software no interrumpen nada, ya que

cumplen una función muy similar a una llamada a subrutina (por ejemplo, CALL en el caso

de una PC).

Interrupciones hardware, son causadas cuando un dispositivo hardware requiere la atención

de la CPU para que se ejecute su manejador (rutina de interrupción).

♦ Internas: Son generadas dentro del CPU. Por ejemplo, un desbordamiento en la división,

un código de operación no valido (illegal opcode), etc.

♦ Externas: Son interrupciones generadas externamente al CPU, pudiendo ser generadas

 por dispositivos dentro de la placa del sistema (mainboard) o por una unidad de E/S de

Laboratorio de Arquitectura de Computadoras 1

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 2/28

 

algún periférico fuera de la placa del sistema. Por ejemplo: El teclado, Un temporizador,

Un DMA al finalizar la transferencia, etc. Estas se clasifican en:

Enmascarables:  Cuando las interrupciones pueden ser activadas (permitidas) o

desactivadas (inhibidas) por programa (software). 

 No enmascarables: Cuando las interrupciones no pueden ser desactivadas (inhibidas) por programa (software).

5.2 Interrupciones en la PC

La CPU 80x86 de una PC, posee tres señales para lo que son interrupciones externas (las cuales

se mantienen aun por compatibilidad en PCS actuales basados en procesadores Pentium).

CPU

INTR

NMI

RESET

INTA

 

Figura 6.1 Líneas de interrupción.

Donde:

Interrupt request (INTR): Solicitud de interrupción, está disponible para ser utilizada por

dispositivos periféricos externos que necesiten ser atendidos por el CPU, el procesador 80x86

muestrea esta señal cada vez que va a iniciar una instrucción, si detecta que tiene un nivel

lógico ‘1’, reconoce la interrupción y salta a la rutina de servicio correspondiente para

atender dicho requerimiento. Esta línea de interrupción es enmascarable, puede ser habilitada

ó deshabilitada con la bandera de interrupción (IF) del PSW. (CLI en Assembler y desable() en C++ hace que IF = 0 con lo que sé deshabilita INTR, STI en Assembler y enable()  en

C++ hace que IF = 1 con lo que habilita INTR permitiendo así las interrupciones por esta

línea).

Nonmaskable interrupt request (NMI): Esta disponible para ser utilizada por periféricos

externos que necesiten ser atendidos por el CPU, esta señal no es enmascarable, la petición de

interrupción en este caso es capturada dentro del CPU en el flanco de subida (transición de 0

a 1 de NMI) de la señal NMI y se salta a la rutina de servicio cuando se completa la

instrucción en curso. Esta es utilizada frecuentemente para la detección de errores de paridad

y otras fallas mayores del sistema, tales como la falta de energía.

System reset (RESET): Es utilizada para generar una inicialización completa del procesador

80x86, al pasar a nivel ‘1’, se interrumpe la ejecución de todo y sé inicializan los registrosinternos del procesador y cuando vuelve a ‘0’ la señal, el control es transferido al inicio de la

rutina de servicio de RESET, esta rutina inicializa el resto de los recursos del sistema, como

 por ejemplo los puertos I/O, las banderas de interrupción, los datos iniciales en la memoria,

inicia una serie de tests, asegurando el correcto inicio de todo el sistema. Siempre que el

microprocesador es restaurado, inicia la ejecución de instrucciones en la localidad de

memoria FFFF0h (para el 8086) e inhabilita interrupciones futuras restaurando el bit de

 bandera IF.

INTA: La señal de reconocimiento de interrupción, es una respuesta a la terminal de entrada

INTR. La terminal INTA es normalmente empleada para ubicar el número de vector de

interrupción en el bus de datos, en respuesta a la solicitud de interrupción.

La figura 6.2 muestra el diagrama de conexiones de la CPU y los controladores de interrupciones.

Laboratorio de Arquitectura de Computadoras 2

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 3/28

 

INTA

INT

DATOS

80x86

INT

INTA

SP/ EN

DATOS

INT

INTA DATOS

BUS DE DATOS

IRQ0IRQ1

IRQ3IRQ4IRQ5IRQ6IRQ7

IRQ8IRQ9IRQ10IRQ11IRQ12IRQ13IRQ14IRQ15

SP/ EN1 0

CAS 0CAS 1CAS 2

8259A 8259A(master) (esclavo)

 Figura 6.2 Controladores de interrupciones en la PC

Impresora

PICIRQ7

CPU

INT

INTA

00000H Vector 0

Vector 1

Vector 15

00004H

Programa de

la RSI

MEMORIA

JMP printer 

FFFFFH

 

PC

Figura 6.3 Secuencia de eventos que se generan debido a una interrupción.

Las líneas de interrupción (IRQx), están conectadas a los periféricos tal como muestra la tabla

siguiente. Además se indica el nivel de prioridades (IRQ0 es la de mayor prioridad)

Línea deinterrupción

Dispositivo conectado* = Puede estar ubicado en otra línea de IRQ (o podría no estar presente)

Númerode vector

IRQ 0 Temporizador (TIMER, contador 0) 08h

IRQ 1 Teclado (KEYBOARD) 09h

IRQ 2 Cascada con el PIC esclavo 0Ah

IRQ 3 Puerto de comunicaciones serial #2 (COM2) 0BhIRQ 4 Puerto de comunicaciones serial #1 (COM1) 0Ch

IRQ 5 *Tarjeta de sonido (SOUND BLASTER) 0Dh

IRQ 6 Controlador estándar de disquetes (FDD) 0Eh

IRQ 7 Puerto paralelo (LPT1, típicamente utilizado para colocar una impresora) 0Fh

IRQ 8 Reloj de tiempo real/Sistema CMOS (REAL TIME CLOCK/CMOS) 70h

IRQ 9 (libre) 71h

IRQ 10 Controlador de bus serie universal (USB) 72h

IRQ 11 (libre) 73h

IRQ 12 *MODEM 74h

IRQ 13 Procesador de datos numéricos (FPU) 75h

IRQ 14 Controlador primario IDE 76h

IRQ 15 *Controlador secundario IDE 77hTabla 6.1 Asignación de interrupciones en la PC

Laboratorio de Arquitectura de Computadoras 3

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 4/28

 

5.3 Controlador de interrupciones programable PIC 8259A

1

2

3

4

5

6

7

8

9

10

11

12

28

27

26

25

24

23

22

21

20

19

18

17

CS

WR

RD

D7

D6

D5

D4

D3

D2

D1

D0

GND

VCC

 A0

INTA

IR7

IR6

IR5

IR4

IR3

IR2

IR1

IR0

INT

82C59A

CAS1

CAS0

13

14 15

16

CAS2

SP/EN

RDWR

82C59A

11

10987654

27132

161726

18

19202122232425

IR0

IR1IR2IR3IR4IR5IR6IR7

D0

D1D2D3D4D5D6D7

 A0

CS

SP/ENINT

INTA

121315

CAS0CAS1CAS2

 

Figura 6.4. Diagramas del Circuito Integrado 82C59A. 

El 82C59 es un IC, diseñado para manejar interrupciones, sus principales características son:

Puede manejar hasta 8 interrupciones.•

Puede asignar prioridades a cada interrupción.

Programable por software.

Permite su conexión con otros PICs (hasta 8 PICs esclavos) de modo que puede llegar a

manejar hasta 64 interrupciones.

Tiene la habilidad de aceptar señales de interrupción por flancos (edge triggered) o por nivel

(level sensitive).

Tiene la capacidad de indicar al CPU la dirección de la rutina asociada al dispositivo que

genera la interrupción.Tiene capacidad de habilitación o inhabilitación individual de cada entrada de interrupción. 

Descripción de pines:

CS’ Habilita la comunicación con la CPU.

WR’ Permite al 8259 aceptar comandos de la CPU.

RD’ Permite al 8259 dejar la información en el bus de datos.

D7…D0Bus de datos bidireccional, por el que se transmite la información de control/estado y el

número de vector de interrupción.

CAS0 ... CAS2Líneas de cascada, actúan como salida en el 8259 maestro y como entrada en los 8259

esclavos, en un sistema con varios 8259 interconectados, constituyendo un bus local.SP’/EN’

Pin de doble función: en el buffered mode del 8259 actuará como EN’, para habilitar los

 buffers del bus; en el modo normal indicará si el 8259 es maestro o esclavo (SP’).

INTConectado a la patilla INT de la CPU para producir la interrupción cuando llegue elmomento.

IR0 … IR7

Líneas asíncronas de petición de interrupción. Una petición de interrupción se ejecutamanteniendo IR en alto hasta que se recibe el reconocimiento (modo por flancos) osimplemente poniendo en alto la línea IR (modo por niveles).

INTA’

Línea de reconocimiento de interrupción, por medio de esta línea se fuerza al 8259 adepositar en el bus la información del vector de interrupción. INTA es independiente deCS’.

A0En conjunción con CS’, WR’ y RD’ es empleada para enviar las palabras de comando al

8259 y para solicitar información al mismo. Suele ir conectada a la línea A0 de la CPU.

Laboratorio de Arquitectura de Computadoras 4

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 5/28

 

5.4

5.5

Programación del PIC 8259A

La programación de PIC se lleva a cabo en dos formas: 

Comandos de inicialización (inicialization command words, ICW): Cargan a los registros de

control internos, el modo de operación del PIC, hay 4 ICW: ICW1 ... ICW4.

Comandos de operación (operational command words, OCW): Permiten efectuar algunas

variaciones a los modos de operación. Son 3 OCW: OCW1, OCW2 y OCW3.

♦ Comandos de operación: OCW1: Mascara de interrupciones (interrupt mask register,

IMR): Una lectura de este registro permite determinar el estado de cada IRQ, si b i = 1

indica que dicha IRQi  esta deshabilitada, si bi = 0 indica que IRQi  esta habilitada para

atención de interrupción. Una escritura en este registro permite habilitar/deshabilitar

selectivamente cada IRQ. Por ejemplo:

Para efectuar una lectura del IMR se efectuará:IN AL, 21H ; Lenguaje Assemblerdato = inportb(0x21); // Lenguaje C

Para realizar una escritura sobre el IMR: OUT 21h, AL ; Lenguaje Assembleroutportb(0x21, dato); // Lenguaje C

Con AL (con AL = 0FFH) deshabilitará todas las IRQ.

En una IBM-PC, estos comandos son ejecutados automáticamente cuando se enciende la PC (o se

efectúa un RESET). Aquí se especifican, entre otras cosas, si las interrupciones son por flanco o

nivel, si hay conectados PICs esclavos, etc. Para mayor información ver en “Microsystem

Componentes Handbook: Microprocessors and Peripherals, Vol I, INTEL Corporation”

Vectores de interrupción

Un vector de interrupción es un conjunto de dos valores, almacenados en 4 bytes del espacio de

memoria, que representan la dirección de memoria donde se encuentra almacenada la rutina de

servicio de interrupción asociada a una interrupción. En los primeros dos bytes de un vector, se

encuentra el desplazamiento, y en los dos bytes siguientes se encuentra el segmento de dicha

dirección.

Tabla de vectores de interrupción:

CS_255

IP_255VECTOR 255

0000 : 03FE h

0000 : 03FC h

CS_254

IP_254VECTOR 254

0000 : 03FA h

0000 : 03F8 h

CS_1

IP_1VECTOR 1

0000 : 0006 h

0000 : 0004 h

CS_0

IP_0VECTOR 0

0000 : 0002 h

0000 : 0000 h

Segmento : Offset

 

Laboratorio de Arquitectura de Computadoras 5

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 6/28

 

Después de que se genera una interrupción, el CPU debe proceder a ejecutar la rutina de servicio

que atenderá dicha interrupción, para esto se dispone de una tabla de vectores de interrupción.

Esta tabla en el caso de la PC es capaz de soportar hasta 256 interrupciones, cuando se produce

una interrupción, se necesita el segmento (CS) y el desplazamiento (IP) de la primera instrucción

de la rutina de servicio, estos datos son almacenados en la tabla de vectores de interrupción:

Al producirse la interrupción, el CPU determina el número del vector asociado a la

interrupción y salta a la dirección contenida dentro del vector, observe que cada vector utiliza 4

 bytes (ver figura 6.3).

Para leer e instalar un vector de interrupción de una manera cómoda y práctica se hace uso de

la INT 21h del DOS, tal como muestra la siguiente tabla.

25H ESTABLECER EL VECTOR

Entrada AH = 25h

AL = número del vector de interrupción.DS:DX = Dirección del nuevo procedimiento para el vector de interrupción.

 Notas Antes de cambiar el vector de interrupción, se sugiere que el vector de interrupción actualsea primero guardado utilizando la función 35H del DOS. Esto permite un vínculo para queel vector original pueda ser posteriormente restaurado.

35H LEER EL VECTOR DE INTERRUPCION

Entrada AH = 35hAL = número del vector de interrupción.

Salida ES:BX = Dirección archivada en el vector.

 Notas Esta función del DOS es usada con la función 25H para instalar/retirar los identificadores

de los interrupciones.

Ejemplo: Leer el valor almacenado en el vector 8 de la IRQ0, guardarlo e instalar la RTI UPC en

el vector.

Lenguaje Assembler Lenguaje C

; se lee el vector y se guardaMOV AH, 35HMOV AL, 08H ; num. vector 08hINT 21HMOV oldvec8_off, BX

MOV oldvec8_seg, ES; se instala la rutina de interrupción UPCMOV DX, OFFSET UPCMOV AX, SEG UPCPUSH DSMOV DS, AX

MOV AH, 25HMOV AL, 08H ; instala vectorINT 21HPOP DS

/* se lee vector y se guarda */

oldvec8 = getvect (0x08);

/* se instala la rutina de interrupción UPC */

setvect (0x08, UPC);

Laboratorio de Arquitectura de Computadoras 6

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 7/28

 

5.6 Instalación de rutinas de servicio de interrupción (RSI)

Es la rutina (o procedimiento) asociada a una interrupción, y será ejecutada en caso se encuentre

habilitada. Su estructura es similar a un procedimiento convencional, con la salvedad que la

instrucción de retorno es IRET.

Dicha rutina, al estar en memoria, tiene un offset (desplazamiento), y un segmento. Ambos

valores deberán ser almacenados en la tabla de vectores de interrupción (instalación de los

vectores de interrupción).

Máscara de interrupción (IMR):

Este registro de 8 bits, nos permite habilitar (0) /deshabilitar (1), cada una de las interrupciones

asociadas a los pines IRQ.

PIC Master (20h – 21h):

IRQ7 IRQ6 IRQ5 IRQ4 IRQ3 IRQ2 IRQ1 IRQ0

01234567

IMR (21h): 

PIC Esclavo (A0h – A1h):

IRQ15 IRQ14 IRQ13 IRQ12 IRQ11 IRQ10 IRQ9 IRQ8

01234567

IMR (A1h): 

Ejemplo: Escriba las instrucciones para habilitar la interrupción del COM1 (IRQ4).•

void main(){

unsigned char oldimr, newimr;oldimr = inportb(0x21); // Lee mascara IMR del PICnewimr = oldimr & 0xEF; // Habilita la IRQ4 (1110 1111b)outportb(0x21, newimr); // Envía al PIC la nueva IMR

}

••

Consideraciones previas: Al implementar su RSI, deberá tener en cuenta lo siguiente:

La instalación de vectores de interrupción y la habilitación de interrupciones es hecha en el

 programa principal, no en la rutina de servicio.

La rutina no deberá ser demasiado extensa. Esto implica la no-implementación de bucles en

el interior de la RTI.

Al terminar el programa, deberá enviar el EOI: outportb(0x20,0x20);Téngase en cuenta los niveles de prioridad.

Pasos a seguir para la instalación / desinstalación de la RSI: (Suponga la IRQ1 y vector 9h)

Programa principal:

Instalación:

a) Deshabilitar interrupciones.

 b) Leer y Guardar IMR.

c) Modificar el IMR para que permita las interrupciones de la línea IRQ1.

d) Leer y Guardar el vector 09H.

e) Colocar el nuevo vector 09H para que apunte a nuestra rutina de servicio.

f) Habilitar interrupciones.

g) Esperar hasta que se indique que se debe terminar la ejecución del programa (bucle infinito)

Laboratorio de Arquitectura de Computadoras 7

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 8/28

 

Desinstalación: (para salir del programa)

h) Deshabilitar interrupciones.

i) Restaurar el vector 09H.

 j) Restaurar el IMR.

k) Habilitar interrupciones.

l) Terminar el programa.

La rutina de servicio (RSI):

a) Guardar todos los registros a utilizar.

 b) Rutina de servicio (programa a realizar).

c) Restaurar todos los registros utilizados.

d) Enviar al PIC el EOI (End of interrupt), enviando un 20H a la dirección 20H del espacio de E/S.

6. Aplicaciones con interrupciones en la PC

6.1 Programa 1:

/**********************************************************************************G6_E1.CPPEste programa muestra como contar las interrupciones generadas por la IRQ0conectada al canal 0 del TIMER de la PC.

Descripción:La frecuencia de entrada al CH0 del TIMER de la PC es de 1.193.180 Hz, el cual esdividida entre 65,535 para producir 18.2 Hz (interrupciones/seg).Nuestro programa contará dichas interrupciones y las mostrará en la pantalla de laPC. Se saldrá del programa cuando se halla generado 91 interrupciones (18.2*5) odespués de 5 segundos.

Autor: Ing. Javier Barriga Hoyle*********************************************************************************/#include <conio.h>#include <stdio.h>#include <dos.h>

#ifdef __cplusplus#define __CPPARGS ...

#else#define __CPPARGS

#endif

// Prototiposvoid interrupt (*old_timer)(__CPPARGS); // Vector antiguo

void interrupt new_timer(__CPPARGS); // Nueva RSIvoid instala_imr_vector(void);void restaura_imr_vector(void);

// Declaración de variables globalesunsigned char oldimr, newimr;int num_int;

void main(void){

clrscr(); // Borra pantallainstala_imr_vector(); // Modifica IMR e instala vectornum_int = 0; // Contador de interrupciones = 0

while(num_int <= 91) // Cuenta 5 segundos (91 interrupciones){

gotoxy(25,5); // (Columna, fila)

Laboratorio de Arquitectura de Computadoras 8

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 9/28

 

printf("Interrupciones IRQ0: %d\r", num_int);}restaura_imr_vector(); // Restaura IMR y vector original

}

void interrupt new_timer(__CPPARGS)

{old_timer(); // Llama a la rutina antiguanum_int++; // Incrementa cada vez que ocurre una INTRoutportb(0x20,0x20); // Envía el EOI

}

void instala_imr_vector(void){

disable(); // Deshabilita interrupcionesoldimr = inportb(0x21); // Lee la máscara IMRnewimr = 0xFE&oldimr; // Activa IRQ0 = 1111 1110outportb(0x21,newimr);old_timer = getvect(0x08); // Lee vector originalsetvect(0x08, new_timer); // Instala nuevo vector

enable(); // Habilita interrupciones}

void restaura_imr_vector(void){

disable();setvect(0x08, old_timer); // Restaura vector originaloutportb(0x21,oldimr); // Restaura IMR originalenable();

}

6.2 Programa 2:

/**********************************************************************************G6_E2.CPPEste programa imprime en la pantalla las interrupciones generadas por la IRQ0 delcomputador a intervalos de 1 seg. hasta llegar a los 10 seg.

Descripción:a) Considerar que la IRQ0 genera 18.2 interrupciones por segundo.b) El programa cuenta cada 1 segundo hasta llegar a los 10 segundos.c) Cada 18 interrupciones aproximadamente se incrementa en 1.

Autor: Ing. Javier Barriga Hoyle**********************************************************************************/ #include <conio.h>

#include <stdio.h>#include <dos.h>

#ifdef __cplusplus#define __CPPARGS ...

#else#define __CPPARGS

#endif

// Prototiposvoid interrupt (*old_timer)(__CPPARGS); // Vector antiguovoid interrupt new_timer(__CPPARGS); // Nueva RSIvoid instala_imr_vector(void);void restaura_imr_vector(void);

// Defino variables globalesunsigned char oldimr, newimr;

Laboratorio de Arquitectura de Computadoras 9

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 10/28

 

int num_int, num_seg;void main(void){

clrscr(); // Borra pantallainstala_imr_vector(); // Modifica IMR e instala vector

for(num_seg=1; num_seg<=10; num_seg++){

while(num_int<=18); // Cada 18 interrupciones, cuenta 1 segnum_int =0 ; // Reinicia contadorprintf("transcurrio %d segundos\n", num_seg);

}restaura_imr_vector(); // Restaura IMR y vector original

}

void interrupt new_timer(__CPPARGS){

old_timer(); // Llama a la rutina antiguanum_int++; // Incrementa el contadoroutportb(0x20,0x20); // Envía el EOI

}

void instala_imr_vector(void){

disable(); // Deshabilita interrupcionesoldimr = inportb(0x21); // Lee la máscara IMRnewimr = 0xFE & oldimr; // Activa IRQ0 = 1111 1110outportb(0x21,newimr); // Envía nueva IMR al PICold_timer = getvect(0x08); // Lee vector originalsetvect(0x08, new_timer); // Instala nuevo vectorenable(); // Habilita interrupciones

}

void restaura_imr_vector(void){

disable(); // Deshabilita interrupcionessetvect(0x08, old_timer); // Restaura vector originaloutportb(0x21,oldimr); // Restaura IMR originalenable(); // Habilita interrupciones

}

 Nota: Observe el programa G6_E2A.C, es una variación al programa G6_E2.C en la rutina de

interrupción y el programa principal.

6.3 Programa 3:

/**********************************************************************************G6_E3.CPPEscriba un programa en lenguaje "C", que permita programar la interrupción deteclado (IRQ1). Su programa deberá operar como sigue:

Descripción:a) Borrar la pantalla e instalar la rutina de servicio de interrupción ISR para

la IRQ1.b) Todo lo que Ud. escriba por el teclado deberá aparecer en la pantalla en

forma normal.c) Cuando se pulse ALT_Z, aparecerá el mensaje “Hola”, luego del cual UD podrá

seguir escribiendo.d) Se sale de la interrupción al pulsar ESC.=============================================================================*/#include <stdio.h>#include <dos.h>#include <conio.h>

Laboratorio de Arquitectura de Computadoras 10

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 11/28

 

#ifdef __cplusplus#define __CPPARGS ...

#else#define __CPPARGS

#endif

// Prototiposvoid interrupt (*old_teclado)(__CPPARGS); // Vector antiguovoid interrupt new_teclado(__CPPARGS); // Nueva RSIvoid instala_imr_vector(void);void restaura_imr_vector(void);

// Declaración de variables globalesunsigned char oldimr, newimr, datolisto, car, ESC = 0x1B ;int fin = 0, wcar, ALT_Z = 0x2C00;

void main(void){

clrscr(); // Borra pantallainstala_imr_vector(); // Modifica IMR e instala vector

datolisto = 0;

// Programa que espera que se genere la interrupciónwhile(!fin){

if(datolisto == 1) // Se activo la interrupción{

datolisto = 0; // Reinicia para aceptar otra interrupcióncar = getch(); // Lee tecladoif (car == ESC) fin=1;

wcar = car;wcar = wcar<<8;

if (wcar == ALT_Z)printf ("Hola ");

else

printf ("%c",car);}

}// termina el programa y recupera la mascara y el vector original

restaura_imr_vector();}

void interrupt new_teclado(__CPPARGS){

old_teclado(); // Llama a la rutina antiguadatolisto = 1; // Activo bandera de interrupciónoutportb(0x20,0x20); // Envía EIO

}

void instala_imr_vector(void){disable(); // Deshabilita las interrupcionesoldimr = inportb(0x21); // Lee la mascara del PICnewimr = oldimr&0xFD; // Activa IRQ1 = 1111 1101outportb(0x21,newimr); // Guarda la nueva mascaraold_teclado = getvect(0x09); // Guarda el vector originalsetvect(0x09,new_teclado); // Guarda el nuevo vector de la ISRenable(); // Habilita las interrupciones

}

void restaura_imr_vector(void){

disable(); // Deshabilita las interrupcionesoutportb(0x21,oldimr); // Recupera la mascara original

setvect(0x09,old_teclado); // Restaura el vector originalenable(); // Habilita las interrupciones

}

Laboratorio de Arquitectura de Computadoras 11

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 12/28

 

7. Aplicaciones con interrupciones en la tarjeta de puerto paralelo (IRQ7)

El siguiente circuito muestra las conexiones a realizar para generar interrupciones (IRQ7) en la

PC a través de la tarjeta de interfase conectada al puerto paralelo. (NOTA: esta aplicación puede

ser ejecutada conectando directamente la salida del CI 74HC14 al pin 10 del puerto paralelo, sin

usar la tarjeta de interfase)

 ADC0804

L

P

T

D

B

2

5

DAC0830

P

P

I

8

2

C

5

5

TIMER 82C54 P

 A

P

B

P

C

G

2

G

1

C

L

K

2

C

L

K

1

O

U

T

2

O

U

T

1

G

2

G

1

C

L

K

2

C

L

K

1

V

I

+

V

I

-

V

R

E

F

 A

G

N

D

V

R

E

F

 A

G

N

D

R

F

B

O

U

T

2

O

U

T

1

IRQ7LIBRE ADC

J10

3 2 1

+

5

V

G

N

D

8 MHZ

Salida digital (8 leds)

Power E/S Timer SW Timer 

 

+5V

S1

START

+ C110uF

R210K

R1

330

PIN 1

74HC14

 Figura 6.5. Pulsador con eliminador de rebote conectado a la tarjeta LPT.

7.1 Programa 4

a) Quite el JUMPER del J10 de la tarjeta para desconectar la INTR’ del ADC (pin 3) y la IRQ7

(pin 2), con la finalidad de conectar externamente al pin 1 del J10 un pulsador sin rebotes y

generar interrupciones. b) Implemente el circuito (figura 6.5) en un protoboard y conecte la salida de la compuerta (pin 2)

del CI 74HC14 al pin 1 del J10 de la tarjeta.

c) Cargue el programa Turbo C++ 3.0, y abra el programa G6_E4.C, luego compile con ALT+F9,

y ejecute el programa con CTRL.+F9.

d) Observará que cada vez que pulsa S1 (START), generará una interrupción, incrementa el

contador y lo visualizará en la pantalla. (sugerencia: analice el programa y trate de entenderlo

 para futuras aplicaciones).

/**********************************************************************************G6_E4.CPPEste programa cuenta las interrupciones generadas externamente por la línea IRQ7del computador las imprime en pantalla y las envía a 8 leds conectados al Puerto C

del PPI de la tarjeta LPT V2.0

Descripción:

Laboratorio de Arquitectura de Computadoras 12

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 13/28

 

a) Conecte un pulsador sin rebote a la línea IRQ7 (jumper J10).b) Conecte 8 leds al Puerto A del PPI.c) Cada vez que se active el pulsador, generara una interrupción a la CPU y

nuestro programa llamara a la RTI, que se encarga de incrementar num_int y loenvía a la pantalla y a los leds.

c) El programa termina cuando se alcance 10 interrupciones.

Autor: Ing. Javier Barriga Hoyle**********************************************************************************/#include <conio.h>#include <stdio.h>#include <dos.h>#include "BymDOS.h" // Librería para la tarjeta LPT V2.0

int Base = 0x378; // Dirección base del puerto paralelo

#ifdef __cplusplus#define __CPPARGS ...

#else#define __CPPARGS

#endif

// Prototiposvoid interrupt (*old_irq7)(__CPPARGS); // Vector antiguovoid interrupt new_irq7(__CPPARGS); // Nueva RSIvoid instala_imr_vector(void);void restaura_imr_vector(void);

// Defino variables globalesunsigned char oldimr, newimr;int contador, num_int;

void main(void){

clrscr(); // Borra pantalla

inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0xout(0x7B, 0x80); // Configura PPI como PA = PB = PC = outsinstala_imr_vector(); // Modifica el IMR e instala la RTI

/* Habilita la IRQ_EN del puerto paralelo, poniendo en UNO el bit 4 del puerto0x37A (base+2) */outportb(0x37A, inportb(0x37A) | 0x10); // IRQ_EN = 1

contador = 0; // Inicializa contador

printf("\t*********************************************************\n");printf("\t* PROGRAMA QUE CUENTA LAS INTERRUPCIONES EXTERNAS *\n");printf("\t* GENERADAS EN LA LINEA IRQ7 *\n");printf("\t* *\n");

printf("\t* El numero de interrupciones generadas por el pulsador *\n");printf("\t* se imprime en pantalla y también en el PortA del PPI. *\n");printf("\t*********************************************************\n\n");

// Espera que se genere las interrupcioneswhile(contador <= 10) // Cuenta 10 interrupciones{

xout(0x78, contador); // Envía a los 8 leds del PA del PPIprintf("\t\t\tInterrupciones IRQ7: %d\r", contador);

}// Termina y recupera la mascara y el vector original

restaura_imr_vector(); // Restaura valores originales} //FIN de main 

void interrupt new_irq7(__CPPARGS) // Rutina de interrupción

{old_irq7(); // Llama al vector antiguocontador++; // Incrementa contador

Laboratorio de Arquitectura de Computadoras 13

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 14/28

 

outportb(0x20, 0x20); // Envía el EOI} //FIN de new_irq7 

void instala_imr_vector(void){

disable(); // Deshabilita interrupciones

oldimr = inportb(0x21); // Lee la mascara del PICnewimr = 0x7F&oldimr; // Activa IRQ7 = 0111 1111outportb(0x21, newimr); // Envía el PIC nueva IMRold_irq7 = getvect(0x0F); // Vector de la IRQ7 el numero 15 (0x0F)setvect(0x0F, new_irq7); // Instala la RTI new_irq7enable(); // Habilita interrupciones

} //FIN de instala_imr_vector 

void restaura_imr_vector(void){

disable(); // Deshabilita interrupcionessetvect(0x0F, old_irq7); // Recupera vector originaloutportb(0x21, oldimr); // Recupera mascara originalenable(); // Habilita interrupciones

} //FIN de restaura_imr_vector 

Ejercicio 1: Variación al programa G6_E4.CPP

a) En la tarjeta de interfase conecte al puerto B del PPI un dipswitch de 8 bits y al puerto A del

PPI 8 Leds, de tal manera que cada vez que pulsemos S1 (figura 6.6) lea el dato del dipswitch

del PB y lo envíe a los 8 Leds del PA.

0s

1s

Entrada digital (8 bits)

 ADC0804

L

P

T

D

B

2

5

DAC0830

P

P

I

8

2

C

5

5

TIMER 82C54 P

 A

P

B

P

C

G2G1

C

LK

2

C

LK

1

O

UT

2

O

UT

1

G2G1

C

LK

2

C

LK

1

V

I

+

V

I

-

V

R

EF

 A

G

ND

V

R

EF

 A

G

ND

R

F

B

O

U

T2

O

U

T1

IRQ7

LIBRE ADC

J10

3 2 1

+

5V

G

ND

8 MHZ

Salida digital (8 leds)

Power E/S Timer SW Timer 

 

+5V

S1

START

+ C110uF

R210K

R1

330

PIN 1

74HC14

 

Figura 6.6 Diagrama de conexión para el ejercicio 1.

Laboratorio de Arquitectura de Computadoras 14

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 15/28

 

 b) Escriba el programa en Lenguaje C para que cada vez que se pulse, se genere la interrupción y

se lea el dipswitch del puerto B y el valor digital leído se envíe al puerto A del PPI. Su programa

termina después de 10 interrupciones.

Solución: programa G6_EJE1.CPP (no mire la solución hasta que UD no lo haya realizado).

Ejercicio 2: Variación al programa G6_E4.CPP

a) En la tarjeta de interfase conecte al puerto A del PPI un LCD, al puerto C del PPI 8 leds y un

 pulsador sin rebotes a la IRQ7 (pin1 de J10), tal como muestra la figura 6.7.

 b) Escriba un programa en Lenguaje C, que tenga como rutina principal prender los leds desde los

extremos hacia el centro y luego apagarse desde el centro hacia los extremos. Este funcionará en

forma indefinida hasta que pulse la tecla ESC (escape).

c) Cada vez que se active el pulsador, generará una interrupción y en la RTI se incrementará el

número de interrupciones cuyo valor se enviará al LCD.

Salida digital (8 leds)

   G

   N   D

   V

   C   C

   V

   L   C

   R

  s

   R

   /   W

   E

  n

   D

   0

   D

   1

   D

   2

   D

   3

   D

   4

   D

   5

   D

   6

   D

   7

 ADC0804

L

P

T

D

B

2

5

DAC0830

P

P

I

8

2

C

5

5

TIMER 82C54 P

 A

P

B

P

C

G

2

G

1

C

LK

2

C

LK

1

O

UT

2

O

UT

1

G

2

G

1

C

LK

2

C

LK

1

V

I

+

V

I

-

V

R

E

F

 A

G

N

D

V

R

E

F

 A

G

N

D

R

F

B

O

U

T

2

O

U

T

1

IRQ7

LIBRE ADC

J10

3 2 1

+

5V

G

ND

8 MHZ

Power E/S Timer SW Timer 

INTERRUPCIONES

IRQ7 = 0

 +5V

S1

START

+ C110uF

R210K

R1

330

PIN 1

74HC14

 Figura 6.7 Diagrama de conexión para el ejercicio 2.

Solución: programa G6_EJE2.CPP (no mire la solución hasta que UD no lo haya realizado).

Laboratorio de Arquitectura de Computadoras 15

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 16/28

 

8. Descripción del ADC0804 de la Tarjeta LPT (parte 2)

Este convertidor análogo digital de 8 bits es un ADC común de bajo costo y se utiliza en

aplicaciones que no requieren un alto grado de exactitud. Por ejemplo, requiere hasta 100 µseg.

 para convertir una entrada analógica de voltaje a una salida en código digital.

El reloj se genera con un circuito RC y se conectan a las entradas CLK IN y CLKR. Para una

frecuencia de 640 KHz el tiempo de conversión es aproximadamente 100 µseg. y se calcula con

la siguiente ecuación: Fclk = 1 / (1.1 R*C).

El reloj del ADC en esta tarjeta está controlado por un potenciómetro de 10K y un

condensador de 150 pF. El valor de R debe estar cerca de los 10K para conseguir una frecuencia

entre <600-640> KHz.

CLK IN

RD

WR

 A GND

CS

DB7 (MSB)

 ADC0804

1

2

3

4

5

6

7

8

9

10 11

12

13

14

15

16

17

18

19

20

INTR

VIN (+)

VIN (-)

D GND

VREF

 /2 DB6

DB5

DB4

DB3

DB2

DB1

DB0 (LSB)

CLK R

VCC

 

Figura 6.8 Diagrama del ADC0804.

VCC

U6

 ADC0804

181716

14131211

1235

8

6

7

9

4

19

15

DB0DB1DB2

DB4DB5DB6DB7

CSRD

WRINTR

 AGND

VI+

VI-

VREF

CLK

CLKR

DB3

R210K

C810uF/25V

J5

IN_ADC

1234

C2150pF

J6

IN_ADC

1234

CS_ADC

IRQ

P1

P14

PARA ADC

 

RDWR

SD0

SD6SD5SD4

SD7

SD3SD2SD1

VI+

VI-

VREF

 AGND

VI+VI-VREF AGND

VI+VI-VREF AGND

 Figura 6.9 Esquemático del ADC0804 dentro de la Tarjeta.

Para trabajar con un convertidor analógico digital (ADC), se debe preferiblemente leer la hoja de

datos del fabricante. Pero, todos por lo general siguen estos pasos:

Laboratorio de Arquitectura de Computadoras 16

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 17/28

 

a) Para capturar el dato analógico y empezar la conversión se debe activar la señal WR. Es decir,

enviar un pulso bajo (WR = 0), por un tiempo pequeño (aprox. 300 nS). Esto se consigue

enviando cualquier valor (por ejemplo: 00h) por el puerto donde esté mapeado el ADC.

♦ En nuestro caso, para el puerto paralelo, las macros diseñadas para el uso con la tarjeta

 permiten generar las señales RD’, WR’ y operarla como si se estuviera trabajando con elBUS ISA.

Assembler:MOV AL, 00h ; Cargo cualquier dato en ALXOUT 6CH, AL ; Se envía por el puerto el dato “0” (WR = 0)

Lenguaje C:xout(0x6C, 0x00); //Se envía por el puerto el dato “0” (WR = 0)

♦ Si se está trabajando con el BUS ISA y el ADC está mapeado en el puerto de E/S 0300h,

entonces las instrucciones a usar serían:

Assembler:MOV AL, 00h ; Cargo cualquier dato en ALMOV DX, 300hOUT DX, AL ; Se envía por el puerto el dato “0” (WR = 0)

Lenguaje C:outportb(0x300,0x00); //Se envía por el puerto el dato “0” (WR = 0)

 b) El ADC toma un tiempo para realizar la conversión (aproximadamente 100 µS), luego del cual

 pone en CERO el pin INTR para avisar que el dato (digital) está listo para ser leído. Para

realizar la lectura por el puerto existen tres formas:

Técnicas para la lectura del dato digital en el ADC

Espera:

Consiste en que una vez activada la señal WR (paso (a)), generar un retardo que sea mayor que el

tiempo de conversión del ADC (Por ejemplo, 1 ms), y luego proceder a leer el dato digital. Ver

diagrama de flujo.

 Activar la señal WR

Retardo de 1 mseg

Leer dato digital del ADC 

Programa:xout(0x6C,0x00); // Empieza conversión (WR = 0)delay(1); // Espero 1 mseg para que conviertadato_adc = xin(0x6C); // Se lee el dato digital

Polling (encuesta):

Consiste en que una vez activada la señal WR (paso (a)), empezar a testear si la señal INTR del

ADC está en cero. Si es cero, leer el dato, caso contrario seguir testeando. Ver diagrama de flujo.

Laboratorio de Arquitectura de Computadoras 17

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 18/28

 

 Activar la señal WR

Leer dato digital del ADC

¿INTR = 0?

NO

SI

 

Programa:

xout(0x6C,0x00); // Inicia conversiónwhile (flag_int != 0x40) // Testea si INTR=0?{

flag_int = inportb(0x379)&0x40; // Lee para ver si INTR = 0 (bit 6)}dato_adc = xin(0x6C); // lee dato del ADC

Interrupciones

Para emplear esta técnica se tiene que hacer uso de la línea de interrupción IRQ7 y del vector 15.

En este caso el programa es más complicado y se requiere tener muy bien los conceptos de

interrupciones, vectores de interrupción y máscara de interrupción. Al final de este capítulo se

tendrá varios programas ejemplos que hacen uso de las interrupciones.

PUERTO 6Ch

IRQ7

PROGRAMA

RTI del ADC

DIR. BASE 378H

 ADC0804

CPU

 

Laboratorio de Arquitectura de Computadoras 18

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 19/28

 

APLICACIONES DEL ADC0804

Para usar este Circuito Integrado dentro de la Tarjeta se tiene que incluir en cada programa como

cabecera la librería de funciones “BymDOS.h” de la siguiente manera:

#include “BymDOS.h”

Además, dentro del programa principal se debe colocar la instrucción: inicio_tarjeta();  que se

encarga de poner todas las señales de control de los circuitos integrados en un valor que evite

conflictos, tales como RD’ = 1, WR’ =1 y los CS’ = 1.

Las señales analógicas a convertir pueden provenir de diversas fuentes tales como sensores

de temperatura, posición, velocidad, presión, flujo, etc. Los siguientes programas en Lenguaje C,

muestran como utilizar el ADC en algunas aplicaciones básicas, para ello hemos empleado un

 potenciómetro de 10K que genere voltajes entre 0 y 5 voltios. El objetivo de estos programas es

que se familiaricen con las diversas formas de trabajar con el ADC, luego del cual podrán usarlo

en cualquier aplicación real.

8.1 Programa 5: Muestrea el ADC usando la técnica de espera

Realice la siguiente conexión.

+5V

 ADC0804

L

PT

D

B

2

5

DAC0830

PP

I

8

2

C

5

5

TIMER 82C54 P A

P

B

P

C

G

2

G

1

C

L

K

2

C

L

K

1

O

U

T

2

O

U

T

1

G

2

G

1

C

L

K

2

C

L

K

1

V

I

+

V

I

-

V

R

E

F

 A

G

N

D

V

R

E

F

 A

G

N

D

R

F

B

O

U

T

2

O

U

T

1

IRQ7

LIBRE ADC

J10

3 2 1

+

5

V

G

N

D

8 MHZ

Salida digital (8 leds)

Power E/S Timer SW Timer 

Unir con el jumper el pin3 y el

pin2 de J10, para que la línea

INTR del ADC se conecte

con el pin 10 del conector 

DB25 (bit 6 del puerto 379h).

 Figura 6.10 Diagrama de conexión programa 5.

/**********************************************************************************G6_E5.CPP: (Técnica de espera)Este programa muestrea un voltaje analógico (0 V - 5 V) en un potenciómetro y loimprime en la pantalla, además lo envía al PortA (puede ser B o C) del PPI el datoen binario para ser visualizado en 8 leds. Toma 10 muestras a intervalos de 2segundos.

Descripción:a) Conecte 8 leds al PortA del PPI.

Laboratorio de Arquitectura de Computadoras 19

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 20/28

 

b) Implemente un circuito con un potenciómetro entre 0 y 5V.c) El punto central de éste conéctelo al terminal (VI+) de la bornera azul o al

molex;d) El terminal VI-, conéctelo a tierra;e) El terminal AGND conéctelo a tierra.f) El terminal VREF puede conectarse a otro potenciómetro con un voltaje de

salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en latoma de muestras.

Autor: Ing. Javier Barriga Hoyle******************************************************************************/#include <dos.h>#include <conio.h>#include <stdio.h>#include "BymWin.h" // Librería usada por la tarjeta LPT V2.0 

int Base = 0x378; // Dirección del puerto paralelo 

/* Declaración de variables globales */unsigned char dato_adc;

int i;float voltios;

/* Inicia programa principal */void main(void){

inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B, 0x80); // Configura PPI con PA=PB=PC= OUTs (modo 0)

printf("\t****************************************************\n");printf("\t* LECTURA DE UNA SENAL ANALOGICA USANDO EL ADC0804 *\n");printf("\t* (Tecnica de espera) *\n");printf("\t* *\n");printf("\t* Captura 10 muestras a intervalos de 2 segundos, *\n");

printf("\t* lo imprime en pantalla y lo muestra en 8 leds. *\n");printf("\t* Varíe el potenciómetro para muestras diferentes. *\n");printf("\t****************************************************\n\n");

/* Proceso de lectura de 10 muestras del ADC a intervalos de 2 seg. */for(i=0; i<10; i++){

xout(0x6C, 0x00); // Inicia conversiónSleep(1); // Espera 1 ms para que termine conversióndato_adc = xin(0x6C); // Lee dato del ADCxout(0x78, dato_adc); // Envía al PortA del PPIvoltios = ((float)dato_adc*5)/255; // Convierte a flotante

/* Muestra en pantalla en formato decimal y binario el dato convertido */

printf("Valor ADC (%d) = %0.4f voltios\n",i,voltios); // 4 decimales print_binario(dato_adc);Sleep(2000); // Espera 2 seg para tomar nueva muestra

}} // Fin de main

8.2 Programa 6: Utilice la conexión del programa 5 (figura 6.10). 

/******************************************************************************G6_E6.CPP: (Técnica de polling)Este programa muestrea un voltaje analógico (0 V - 5 V) en un potenciómetro y loimprime en la pantalla, además lo envía al PortA (puede ser B o C) del PPI el

dato en binario para ser visualizado en 8 leds. Toma 10 muestras a intervalos de2 segundos.

Laboratorio de Arquitectura de Computadoras 20

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 21/28

 

Descripción:a) Conecte 8 leds al PortA del PPI.b) Implemente un circuito con un potenciómetro entre 0 y 5V.c) El punto central de éste conéctelo al terminal (VI+) de la bornera azul o al

molex;d) El terminal VI-, conéctelo a tierra;

e) El terminal AGND conéctelo a tierra.f) El terminal VREF puede conectarse a otro potenciómetro con un voltaje de

salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en latoma de muestras.

Autor: Ing. Javier Barriga Hoyle******************************************************************************/ #include <dos.h>#include <conio.h>#include <stdio.h>#include "BymWin.h" // Librería usada por la tarjeta LPT V2.0 

int Base = 0x378; // Dirección del puerto paralelo 

/* Declaración de variables globales */unsigned char dato_adc;int i, flag_int;float voltios;

/* Inicio programa principal */void main(void){

inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B, 0x80); // Configura PPI con PA=PB=PC= OUTs (modo 0)

printf("\t****************************************************\n");printf("\t* LECTURA DE UNA SENAL ANALOGICA USANDO EL ADC0804 *\n");printf("\t* (Tecnica de polling) *\n");

printf("\t* *\n");printf("\t* Captura 10 muestras a intervalos de 2 segundos, *\n");printf("\t* lo imprime en pantalla y lo muestra en 8 leds. *\n");printf("\t* Varíe el potenciómetro para muestras diferentes. *\n");printf("\t****************************************************\n\n");

/* Proceso de lectura de 10 muestras del ADC a intervalos de 2 seg. */for(i=0; i<10; i++){

xout(0x6C, 0x00); // Inicia conversión

while (flag_int != 0x40) // ¿INTR = 0? o ¿terminó conversión?flag_int = _inp(Base+1)&0x40; /* Aquí no se usa xin, porque la línea

IRQ7 va directamente al puerto 379h */

dato_adc = xin(0x6C); // Terminó conversión, leo dato del ADCxout(0x78, dato_adc); // Envía al PortA del PPIvoltios = ((float)dato_adc*5)/255; // Convierte a flotante

/* Muestra en pantalla en formato decimal y binario el dato convertido */printf("Valor ADC (%d) = %0.4f voltios\n",i,voltios); // 4 decimales print_binario(dato_adc);printf("\n”); // Cambia línea Sleep(2000); // Espera 2 seg para tomar nueva muestra

}} // Fin de main

Laboratorio de Arquitectura de Computadoras 21

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 22/28

 

8.3 Programa 7: Emplea la técnica de interrupciones. Use la figura 6.10 (programa 5) 

/******************************************************************************G6_E7.CPP: (Emplea la interrupción IRQ7 para leer el ADC)Este programa muestrea a intervalos de 2 seg. un voltaje analógico (0V-5V) de un

potenciómetro y lo imprime en la pantalla, además envía el dato en binario alPortA (puede ser B o C) del PPI para que se vea en los 8 leds.El retardo de DOS segundos se genera llamando a la función delay.El programa termina cuando se pulse ESC(escape)

Descripción:a) Implemente un circuito con un potenciómetro entre 0 y 5V.b) El punto central de éste conéctelo al terminal (VI+) de la bornera azul o al

molex;c) El terminal VI-, conéctelo a tierra.d) El terminal AGND conéctelo a tierra.e) El terminal VREF puede conectarse a otro potenciómetro con un voltaje de

salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en latoma de muestras.

Autor: Ing. Javier Barriga Hoyle******************************************************************************/#include <dos.h>#include <conio.h>#include <stdio.h>#include "BymDOS.h" // Librería para la tarjeta LPT V2.0

int Base = 0x378; // Dirección base del puerto paralelo

#ifdef __cplusplus#define __CPPARGS ...

#else#define __CPPARGS

#endif

/* Prototipos */void interrupt (*old_adc)(__CPPARGS); // Vector antiguovoid interrupt new_adc(__CPPARGS); // Nueva RSIvoid instala_imr_vector(void);void restaura_imr_vector(void);

/* Declaración de variables globales */unsigned char oldimr, newimr, datolisto, car, dato_adc;int muestras, Fin;float voltios;

void main(void){

clrscr(); // Borra pantalla

inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0xout(0x7B,0x80); // Configura PPI como PA = PB = PC = outsinstala_imr_vector(); // Modifica IMR e instala vector de IRQ7

/* Habilita la IRQ_EN del puerto paralelo, poniendo en UNO el bit 4 del puerto0x37A (base+2) */outportb(0x37A, inportb(0x37A) | 0x10); // IRQ_EN = 1

printf("\n");printf("\t*********************************************************\n");printf("\t* PROGRAMA QUE CAPTURA SEÑALES ANALOGICAS PROVENIENTES *\n");printf("\t* DE UN POTENCIOMETRO, USANDO LA INTERRUPCION IRQ7 *\n");printf("\t* *\n");printf("\t* El valor obtenido se envía a la pantalla y al PortA *\n");printf("\t* del PPI. Las muestras se realizan cada 2 segundos. *\n");printf("\t* Para salir del programa, pulse ESC(escape). *\n");printf("\t*********************************************************\n\n");

Laboratorio de Arquitectura de Computadoras 22

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 23/28

 

Fin = 0;muestras = 0;while(!Fin) // El programa continua hasta que se pulse ESC{

xout(0x6C, 0x00); // Inicia conversión del ADCif(datolisto == 1) // ¿Terminó conversión INT=0?

{dato_adc = xin(0x6C); // SI, procede a leerse el datoxout(0x78, dato_adc); // Envía dato leído al PortA del PPIvoltios = (float)dato_adc * 5 / 255; // Convierte a flotantegotoxy(22,12);printf("lectura ADC(%d) = %0.4f voltios",muestras,voltios); // 4 decimalesdatolisto = 0; // Borra flag para otra interrupcióndelay(2000); // Retardo de 2 segundos

if(kbhit()) // ¿Se activó alguna tecla?{

car = getch(); // SI, entonces se lee la tecla y si es ESCif(car == 27) Fin=1; // salir del programa

}

}}restaura_imr_vector(); // Restaura IMR y vector original

}

void interrupt new_adc(__CPPARGS){

old_adc(); // Llama al vector originaldatolisto = 1; // Flag que indica que se genero interrupciónmuestras++; // Incrementa número de muestrasoutportb(0x20,0x20); // Envía el EOI

}

void instala_imr_vector(void){

disable(); // Deshabilita interrupcionesoldimr = inportb(0x21); // Lee la máscara IMRnewimr = 0x7F & oldimr; // Activa IRQ7 = 0111 1111outportb(0x21,newimr); // Envía nueva IMR al PICold_adc = getvect(0x0F); // Lee vector originalsetvect(0x0F,new_adc); // Instala nuevo vectorenable(); // Habilita interrupciones

}

void restaura_imr_vector(void){

disable(); // Deshabilita interrupcionessetvect(0x0F,old_adc); // Restaura vector originaloutportb(0x21,oldimr); // Restaura IMR original

enable(); // Habilita interrupciones}

8.4 Programa 8: Emplea 2 interrupciones IRQ0 y la IRQ7. Use la figura 6.10 (programa 6) 

/******************************************************************************G6_E8.CPP: (Emplea las interrupciones IRQ0 y IRQ7)Este programa muestrea a intervalos de 1 seg. un voltaje analógico (0V-5V) de unpotenciómetro y lo imprime en la pantalla, además envía el dato en binario alPortA (puede ser B o C) del PPI para que se vea en los 8 leds.El retardo de DOS segundos se genera programando la interrupción IRQ0.La línea INT del ADC se conecta a la interrupción IRQ7.El programa termina cuando se pulse ESC(escape).

Descripción:

Laboratorio de Arquitectura de Computadoras 23

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 24/28

 

a) Implemente un circuito con un potenciómetro entre 0 y 5V.b) El punto central de éste conéctelo al terminal (VI+) de la bornera azul o al

molex;c) El terminal VI-, conéctelo a tierra.d) El terminal AGND conéctelo a tierra.e) El terminal VREF puede conectarse a otro potenciómetro con un voltaje de

salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en latoma de muestras.

Autor: Ing. Javier Barriga Hoyle******************************************************************************/#include <dos.h>#include <conio.h>#include <stdio.h>#include "BymDOS.h" // Librería para la tarjeta LPT V2.0

int Base = 0x378; // Dirección base del puerto paralelo

#ifdef __cplusplus#define __CPPARGS ...

#else#define __CPPARGS#endif

/* Prototipos */void interrupt (*old_adc)(__CPPARGS); // Vector antiguo IRQ7void interrupt new_adc(__CPPARGS); // Nueva RSIvoid interrupt (*old_timer)(__CPPARGS); // Vector antiguo IRQ0void interrupt new_timer(__CPPARGS); // Nueva RSIvoid instala_imr_vector(void);void restaura_imr_vector(void);

/* Declaración de variables globales */unsigned char oldimr, newimr, datolisto, car, dato_adc;int Fin, num_int, muestras;

float voltios;

void main(void){

clrscr(); // Borra pantallainicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0instala_imr_vector(); // Modifica IMR e instala el vector de IRQ7xout(0x7B,0x80); // Configura PPI como PA = PB = PC = outs

/* Habilita la IRQ_EN del puerto paralelo, poniendo en UNO el bit 4 del puerto0x37A (base+2) */outportb(0x37A, inportb(0x37A) | 0x10); // IRQ_EN = 1

printf("\n");

printf("\t*********************************************************\n");printf("\t* PROGRAMA QUE CAPTURA SEÑALES ANALOGICAS PROVENIENTES *\n");printf("\t* DE UN POTENCIOMETRO, USANDO LAS INTERRUPCIONES IRQ0-7 *\n");printf("\t* *\n");printf("\t* El valor obtenido se envía a la pantalla y al PortA *\n");printf("\t* del PPI. Las muestras se realizan cada 1 segundo. *\n");printf("\t* Para salir del programa, pulse ESC(escape). *\n");printf("\t*********************************************************\n\n");

muestras = 0; // Inicia contador de muestras en ceronum_int = 0; // Inicia Contador de interrupciones a ceroFin = 0; // Flag de finxout(0x6C, 0x00); // Inicia conversión del ADC en t = 0 segwhile(!Fin) // El programa continua hasta que se pulse ESC{

if(datolisto == 1) // ¿Terminó conversión INT = 0?{

dato_adc = xin(0x6C); // SI, procede a leerse el dato

Laboratorio de Arquitectura de Computadoras 24

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 25/28

 

xout(0x78, dato_adc); // Envía dato leído al PortA del PPIvoltios = (float)dato_adc * 5 / 255; // Convierte a flotantegotoxy(22,12);printf("lectura ADC(%d) = %0.4f voltios",muestras,voltios); // 4 decimalesdatolisto = 0; // Borra flag para otra interrupción

if(kbhit()) // ¿Se activo alguna tecla?{

car = getch(); // SI, entonces se lee la teclaif(car==27) Fin=1; // Salir del programa

}}

}restaura_imr_vector(); // Restaura el IMR y vector original

}

void interrupt new_timer(__CPPARGS){

old_timer(); // Llama al vector originalnum_int++; // Incrementa número de interrupciones

if(num_int > 18) // ¿Paso 1 segundo?{num_int = 0; // Reinicia contador de interrupcionesxout(0x6C, 0x00); // Inicia conversión del ADCmuestras++; // Incrementa número de muestras

}outportb(0x20,0x20); // Envía el EOI

}

void interrupt new_adc(__CPPARGS){

old_adc(); // Llama al vector originaldatolisto = 1; // Flag que indica que termino conversiónoutportb(0x20,0x20); // Envía el EOI

}

void instala_imr_vector(void){

disable(); // Deshabilita interrupcionesoldimr = inportb(0x21); // Lee la máscara IMRnewimr = 0x7E & oldimr; // Activa IRQ7 = 0111 1110outportb(0x21,newimr); // Envía nueva IMR al PICold_timer = getvect(0x08); // Lee vector originalsetvect(0x08,new_timer); // Instala nuevo vectorold_adc = getvect(0x0F); // Lee vector originalsetvect(0x0F,new_adc); // Instala nuevo vectorenable(); // Habilita interrupciones

}

void restaura_imr_vector(void){disable(); // Deshabilita interrupcionessetvect(0x08,old_timer); // Restaura vector originalsetvect(0x0F,old_adc); // Restaura vector originaloutportb(0x21,oldimr); // Restaura IMR originalenable(); // Habilita interrupciones

}

Laboratorio de Arquitectura de Computadoras 25

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 26/28

 

8.5 Programa 9: Emplea 2 interrupciones IRQ0 y la IRQ7. Use la figura 6.9 (programa 6), pero

ahora los datos se guardaran en un archivo para luego graficarlos. 

/******************************************************************************G6_E9.CPP: (Emplea las interrupciones IRQ0 y IRQ7)

Este programa muestrea a intervalos de 1/2 seg. un voltaje analógico (0V-5V) deun potenciómetro y lo imprime en la pantalla, además envía el dato en binario alPORT A (puede ser B o C) del PPI para que se vea en los 8 leds.El retardo de 1/2 segundo se genera programando la interrupción IRQ0.La línea INT del ADC se conecta a la interrupción IRQ7.El programa termina cuando se alcance las 200 muestras. Los datos se almacenanen un archivo.

Descripción:a) Implemente un circuito con un potenciómetro entre 0 y 5V.b) El punto central de éste conéctelo al terminal (VI+) de la bornera azul o al

molex;c) El terminal VI-, conéctelo a tierra.d) El terminal AGND conéctelo a tierra.e) El terminal VREF puede conectarse a otro potenciómetro con un voltaje de

salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en latoma de muestras.

Autor: Ing. Javier Barriga Hoyle******************************************************************************/ #include <dos.h>#include <conio.h>#include <stdio.h>#include "BymDOS.h" // Librería para la tarjeta LPT V2.0

int Base = 0x378; // Dirección base del puerto paralelo

#ifdef __cplusplus#define __CPPARGS ...

#else#define __CPPARGS#endif

/* Prototipos */void interrupt (*old_adc)(__CPPARGS); // Vector antiguo IRQ7void interrupt new_adc(__CPPARGS); // Nueva RSIvoid interrupt (*old_timer)(__CPPARGS); // Vector antiguo IRQ0void interrupt new_timer(__CPPARGS); // Nueva RSIvoid instala_imr_vector(void);void restaura_imr_vector(void);

/* Declaración de variables globales */unsigned char oldimr, newimr, datolisto, car, dato_adc;int Fin, num_int, muestras;

float voltios;

void main(void){

FILE *archivo;clrscr(); // Borra pantallainicio_tarjeta(); // Inicializa tarjeta LPT V2.0instala_imr_vector(); // Modifica IMR e instala el vector de IRQ7xout(0x7B,0x80); // Configura PPI como PA = PB = PC = outs

/* Habilita la IRQ_EN del puerto paralelo, poniendo en UNO el bit 4 del puerto0x37A (base+2) */outportb(0x37A, inportb(0x37A) | 0x10); // IRQ_EN = 1

printf("\n");printf("\t*********************************************************\n");printf("\t* PROGRAMA QUE CAPTURA SEÑALES ANALOGICAS PROVENIENTES *\n");

Laboratorio de Arquitectura de Computadoras 26

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 27/28

 

printf("\t* DE UN POTENCIOMETRO, USANDO LAS INTERRUPCIONES IRQ0-7 *\n");printf("\t* *\n");printf("\t* El valor obtenido se envía a la pantalla y al PortA *\n");printf("\t* del PPI. Ademas, cada muestra se guarda en un archivo *\n”);printf(“\t* Las muestras se realizan cada 1/2 segundo. *\n");printf("\t* Para salir del programa, pulse ESC(escape). *\n");

printf("\t*********************************************************\n\n");

muestras = 0; // Inicia contador de muestras en ceronum_int = 0; // Inicia Contador de interrupciones a ceroFin = 0; // Flag de fin

archivo = fopen("d:\\prog_cpp\\muestreo.txt","w+"); // Crea archivo

xout(0x6C, 0x00); // Inicia conversión del ADC en t = 0while(muestras <= 200) // El programa continúa hasta que se pulse ESC{

if(datolisto == 1) // ¿Terminó conversión INT = 0?{

dato_adc = xin(0x6C); // SI, procede a leerse el dato

xout(0x78, dato_adc); // Envía dato leído al PortA del PPIvoltios = (float)dato_adc * 5 / 255; // Convierte a flotantefprintf(archivo,"%f\n",voltios); // Almacena dato en el archivogotoxy(22,12);printf("lectura ADC(%d) = %0.4f voltios",muestras,voltios); // 4 decimalesdatolisto = 0; // Borra flag para otra interrupción

}}fclose(archivo); // Cierra archivorestaura_imr_vector(); // Restaura IMR y vector original

}

void interrupt new_timer(__CPPARGS){

old_timer(); // Llama al vector original

num_int++; // Incrementa número de interrupcionesif(num_int > 9) // ¿Paso 1/2 segundo?{

num_int = 0; // SI, reinicio contador de interrupcionesxout(0x6C, 0x00); // Inicia conversión del ADCmuestras++; // Incrementa número de muestras

}outportb(0x20,0x20); // Envía el EOI

}

void interrupt new_adc(__CPPARGS){

old_adc(); // Llama al vector originaldatolisto = 1; // Flag que indica que termino conversión

outportb(0x20,0x20); // Envía el EOI}

void instala_imr_vector(void){

disable(); // Deshabilita interrupcionesoldimr = inportb(0x21); // Lee la máscara IMRnewimr = 0x7E & oldimr; // Activa IRQ7 = 0111 1110outportb(0x21,newimr); // Envía nueva IMR al PICold_timer = getvect(0x08); // Lee vector originalsetvect(0x08,new_timer); // Instala nuevo vectorold_adc = getvect(0x0F); // Lee vector originalsetvect(0x0F,new_adc); // Instala nuevo vectorenable(); // Habilita interrupciones

}

void restaura_imr_vector(void){

Laboratorio de Arquitectura de Computadoras 27

7/17/2019 G6 PICddd

http://slidepdf.com/reader/full/g6-picddd 28/28

 

disable(); // Deshabilita interrupcionessetvect(0x08,old_timer); // Restaura vector originalsetvect(0x0F,old_adc); // Restaura vector originaloutportb(0x21,oldimr); // Restaura IMR originalenable(); // Habilita interrupciones

}

8.6

Programa 10: Ejecute el programa gráfica.cpp y se mostrará en pantalla la forma de la señal

obtenida. 

9. Bibliografía 

BREY, Barry

2001 Los Microprocesadores Intel: 8086/8088, 80186, 80286, 80386 y 80486.

Arquitectura, programación e interfaces. 5ta Edición. Ed. Prentice may

(621.3981 BREY)

Revisar:

Capítulo 11, sección 11: Conversores AD y DA

Capítulo 12, todas las secciones: Interrupciones