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
Top Related