Está en la página 1de 111

TARJETA DE DESARROLLO PARA PUERTO PARALELO

LPT BYM V2.0










Manual de referencia












Ing. Javier Barriga Hoyle i
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
INDICE: N Pagina

1. Introduccin. 6
2. Listado de componentes de la tarjeta LPT- BYM. 7
3. Equipo de Experimentos DISEN-EXP. 8
4. Puertos de E/S de la Tarjeta LPT- BYM. 9
5. Descripcin del PPI 82C55 de la Tarjeta LPT- BYM. 10
5.1 Modos de Operacin del PPI. 11
5.2 Programacin del PPI. 11
6. Descripcin del TIMER 82C54 de la Tarjeta LPT- BYM 13
6.1 Modos de Operacin del TIMER 14
6.2 Programacin del TIMER 15
7. Descripcin del Conversor Anlogo Digital ADC0804 de la Tarjeta LPT- BYM 19
8. Descripcin del Conversor Digital Anlogo DAC0830 de la Tarjeta LPT- BYM 22
8.1 Estructura interna del ADC030 22
9. Sistema Operativo y uso de la Tarjeta LPT ByM 24
9.1 Uso del UserPort (Win2000 o WinXP) 24
9.2 Estructura de un programa en Lenguaje C 25
10. Aplicaciones del PPI 82C55 26
10.1 LEDS y DIPSWITCH 26
Programa 10.1: Lectura del dato de un dipswitch de 8 bits conectado al PORTB y lo
enva por el PORTA para ser visualizado en 8 leds. 26
Programa 10.2: Prende y apaga (intermitencia) 8 leds conectados al PORTA. 27
Programa 10.3: Produce prendido secuencial a la izquierda y se apaga secuencialmente
a la derecha. 27
Programa 10.4: Prende secuencialmente los leds desde los extremos hacia el centro y
luego se apaga hacia los extremos. 28
10.2 DISPLAY DE CRISTAL LQUIDO (LCD) 29
Programa 10.5: Programa que enva 2 mensajes al LCD (manejo bsico). 29
10.3 TECLADO HEXADECIMAL 4x4 33
Programa 10.6: Lectura del teclado hexadecimal conectado al PORTC del PPI mediante
exploracin de teclas. El valor ledo lo enva al PORTA. 34
Programa 10.7: Manejo del Teclado hexadecimal conectado al PORTC del PPI usando
el decodificador 74C922. El valor ledo lo enva al PORTA. 37
10.4 DISPLAY 7 SEGMENTOS 38
Programa 10.8: Manejo de 4 displays multiplexados en el tiempo, conectados al PPI. 39
Programa 10.9: Manejo de 8 displays multiplexados en el tiempo, conectados al PPI. 40
10.5 MOTOR DE PASO A PASO 42
Programa 10.10: Control de un motor de paso en modo paso completo. 42
Programa 10.11: Control de un motor de paso en modo medio paso. 44
Programa 10.12: Control de un motor de paso en modo una sola bobina. 45
Programa 10.13: (PPI_13.CPP) Control de la velocidad de un motor de paso (paso completo). 46




Ing. Javier Barriga Hoyle ii
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
11. Aplicaciones del TIMER 82C54 48
11.1 GENERACION DE SEALES A DIFERENTES FRECUENCIAS (MODO 2 y 3) 48
Programa 11.1: (TIMER_1.CPP) Uso del TIMER en modo 2 y 3. 48
Programa 11.2: (TIMER_2.CPP) Uso del TIMER en modo 3, cascada. 49
Programa 11.3: (TIMER_3.CPP) Uso del comando de enclavamiento. 50
Programa 11.4: (TIMER_4.CPP) Uso del comando Read-Back. 52
11.2 PROGRAMAS QUE GENERA SONIDO y PWM 53
Programa 11.5: (TIMER_5.CPP) Genera sonido en el parlante de la PC: Usar Turbo C++ 3.0. 53
Programa 11.6: (TIMER_6.CPP) Genera sonido en el parlante conectado al TIMER de la
tarjeta LPT. 54
Programa 11.7: (TIMER_7.CPP) Control de la velocidad de un motor DC usando PWM a
travs del teclado de la computadora. 56
Programa 11.8: (TIMER_8.CPP) Control de la velocidad de un motor DC usando PWM a
travs de un teclado 4x4 hexadecimal. 59
12. Aplicaciones del ADC 0804 (Sin interrupciones) 63
Programa 12.1: (ADC_1.CPP) Leer el voltaje de un potencimetro (Tcnica de espera). 63
Programa 12.2: (ADC_2.CPP) Leer el voltaje de un potencimetro (Tcnica de polling). 65
Programa 12.3: (ADC_3.CPP) Leer el voltaje de un potencimetro y mostrarlo en un LCD
(Tcnica de polling). 66
Programa 12.4: (ADC_4.CPP) Control de la velocidad de un motor DC usando PWM y un
potencimetro conectado al ADC. 70
13. Aplicaciones con interrupciones: Pulsadores, ADC0804, TIMER, etc. 73
13.1 Aplicaciones con interrupciones: Sistema Operativo Win2000 o WinXP. 73
Programa 13.1: (IRQ0_1.CPP) Cuenta las interrupciones producidas por la IRQ0. 73
Programa 13.2: (IRQ0_2.CPP) Utiliza las interrupciones generadas por la IRQ0 para producir
retardos. 74
Programa 13.3: (IRQ0_3.CPP) Utiliza las interrupciones generadas por la IRQ0 para producir
retardos en el desplazamiento de bits y tambin capturar datos analgicos. 76
13.2 Aplicaciones con interrupciones: Sistema Operativo Win98. 79
Programa 13.4: (IRQ7_1.CPP) Cuenta las interrupciones producidas por un pulsador sin
rebotes conectado a la lnea IRQ7. 79
Programa 13.5: (IRQ7_2.CPP) Utiliza la IRQ7 para leer el dato del dipswitch conectado al
PortB del PPI y lo muestra en PortA del PPI. 81
Programa 13.6: (IRQ7_3.CPP) Muestra en el LCD el nmero de interrupciones generadas
por la IRQ7, mientras la CPU desplaza bits por los LEDS del PortC. 83
Programa 13.7: (IRQ7_4.CPP) Usa la tcnica de interrupciones para leer el voltaje analgico
del ADC (la lnea IRQ7 se conecta al pin INTR del ADC). 88
Programa 13.8: (IRQ7_5.CPP) Uso de las interrupciones IRQ7 (ADC) e IRQ0 (TIMER de la
PC) para muestrear datos analgicos. Muestra en pantalla los datos ledos. 91
Programa 13.9: (IRQ7_6.CPP) Uso de las interrupciones IRQ7 (ADC) e IRQ0 (TIMER de la
PC) para muestrear datos analgicos. Almacena en un archivo de texto los datos ledos. 93
14. Aplicaciones del DAC 0830 96
Programa 14.1: (DAC_1.CPP) Programa de prueba del DAC. 96
Programa 14.2: (DAC_2.CPP) Programa que lee un voltaje del ADC0804, lo convierte a
digital y luego lo enva al DAC0830 para que lo muestre el voltaje en un multmetro. 97

Apendices:
A. Driver L293D. 99
B. Temporizador 8253 de la PC. 100
C. Modulacin por Ancho de Pulsos (PWM). 101
C.1 Generacin de PWM con TIMER 101
C.2 Driver L293D 103



Ing. Javier Barriga Hoyle iii
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
D. Interrupciones. 104
D.1 Conceptos. 104
D.2 Interrupciones en la PC 104
D.3 Controlador de interrupciones programable PIC 8259 106
D.4 Vectores de interrupcin 107
D.5 Instalacin de vectores de interrupcin 107
D.6 Mscara de interrupcin (IMR): 108
D.7 Instalacin de rutinas de servicio de interrupcin (RSI) 109
E. Esquematicos de algunos circuitos 110
E.1 Salida de datos por LEDS 110
E.2 Entrada de datos de 8 bits usando un dipswitch 110
E.3 Displays (cuatro) multiplexados en BCD 110
E.4 Displays (cuatro) multiplexados en HEXADECIMAL 111
E.5 Displays (ocho) multiplexados en salida binaria codificada en software 111
E.6 Control de un motor de pasos con el PORTA del PPI 111
E.7 Control de un motor DC usando el TIMER (PWM) y el PPI 112

Bibliografa 112





Ing. Javier Barriga Hoyle 1
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
1. Introduccion
Tarjeta de desarrollo para puerto paralelo LPT- BYM V2.0
Se trata de una tarjeta de circuito impreso metalizado de dimensiones 110x120 mm, provista de un
conector DB25H para comunicarse con el puerto paralelo de la computadora. Contiene los
siguientes Circuitos Integrados: (1) Interfase de puertos programables PPI 82C55, (1)
Temporizador Programable TIMER 82C54, (1) Convertidor Anlogo/Digital ADC0804 de 8 bits
de resolucin, (1) Convertidor Digital/Anlogo de 8 bits de resolucin, (1) Lnea de conexin para
generar interrupciones a travs de la IRQ7 del computador.
Todos los Circuitos Integrados que contiene la tarjeta sirven de soporte al microprocesador y
microcontrolador, por lo tanto su estudio y el manejo prctico de estos, servirn para una buena
formacin del profesional, permitindole afrontar con xito en el futuro cualquier diseo basado en
microprocesadores o microcontroladores.
La tarjeta se puede programar en Lenguaje Ensamblador o Lenguaje C (DOS o Windows), para
ello se ha diseado unas libreras de Macros y Funciones para cada uno de los lenguajes
mencionados que permitirn manejar la tarjeta y cualquier aplicacin que se desee realizar.
La siguiente fotografa muestra la tarjeta LPT-BYM V2.0. El manual contiene el manejo y algunas
aplicaciones que se le puede dar, as como la descripcin de sus chips.



Fotografa 1. Tarjeta LPT-BYM V2.0

OBS: La tarjeta est diseada para que pueda ser utilizada con el mdulo de experimentos DISEN-
EXP (fotografa 2), o desarrollar sus propias aplicaciones.



Ing. Javier Barriga Hoyle 2
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
2. Lista de componentes de la tarjeta LPT- BYM V2.0
Circuitos Integrados: Se emplea Chips con tecnologa CMOS.
(U1) 74HC245
(U2) 74HC373
(U3) 74LS257
(U4) Interfase Perifrica Programable PPI 82C55
(U5) Temporizador / Contador Programable TIMER 82C54
(U6) Convertidor Anlogo Digital de 8 bits ADC0804
(U7) Convertidor de Digital a Analgico de 8 bits DAC0830

Componentes discretos.
(OSC1) Oscilador de 8 MHz.
(D1) Diodo 1N4007
(R2) Potencimetro de 10 K.
(R1,R3,R4) Resistencias de 10 K / de Vatio
(C1) Condensador electroltico de 10 F / 25V
(C2) Condensador cermico monoltico de 150 pF / 50V (*)
(C3,C4,C5,C6,C7) Condensadores cermicos monolticos de 1 nF / 25V (*)
(C8) Condensador de Tantalum de 10 F / 25V (*)
(C9,C10,C11) Condensadores electrolticos de 100 F / 25V

Conectores.
(1) Conector DB 25 pines hembra / 90 (PUERTO PARALELO)
(3) Molex de 10 pines. (PORT_A, PORT_B, PORT_C))
(1) Molex de 4 pines. (IN_ADC)
(1) Dipswitch de 4 bits. (SW TIMER)
(1) Bornera de dos pines. (POWER)
(1) Bornera de 4 pines. (IN_ADC)
(1) Bornera de 5 pines. (DAC_OUT)
(1) Bornera de 6 pines. (TIMER)


(*) Estos condensadores pueden ser tambin de otra calidad.






















Ing. Javier Barriga Hoyle 3
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
3. Equipo de Experimentos DISEN-EXP
Permite la experimentacin prctica con elementos reales de carcter analgico o digital. El equipo
se describe completamente en el captulo 10 del manual Aplicaciones prcticas con el C 8051. Va
montado en una caja de plstico de dimensiones: 260x185x75 mm, vase fotografa nmero 2. La
caja incluye la fuente de alimentacin. Los mdulos de prcticas que incorpora son:

Puerto de salida digital con 8 indicadores LED.
Puerto de entrada digital con 8 interruptores con supresor de rebotes.
Cuatro pulsadores (dos con rebotes y dos sin rebotes).
Cuatro rels de doble contacto conmutado.
Dos potencimetros lineales (Valor analgico entre 0 y 5 V)
Indicador analgico (vmetro) con 10 diodos LED.
Teclado matricial de 12 teclas.
Display de cuatro dgitos de 7 segmentos.
Display de cristal lquido (LCD) de 2 lneas de 16 caracteres.
Generador de onda cuadrada con ajuste de los tiempos Ton y Toff.
Emisor y Receptor de infrarrojos.
Amplificador de audio y altavoz.
Control de temperatura de un conjunto calefactor-termistor.
Conjunto Motor DC, excitador para motor, y encoder ptico incremental.
Regulacin de luminosidad de una lmpara de 12 V por control de fase mediante triac.




Fotografa 2. Equipo de experimentos DISEN - EXP.


Nota: Mdulo desarrollado por el Ing. Javier Martnez Prez, autor del libro Prcticas con
Microcontroladores de 8 bits: Aplicaciones industriales


Ing. Javier Barriga Hoyle 4
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
4. Puertos de E/S de la Tarjeta LPT- BYM V2.0
La tarjeta ha sido diseada de tal manera que todos los circuitos integrados principales operen
como si estuvieran trabajando con el puerto ISA. Es decir, todos tienen una direccin de acceso
independiente del puerto paralelo, que tiene su direccin base 378h. El siguiente cuadro muestra los
puertos de E/S del PPI, TIMER, ADC y DAC.

Circuitos Integrados Direcciones
DAC 0830
ADC 0804
Puerto nico = 5C h
Puerto nico = 6C h
PPI 82C55
Puerto A (PA) = 78 h
Puerto B (PB) = 79 h
Puerto C (PC) = 7A h
Registro de Control (RC) = 7B h
TIMER 82C54
Canal 0 (CH0) = 74 h
Canal 1 (CH1) = 75 h
Canal 2 (CH2) = 76 h
Registro de Control (RC) = 77 h


Cuadro 1. Mapeo de los Circuitos Integrados dentro del puerto paralelo.

Las instrucciones diseadas para el manejo de los puertos de E/S de la tarjeta son las siguientes:

Lenguaje Ensamblador
Para salida de datos por el puerto:

XOUT PUERTO, AL

Para entrada de datos por el puerto:

XIN AL, PUERTO

Donde:
PUERTO: Es la direccin de E/S de cada circuito integrado (ver cuadro 1).
AL: Es el registro que el Microprocesador emplea para enviar datos al exterior o para
almacenar el dato ledo desde el exterior.

Lenguaje C
Para salida de datos por el puerto:

xout (puerto, dato);

Para entrada de datos por el puerto:

y = xin (puerto);

Donde:
puerto: Es la direccin de E/S de cada circuito integrado (ver cuadro 1).
dato: Es el valor (constante tipo unsigned char) que el Microprocesador enviar hacia el
exterior.
y: Es una variable declarada como unsigned char, almacenar dato ledo del puerto.


Ing. Javier Barriga Hoyle 5
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
5. Descripcin del PPI 82C55 de la Tarjeta LPT- BYM V2.0
El Interfaz Perifrico Programable PPI 82C55, es un dispositivo de E/S general, programable,
capaz de controlar 3 puertos de 8 bits cada uno (24 lneas en total) con diferentes configuraciones
de entrada/salida y en hasta 3 modos de operacin.






















Figura 5.1. Diagramas del PPI 82C55 y funcin de los pines de control.

VCC
VCC
VCC VCC
RD
WR
SD1
SD2
SD0
SD3
SD4
SD5
SD7
SD6
J2
PORT_A
1
2
3
4
5
6
7
8
9
10
J3
PORT_B
1
2
3
4
5
6
7
8
9
10
J4
PORT_C
1
2
3
4
5
6
7
8
9
10
R1
10k
C1
10uF
U4
82C55
34
33
32
31
30
29
28
27
5
36
9
8
35
6
4
3
2
1
40
39
38
37
18
19
20
21
22
23
24
25
14
15
16
17
13
12
11
10
D0
D1
D2
D3
D4
D5
D6
D7
RD
WR
A0
A1
RESET
CS
PA0
PA1
PA2
PA3
PA4
PA5
PA6
PA7
PB0
PB1
PB2
PB3
PB4
PB5
PB6
PB7
PC0
PC1
PC2
PC3
PC4
PC5
PC6
PC7
CS_PPI
A1
A0
P1
P14

Figura 5.2. Esquemtico del PPI 82C55 dentro de la Tarjeta.

PA
PB
PC
Bus de
datos
Puerto A
Puerto B
Puerto C
D7-D0
RD
A1
A0
CS
WR
82C55

Funcin de los pines A1 y A0

A1 A0 FUNCION
0 0
0 1
1 0
1 1
Puerto A
Puerto B
Puerto C
Registro de control
1
82C55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
40
39
38
37
36
35
34
33
32
31
30
29
28
27
26
25
24
23
22
21
PA3
PA2
PA1
PA0
RD
CS
GND
A1
A0
PC7
PC5
PC4
PC3
PC0
PC1
PC2
PC3
PB0
PB1
PB2
PA4
PA5
PA6
PA7
WR
RESET
D0
D1
D2
D3
D4
D5
D6
D7
VCC
PB7
PB6
PB5
PB4
PB3



Ing. Javier Barriga Hoyle 6
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Los puertos del PPI se llaman normalmente: Puerto A (PA), Puerto B (PB), Puerto C (PC) y Puerto
de configuracin interno (RC).

5.1 Modos de Operacin del PPI
El PPI presenta tres modos de operacin: Modo 0, Modo 1 y Modo 2.
Modo 0: (Entrada/Salida bsica) En este modo, los puertos A, B y C pueden ser
individualmente programados como puertos de entrada o salida. El puerto C es dividido en dos
grupos de 4 bits, direccionables cada uno en forma independiente.
Modo 1: (Comunicacin paralela unidireccional) En este modo el puerto A o el B funcionan
como registros de entrada. Esto permite que los datos externos enviados se almacenen en el
puerto hasta que el Procesador est listo para leerlos. En cambio el puerto C se utiliza para
gestionar las seales de reconocimiento o control que hacen funcionar al puerto A o al puerto
B como puertos de entrada mediante una seal de habilitacin estroboscpica.
Modo 2: (Comunicacin paralela bidireccional) Este modo slo es vlido para el grupo A,
donde el puerto A se vuelve bidireccional permitiendo transmitir y recibir datos en los 8 bits
del bus.
Los bits PC
3
, PC
4
, PC
5
, PC
6
y PC
7
son usadas como lneas de control en el protocolo de
comunicacin.
Las 3 lneas restantes del puerto C, pueden estar como E/S convencionales.
El puerto B, puede hacerlo en modo 0 o modo 1 simultneamente al puerto A.
En este manual slo vamos a utilizar el Modo 0, por ser el ms empleado. Sin embargo, puede
tambin usarse en los otros modos, para lo cual recomiendo leer bien la hoja de datos del
fabricante.

5.2 Programacin del PPI
Para utilizar el PPI en cualquier aplicacin, lo primero que se tiene que hacer es configurarlo. Es
decir, enviarle al puerto de configuracin un valor (constante) obtenido de la figura 5.3a, donde se
le indica la forma como va a operar cada puerto.
Para programarlo slo se emplea dos comandos bsicos. Donde el bit 7 del registro de control
selecciona los comandos A o B.
Si el bit 7 = 1, el comando A es seleccionado, y sirve para programar la funcin del grupo A y
B en modo 0, 1 o 2.














Figura 5.3a. Byte de comando A.
Puerto C (PC3 a PC0)
1 = entrada
0 = salida
Puerto B
1 = entrada
0 = salida
Modo
00 = modo 0
01 = modo 1
Grupo B
Puerto C (PC7 - PC4)
1 = entrada
0 = salida
Puerto A
1 = entrada
0 = salida
Modo
00 = modo 0
01 = modo 1
1X = modo 2
Grupo A
1
7 6 5 4 3 2 1 0


Ing. Javier Barriga Hoyle 7
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Si el bit 7 = 0, el comando B es seleccionado, y permite que cualquier bit del PC se active (1) o
se desactive (0) si el 8255 se programa en el modo 1 o 2.










Figura 5.3b. Byte de comando B.

a) CONFIGURACIN.- Para configurar el PPI se emplear la figura 3a.
La instruccin a emplear sera:
xout (0x7B, constante);

Donde:
constante; es el obtenido de la palabra de control.
0x7B; es la direccin del puerto de configuracin.

Ejemplo 5.1: Configurar el PPI como: PA = entrada, PB = salida, y PC = entrada; MODO 0
Palabra de control: 1 0 0 1 1 0 0 1 = 99h
La instruccin sera: xout (0x7B, 0x99);

Ejemplo 5.2: Configurar el PPI como: PA = salida, PB = entrada; MODO 1 (PC es no importa)
Palabra de control: 1 0 1 0 X 1 1 X = A6h
La instruccin sera: xout (0x7B, 0xA6);

Ejemplo 5.3: Configurar el PPI como: PA = salida; MODO 2 (PC es no importa)
Palabra de control: 1 1 0 0 X 0 0 X = C0h
La instruccin sera: xout (0x7B, 0xC0);
b) ESCRITURA: Para enviar cualquier dato de 8 bits en sus puertos, se puede hacer de 2 formas;
(1) a travs de una variable tipo char, y (2) enviar directamente el valor.
Escribir en el PA: xout (0x78, var); o xout (0x78, 0x00);
Escribir en el PB: xout (0x79, var); o xout (0x79, 57);
Escribir en el PC: xout (0x7A, var); o xout (0x7A, 0xFF);
c) LECTURA.- Para leer cualquier dato de 8 bits colocados en sus puertos es necesario designar
una variable tipo unsigned char para almacenar el dato ledo.
Leer del PA: y = xin (0x78); // y, almacena dato ledo del puerto.
Leer del PB: z = xin (0x79); // z, almacena dato ledo del puerto.
Leer del PC: p = xin (0x7A); // p, almacena dato ledo del puerto.


0
7 6 5 4 3 2 1 0
X X X
Activar y desactivar bit
1 = activar
0 = desactivar
Selecciona un bit


Ing. Javier Barriga Hoyle 8
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
6. Descripcin del TIMER 82C54 de la Tarjeta LPT- BYM V2.0
El Temporizador Programable TIMER 82C54, es un dispositivo de E/S que contiene tres
contadores (temporizadores) de 16 bits independientes. Cada contador es capaz de contar en binario
o decimal codificado en binario (BCD). La frecuencia mxima de entrada permitida para cualquier
contador es de 10 MHz. Este dispositivo es til siempre que el microprocesador deba controlar
eventos en tiempo real. Tambin se lo emplea para el control de velocidad y direccin de un motor
de corriente continua (pwm).
El TIMER puede programarse para trabajar con los tres contadores simultneamente y bajo 6
modos de operacin cualesquiera cada uno. Por ejemplo, se puede tener el contador 0 (CH0)
operando a la frecuencia de 1 MHz - Modo 2, al contador 1 (CH1) operando a la frecuencia de 5
KHz Modo 3 y al contador 2 (CH2) operando a la frecuencia de 200 Hz Modo 4.

1
82C54
2
3
4
5
6
7
8
9
10
11
12
24
23
22
21
20
19
18
17
16
15
14
13
D7
D6
D5
D4
D3
D2
D1
D0
CLK0
OUT0
GATE0
GND
VCC
A1
A0
CLK2
OUT2
GATE2
CLK1
GATE1
OUT1
WR
RD
CS
CLK Bus de
datos
Canal 0
Canal 1
Canal 2
D7-D0
RD
A1
A0
CS
WR
82C54
GATE
OUT
CLK
GATE
OUT
CLK
GATE
OUT


Figura 6.1. Diagramas del TIMER 82C54.


VCC
VCC
WR
SD2
SD0
SD1
SD4
SD6
SD7
SD3
SD5
RD
8 MHz
GATES
8 MHz
CLK1
G1
OUT1
CLK2
G2
OUT2
G1
G2
CLK1
CLK2
CLK1
CLK2
G1
G2
OUT1
OUT2
U5
82C54
8
7
6
5
4
3
2
1
22
23
19
20
21
9
11
10
15
14
13
18
16
17
D0
D1
D2
D3
D4
D5
D6
D7
RD
WR
A0
A1
CS
CLK0
G0
OUT0
CLK1
G1
OUT1
CLK2
G2
OUT2
J9
TIMER
1
2
3
4
5
6
S1
SW TIMER
1
2
3
4
8
7
6
5
OSC1
8MHz
1
7 8
14
N/C
GND OUTPUT
+5 VDC
R3
10K
CS_TIMER
A1
A0
P1
P14
D
A
T
O
S


Figura 6.2. Esquemtico del TIMER 82C54 dentro de la Tarjeta.


El 82C54 se selecciona con su terminal CS para programarla (leer o escribir) en cada contador. La
seleccin de sus contadores se logra mediante los terminales A1 y A0.



Ing. Javier Barriga Hoyle 9
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
A1 A0 FUNCION
0 0
0 1
1 0
1 1
Canal 0 (CH0)
Canal 1 (CH1)
Canal 2 (CH2)
Registro de control

El TIMER de la tarjeta de interfase, tiene tres canales o contadores independientes CANAL 0
(CH0), CANAL 1 (CH1) y CANAL 2 (CH2). De los cuales:

CANAL 0: Opera con una frecuencia de entrada de 8 MHz (fija) proporcionada por un
oscilador y es usado para generar retardos de precisin, por lo que su salida OUT 0, no est
disponible para el usuario.

CANAL 1: Est disponible y puede operar a la frecuencia de 8 MHz colocando G1 (Gate) y
CLK1 en el SW TIMER en ON. Pero, si desea usar distintas frecuencias de entrada, se tiene
que colocar CLK1 en OFF, para impedir que ingrese los 8 MHz.

CANAL 2: Opera similar al canal 1, slo que se controla con G2 y CLK2.

6.1 Modos de Operacin del TIMER
El TIMER presenta seis modos de operacin para cada uno de los contadores: Modo 0 a Modo 5.
Modo 0: Permite usarlo como un contador de eventos. Por ejemplo, si es programada una
cuenta de 7, la salida toma el valor 0 lgico por 7 cuentas iniciando en N.

OUT
CLK
N 1 2 3 4 5 6 7
Cuenta de 7 cargada

Modo 1: Funciona como un multivibrador monoestable redisparable. Por ejemplo, si la cuenta
es 5, la salida toma el valor 0 lgico durante 5 periodos de reloj.

OUT
CLK
1 2 3 4 5
Disparo con cuenta de 5
G

Modo 2: Permite que el contador genere una serie continua de pulsos (duty cycle aproximado
de 90%). Se utiliza bastante para generar interrupciones. Por ejemplo, para una cuenta de 5, la
salida toma el valor 1 lgico durante 4 periodos de reloj y el valor 0 lgico durante un periodo.

OUT
CLK
1 2 3 4 5 1 2 3
Cuenta de 5 cargada
4 5 1 2 3 4 5 1 2 3 4



Ing. Javier Barriga Hoyle 10
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Modo 3: Permite generar una onda cuadrada en su salida (duty cycle aproximado de 50%). Si
la cuenta es par, la salida permanece en 1 durante la mitad de la cuenta y en 0 durante la otra
mitad. Si la cuenta es impar, la salida permanece en 1 por un periodo de reloj ms del tiempo
que est en estado 0. Por ejemplo, para una cuenta de 5, la salida es 1 durante tres periodos de
reloj y en 0 durante dos periodos.

OUT
CLK
1 2 3 4 5 6 1 2
Cuenta de 5 cargada
3 4 5 6 1 2 3 4 5 6 1

Modo 4: Permite que el contador genere un solo pulso en su salida. Por ejemplo, si la cuenta es
programada con un 8, la salida permanece en alto durante 8 periodos de reloj y en estado bajo
durante un periodo.

OUT
CLK
1 2 3 4 5 6 7 8
Disparo con cuenta de 8

Modo 5: Un circuito monoestable disparado por hardware que funciona como el modo 4,
excepto que es iniciado por un pulso de disparo en la terminal G, en vez de por software. Este
modo tambin es parecido al modo 1 porque es redisparable.

OUT
CLK
1 2 3 4 5
Disparo con cuenta de 5
G


NOTA: Para mayor informacin sobre estos modos, puede consultar el datasheet del 82C54.
6.2 Programacin del TIMER
Cada contador es programado individualmente escribiendo una palabra de control, seguida por la
cuenta inicial. La figura 6, muestra la estructura de la palabra de control, que permite al
programador seleccionar al contador, el modo y el tipo de operacin (lectura o escritura).

SC1 SC0 RW1 RW0 M2 M1 M0 BCD
D7
0
0
1
1
0
1
0
1
Elegir contador
Contador 0
Contador1
Contador 2
Comando Read Back
0
0
1
1
0
1
0
1
Operacin:
Comando de enclavamiento
Leer/escribir byte bajo
Leer/escribir byte alto
Leer/escribir byte bajo
y despus el alto
0
0
x
x
1
1
0
0
1
1
0
0
0
1
0
1
0
1
Modo:
Modo 0
Modo 1
Modo 2
Modo 3
Modo 4
Modo 5
0
1
Contador:
Binario 16 bits
BCD de 4 dcadas
D6 D5 D4 D3 D2 D1 D1

Figura 6.3. Palabra de control del TIMER.


Ing. Javier Barriga Hoyle 11
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
La palabra de control selecciona tambin una cuenta binaria o BCD. Cada contador puede
programarse con una cuenta de 1 a FFFFh. Una cuenta de 0 es igual a FFFFh + 1 (65536) o 10000
en BCD. La cuenta mnima de 1 es aplicable a todos los modos de operacin excepto los modos 2 y
3, las cuales tienen una cuenta mnima de 2.
a) CONFIGURACION:
Ejemplo 6.1: Configurar el CH0 del TIMER en modo 2, cuenta binaria, operacin leer y escribir
byte bajo y luego el byte alto.
Palabra de control: 00110100 = 34h
La instruccin sera: xout (0x77, 0x34);

Ejemplo 6.2: Configurar el CH1 del TIMER en modo 3, cuenta binaria, operacin leer y escribir
byte bajo y luego el byte alto.
Palabra de control: 01110110 = 76h
La instruccin sera: xout (0x77, 0x76);

Ejemplo 6.3: Configurar el CH2 del TIMER en modo 4, cuenta binaria, operacin leer y escribir
byte bajo y luego el byte alto.
Palabra de control: 10111000 = 0B8h
La instruccin sera: xout (0x77, 0xB8);

b) OPERACIONES DE ESCRITURA:
El 82C54 es muy flexible a la hora de ser programado. Basta con tener en cuenta dos cosas:
Primero, escribir siempre la palabra de control, antes de enviar la cuenta inicial al contador.
Segundo, dicha cuenta inicial debe seguir exactamente el formato seleccionado en la palabra
de control (enviar slo Byte bajo, enviar slo Byte alto, o bien enviar ambos
consecutivamente). Teniendo en cuenta que cada contador tiene su propio puerto y que la
palabra de control indica el contador al que est asociada, no hay que seguir un orden especial
a la hora de programar los contadores. Esto significa que, por ejemplo, se puede enviar la
palabra de control de cada contador seguida de su cuenta inicial, o bien enviar todas las
palabras de control para los 3 contadores y despus las 3 cuentas iniciales.


Ejemplo 6.4: Programe el CH0 del TIMER para obtener una seal cuadrada con frecuencia de 200
Hz, sabiendo que la frecuencia de entrada es de 8 MHz.

void main ()
{
// Configura el canal 0 (CH0)
xout(0x77, 0x36); // CH0, Modo 3, cuenta binario

// Frecuencia de entrada al CH0 = 8 MHz. Para obtener una frecuencia de 200 Hz
// (T=5 ms), se tiene que dividir (8 MHz/200 Hz)= 40000; ==> el factor N = 9C40h

xout (0x74, 0x40); // Se enva Byte LSB al CH0
xout (0x74, 0x9C); // Se enva Byte MSB al CH0
}







Ing. Javier Barriga Hoyle 12
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Ejemplo 6.5: Programe el CH1 y CH2 del TIMER para obtener una seal cuadrada con frecuencia
de 1 KHz en el CH1 y una seal para generar interrupciones de 250 Hz en el CH2. La frecuencia de
entrada es de 8 MHz.

void main ()
{
/* Configura el canal 0 (CH0) y el canal 1 (CH1) */
xout(0x77, 0x76); // CH1, Modo 3, cuenta binario
xout(0x77, 0xB4); // CH2, Modo 2, cuenta binario

/* Frecuencia de entrada al CH1=CH2= 8 MHz. Para obtener una frecuencia de 1 KHz
en CH1, se tiene que dividir (8 MHz/1 KHz)= 8000; ==> el factor N1 = 1F40h.
Para obtener una frecuencia de 250 Hz en CH2, se tiene que dividir (8 MHz/250
Hz)= 32000; ==> el factor N2 = 7D00h. */

xout (0x75, 0x40); // Se enva Byte LSB al CH1
xout (0x75, 0x1F); // Se enva Byte MSB al CH1
xout (0x76, 0x00); // Se enva Byte LSB al CH2
xout (0x76, 0x7D); // Se enva Byte MSB al CH2
}

c) OPERACIONES DE LECTURA:
Existen tres posibles mtodos para leer el valor de un contador en el 8254. El primero es el
comando de enclavamiento, el segundo consiste en el comando Read-Back, slo disponible en el
8254 (y no en el 8253), y el tercer mtodo consiste en leer simplemente el contador accediendo al
puerto correspondiente (este mtodo requiere inhibir la entrada CLK al contador) con objeto de
evitar leer la cuenta en medio de un proceso de actualizacin de la misma, lo que dara un resultado
incorrecto.
Comando de enclavamiento

SC1 SC0 0 0 X X X X
D7 D6 D5 D4 D3 D2 D1 D0
Selecciona contador
00 - Contador 0
01 - Contador 1
10 - Contador 2

Figura 6.4. Comando de enclavamiento.

Comando Read-back:

1 1 COUNT STATUS CNT 2 CNT 1 CNT 0 0
D7 D6 D5 D4 D3 D2 D1 D0
Selecciona bits
del contador
Estado del registro de los
contadores seleccionados
Cuenta del registro de los
contadores seleccionados


Figura 6.5. Comando Read-Back.

Cuando se hace uso de este comando enviando 11010010, el TIMER devuelve solo la cuenta
actual del contador 0; pero si se enva 11000010, el TIMER devuelve la cuenta en el contador 0 y
su registro de estado con la informacin de la figura 6.6.


Ing. Javier Barriga Hoyle 13
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
OUTPUT
NULL
COUNT
RW1 RW0 M2 M1 M0 BCD
D7 D6 D5 D4 D3 D2 D1 D0
valor de la
patilla OUT
1
0
"Null Count"
Cuenta disponible para ser ledo
Modo del contador
Contador:
0 - Binario 16 bit
1 - BCD 4 dcadas
Operacin de lectura/escritura


Figura 6.6. Registro de estado (status).


Ejemplo 6.6: Leer la cuenta del canal 1 (CH1) y canal 2 (CH2) usando el comando de
enclavamiento (slo se muestra las instrucciones principales).

void main ()
{
unsigned char X1, X2, Y1, Y2;

xout(0x77, 0x40); // Se enva palabra de enclavamiento del CH1
X1 = xin(0x75); // Lee Byte LSB
X2 = xin(0x75); // Lee Byte MSB

xout(0x77, 0x80); // Se enva palabra de enclavamiento del CH2
Y1 = xin(0x76); // Lee Byte LSB
Y2 = xin(0x76); // Lee Byte MSB
}

Ejemplo 6.7: Leer las cuentas del canal 0 (CH0), canal 1 (CH1) y canal 2 (CH2) usando el
comando Read-Back (slo se muestra las instrucciones principales)..

void main()
{
unsigned char X1,X2,Y1,Y2,Z1,Z2;

xout(0x77, 0xDE); // Se enva comando Read-back

X1 = xin(0x74); // Lee Byte LSB del CH0
X2 = xin(0x74); // Lee Byte MSB del CH0

Y1 = xin(0x75); // Lee Byte LSB del CH1
Y2 = xin(0x75); // Lee Byte MSB del CH1

Z1 = xin(0x76); // Lee Byte LSB del CH2
Z2 = xin(0x76); // Lee Byte MSB del CH2
}


Ejemplo 6.8: Usando el comando Read-Back, leer la cuenta y estado del canal 1 (CH1). Almacenar
en estado el Byte de estado y en data la cuenta (slo se muestra las instrucciones principales).

void main()
{
unsigned char estado, data_low, data_high;
unsigned int data;

xout(0x77, 0xC4); // Enva comando Read-back para CH1
estado = xin(0x75); // Lee Byte de estado del CH1
data_low = xin(0x75); // Lee el valor de cuenta (LOW) del CH1
data_high = xin(0x75); // Lee el valor de cuenta (HIGH) del CH1
data = data_high<<8 | data_low; // Se unen para formar un word
}


Ing. Javier Barriga Hoyle 14
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
7. Descripcin del Conversor Anlogo Digital ADC0804 de la Tarjeta LPT- BYM V2.0
Este convertidor anlogo digital de 8 bits es un ADC comn de bajo costo y se utiliza en
aplicaciones que no requieren un alto grado de exactitud. Por ejemplo, requiere hasta 100 S para
convertir una entrada analgica de voltaje a una salida en cdigo 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 conversin es aproximadamente 100 S y se calcula con la
siguiente ecuacin: Fclk = 1 / (1.1 R*C).
El reloj del ADC en esta tarjeta est controlado por un potencimetro 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.

1
ADC0804
2
3
4
5
6
7
8
9
10
20
19
18
17
16
15
14
13
12
11
AGND
Vref / 2
DGND
VCC
CLK R
DB0 (LSB)
DB1
DB3
DB4
DB5
DB6
DB7 (MSB)
CS
RD
WR
CLK IN
INTR
VI (+)
VI (-)
DB2


Figura 7.1. Diagrama del ADC0804.



VREF
VREF
RD
SD1
SD3
SD6
SD5
AGND
VI-
AGND
VI+
VI-
VI+
VREF
SD0
SD4
AGND
SD2
VI+
WR
SD7
VI-
C2
150pF
J5
IN_ADC
1
2
3
4
J6
IN_ADC
1
2
3
4
J10
123
R2
10K
U6
ADC0804
18
17
16
14
13
12
11
1
2
3
5
8
6
7
9
4
19
15
DB0
DB1
DB2
DB4
DB5
DB6
DB7
CS
RD
WR
INTR
AGND
VI+
VI-
VREF
CLK
CLKR
DB3
P1
P14
CS_ADC
P10
IRQ7 ADC


Figura 7.2. Esquemtico del ADC0804 dentro de la Tarjeta.


Para trabajar con un convertidor analgico digital (ADC), se debe preferiblemente leer la hoja de
datos del fabricante. Pero, todos por lo general siguen estos pasos:
a) Para capturar el dato analgico y empezar la conversin se debe activar la seal WR. Es decir,
enviar un pulso bajo (WR = 0), por un tiempo pequeo (aproximado 300 ns). Esto se consigue
enviando cualquier valor (por ejemplo: 00h) por el puerto donde est mapeado el ADC.


Ing. Javier Barriga Hoyle 15
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
En nuestro caso, para el puerto paralelo, las macros diseadas para el uso con la tarjeta
permiten generar las seales RD, WR y operarla como si se estuviera trabajando con el BUS
ISA.

Assembler:

MOV AL, 00h ; Cargo cualquier dato en AL
XOUT 6CH, AL ; Se enva el dato 0 (WR = 0)

Lenguaje C:

xout(0x6C, 0x00); // Se enva 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 seran:

Assembler:

MOV AL, 00h ; Cargo cualquier dato en AL
MOV DX, 300h ; Carga direccin del puerto
OUT DX, AL ; Se enva el dato 0 (WR = 0)

Lenguaje C:

outportb(0x300,0x00); // Se enva el dato 0 (WR = 0)

b) El ADC toma un tiempo para realizar la conversin (aproximadamente 100 s), luego del cual
pone en CERO el pin INTR para avisar que el dato (digital) est listo para ser ledo. Para
realizar la lectura por el puerto existen tres formas:


Tcnicas para la lectura del dato digital en el ADC
Espera:
Consiste en que una vez activada la seal WR (paso (a)), generar un retardo que sea mayor que el
tiempo de conversin del ADC (Por ejemplo, 1 ms), y luego proceder a leer el dato digital. Ver
diagrama de flujo.

Activar la seal WR
Retardo de 1 mseg
Leer dato digital del ADC


Programa:
xout(0x6C,0x00); // Empieza conversin (WR = 0)
delay(1); // Espero 1 ms para que convierta
dato_adc = xin(0x6C); // Lee el dato digital








Ing. Javier Barriga Hoyle 16
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Polling (encuesta):
Consiste en que una vez activada la seal WR (paso (a)), empezar a testear si la seal INTR del
ADC est en cero. Si es cero, leer el dato, caso contrario seguir testeando. Este modo es mucho
mejor que el anterior y es el adecuado cuando no se usa interrupciones. Ver diagrama de flujo.

Activar la seal WR
Leer dato digital del ADC
INTR = 0?
NO
SI


Programa:
xout(0x6C,0x00); // Inicio conversin
while(flag_int != 0x40) // testeo si INTR=0? (pin 10, puerto 379h)
{
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 tcnica se tiene que hacer uso de la lnea de interrupcin IRQ7 y del vector 15.
En este caso el programa es ms complicado y se requiere conocer muy bien los conceptos de
interrupciones, vectores de interrupcin y mscara de interrupcin (ver Apndice D). Al final de
este manual se tendr varios programas ejemplos que hacen uso de las interrupciones.

PUERTO 6Ch
IRQ7
PROGRAMA
RTI del ADC
DIR. BASE 378H
ADC0804
CPU









Ing. Javier Barriga Hoyle 17
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
8. Descripcin del Conversor Digital Anlogo DAC0830 de la Tarjeta LPT- BYM V2.0
Este dispositivo es un convertidor digital anlogo que transforma un nmero binario de 8 bits en un
voltaje analgico. El nmero de niveles de voltaje que genera el convertidor es igual al nmero de
combinaciones de entradas binarias. Es decir, un convertidor de 8 bits genera (2
8
) 256 niveles de
voltaje distintos, un convertidor de 10 bits genera (2
10
) 1024 niveles y as sucesivamente.
El DAC0830 es un convertidor de velocidad media que transforma una entrada digital en una salida
analgica en aproximadamente 1.0 s.

1
DAC0830
2
3
4
5
6
7
8
9
10
20
19
18
17
16
15
14
13
12
11
Vref
Rfb
GND
VCC
ILE (BYTE1/ BYTE2)
WR2
XFER
DI5
DI6
DI7 (MSB)
Iout 1
Iout 2
CS
WR1
GND
DI3
DI2
DI1
DI0 (LSB)
DI4


Figura 8.1. Diagrama del DAC0830.


U7
DAC0830
7
6
5
4
16
15
14
13
1
2
18
17
19
10 3
11
12
9
8
DI0
DI1
DI2
DI3
DI4
DI5
DI6
DI7
CS
WR1
WR2
XFER
ILE
DGND AGND
IOUT1
IOUT2
RFB
VREF
AGND
SD3
VREF
SD1
VCC
SD2
RFB
SD4
WR
VREF
SD0
IOUT2
CS_DAC
SD5
P1
IOUT2
RFB
R4
10K
IOUT1
J7
DAC_OUT
1
2
3
4
5
SD6
IOUT1
SD7
AGND


Figura 8.2. Esquemtico del DAC0830 dentro de la Tarjeta.

Este convertidor tiene un bus de datos de 8 bits para la conexin del cdigo digital de entrada y un
par de salidas analgicas llamadas Iout1 e Iout2, las cuales estn diseadas como entradas para un
amplificador operacional externo.
Como es un conversor de 8 bits, la amplitud de paso del voltaje de salida est definida como -Vref
(voltaje de referencia) dividido entre 255. Por ejemplo, si el voltaje de referencia es -5.0 V, la
amplitud del paso de voltaje ser de +0.0196 V. Observe que el voltaje de salida es de polaridad
opuesta al de referencia. La amplitud del paso de voltaje tambin se conoce como resolucin del
convertidor.

8.1 Estructura interna del DAC0830
La figura 8.3, muestra la estructura interna del DAC, el cual contiene dos registros internos. El
primero es un registro de retencin, mientras que el segundo est conectado al convertidor de
escalera interno R-2R. Los dos registros permiten retener un byte mientras otro es convertido. En


Ing. Javier Barriga Hoyle 18
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
muchos casos, deshabilitamos el primer registro y utilizamos solamente el segundo para aplicar
datos al convertidor, esto puede lograrse conectando un 1 lgico a ILE y un 0 lgico a CS.


Figura 8.3. Estructura interna del DAC0830.

Ambos registros son transparentes. Es decir, cuando la entrada LE tiene un nivel 1 lgico, el dato
atraviesa el registro, pero cuando la entrada LE asume el estado lgico 0, el dato es retenido. El
convertidor tiene una terminal de entrada de referencia (Vref) que establece la amplitud del voltaje
de salida de escala completa. Si -10 V son aplicados a Vref, el voltaje de salida a escala completa
(11111111
2
) es +10 V. La salida del convertidor R-2R aparece en Iout1 e Iout2. Estas salidas estn
diseadas para aplicarse a un amplificador operacional como el 741 o equivalente.

























Ing. Javier Barriga Hoyle 19
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
9. Sistema Operativo y uso de la Tarjeta LPT ByM V2.0
Para utilizar esta Tarjeta de una manera correcta, depender del Sistema Operativo y del Lenguaje
C empleado. La siguiente tabla muestra el archivo de cabecera o librera adecuada a usar.

Lenguaje Window98 Windows 2000 o XP
Borland C++ 3.0

Visual C++ 6.0
#include <BymDos.h>

#include <BymWin.h>
#include <BymDos.h>

#include <BymWin.h>

Por las caractersticas del Sistema Operativo que est usando se tiene que tener en cuenta lo
siguiente:
Windows 98: El acceso al puerto paralelo es libre (no protegido), as que no hay problema de
correr los programas propuestos incluso los de interrupciones.
Windows 2000 o XP: El acceso al puerto paralelo est protegido, por lo que es necesario
desprotegerlo antes de ejecutar cualquier programa. Para ello se utiliza el UserPort 1.0, el cual
desprotege el puerto paralelo, pero no se puede ejecutar programas con interrupciones (IRQ7).
Adems, dentro del programa principal se debe colocar la instruccin: inicio_tarjeta(), que se
encarga de poner todas las seales de control de los circuitos integrados en un valor que evite
conflictos, tales como RD = 1, WR =1 y los CS = 1.
9.1 Uso del UserPort (Win2000 o WinXP)
Para utilizar este programa que permite desproteger y emplear el puerto paralelo, primero tiene que
copiarse el archivo UserPort.sys en la carpeta:


C:\WINNT\system32\drivers\UserPort.sys


Luego, deber dar doble clic en el siguiente icono.


Aparecer el siguiente cuadro:


NOTA:
Como el puerto paralelo est
en la direccin 378h, y est
comprendido en los rangos
mostrados por defecto.
Entonces:
Para empezar a trabajar
pulse el botn de Start.
Para terminar pulse el
botn de Stop.
Para salir del UserPort
pulse Exit.


Ing. Javier Barriga Hoyle 20
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
9.2 Estructura de un programa en Lenguaje C
A continuacin se muestra un formato de cmo se debe escribir los programas escritos en Lenguaje
C para WINDOWS (Visual C++) o DOS (Turbo C++), empleando los archivos de cabecera
mnimos que requiere la tarjeta para operar. Depender del programa escrito para agregar ms
archivos de cabecera.
La librera BymWin.h deber copiarse dentro de:

C:\Archivos de programa\Microsoft Visual Studio\VC98\Include\BymWin.h

La librera BymDos.h deber copiarse dentro de:

C:\TC\Include\BymDos.h


VISUAL C++ (Sistema Operativo Win98, Win2000, WinXP):

#include <windows.h>
#include <conio.h>
#include "BymWin.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin del puerto paralelo

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

----------------;
----------------;
----------------;
}



TURBO C++ 3.0 (Sistema Operativo Win98, Win2000, WinXP):

#include <dos.h>
#include <conio.h>
#include "BymDos.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin del puerto paralelo

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

----------------;
----------------;
----------------;
}











Ing. Javier Barriga Hoyle 21
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
10. Aplicaciones del PPI 82C55
Los siguientes programas escritos en Lenguaje C, muestran como utilizar el PPI en algunas
aplicaciones bsicas.
10.1 LEDS y DIPSWITCH
Implemente el circuito mostrado (vlido para los programas PPI_1, PPI_2, PPI_3 y PPI_4).
Cargue el Visual C++ 6.0 en modo consola. Puede usar Win98, Win2000 o WinXP.
Escriba los siguientes programas y luego para ejecutarlos deber tener en cuenta el sistema
operativo que est usando (captulo 9).
Los esquemticos de salida a 8 leds y entrada digital de 8 bits, estn en el Apndice E1 y E2.

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
Power E/S Timer SW Timer
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
0s
1s
Entrada digital (8 bits)
Salida digital (8 leds)

Figura 10.1. Conexin Tarjeta Leds Dipswitch (programas 10.1, 10.2, 10.3 y 10.4).


Programa 10.1: (PPI_1.CPP)
/********************************************************************************
PPI_1.CPP
Este programa lee un dato digital de 8 bits por el PORTB del PPI y lo enva por
el PORTA para ser visualizado en 8 Leds.

Descripcin:
a) Conecte con un cable flat el PB del PPI con un dipswitch de 8 bits que permita
ingresar datos digitales a la tarjeta.
b) Conecte con un cable flat el PA del PPI con 8 Leds que permita visualizar los
datos digitales enviados por el microprocesador.
c) Escriba el programa en Visual C++ (modo consola).
d) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)
e) Ejecute su programa dndole diferentes valores al dipswitch y observar que
el valor colocado se visualizar en los leds.
f) Repita el paso (e) cuantas veces crea necesario.

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

int Base = 0x378; // Direccin del puerto paralelo


Ing. Javier Barriga Hoyle 22
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
unsigned char data;

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B, 0x82); // Configura PPI -> PA=out, PB=in, PC=out
data = xin(0x79); // Se lee dato del PB del PPI
xout(0x78, data); // Se enva por PA del PPI
}


Programa 10.2: (PPI_2.CPP)
/********************************************************************************
PPI_2.CPP
Este programa emplea el PA del PPI para generar intermitencia en los 8 leds. Es
decir, enva el dato 0xFF (leds ON) luego de 1/2 Seg. se enva 0x00 (leds OFF).
La operacin se realiza 10 veces.

Descripcin:
a) Conecte con un cable flat el PA del PPI con 8 leds que permita ver los datos
digitales enviados por el Computador.
b) Escriba el programa en Visual C++ (modo consola)
c) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin del puerto paralelo

int i;

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B, 0x82); // Configura PPI -> PA=out, PB=in, PC=out
for(i=0; i<10; i++) // Bucle de 10 veces de repeticin
{
xout(0x78, 0xFF); // Leds ON
Sleep(200); // Retardo de 200 ms
xout(0x78, 0x00); // Leds OFF
Sleep(200);
}
}


Programa 10.3: (PPI_3.CPP)
/********************************************************************************
PPI_3.CPP
Este programa a travs del PA del PPI genera prendido secuencial a la izquierda y
luego se apaga secuencialmente a la derecha.
La operacin se realiza 10 veces a intervalos de 150 ms.

Descripcin:
a) Conecte con un cable flat el PA del PPI con 8 leds que permita visualizar los
datos digitales enviados por el microprocesador a travs del PPI.
b) Escriba el programa en Visual C++ (modo consola)
c) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)
Autor: Ing. Javier Barriga Hoyle
********************************************************************************/
#include <windows.h>


Ing. Javier Barriga Hoyle 23
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
#include <stdio.h>
#include <conio.h>
#include "BymWin.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin del puerto paralelo

/* Variables globales */
int i;
unsigned char p;

/* Inicia programa principal */
void main ()
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B, 0x82); // Configura PPI -> PA=out, PB=in, PC=out

/* Prendido secuencial a la izquierda */
p = 0x01; // p = 0000 0001b
for(i=0; i<10; i++)
{
while(p != 255)
{
xout(0x78, p); // Se enva al PA del PPI
Sleep(150); // Retardo de 150 ms
p = p << 1; // Desplaza un bit a la izquierda
p = p | 0x01; // OR lgica
}

// Apagado secuencial a la derecha
while(p != 0)
{
xout(0x78, p); // Se enva al PA del PPI
Sleep(150); // Retardo de 150 ms
p = p >> 1; // Desplaza un bit a la derecha
}
}
xout(0x78, 0x00); // Se apaga los leds
}


Programa 10.4: (PPI_4.CPP)
/********************************************************************************
PPI_4.CPP
Este programa prende secuencialmente los bits desde los extremos al centro
y luego se apaga hacia los extremos (muy vistoso).

Descripcin:
a) Conecte con un cable flat el PA del PPI con 8 leds que permita ver los datos
digitales enviados por el Computador.
b) Escriba el programa en Visual C++ (modo consola)
c) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin del puerto paralelo

/* Variables globales */
unsigned char x, y, z;
int i, j;

void main(void) // Inicia programa principal


Ing. Javier Barriga Hoyle 24
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B, 0x82); // Configura PPI -> PA=out, PB=in, PC=out
x = 0;
for(i=1 ;i<=5; i++) // Bucle de 5 veces de repeticion
{
y = 0x01; // Inicializa variables
z = 0x80;
for(j=1;j<=8;j++) // Bucle de 8 veces
{
xout(0x78,x); // Se enva por el PORTA
Sleep(150); // Retardo de 150 ms
x = x^y; // OR-exclusiva
x = x^z;
y = y<<1; // Desplaza un bit a la izquierda
z = z>>1; // Desplaza un bit a la derecha
}
}
xout(0x78,0x00); // Apaga los leds
}


10.2 DISPLAY DE CRISTAL LQUIDO (LCD)
Implemente el circuito mostrado y siga las recomendaciones dados en el captulo 9. La informacin
sobre el LCD como es ms extensa se encuentra en un archivo LCD.pdf

Programa 10.5: (PPI_5.CPP) Programa que enva mensaje al LCD

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
Power E/S Timer SW Timer
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
LCD 2x16
HD 44780
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
LEYENDA:
D[7..0] Bus de datos
En Seal de habilitacin
R/W Seleccin de lectura (0) o escritura (1)
Rs Selector de registro (0 = Reg. Inst, 1 = Reg. Datos)
VCC Tensin de alimentacin, 5 V.
GND Entrada de alimentacin, 0 V.
VLC Entrada de control de constraste (unir al potenciometro)

Figura 10.2. Conexin Tarjeta - LCD.

/********************************************************************************
PPI_5.CPP (Modo a 4 bits)
Este programa enva 2 mensajes a un LCD de 2x16, usando el PortA del PPI de la
Tarjeta LPT V2.0

Descripcin:
a) Las conexiones PPI - LCD es:
PORTA del PPI: PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0
LCD: D7 D6 D5 D4 EN RS X X
(La seal WR se conecta a tierra, porque en este programa solo se escribe en
el LCD).
b) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.


Ing. Javier Barriga Hoyle 25
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
c) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
d) Ejecute su programa.

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

int Base = 0x378; // Direccin del puerto paralelo

#define CONTROL 0 // Constante para el display LCD
#define DATO 1 // Constante para el display LCD
#define DISPLAY_ON 0x0E // Display ON, cursor ON, blink OFF
#define BORRAR_LCD 0x01
#define UCHAR unsigned char

/* Prototipos */
void PutcharLCD(UCHAR direc, UCHAR dato);
void BorraLCD(void);
void InitLCD(void);
void GotoxyLCD(UCHAR fila, UCHAR columna);

/* Mensajes */
char Mensaje1[30] = {"TARJETA LPT BYM V2.0"}; // Ambas filas
char Mensaje2[30] = {"** LO MAXIMO **"}; // Ambas filas

/* Variables globales */
int j;

/* Inicia programa principal */
void main(void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI como PA = PB = PC = outs
InitLCD(); // Inicializa LCD

/* Enva mensaje1 */
while(j<20)
{
GotoxyLCD(1,2); // Posiciona cursor en la fila 1, columna 3
for(j=0; j<11; j++)
{
PutcharLCD(DATO, Mensaje1[j]);
Sleep(200);
}
GotoxyLCD(2,4); // Posiciona cursor en la fila 2, columna 5
for(j=12; j<20; j++)
{
PutcharLCD(DATO, Mensaje1[j]);
Sleep(200);
}
}
Sleep(2000); // Espera 2 segundos
BorraLCD();

/* Enva mensaje2 */
for(j=0; j<15; j++)
{
PutcharLCD(DATO, Mensaje2[j]);
Sleep(200);
}
} /* FIN de main */


/*-------------------------------------------------------------------------------


Ing. Javier Barriga Hoyle 26
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Funcin: void InitLcd(void)
Inicializa el display LCD.
-------------------------------------------------------------------------------*/
void InitLCD(void)
{
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
/* RS debe ser estable antes del flanco de subida de EN */
xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(5); // Demora superior a 4,1 ms

xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(1); // Demora superior a 100 s

xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(1); // Demora superior a 100 s
/* Selecciona interface de 4 bits */
xout(0x78, 0x28); // DB[7..4] EN RS X X
// 0010 1 0 0 0
xout(0x78, 0x20); // DB[7..4] EN RS X X
// 0010 0 0 0 0

/* Tras esta inicializacin el display queda en modo 4 bits */
Sleep(1); // Demora superior a 100 s
BorraLCD(); // Borra el LCD y lleva cursor al origen
} // FIN DE InitLcd

/*-------------------------------------------------------------------------------
Funcin: void PutcharLcd(UCHAR direc, UCHAR dato)
Envia al display LCD un "dato". Si:
direc = 0, se accede al registro de instrucciones
direc = 1, se accede al registro de datos
-------------------------------------------------------------------------------*/
void PutcharLCD(UCHAR direc, UCHAR dato)
{
UCHAR temp, temp2;
temp2 = 0x08; // Para activar EN
if (direc == DATO) // Es instruccin o dato?
{
temp2 |= 0x04; // Selecciona Dato/Control con RS
xout(0x78, 0x04); // DB[7..4] EN RS X X
} // 0000 0 1 0 0
else
xout(0x78, 0x00); // DB[7..4] EN RS X X
// 0000 0 0 0 0
/* RS debe ser estable antes del flanco de subida de EN */

/* Primero se enva el nibble alto */
temp = (dato & 0xf0) | temp2;
xout(0x78, temp); // Manda nibble alto con EN = 1
temp &= 0xf5;
xout(0x78, temp); // Desactiva EN

/* Despus se manda el nibble bajo */
temp = (dato << 4) | temp2;
xout(0x78, temp); // Manda nibble bajo con EN = 1
temp &= 0xf5;
xout(0x78, temp); // Desactiva EN


Ing. Javier Barriga Hoyle 27
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Sleep(1);
} // FIN DE PutcharLcd

/*-------------------------------------------------------------------------------
Funcin: void BorraLCD(void)
Establece control del LCD, Borra el LCD, establece Modo de entrada,
y pone el cursor en el origen.
-------------------------------------------------------------------------------*/
void BorraLCD(void)
{
PutcharLCD(CONTROL, DISPLAY_ON); // Display on, cursor ON, blink off
PutcharLCD(CONTROL, BORRAR_LCD); // Borrar el Display
PutcharLCD(CONTROL, 0x06); // Incremento automtico de AC al escribir
PutcharLCD(CONTROL, 0x02); // Cursor en la esquina izquierda
} // FIN DE BorraLCD

/*-------------------------------------------------------------------------------
Funcin: void GotoxyLCD(UCHAR fila, UCHAR columna)
Posiciona el cursor en la posicin especificada por fila, columna.
Si alguna de las coordenadas es invalida no se hace nada.
Coordenadas validas: fila = 1..2, columna = 1..16
-------------------------------------------------------------------------------*/
void GotoxyLCD(UCHAR fila, UCHAR columna)
{
UCHAR pos_fila, cursor;
if((fila<1 || fila>2) || (columna<1 || columna>16))
return;
switch(fila)
{
case 1:
pos_fila = 0x80; // Posicin de memoria 00h ---> 27h
cursor = pos_fila + columna;
PutcharLCD(CONTROL, cursor); // Posiciona cursor
break;

case 2:
pos_fila = 0xC0; // Posicin de memoria 40h ---> 67h
cursor = pos_fila + columna;
PutcharLCD(CONTROL, cursor); // Posiciona cursor
break;
}
}



















Ing. Javier Barriga Hoyle 28
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
10.3 TECLADO HEXADECIMAL 4x4
El teclado matricial mostrado en la figura es uno de los ms comunes que existen en el mercado,
por ello, saber usarlo es indispensable para cualquier proyecto que se tenga que ingresar datos
como: claves, parmetros de temperatura, etc.
El teclado tiene 9 pines, de los cuales, 4 corresponden a las filas, 4 corresponden a las columnas y
un pin que no se usa. Para utilizarlo en un circuito con Microprocesador o Microcontrolador, es
necesario conectarle 4 resistencias de 10K a +5V en las columnas (pull up).

1 2 3 F
4 5 6 E
7 8 9 D
A 0 B C
F
0
F
1
F
2
F
3
C
1
C
2
C
3
X
1 2 3 F
4 5 6 E
7 8 9 D
A 0 B C
+ 5V
10 K
Fila 0
Fila 1
Fila 2
Fila 3
C
o
l
u
m
n
a

0
C
o
l
u
m
n
a

1
C
o
l
u
m
n
a

2
C
o
l
u
m
n
a

3
D0
D1
D2
D3
D4
D5
D6
D7
Pines del teclado
C
0

(a) (b)

Figura 10.3. (a) Diagrama del teclado, (b) Forma de utilizarlo.

Para programar al teclado se puede hacer de dos maneras: Explorar directamente el teclado a travs
de filas y columnas, o usando un decodificador de teclado.

Explorar filas y columnas:

1 2 3 F
4 5 6 E
7 8 9 D
A 0 B C
+ 5V
10 K
0
1
1
1
1
1
0
1
Tecla
pulsada
Fila 0, activa


Filas
Columnas
Mtodo:
Se enva por las filas el nibble 1110, en ese
instante se activa toda la fila 0, y las dems
filas estarn inactivas. Se pulsa el nmero 3,
entonces al leerse las columnas se tendr el
nibble 1011. Con ambos nibbles (1011 1110),
se puede determinar el cdigo correspondiente
de la tecla pulsada.

Figura 10.4. Exploracin de teclado.

Para explorar el teclado y averiguar en cada instante cul es la tecla pulsada, se sigue el siguiente
mtodo. Se trabaja con el nivel lgico HIGH (1) actuando como inactivo y el nivel lgico LOW (0)
como activo. Por los terminales de las filas del teclado se introducen cuatro niveles lgicos, uno


Ing. Javier Barriga Hoyle 29
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
activo (0) y los otro tres inactivos (1). Si existe alguna tecla pulsada en la fila por la que tiene el
nivel LOW, dicho nivel saldr por la columna correspondiente con la que se haga contacto. En
consecuencia, leyendo los estados lgicos de los terminales de las columnas (C3,C2,C1,C0)
averiguaremos si hay alguna tecla pulsada en la fila por la que se ha introducido el nivel LOW, ya
que si no hay ninguna en todas las columnas se leer nivel HIGH inactivo. Procediendo
secuencialmente a introducir el nivel LOW por cada una de las cuatro filas y a leer los niveles de
salida de las columnas, se podr determinar la tecla pulsada en cada momento.


Programa 10.6: (PPI_6.CPP) Lectura del teclado hexadecimal mediante exploracin de teclas.
Implemente el circuito mostrado y siga las recomendaciones dados en el captulo 9. No olvide que
la forma de conectar un teclado es como en la figura 10.3(b).

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
Power E/S Timer SW Timer
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
1 2 3 F
4 5 6 E
7 8 9 D
A 0 B C
Salida digital (8 leds)
Columnas
Filas


Figura 10.5. Conexin Tarjeta - PPI - Teclado.

/********************************************************************************
PPI_6.CPP (MODO 0)
Este programa explora las filas y columnas del teclado para determinar en
cualquier instante el cdigo de la tecla pulsada. Para ello se conecta el PortC
del PPI al teclado. El valor ledo se muestra en pantalla y en los LEDS
conectados al PortA del PPI.
Se sale del programa cuando se pulsa ESC.

Descripcin:
a) Las conexiones PPI - TECLADO es:
PORTC del PPI: PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0
TECLADO: C3 C2 C1 C0 F3 F2 F1 F0

b) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
c) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
d) Ejecute su programa.

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

int Base = 0x378; // Direccin del puerto paralelo
/* Prototipos */


Ing. Javier Barriga Hoyle 30
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
unsigned char keyNumber(unsigned char dato);
unsigned char kbRead(unsigned char tec);

/* Variables globales */
unsigned char tecla,ncol,scan,car;
int Fin;

/* Inicia programa principal */
void main(void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B, 0x88); /* Configura PPI con PA=PB=OUTs (modo 0)
PC[7..4]=IN, PC[3..0]=OUT (modo 0) */
Fin = 0;
while(!Fin) // Espera ESC para terminar
{
scan = 0xfe; // Byte de inicio de scan de teclado
ncol = 4; // Nmero de columnas a explorar
for(ncol; ncol>0; ncol--)
{
xout(0x7A, scan); // Enva dato al PortC
Sleep(10); // Retardo de 10 ms
car = xin(0x7a); // Lee el teclado (columna, fila)
if((scan-car) != 0) // Se ha pulsado tecla?
{
tecla = kbRead(car); // Devuelve cdigo tecla vlido
printf("Tecla pulsada = %c \n",tecla);
Sleep(200); // Retardo para eliminar rebote
xout(0x78, tecla); // Se enva a los leds
}
scan = (scan<<1) | 1; // Selecciona siguiente fila
}
if(kbhit()) // Se puls tecla de la PC?
{
car = getch(); // SI, Lee del teclado
if(car == 0x1B) Fin = 1; // Si es ESC, sale del programa
}
}
} /* Fin de main */

/*----------------------------------------------------------------------------
Determina el nmero de la tecla pulsada. Realiza la operacin:
"nmero = fila * 2 + columna".
-----------------------------------------------------------------------------*/
unsigned char keyNumber(unsigned char dato)
{
unsigned char fila,col;
fila = dato & 0x0f;
switch(fila)
{
case 0x0e: fila=0; break; /* 0000.111_ */
case 0x0d: fila=1; break; /* 0000.11_1 */
case 0x0b: fila=2; break; /* 0000.1_11 */
case 0x07: fila=3; break; /* 0000._111 */
default: fila=0xff; break;
}
col = dato & 0xf0; // Lee para determinar la columna
switch(col)
{
case 0xe0: col=0; break; /* 111_.0000 */
case 0xd0: col=1; break; /* 11_1.0000 */
case 0xb0: col=2; break; /* 1_11.0000 */
case 0x70: col=3; break; /* _111.0000 */
default: col=0xff; break;
}
if((fila == 0xff)||(col == 0xff))


Ing. Javier Barriga Hoyle 31
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
col = 0xff; // Retorna tecla pulsada invlida
else
col = (fila<<2) + col; /* Determina el nmero de la tecla
pulsada */
return(col);
} /* fin de keyNumber */

/*----------------------------------------------------------------------------
Determina el cdigo de la tecla pulsada y devuelve el cdigo ASCII.
-----------------------------------------------------------------------------*/
unsigned char kbRead(unsigned char tec)
{
/* La siguiente tabla se usa para hallar el cdigo de cada tecla */
unsigned char kbTable[16]={'1', '2', '3', 'F', /* fila 0 */
'4', '5', '6', 'E', /* fila 1 */
'7', '8', '9', 'D', /* fila 2 */
'A, '0', 'B', 'C'}; /* fila 3 */

tecla = keyNumber(tec); // Codifica tecla en fila, columna
if(tecla != 0xff) // Si solo se ha pulsado una tecla, traduce
tecla = kbTable[tecla]; // desde kbTable el cdigo de tecla
return(tecla); // Retorna tecla pulsada
} /* fin de kbRead */



Usando decodificador de teclado 74C922
Se encarga de realizar la exploracin de filas y columnas, nuestro programa es ms sencillo ya que
slo se testea la lnea de control (data available) y cuando la lnea est activa, se lee los 4 bits de
datos correspondientes a la tecla pulsada. La lnea output enable lo podemos conectar a tierra.

1
74C922
2
3
4
5
6
7
8
9
18
17
16
15
14
13
12
11
10
COLUMN X3
GND
VCC
DATA OUT A
DATA OUT B
DATA OUT C
OUTPUT ENABLE
DATA AVAILABLE
COLUMN X1
COLUMN X2
ROW Y1
ROW Y2
ROW Y3
ROW Y4
OSCILADOR
KEYBOUNCE MASK
COLUMN X4
DATA OUT D
X4
Data D
74C922
X3
X2
X1
Y4
Y3
Y2
Y1
Data Available
Data C
Data B
Data A
DA
D
C
B
A
Output Enable OE
OSC Oscilador
Keybounce Mask KBM
Row Y1
Row Y2
Row Y3
Row Y4
Column X1
Column X2
Column X3
Column X4

(a) (b)

Figura 10.6. (a) Circuito Integrado 74C922, (b) Diagrama simplificado del decodificador.

X4
74C922
X3
X2
X1
Y4
Y3
Y2
Y1
DA
D
C
B
A
OE
O
S
C
K
B
M
1 2 3 F
4 5 6 E
7 8 9 D
A 0 B C
+ 5V
10 K
PC7
PC3
PC2
PC1
PC0
22 uF 2.2 uF

P
P
I

Figura 10.7. Diagrama de conexin: Decodificador y Teclado.



Ing. Javier Barriga Hoyle 32
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 10.7: (PPI_7.CPP) Manejo del Teclado hexadecimal a travs de un decodificador.
Implemente el circuito mostrado y siga las recomendaciones dados en el captulo 9. No olvide que
la forma de conectar un teclado es como en la figura 10.3(b).

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
Power E/S Timer SW Timer
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
1 2 3 F
4 5 6 E
7 8 9 D
A 0 B C
Salida digital (8 leds)
Filas
Columnas
Y[4..1]
X[4..1]
Data out
74C922

Figura 10.8. Conexin Tarjeta - Decodificador - Teclado - LEDS.

/********************************************************************************
PPI_7.CPP (PPI en Modo 0)
Este programa lee el cdigo de la tecla presionada de un teclado 4x4, lo muestra
en la pantalla y en 8 leds conectados al PortA del PPI. Sale del programa cuando
se pulsa ESC.
La decodificacin se lleva a cabo a travs del Circuito Integrado 74C922.

Descripcin:
a) Las conexiones PPI - 74C922 es:
PORTB del PPI: PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
74C922: Data_En X X X D C B A

(La seal OE se conecta a tierra, para que est siempre disponible).
b) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
c) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
d) Ejecute su programa.

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

int Base = 0x378; // Direccin del puerto paralelo

/* Prototipos */
unsigned char kbRead(void);

/* Variables globales */
unsigned char tecla, car;
int Fin;

void main(void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B, 0x82); // Configura PPI como PA=PC=OUTs, PB=IN
Fin = 0;


Ing. Javier Barriga Hoyle 33
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
while(!Fin) // Espera ESC para terminar
{
while(!(xin(0x79)&0x80)); // Espera que se pulse tecla
while( (xin(0x79)&0x80)); // Espera que se suelte tecla
car = ReadTecla(); // Lee tecla pulsada
printf("Valor leido %c \n", car); // Imprime en pantalla
xout (0x78, car); // Enva al PortA del PPI

if(kbhit()) // Se puls tecla de la PC?
{
car = getch(); // SI, lee del teclado
if(car == 0x1B) Fin = 1; // Si es ESC, sale del programa
}
}
} /*Fin de main */

/*----------------------------------------------------------------------------
Funcin que determina el cdigo de la tecla pulsada y devuelve ASCII.
----------------------------------------------------------------------------*/
unsigned char ReadTecla(void)
{
/* La siguiente tabla se usa para hallar el cdigo de cada tecla */
unsigned char kbTable[16]={'1', '2', '3', 'F', /* fila 0 */
'4', '5', '6', 'E', /* fila 1 */
'7', '8', '9', 'D', /* fila 2 */
'A, '0', 'B', 'C'}; /* fila 3 */

tecla = xin(0x79)&0x0f; /* Lee del PortB del PPI y habilita los
4 bits menos significativos */
tecla = kbTable[tecla]; /* devuelve desde kbTable el cdigo
asignado a la tecla presionada*/
return(tecla);
} /* fin de ReadTecla */


10.4 DISPLAY 7 SEGMENTOS
El DISPLAY de 7 segmentos es un dispositivo de salida que permite visualizar nmeros en
formato BCD. La forma de uso que se le da es diversa y depende bsicamente del proyecto a
realizar, puede usarse con un decodificador 7447/7448 o la decodificacin se realiza por software,
en algunos casos se utiliza un PLD para decodificar en cdigo hexadecimal. Cuando se tiene que
usar varios displays lo ms recomendable es conectarlos en un bus comn y el programa ejecuta la
multiplexacin en el tiempo para mostrar los dgitos (Ej. Programa 10.8).
Tambin se puede usar para desplazar mensajes en forma de caracteres, en este caso la
decodificacin para generar las letras se hace por software (Ej. Programa 10.9).

a
b
c
d
e
f
g
a
b
c
d
e
f
g
Anodo / Ctodo
comn


Figura 10.9. Display de 7 segmentos.

Los displays pueden se de nodo comn o ctodo comn, los primeros se alimentan con VCC y sus
segmentos se activan con cero, y los segundos se alimentan con Tierra (GND) y sus segmentos se
activan con uno.



Ing. Javier Barriga Hoyle 34
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 10.8: (PPI_8.CPP) Manejo de 4 displays multiplexados.
Implemente el circuito mostrado y siga las recomendaciones dados en el captulo 9. Las entradas
del decodificador 7448 (A, B, C, D) y las bases de los 4 transistores PNP se conectan al PortA del
PPI de la Tarjeta LPT BYM V2.0 (figura 10.10). Ver apndice E.3 (Esquemtico de los 4 displays).

PA3
PA2
PA1
PA0
PA7
PA6
PA5
PA4
D7..D0
RD
WR
A0
A1
RESET
CS
PPI 82C55
D
E
C
O
D
E
R
D
C
B
A
+5v +5v +5v +5v
a
b
c
d
e
f
g
7448
Displays Anodo comn
Q3 Q2 Q1 Q0
D
R
I
V
E
R
a
b
c
d
e
f
g
ULN2003A


Figura 10.10. Conexin del PPI y 4 displays multiplexados.

/********************************************************************************
PPI_8.CPP (PPI en Modo 0)
Este programa visualiza un nmero de 4 dgitos en BCD, almacenados en un arreglo
donde el nibble alto controla el transistor y el nibble bajo los nmeros a ser
mostrados en los 4 displays multiplexados. Se emplea el PortA del PPI.

Descripcin:
a) Las conexiones PPI - DISPLAY es:
PORTA del PPI: PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0
TRANSISTORES: Q3 Q2 Q1 Q0
7447: D C B A

b) Los transistores se activan con CEROS (Q3=0111, Q2=1011, Q1=1101, Q0=1110)
y los segmentos de los displays se activan con UNOS.
c) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
d) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
e) Ejecute su programa.

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

int Base = 0x378; // Direccin del puerto paralelo

void retardo(void); // Prototipo de funcin retardo

/* Variables globales */
unsigned char tabla[4]={0x75,0xB7,0xD9,0xE3}; // Defino el arreglo tabla
int i,j;

void main(void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI como PA=PB=PC=OUTs (modo 0)

for(i=0; i<=10000; i++) // Tiempo de visualizacin del nmero
{
for(j=0; j<=3; j++) // Se multiplexa los datos en el tiempo
{
xout(0x78,tabla[j]); // Se enva al puerto valor de tabla


Ing. Javier Barriga Hoyle 35
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
retardo(); // Se genera un retardo menor de 1 ms
}
}
xout(0x78,0xFF); // Se apaga los displays
} /* Fin de main */

/* Retardo aproximado de 0.5 ms para una computadora PIII de 450 MHz */
void retardo(void)
{
for(double n=0; n<65535; n++);
} /* Fin de retardo */


Programa 10.9: (PPI_9.CPP) Manejo de 8 displays multiplexados.
Implemente el circuito mostrado y siga las recomendaciones dados en el captulo 9. Los displays se
conectan al PortA del PPI y los transistores al PortB del PPI para enviar una cadena de caracteres
debidamente codificados por software. Ver esquemtico en el apndice E.5.

PA7
PA6
PA5
PA4
PA3
PA2
PA1
PA0
D7 - D0
RD
WR
A0
A1
RESET
CS
g
f
e
d
c
b
a
PB7
PB6
PB5
PB4
PB3
PB2
PB1
PB0
+5v
+5v
+5v
Se activan con ceros
Displays nodo comn
PPI 82C55
Driver
U
L
N
2
8
0
3
Q7
Q4
Q0

Figura 10.11. Conexin PPI - ULN2803 - 8 displays multiplexados.

/******************************************************************************
PPI_9.CPP (PPI en modo 0)
Este programa desplaza un mensaje en 8 displays multiplexados en el tiempo.

DESCRIPCION:
a) Conecte con un cable el PortA del PPI a las entradas de los displays
Las conexiones PPI - DISPLAY son:
PORTA del PPI: PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0
DISPLAYS: X g f e d c b a
b) Las conexiones PPI - TRANSISTORES son:
PORTB del PPI: PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0
TRANSISTORES: Q7 Q6 Q5 Q4 Q3 Q2 Q1 Q0
c) Los datos que se envan al display salen por el PortA (78h) y tienen que
ser previamente codificados a siete segmentos. Los segmentos se activan con
UNO. (Ej. letra H = 01110110b = 0x76)
d) Los transistores se controlan por el PortB del PPI (79h) usando los 8 bits.
se activan con CEROS. (Ej. activar Q7=01111111 = 0x7f)

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

int Base = 0x378; // Direccin del puerto paralelo
/* Prototipos */


Ing. Javier Barriga Hoyle 36
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
void retardo(void);

/* mensaje1: HOLA */
unsigned char mensaje1[8] = {0x00,0x00,0x76,0x3f,0x38,0x77,0x00,0x00};

/* mensaje2: Tarjeta LPT BYM V2.0 */
unsigned char mensaje2[35]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,
0x77,0x50,0x1e,0x79,0x78,0x77,0x00,0x38,
0x73,0x78,0x00,0x7c,0x6e,0x37,0x00,0x1c,
0x5b,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00};

unsigned char transistor[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe1};
//{Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0}

/* Variables globales */
int h,i,j,k;
unsigned char *p, *q; // Punteros

void main(void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI como PA=PB=PC=OUTs (modo 0)

/* Visualiza mensaje1 en forma intermitente */
for(h=0; h<5; h++) // Numero de veces de intermitencia
{
for(i=0; i<=50; i++) // Tiempo de visualizacin del numero
{
for(j=0; j<=7; j++) // Se multiplexa los datos en el tiempo
{
xout(0x78,mensaje1[j]); // Se enva dato de tabla
xout(0x79,transistor[j]); // Se activa posicin de transistor
retardo(); // Se genera un retardo de 1/2 ms
}
}
xout(0x78,0x00); // Se apaga los displays
Sleep(250); // Se genera retardo de 250 ms
}

/* Desplaza mensaje2 de derecha a izquierda */
for(h=0; h<3; h++) // Nmero de veces a desplazar el mensaje
{
p = &mensaje2[0]; // Asigna direccin de mensaje a p
q = &transistor[0]; // Asigna direccin de transistor a q
for(i=0; i<=26; i++) // Nmero de caracteres a desplazar
{
for(j=0; j<=15; j++) // Tiempo de visualizacin del mensaje
{
for(k=0; k<=7; k++) // Se multiplexa los datos en el tiempo
{
xout(0x78, *(p+k)); // Se enva el carcter
xout(0x79, *(q+k)); // Se enva la posicin del transistor
retardo(); // Se genera un retardo de 1/2 ms
}
}
p++; // Incrementa puntero
}
}
}

/* Retardo aproximado de 0.5 ms para una computadora PIII de 450 MHz */
void retardo(void)
}
for(double n=0; n<65535; n++);
}


Ing. Javier Barriga Hoyle 37
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
10.5 MOTOR DE PASO A PASO
Los 4 programas que se muestran a continuacin controlan un motor de pasos de 6 hilos (4
bobinas). Para ello se emplea el PPI 82C55 contenido en la tarjeta de interfase LPT V2.0 (puede
tambin controlarse directamente desde el puerto paralelo). Para mayor informacin sobre motores
paso a paso pueden leer el archivo MOTORES PAP.pdf

Figura 10.12. Fotografa de tres modelos de motores de paso.

Como se sabe para controlar estos motores, se hace necesario usar un driver por cada bobina
implementado a base de transistores de potencia junto con opto acopladores. Tambin de una
manera sencilla en ciertas aplicaciones se emplea al CI L293D (Apndice A), que es un driver de 4
canales capaz de proporcionar una corriente de salida de hasta 1A por canal. Cada canal es
controlado por seales de entrada compatibles TTL y cada pareja de canales dispone de una seal
de habilitacin que desconecta las salidas de los mismos.
Para controlar el motor se dispone de dos modos bsicos y un tercer modo poco empleado:
Accionamiento Paso Completo: Siempre hay 2 bobinas activadas, consiguindose un par
motor ms elevado a costa de un mayor consumo de potencia.
Accionamiento por Medios Pasos: Unas veces se encuentra activada una bobina y otras veces
se activan dos bobinas, consiguindose mayor resolucin en el posicionamiento del motor.
Accionamiento Onda o Una sola bobina: En cada instante de tiempo se encuentra activada una
bobina del motor. Es poco empleado.


Programa 10.10: (PPI_10.CPP) Control de un motor de paso en modo paso completo.
Implemente el circuito mostrado y siga las recomendaciones dados en el captulo 9. El motor se
controla con los 4 bits menos significativos del PortA del PPI. Ver esquemtico en el apndice E.6.

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
Power E/S Timer SW Timer
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
E1
IN1
IN2
IN3
IN4
E2
OUT1
OUT2
OUT3
OUT4
L293D

PA[3..0]
Vs
Vs
Yellow
Blue
White
Red
Motor PAP
(6 hilos)
Vs = Vss = 5V hasta 36V

Figura 10.13. Conexin Tarjeta - L293D - Motor DC.



Ing. Javier Barriga Hoyle 38
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/********************************************************************************
PPI_10.CPP: (motor paso a paso de 6 hilos - control paso completo)
El programa permite controlar a travs de un PPI el avance en sentido horario o
antihorario pulsando las teclas (D)erecha e (I)zquierda.
Los valores digitales a enviarse al motor son 10, 9, 5 y 6 para giro horario y 6,
5, 9 y 10 para giro antihorario. Se sale del programa cuando se pulsa ESC.

Descripcin:
a) Conecte con un cable flat los 4 bits menos significativos del PA
del PPI con las entradas al driver L293D.
b) Las salidas del driver irn a las bobinas del motor de paso.
c) Escriba el programa en Visual C++ (modo consola)
d) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin base del puerto paralelo

/* Variables globales */
unsigned char Giro[4]={10,9,5,6}; // Valores de activacin de las bobinas
unsigned char car;
int i, fin, sentido;

/* Inicia programa principal */
void main (void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B,0x80); // Configura PPI, PA=PB=PC=salidas

i = 0; // Inicializa variables
fin = 0;
sentido = 1;

printf ("\n********* CONTROL DE UN MOTOR PAP *********\n");
printf (" (Modo: paso completo)\n");
printf ("\nGIRO A LA DERECHA ............ : pulse (D)\n");
printf ("\nGIRO A LA IZQUIERDA .......... : pulse (I)\n");
printf ("\nPARA SALIR DEL PROGRAMA ...... : pulse (ESC)\n\n");

while(!fin)
{
car = getch();
if(car == 27) fin = 1; // Si es ESC, sale del programa
if(car == 'D') sentido = 1; // Gira a la derecha
if(car == 'd') sentido = 1;
if(car == 'I') sentido = 0; // Gira a la izquierda
if(car == 'i') sentido = 0;
if(sentido)
{
xout(0x78, Giro[i]); // Enva dato al PA del PPI, derecha
i++;
if(i>3) i=0;
}
else
{
i--;
if(i<0) i=3;
xout(0x78, Giro[i]); // Enva dato al PA del PPI, izquierda
}
}
}


Ing. Javier Barriga Hoyle 39
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 10.11: (PPI_11.CPP) Control de un motor de paso en modo medio paso (figura 10.13).

/********************************************************************************
PPI_11.CPP: (motor paso a paso de 6 hilos - control medio paso)
El programa permite controlar a travs de un PPI el avance en sentido horario o
antihorario pulsando las teclas (D)erecha e (I)zquierda.
Los valores digitales a enviarse al motor son 10,8,9,1,5,4,6,2 para giro horario
y 2,6,4,5,1,9,8,10 para giro antihorario. Se sale del programa cuando se pulsa
ESC.

Descripcin:
a) Conecte con un cable flat los 4 bits menos significativos del PA
del PPI con las entradas al driver L293D.
b) Las salidas del driver irn a las bobinas del motor de paso.
c) Escriba el programa en Visual C++ (modo consola)
d) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin base del puerto paralelo

/* Variables globales */
unsigned char Giro[8]={10,8,9,1,5,4,6,2}; // Valores para las bobinas
unsigned char car;
int i, fin, sentido;

/* Inicia programa principal */
void main (void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B,0x80); // Configura PPI, PA=PB=PC=salidas

i = 0; // Inicializa variables
fin = 0;
sentido = 1;

printf ("\n********* CONTROL DE UN MOTOR PAP *********\n");
printf (" (Modo: medios pasos)\n");
printf ("\nGIRO A LA DERECHA ............ : pulse (D)\n");
printf ("\nGIRO A LA IZQUIERDA .......... : pulse (I)\n");
printf ("\nPARA SALIR DEL PROGRAMA ...... : pulse (ESC)\n\n");

while(!fin){
car = getch();
if(car == 27) fin = 1; // Si es ESC, sale del programa
if(car == 'D') sentido = 1; // Gira a la derecha
if(car == 'd') sentido = 1;
if(car == 'I') sentido = 0; // Gira a la izquierda
if(car == 'i') sentido = 0;
if(sentido){
xout(0x78, Giro[i]); // Enva dato al PA del PPI, derecha
i++;
if(i>7) i=0;
}
else{
i--;
if(i<0) i=7;
xout(0x78, Giro[i]); // Enva dato al PA del PPI, izquierda
}
}
}


Ing. Javier Barriga Hoyle 40
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 10.12: (PPI_12.CPP) Control de un motor de paso en modo una sola bobina (figura
10.13).

/********************************************************************************
PPI_12.CPP: (motor paso a paso de 6 hilos - control una sola bobina)
El programa permite controlar a travs de un PPI el avance en sentido horario o
antihorario pulsando las teclas (D)erecha e (I)zquierda.
Los valores digitales a enviarse al motor son 8,1,4,2 para giro horario y 2,4,1,8
para giro antihorario. Se sale del programa cuando se pulsa ESC.

Descripcin:
a) Conecte con un cable flat los 4 bits menos significativos del PA
del PPI con las entradas al driver L293D.
b) Las salidas del driver irn a las bobinas del motor de paso.
c) Escriba el programa en Visual C++ (modo consola)
d) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin base del puerto paralelo

/* Variables globales */
unsigned char Giro[4]={8,1,4,2};
unsigned char car;
int i, fin, sentido;

/* Inicia programa principal */
void main (void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B,0x80); // Configura PPI, PA=PB=PC=salidas

i = 0; // Inicializa variables
fin = 0;
sentido = 1;

printf ("\n********* CONTROL DE UN MOTOR PAP *********\n");
printf (" (Modo: una sola bobina por vez)\n");
printf ("\nGIRO A LA DERECHA ............ : pulse (D)\n");
printf ("\nGIRO A LA IZQUIERDA .......... : pulse (I)\n");
printf ("\nPARA SALIR DEL PROGRAMA ...... : pulse (ESC)\n\n");

while(!fin){
car = getch();
if(car == 27) fin = 1; // Si es ESC, sale del programa
if(car == 'D') sentido = 1; // Gira a la derecha
if(car == 'd') sentido = 1;
if(car == 'I') sentido = 0; // Gira a la izquierda
if(car == 'i') sentido = 0;
if(sentido){
xout(0x78, Giro[i]); // Enva dato al PA del PPI, derecha
i++;
if(i>3) i=0;
}
else {
i--;
if(i<0) i=3;
xout(0x78, Giro[i]); // Enva dato al PA del PPI
}
}
}


Ing. Javier Barriga Hoyle 41
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 10.13: (PPI_13.CPP) Control de la velocidad de un motor de paso en modo paso
completo (figura 10.13).

/********************************************************************************
PPI_13.CPP:(motor paso a paso de 6 hilos - control de velocidad en paso completo)
El programa permite controlar a travs de un PPI el avance en sentido horario o
antihorario pulsando las teclas (D)erecha e (I)zquierda.
Tambin podemos aumentar o disminuir la velocidad en cualquier sentido.
Los valores digitales a enviarse al motor son 8,1,4,2 para giro horario y 2,4,1,8
para giro antihorario.
Se sale del programa cuando se pulsa ESC.

Descripcin:
a) Conecte con un cable flat los 4 bits menos significativos del PA
del PPI con las entradas al driver L293D.
b) Las salidas del driver irn a las bobinas del motor de paso.
c) Escriba el programa en Visual C++ (modo consola)
d) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin base del puerto paralelo

/* Prototipos */
void velocidad (int x); // Controla velocidad del motor

/* Variables globales */
unsigned char GiroCo[8]={10,9,5,6,10,9,5,6}; // Paso completo
int Veloci[8]={1500,1200,900,600,300,200,100,50}; // max=50, min=1500

unsigned char car;
int i,v,fin,vel,tecla,sentido;

/* Inicia programa principal */
void main (void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B,0x80); // Configura PPI, PA=PB=PC=salidas

i = 0; // Inicializa variables
fin = 0;
v = 0; // Variable para la velocidad
sentido = 1;

printf ("\n****** CONTROL DE VELOCIDAD DE UN MOTOR PAP ******\n");
printf (" (Modo: paso completo)\n");
printf ("\nGIRO A LA DERECHA ............ : pulse (D)\n");
printf ("\nGIRO A LA IZQUIERDA .......... : pulse (I)\n");
printf ("\nAUMENTO DE VELOCIDAD ......... : pulse (A)\n");
printf ("\nDISMINUYE VELOCIDAD .......... : pulse (Z)\n");
printf ("\nPARA SALIR DEL PROGRAMA ...... : pulse (ESC)\n\n");

while(!fin)
{
tecla = 0;
car = getch();
car = toupper(car); // Convierte a mayscula
if(car == 27)
{
fin = 1; // Si es ESC, sale del programa


Ing. Javier Barriga Hoyle 42
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
tecla = 1;
}
if(car == 'D') sentido = 1; // Gira a la derecha
if(car == 'I') sentido = 0; // Gira a la izquierda
if(car == 'A')
{
v++; // Aumenta velocidad
if(v>7) v=7;
}
if(car == 'Z')
{
v--; // Disminuye velocidad
if(v<0) v=0;
}
vel = Veloci[v]; // Retorna factor de velocidad

while(!tecla)
{
if(sentido)
{
xout(0x78, GiroCo[i]); // Enva dato al PA del PPI
velocidad(vel); // Llama a retardo de velocidad
i++;
if(i>7) i=0;
}
else
{
i--;
if(i<0) i=7;
xout(0x78, GiroCo[i]); // Enva dato al PA del PPI
velocidad(vel); // Llama a retardo de velocidad
}
if (kbhit()) tecla=1;
}
}
} /* Fin de main */

void velocidad(int x)
{
int m, n, p;
p = x;

for(m=0; m<=p; m++)
{
for(n=0; n<=20000; n++); // Bucle de retardo
}
} /* Fin de velocidad */



















Ing. Javier Barriga Hoyle 43
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
11. Aplicaciones del TIMER 82C54
Para hacer uso del TIMER de la Tarjeta LPT ByM V2.0, tiene que entender en primer lugar como
se programa, configura y opera. Luego puede implementar y ejecutar los siguientes programas
bsicos hasta llegar al control de un motor de corriente continua usando PWM.
En la siguiente figura se observa la Tarjeta LPT y las salidas del TIMER y SWITCH a usar. Por
razones de espacio y comodidad en los programas se mostrar slo las conexiones a realizar
mediante un diagrama pequeo y claro. Los esquemticos los puede encontrar en el apndice E.
Recuerde que el Canal 0 no est disponible externamente, ya que este se puede utilizar para generar
retardos de precisin, quedando su uso interno. En consecuencia, slo estn disponibles
externamente los Canales 1 y 2 (OUT1 y OUT2). La frecuencia que alimenta al TIMER es un
oscilador de 8 MHz.

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
Power E/S TIMER SW TIMER
+
5
V
G
N
D
ON
4 3 2 1
ADC0804
L
P
T
D
B
2
5
DAC0830
P
P
I
8
2
C
5
5
P
B
P
C
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
TIMER 82C54
P
A
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
+
5
V
G
N
D
8 MHZ
POWER E/S TIMER SW TIMER

Figura 11.1. Diagrama que muestra la ubicacin del SW y E/S del TIMER en la Tarjeta.

11.1 GENERACION DE SEALES A DIFERENTES FRECUENCIAS (MODO 2 y 3)
Se recomienda observar la posicin y significado que tiene cada bit del Dipswitch (SW), as mismo
con las conexiones en la bornera azul de entrada y salida (E/S).

Programa 11.1: (TIMER_1.CPP) Uso del TIMER en modo 2 y 3.
Realice las conexiones mostradas y siga las instrucciones dadas en el programa. Como la
frecuencia de salida es alta, es necesario disponer de un osciloscopio para observar las seales.

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
Power
E/S TIMER
SW TIMER
+
5
V
G
N
D
ON
4 3 2 1
OSCILOSCOPIO

Figura 11.2. Conexin del TIMER para el programa 11.1, 11.3 y 11.4


Ing. Javier Barriga Hoyle 44
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/********************************************************************************
TIMER_1.CPP:
Este programa muestra como programar el TIMER 82C54 de la Tarjeta y obtener una
frecuencia de 1 MHz en el CH1 (modo 2) y en el CH2 (modo 3).

Descripcin:
a) Coloque los 4 bits del SW TIMER (S1) en ON, para que la frecuencia de 8 MHz
le llegue al CH1 y CH2. As mismo, los GATE de ambos estn habilitados.
b) Programe al CH1 en modo 2 a una frecuencia de 1MHz, y observe su salida OUT1
en el osciloscopio.
c) Programe al CH2 en modo 3 a una frecuencia de 1MHz, y observe su salida OUT2
en el osciloscopio.
d) Escriba el programa en Visual C++ (modo consola)
e) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin base del puerto paralelo

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

/* Configura los canales 1 y 2 */
xout(0x77, 0x74); // CH1, Modo 2, binario
xout(0x77, 0XB6); // CH2, Modo 3, binario

/* Frecuencia de entrada al CH1 = 8 MHz. Para obtener una frecuencia de 1 MHz
(T =1 s), se tiene que dividir (8 MHz/1 MHz)= 8; ==> el factor N1=0008 */
xout(0x75, 0x08); // Se enva Byte LSB al CH1
xout(0x75, 0x00); // Se enva Byte MSB al CH1

/* Frecuencia de entrada al CH2 = 8 MHz. Para obtener una frecuencia de 1 MHz
(T =1 s), se tiene que dividir (8 MHz/1 MHz)= 8; ==> el factor N1=0008 */
xout(0x76, 0x08); // Se enva Byte LSB al CH2
xout(0x76, 0x00); // Se enva Byte MSB al CH2
} /* FIN de main */



Programa 11.2: (TIMER_2.CPP) Uso del TIMER en modo 3, cascada.
Realice las conexiones mostradas y siga las instrucciones dadas en el programa.

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
Power
E/S TIMER
SW TIMER
+
5
V
G
N
D
ON
4 3 2 1
LED

Figura 11.3. Conexin del TIMER para el programa 11.2.

/********************************************************************************
TIMER_2.CPP:
Este programa muestra como conectar en cascada el CH1 y CH2 del TIMER 82C54 para
obtener una frecuencia de 1Hz en la salida del CH2.


Ing. Javier Barriga Hoyle 45
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Descripcin:

Realice las siguientes conexiones sobre los canales 1 y 2 del TIMER.
a) Coloque los bits 1 y 2 del SW TIMER (S1) en ON, para que los GATES de los 2
canales estn habilitados.
b) Coloque el bit 3 del SW TIMER (S1) en ON, para que el CH1 tenga una frecuencia
de entrada de 8 MHz.
c) Coloque el bit 4 del SW TIMER (S1) en OFF, para que la entrada CLK2 dependa de
la conexin externa (bornera azul).
d) En la bornera del TIMER unir con un cable la salida OUT1 del CH1 a la entrada
CLK2 del CH2.
e) Programe al CH1 en modo 3 a una frecuencia de 160 Hz (N1 = C350h).
f) Programe al CH2 en modo 3 a una frecuencia de 1 Hz (N2 = 00A0h), y observe la
salida OUT2 en un LED.
g) Escriba el programa en Visual C++ (modo consola)
h) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin base del puerto paralelo

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

// Configura los canales 1 y 2
xout(0x77, 0x76); // CH1, Modo 3, binario
xout(0x77, 0XB6); // CH2, Modo 3, binario

/* Frecuencia de entrada al CH1 = 8 MHz. Para obtener una frecuencia de 160 Hz.
(T = 6.25 ms), se tiene que dividir (8 MHz/160 Hz) = 50000 = C350h;
==> el factor N1 = C350h */
xout(0x75, 0x50); // Se enva Byte LSB al CH1
xout(0x75, 0xC3); // Se enva Byte MSB al CH1

/* Frecuencia de entrada al CH2 = 160 Hz. Para obtener una frecuencia de 1 Hz
(T = 1 Seg), se tiene que dividir (160 Hz/1 Hz) = 160 = 00A0h;
==> el factor N2 = 00A0h. */
xout(0x76, 0xA0); // Se enva Byte LSB al CH2
xout(0x76, 0x00); // Se enva Byte MSB al CH2

} /* FIN de main */



Programa 11.3: (TIMER_3.CPP) Uso del comando de enclavamiento.
Realice las conexiones mostradas en la figura 11.2 y siga las instrucciones dadas en el programa.
Este programa usa el comando de enclavamiento para leer el registro contador.

/********************************************************************************
TIMER_3.CPP:
Este programa muestra como usar el comando de enclavamiento para leer la cuenta
actual del registro interno de 16 bits del contador CH1.

Descripcin:
Realice las siguientes conexiones sobre el canal 1 del TIMER.
a) Coloque los bits 1 y 2 del SW TIMER en ON, para que los GATES de los 2 canales
estn habilitados.
b) Coloque los bits 3 y 4 del SW TIMER en ON, para que ambos canales reciban los
8 MHz como frecuencia de entrada.


Ing. Javier Barriga Hoyle 46
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
c) Programe al CH1 en modo 3 a una frecuencia de 5 KHz (N1 = 640h).
d) Conecte la salida del canal 1 (out1) al osciloscopio y observe la seal de
salida.
e) Escriba el programa en Visual C++ (modo consola)
f) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin base del puerto paralelo

/* Variables globales */
unsigned char CuentaLow, CuentaHigh, Ch;
unsigned int Cuenta;
const int ESC = 0x1B;

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

printf("\n******* LECTURA DEL REGISTRO CONTADOR DEL TIMER *******\n\n");
printf("\t ***** (Metodo de enclavamiento) *****\n\n");
printf("\nPara salir del programa pulse ...: (ESC)ape\n");
printf("\nPara leer la cuenta pulse .......: (L)eer\n\n\n");

/* Configura al canal 1 */
xout(0x77, 0x76); // CH1, Modo 3, binario

/* Frecuencia de entrada al CH1 = 8 MHz. Para obtener una frecuencia de 5 KHz
(T = 200 s), se tiene que dividir (8 MHz/5 KHz) = 1600 = 0640h;
==> el factor N1 = 0640h. Envo la cuenta al contador 1 */
xout(0x75, 0x40); // Se enva Byte LSB al CH1
xout(0x75, 0x06); // Se enva Byte MSB al CH1

/* Enva el comando de enclavamiento y luego lee la cuenta del contador 1 */
while(Ch != ESC)
{
Ch = getch();
Ch = toupper(Ch); // Convierte a mayscula
if(Ch == 'L')
{
xout(0x77, 0x40); // Se enva 01000000 (enclava)
CuentaLow = xin(0x75); // Lee Byte LSB
CuentaHigh = xin(0x75); // Lee Byte MSB
Cuenta = (CuentaHigh << 8) | CuentaLow; // Se forma un word
printf("Valor actual del registro contador = %d \r",Cuenta);
}
}
printf("\n\nSaliendo del programa\n\n");

} /* FIN de main */












Ing. Javier Barriga Hoyle 47
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 11.4: (TIMER_4.CPP) Uso del comando Read-Back.
Realice las conexiones mostradas en la figura 11.2 y siga las instrucciones dadas en este programa.
El comando Read-Back sirve para leer el registro contador y su estado.

/*******************************************************************************
TIMER_4.CPP:
Este programa muestra como usar el comando Read Back para leer la cuenta actual
del registro interno de 16 bits del contador CH1.

Descripcin:
Realice las siguientes conexiones sobre el canal 1 del TIMER.
a) Coloque los bits 1 y 2 del SW TIMER en ON, para que los GATES de los 2 canales
estn habilitados.
b) Coloque los bits 3 y 4 del SW TIMER en ON, para que ambos canales reciban los
8 MHz como frecuencia de entrada.
c) Programe al CH1 en modo 3 a una frecuencia de 5 KHz (N1 = 640h).
d) Conecte la salida del canal 1 (out1) al osciloscopio y observe la seal de
salida.
e) Escriba el programa en Visual C++ (modo consola)
f) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

Autor: Ing. Javier Barriga Hoyle
********************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "BymWin.h" // Librera usada por la tarjeta LPT V2.0
int Base = 0x378; // Direccin base del puerto paralelo

/* Variables globales */
unsigned char CuentaLow, CuentaHigh, Ch, Estado;
unsigned int Cuenta, ESC=27;

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

printf("\n******* LECTURA DEL REGISTRO CONTADOR DEL TIMER *******\n\n");
printf("\t ***** (Metodo de Read-Back) *****\n\n");
printf("\nPara salir del programa pulse ...: (ESC)ape\n");
printf("\nPara leer la cuenta pulse .......: (L)eer\n\n\n");

/* Configura al canal 1 */
xout(0x77, 0x76); // CH1, Modo 3, binario

/* Frecuencia de entrada al CH1 = 8 MHz. Para obtener una frecuencia de 5 KHz
(T = 200 s), se tiene que dividir (8 MHz/5 KHz) = 1600 = 0640h;
==> el factor N1 = 0640h. Envo la cuenta al contador 1 */
xout(0x75, 0x40); // Se enva Byte LSB al CH1
xout(0x75, 0x06); // Se enva Byte MSB al CH1

/* Enva el comando Read-Back y luego lee el estado y la cuenta del CH1 */
while(Ch != ESC){
Ch = getch();
Ch = toupper(Ch); // Convierte a mayscula
if(Ch == 'L')
{
xout(0x77, 0xC4); // Se enva 11000100 (Read-Back)
Estado = xin(0x75); // Lee Byte de estado
CuentaLow = xin(0x75); // Lee Byte LSB
CuentaHigh = xin(0x75); // Lee Byte MSB
Cuenta = (CuentaHigh << 8) | CuentaLow; // Se forma un word
printf("Estado (hex)= %x - Cuenta contador 1 (hex)= %x
\r",Estado,Cuenta);
}


Ing. Javier Barriga Hoyle 48
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
}
printf("\n\nSaliendo del programa\n\n");
} // Fin de main


11.2 PROGRAMAS QUE GENERA SONIDO y PWM
Programa 11.5: (TIMER_5.CPP) Simulacin de un rgano electrnico usando el teclado, parlante
interno de la PC y programando el canal 2 de su TIMER interno (Apndice B). Debe ejecutarse en
Windows 98, 2000 o XP, pero deber usar el Turbo C++ 3.0 (Borland C++ 3.0).

CLK
GATE
OUT
CANAL 0
CLK
GATE
OUT
CANAL 1
CLK
GATE
OUT
CANAL 2
VCC
R
PB0
PB1
PPI
VCC
IRQ0 - Vector 8
Refresco de
Memoria DRAM
1193180 Hz
40h - 43h
60h - 63h

Figura 11.4 Conexin del TIMER parlante en la PC.

/********************************************************************************
TIMER_5.CPP:
Este programa muestra como programar el TIMER de la PC (puerto 40h - 43h) para
generar sonido con el teclado de la computadora y simular un rgano electrnico.
Las letras vlidas son desde la "A", "B", "C", hasta la letra "G".

Descripcin:
Para programarlo se tiene que observar el circuito que controla el parlante de la
PC (figura 5.1), en la cual se aprecia que el bit 0 y bit 1 del puerto B del PPI
(direccin 60h - 63h) controlan el Gate y la habilitacin del parlante.
Las frecuencias (factores de divisin) o notas musicales son: 2080, 1881, 1648,
1560, 1390, 1212 y 1105. El programa termina cuando se pulsa ESC.

Autor: Ing. Javier Barriga Hoyle
********************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <stdio.h>
#include <conio.h>
#include <ctype.h>

#define RC_TIM 0x43 // Direccin de configuracin del TIMER
#define CH2 0x42 // Direccin del canal 2
#define PORTB 0x61 // Direccin base del PPI
#define ESC 0x1B

/* Prototipos */
void musica (int frecuencia);

/* Variables globales */
unsigned char car, PPI;
int fin, nota_musical[7]={2080,1881,1648,1560,1300,1212,1105};


Ing. Javier Barriga Hoyle 49
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
void main (void) // Inicia programa principal
{
outportb(RC_TIM,0xB6); // Configura CH2 del TIMER
PPI = inportb(PORTB); // Lee el estado del PortB del PPI
PPI = PPI|0x03; // Se hace PB0 = PB1 = 1
outportb(PORTB,PPI); // Parlante habilitado

printf("\n****** GENERACION DE SONIDO POR EL PARLANTE DE LA PC ******\n\n");
printf("\nPara salir del programa pulse ...: (ESC)ape\n");
printf("\nPara generar sonido pulse las letras desde la A hasta G:);


while(!fin){
car = getch();
car = toupper(car); // Convierte a mayscula
if (car=='A') musica(nota_musical[0]);
if (car=='B') musica(nota_musical[1]);
if (car=='C') musica(nota_musical[2]);
if (car=='D') musica(nota_musical[3]);
if (car=='E') musica(nota_musical[4]);
if (car=='F') musica(nota_musical[5]);
if (car=='G') musica(nota_musical[6]);
if (car==27) fin=1; // Es ESC?
}
PPI = inportb(PORTB); // Lee estado del PPI
PPI = PPI & 0xFC; // Se hace PB0 = PB1 = 0
outportb(PORTB,PPI); // Parlante deshabilitado
} // Fin de main

void musica (int frecuencia) // Funcin que cambia frecuencia
{
int byte_low, byte_high;
byte_low = frecuencia %100; // Se toma el resto de la divisin
byte_high = frecuencia /100; // Se toma el cociente de la divisin
outportb(CH2, byte_low); // Se enva byte_LSB al CANAL2 del Timer
outportb(CH2, byte_high); // Se enva byte_MSB al CANAL2 del Timer
}


Programa que genera sonido en el parlante conectado al TIMER de la tarjeta LPT:

Programa 11.6: (TIMER_6.CPP) Simulacin de un rgano electrnico usando las teclas de la PC
y generando el sonido en el parlante conectado al CH2 del TIMER de la tarjeta LPT BYM. Sistema
Operativo Win2000 o WinXP.

1
2
3
4
ON
+ 5V
GND
OUT2
OUT1
G2
G1
CLK2
CLK1
CLK2
CLK1
G2
G1
V
C
C
G
N
D
P
A
7
P
A
6
P
A
5
P
A
4
P
A
3
P
A
2
P
A
1
P
A
0
VCC
4K7
NPN
2N3904

Figura 11.5 Conexin del TIMER parlante externo en la Tarjeta LPT BYM.


Ing. Javier Barriga Hoyle 50
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/********************************************************************************
TIMER_6.CPP:
Este programa muestra como generar sonido usando el TIMER de la tarjeta LPT y un
parlante. Para ello, conecte en cascada el CH1 y CH2 del TIMER para obtener una
frecuencia de 1MHz en la salida del CH2.
Con la frecuencia de 1 MHz en el CH2 y el parlante conectado a la salida de este
canal, se programa para generar sonido con el teclado de la computadora y simular
un rgano electrnico.
Las letras vlidas son desde la "A", "B", "C", hasta la letra "G".
Las frecuencias (factores de divisin) o notas musicales son: 2080, 1881, 1648,
1560, 1390, 1212 y 1105.
El programa termina cuando se pulsa ESC.

Descripcin:

Realice las siguientes conexiones sobre los canales 1 y 2 del TIMER.
a) Coloque el bit 1 del SW TIMER (S1) en ON, para que el GATE1 habilite al CH1.
b) Coloque el bit 2 del SW TIMER (S1) en OFF, para que el GATE2 se controle
por software (bit0 del PORTA del PPI).
c) Coloque el bit 3 del SW TIMER (S1) en ON, para que el CH1 tenga una
frecuencia de entrada de 8 MHz.
d) Coloque el bit 4 del SW TIMER (S1) en OFF, para que la entrada CLK2 dependa de
la conexin externa (bornera azul).
e) En la bornera del TIMER unir con un cable la salida OUT1 del CH1 a la entrada
CLK2 del CH2.
f) Con un cable unir el bit0 del PORTA del PPI con la entrada GATE2 del TIMER
(bornera azul).
g) Programe al CH1 en modo 3 a una frecuencia de 1 MHz (N1 = 0008h).
h) Al CH2 se le enviar una FRECUENCIA de acuerdo a la tecla pulsada.
i) Escriba el programa en Visual C++ (modo consola).
j) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).

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

int Base = 0x378; // Direccin base del puerto paralelo

/* Prototipos */
void musica (int frecuencia);

/* Variables globales */
unsigned char car, PPI;
int fin, nota_musical[7]={2080,1881,1648,1560,1300,1212,1105};

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

/* Configura PPI con PortA como salida */
xout(0x7B, 0x80);

/* Habilita CH2, GATE2 = 1 (habilita parlante) */
xout(0x78, 0x01);

/* Configura los canales 1 y 2 */
xout(0x77, 0x76); // CH1, Modo 3, binario
xout(0x77, 0XB6); // CH2, Modo 3, binario

/* Frecuencia de entrada al CH1 = 8 MHz. Para obtener una frecuencia de 160 Hz.
(T = 6.25 ms), se tiene que dividir (8 MHz/1 MHz) = 8
==> el factor N1 = 0008h */
xout(0x75, 0x08); // se enva Byte LSB al CH1
xout(0x75, 0x00); // se enva Byte MSB al CH1


Ing. Javier Barriga Hoyle 51
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/* Cdigo que genera el sonido */
printf("\n**** GENERACION DE SONIDO POR EL PARLANTE DE LA TARJETA ****\n\n");
printf("\nPara salir del programa pulse ...: (ESC)ape\n");
printf("\nPara generar sonido pulse las letras desde la A hasta G:\n\n");

fin=0;
while(!fin){
car = getch();
car = toupper(car); // Convierte a mayscula
if (car=='A') musica(nota_musical[0]);
if (car=='B') musica(nota_musical[1]);
if (car=='C') musica(nota_musical[2]);
if (car=='D') musica(nota_musical[3]);
if (car=='E') musica(nota_musical[4]);
if (car=='F') musica(nota_musical[5]);
if (car=='G') musica(nota_musical[6]);
if (car==27) fin=1; // Es ESC?
}

/* Deshabilita CH2, GATE2 = 0 (deshabilita parlante) */
xout(0x78, 0x00); // Apaga sonido

} /* FIN de main */

void musica (int frecuencia) // Funcin que cambia frecuencia
{
int byte_low, byte_high;
byte_low = frecuencia %100; // Se toma el resto de la divisin
byte_high = frecuencia /100; // Se toma el cociente de la divisin
xout(0x76, byte_low); // Se enva byte LSB al CH2 del Timer
xout(0x76, byte_high); // Se enva byte MSB al CH2 del Timer
}


Programa 11.7: (TIMER_7.CPP) Control de la velocidad de un motor DC usando PWM a travs
del teclado de la computadora. Este programa muestra como emplear el TIMER 82C54 para
generar la modulacin por ancho de pulsos (PWM). Implemente el siguiente circuito (Ver
Apndice C para cualquier consulta adicional sobre estos CI y el Apndice E.7 para ver el
esquemtico).
PWM
1
2
3
4
ON
5
6
7 2
3
11
1,9
+5V
OUT1
OUT2
10 Sentido de giro
+ 5V
GND
OUT2
OUT1
G2
G1
CLK2
CLK1
CLK2
CLK1
G2
G1
74LS279 L293D
Motor DC



S
W

T
I
M
E
R
E
/
S

T
I
M
E
R
P
O
W
E
R
+

1 = Horario
0 = Antihorario

Figura 11.6. Conexin para control de velocidad de un motor DC usando PWM.

/********************************************************************************
TIMER_7.CPP (Control de velocidad de un Motor DC con PWM)
Este programa emplea los contadores 1 y 2 (CH1 y CH2) del TIMER 82C54 para
generar PWM (Pulse Width Modulation). Se controla la velocidad con las teclas A
(aumenta) y D (disminuye) del teclado de la computadora. Termina el programa
cuando se pulsa la tecla ESC.


Ing. Javier Barriga Hoyle 52
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Descripcin:
a) En el SW TIMER, coloque los bits de la siguiente manera:
G1(Gate 1)=ON, G2(Gate 2)=OFF, CLK1=ON (8MHz) y CLK2=ON (8 MHz).
b) Configure al CH1 en modo 2 a una frecuencia aproximada de 122 Hz.
c) Configure al CH2 en modo 5, este opera a una frecuencia variable ingresada por
teclado.
d) En la bornera azul TIMER, conecte las salidas del CH1 (OUT1) y CH2 (OUT2) al
pin5 y pin6 del 74LS279 respectivamente.
e) La salida PWM que se obtiene en el pin7 del 74LS279, conctela al pin 2 del
DRIVER L293D y de los pines 3 y 11 de ste al motor.
f) Se recomienda ver en un osciloscopio las formas de onda que se generan al
variar la velocidad en las salidas del CH1, CH2 y PWM.
g) El sentido de giro lo controlamos con el bit0 del PortB del PPI (horario = 1,
antihorario = 0).
g) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
h) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
i) Ejecute su programa y siga las instrucciones de la pantalla.

Autor: Ing. Javier Barriga Hoyle
*******************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include "BymWin.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin del puerto paralelo

/* Prototipos */
void EnvioDato(unsigned char NumCanal, unsigned char Data);
void AjusteFrecuenciaCanal2(unsigned char car);
void FrecCanal(unsigned char NumCanal);

/* Variables globales */
unsigned char Data, NumCanal, car;
unsigned int DataWord, Fin, ESC = 0x1B;

/* Inicia programa principal */
void main(void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI con todos los puertos outs

printf("\n\t********* CONTROL DE UN MOTOR DC USANDO PWM *********\n");
printf("\t\t***** Contadores 1 y 2 para PWM *****\n\n");
printf("Para salir del programa pulse ...: (ESC)\n\n");
printf("Para variar la velocidad del motor, pulse:\n");
printf("(1) Aumento de velocidad ........: (A)\n");
printf("(2) Disminuye velocidad .........: (D)\n\n");
printf("Para cambiar sentido de giro (motor parado), pulse :\n");
printf("(3) Sentido horario .............: (H)\n");
printf("(4) Sentido antihorario .........: (J)\n");
printf("Nota: En giro antihorario, las teclas de (A)umento y (D)isminuye se
invierten\n");
printf("\nVariando frecuencia de contador 2 (Contador 1 = 122 Hz)\n\n");

/* Configura CH1 en modo 2 (Rate Generator) y CH2 en modo 5 (Hardware Triggered
Strobe - monoestable) */
xout(0x77, 0x74); // CH1 = 0111 0100 (palabra de control)
xout(0x77, 0xBA); // CH2 = 1011 1010 (palabra de control)

/* Inicializa Canal 1 */
DataWord = 0xFFFF; // Fijo CH1 a frec = (8MHz/65535) = 122 Hz
FrecCanal(1); // Arranca Canal 1, para disparar al Canal 2

/* Inicializa Canal 2, para motor apagado */


Ing. Javier Barriga Hoyle 53
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
DataWord = 0x100E;
FrecCanal(2);

/* Espera que se pulse teclado para variar velocidad */
Fin = 0;
xout(0x79,1); // Giro horario (bit0_PortB = 1)

while(!Fin)
{
car = getch(); // Lee del teclado
car = toupper(car); // Convierte a mayscula
if(car == ESC) Fin = 1; // Si es ESC, sale del programa
if(car == 'H') xout(0x79,1); // Sentido horario
if(car == 'J') xout(0x79,0); // Sentido antihorario
AjusteFrecuenciaCanal2(car); // Ajusta frecuencia de canal 2
}
} // Fin de main

/*----------------------------------------------------------------------------
Funciones que trabajan con el TIMER.
-----------------------------------------------------------------------------*/
void FrecCanal(unsigned char NumCanal) // Enva 2 BYTES al canal
{
EnvioDato(NumCanal, DataWord & 0xff);
EnvioDato(NumCanal, DataWord >> 8);
}

void AjusteFrecuenciaCanal2(unsigned char car) // Calcula nueva frecuencia
{
switch(car)
{
case 'A':
if(DataWord < 0xF000)
DataWord = DataWord + 0x0FFF; // Incrementos cada 4095
break;
case 'D':
if(DataWord > 0x100F)
DataWord = DataWord - 0x0FFF; // Decrementos de 4095
break;
case 27:
printf("\n\nSaliendo del programa\n\n");
}

printf("\tDATA WORD = %u \r",DataWord);
FrecCanal(2); // Enva DataWord
} // Fin de AjusteFrecuenciaCanal2

void EnvioDato(unsigned char NumCanal, unsigned char Data) // Enva al puerto
{
switch(NumCanal)
{
case 1:
xout(0x75, Data); // Enva dato al CH1
break;
case 2:
xout(0x76, Data); // Enva dato al CH2
}
} // Fin de EnvioDato








Ing. Javier Barriga Hoyle 54
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 11.8: (TIMER_8.CPP) Control de la velocidad de un motor DC usando PWM a travs
de un teclado 4x4 hexadecimal. Implemente el siguiente circuito, para la conexin de TIMER
MOTOR revise la figura 11.4 y para la conexin de PPI TECLADO revise las figuras 10.3 y
10.4. (Para cualquier consulta adicional puede revisar el Apndice A, C y E.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
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
Power
E/S Timer
SW Timer
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
1 2 3 F
4 5 6 E
7 8 9 D
A 0 B C
Columnas
Filas
Teclado 4x4
74LS279
L293D
PWM
O
N
O
N
O
N
O
F
F
Motor DC

Figura 11.7. Conexin para control de la velocidad un motor DC usando PWM y un teclado 4x4.

/********************************************************************************
TIMER_8.CPP (Control de velocidad de un Motor DC con PWM)
Este programa emplea los contadores 1 y 2 (CH1 y CH2) del TIMER 82C54 para
generar PWM (modulacin por ancho de pulsos). Se controla la velocidad con las
teclas 1 (aumenta) y 3 (disminuye) del teclado 4x4 conectado al PortC del
PPI. Termina el programa cuando pulsa la tecla 0.

Descripcin:
a) En el SW TIMER, coloque los bits de la siguiente manera:
G1(Gate 1)=ON, G2(Gate 2)=OFF, CLK1=ON (8MHz) y CLK2=ON (8 MHz).
b) Configure al CH1 en modo 2 a una frecuencia aproximada de 122 Hz.
c) Configure al CH2 en modo 5, este opera a una frecuencia variable ingresada por
teclado.
d) En la bornera azul TIMER, conecte las salidas del CH1 (OUT1) y CH2 (OUT2) al
pin5 y pin6 del 74LS279 respectivamente.
e) La salida PWM que se obtiene en el pin7 del 74LS279, conctela al pin 2 del
DRIVER L293D y de los pines 3 y 11 de ste al motor.
f) Recomiendo ver en un osciloscopio las formas de onda que se generan al variar
la velocidad en las salidas del CH1, CH2 y PWM.
g) El sentido de giro lo controlamos con el bit0 del PortB del PPI (horario = 1,
antihorario = 0).
h) Conecte el PortC del PPI al teclado 4x4 hexadecimal (similar programa 6).
i) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
j) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
k) Ejecute su programa y siga las instrucciones de la pantalla.

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


Ing. Javier Barriga Hoyle 55
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include "BymWin.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin del puerto paralelo

/* Prototipos */
void EnvioDato(unsigned char NumCanal, unsigned char Data);
void AjusteFrecuenciaCanal2(unsigned char car);
void FrecCanal(unsigned char NumCanal);
unsigned char keyNumber(unsigned char dato);
unsigned char kbRead(unsigned char tec);

/* Variables globales */
unsigned char Data, NumCanal, car, tecla, ncol, scan, car2;
unsigned int DataWord, Fin, ESC = 0x1B;

/* Inicia programa principal */
void main(void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

xout(0x7B, 0x88); /* Configura PPI con PA=PB=OUTs (modo 0)
PC[7..4]=IN, PC[3..0]=OUT (modo 0) */

printf("\n\t********* CONTROL DE UN MOTOR DC USANDO PWM *********\n");
printf("\t\t***** Contadores 1 y 2 para PWM *****\n\n");
printf("Para salir del programa pulse ...: (ESC)\n\n");
printf("\n\nPara variar la velocidad del motor pulse en el teclado 4x4:\n");
printf("(a) Aumento de velocidad ........: (1)\n");
printf("(b) Disminuye velocidad .........: (3)\n\n");
printf("Para cambiar sentido de giro (motor parado), pulse :\n");
printf("(c) Sentido horario .............: (7)\n");
printf("(d) Sentido antihorario .........: (9)\n");
printf("Nota: En giro antihorario, las teclas de (A)umento y (D)isminuye se
invierten\n");
printf("\nVariando frecuencia de contador 2 (Contador 1 = 122 Hz)\n\n");

/* Configura CH1 en modo 2 (Rate Generator) y CH2 en modo 5 (Hardware Triggered
Strobe - monoestable) */
xout(0x77, 0x74); // CH1 = 0111 0100 (palabra de control)
xout(0x77, 0xBA); // CH2 = 1011 1010 (palabra de control)

/* Inicializa Canal 1 */
DataWord = 0xFFFF; // Fija CH1 a frec = (8MHz/65535) = 122 Hz
FrecCanal(1); // Arranca Canal 1, para disparar al Canal 2

/* Inicializa Canal 2, para motor apagado */
DataWord = 0x100E;
FrecCanal(2);

/* Espera que se pulse teclado para variar velocidad */
Fin = 0;
xout(0x79,1); // Giro horario (bit0_PortB = 1)

while(!Fin) // Espera nmero "0" para terminar
{
scan = 0xfe; // Byte de inicio de scan de teclado
ncol = 4; // Nmero de columnas a explorar
for(ncol; ncol>0; ncol--)
{
xout(0x7A, scan); // Enva dato al PortC
Sleep(10); // Retardo de 10 ms
car2 = xin(0x7a); // Lee el teclado (columna, fila)
if((scan-car2) != 0) // Se ha pulsado tecla?
{


Ing. Javier Barriga Hoyle 56
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
tecla = kbRead(car2); // Devuelve cdigo tecla vlido
if(tecla == 0) Fin = 1; // Si es 0, sale del programa
if(tecla == '7') xout(0x79,1); // Sentido horario
if(tecla == '9') xout(0x79,0); // Sentido antihorario

AjusteFrecuenciaCanal2(tecla); // Ajusta frecuencia de canal 2
Sleep(200); // Retardo para eliminar rebote
}
scan = (scan<<1) | 1; // Selecciona siguiente fila
}
}
} // Fin de main

/*----------------------------------------------------------------------------
Determina el nmero de la tecla pulsada. Realiza la operacin:
"nmero = fila * 2 + columna".
-----------------------------------------------------------------------------*/
unsigned char keyNumber(unsigned char dato)
{
unsigned char fila,col;
fila = dato & 0x0f;
switch(fila)
{
case 0x0e: fila=0; break; /* 0000.111_ */
case 0x0d: fila=1; break; /* 0000.11_1 */
case 0x0b: fila=2; break; /* 0000.1_11 */
case 0x07: fila=3; break; /* 0000._111 */
default: fila=0xff; break;
}
col = dato & 0xf0; // Lee para determinar la columna
switch(col)
{
case 0xe0: col=0; break; /* 111_.0000 */
case 0xd0: col=1; break; /* 11_1.0000 */
case 0xb0: col=2; break; /* 1_11.0000 */
case 0x70: col=3; break; /* _111.0000 */
default: col=0xff; break;
}
if((fila == 0xff)||(col == 0xff))
col = 0xff; // Retorna tecla pulsada invlida
else
col = (fila<<2) + col; /* Determina el nmero de la tecla
pulsada */
return(col);
} // fin de keyNumber

/*----------------------------------------------------------------------------
Determina el cdigo de la tecla pulsada y devuelve el cdigo ASCII.
-----------------------------------------------------------------------------*/
unsigned char kbRead(unsigned char tec)
{
/* La siguiente tabla se usa para hallar el cdigo de cada tecla */
unsigned char kbTable[16]={'1', '2', '3', 'F', /* fila 0 */
'4', '5', '6', 'E', /* fila 1 */
'7', '8', '9', 'D', /* fila 2 */
'A', '0', 'B', 'C'}; /* fila 3 */

tecla = keyNumber(tec); // Codifica tecla en fila, columna
if(tecla != 0xff) // Si solo se ha pulsado una tecla vlida,
tecla = kbTable[tecla]; // traduce desde kbTable el cdigo de tecla
return(tecla); // Retorna tecla pulsada
} /* fin de kbRead */

/*----------------------------------------------------------------------------
Funciones que trabajan con el TIMER.
-----------------------------------------------------------------------------*/
void FrecCanal(unsigned char NumCanal) // Enva 2 BYTES al canal


Ing. Javier Barriga Hoyle 57
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
{
EnvioDato(NumCanal, DataWord & 0xff);
EnvioDato(NumCanal, DataWord >> 8);
}

void AjusteFrecuenciaCanal2(unsigned char car) // Calcula nueva frecuencia
{
switch(car)
{
case '1':
if(DataWord < 0xF000)
DataWord = DataWord + 0x0FFF; // Incrementos cada 4095
break;
case '3':
if(DataWord > 0x100F)
DataWord = DataWord - 0x0FFF; // Decrementos de 4095
break;
case '0':
printf("\n\nSaliendo del programa\n\n");
}
printf("\tDATA WORD = %u \r",DataWord);
FrecCanal(2); // Enva DataWord
} // Fin de AjusteFrecuenciaCanal2

void EnvioDato(unsigned char NumCanal, unsigned char Data) // Enva al puerto
{
switch(NumCanal)
{
case 1:
xout(0x75, Data); // Enva dato al CH1
break;
case 2:
xout(0x76, Data); // Enva dato al CH2
}
} // Fin de EnvioDato




























Ing. Javier Barriga Hoyle 58
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
12. Aplicaciones del ADC 0804 (Sin interrupciones)
Para usar este Circuito Integrado dentro de la Tarjeta se tiene que incluir en cada programa como
cabecera la librera de funciones indicado en el captulo 9 (pgina 24). Como sistema operativo no
hay restricciones, puede ser Win98, Win2000 o XP.
Las seales analgicas a convertir pueden provenir de diversas fuentes tales como censores de
temperatura, posicin, velocidad, presin, flujo, etc. Los siguientes programas en Lenguaje C,
muestran como utilizar el ADC en algunas aplicaciones bsicas, para ello hemos empleado un
potencimetro 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 podrn usarlo en
cualquier aplicacin real.
Para obtener lecturas ms precisas, es necesario que Vref (voltaje de referencia) del ADC, se ponga
en la mitad del voltaje VCC (Vref = 2.5 voltios).


Programa 12.1: (ADC_1.CPP) Tcnica de espera para leer el voltaje de un potencimetro.
Realice la siguiente conexin y siga las instrucciones dadas en este programa.

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
IRQ7
LIBRE ADC
J10
3 2 1
+
5
V
G
N
D
8 MHZ
+5V
Salida digital (8 leds)
Power E/S Timer SW Timer
Unir con el jumper el pin3 y el
pin2 de J10, para que la lnea
INTR del ADC se conecte
con el pin 10 del conector
DB25 (bit 6 del puerto 379h).
5 K
+5V
1 K 1 K

Figura 12.1. Conexin Tarjeta - ADC - Potencimetro - PPI - Leds.

/*******************************************************************************
ADC_1.CPP: (Tcnica de espera)
Este programa muestrea un voltaje analgico (0 V - 5 V) en un potencimetro y lo
muestra en pantalla, adems lo enva al PortA (puede ser B o C) del PPI el dato
en binario para ser visualizado en 8 leds. Toma 10 muestras a intervalos de 2 seg

Descripcin:
a) Conecte 8 leds al PortA del PPI.
b) Implemente un circuito con un potencimetro entre 0 y 5V. El punto central de
ste conctelo al terminal (VI+) de la bornera azul o al molex.
c) El terminal VI-, conctelo a tierra;
d) El terminal AGND conctelo a tierra.
e) El terminal VREF puede conectarse a otro potencimetro con un voltaje de


Ing. Javier Barriga Hoyle 59
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en la
toma de muestras.
f) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
g) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
h) Ejecute su programa.

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

int Base = 0x378; // Direccin del puerto paralelo

/* 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* Vare el potencimetro 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 conversin
Sleep(1); // Espera 1 ms para que termine conversin
dato_adc = xin(0x6C); // Lee dato del ADC
xout(0x78, dato_adc); // Enva al PortA del PPI
voltios = ((float)dato_adc*5)/255; // Convierte a flotante

/* Muestra en pantalla en formato decimal y binario el dato convertido */
printf("Valor ADC = %0.4f voltios\n", voltios); // 4 decimales
print_binario(dato_adc);
Sleep(2000); // Espera 2 seg para tomar nueva muestra
}
} // Fin de main















Ing. Javier Barriga Hoyle 60
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 12.2: (ADC_2.CPP) Tcnica de polling para leer el voltaje de un potencimetro.
Utilice la conexin del programa 12.1 (figura 12.1) y siga las instrucciones dadas en este programa.

/*******************************************************************************
ADC_2.CPP: (Tcnica de polling o encuesta)
Este programa muestrea un voltaje analgico (0 V - 5 V) en un potencimetro y lo
muestra en pantalla, adems lo enva al PortA (puede ser B o C) del PPI el dato
en binario para ser visualizado en 8 leds. Toma 10 muestras a intervalos de 2 seg

Descripcin:
a) Conecte 8 leds al PortA del PPI.
b) Implemente un circuito con un potencimetro entre 0 y 5V. El punto central de
ste conctelo al terminal (VI+) de la bornera azul o al molex.
c) El terminal VI-, conctelo a tierra;
d) El terminal AGND conctelo a tierra.
e) El terminal VREF puede conectarse a otro potencimetro con un voltaje de
salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en la
toma de muestras.
f) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
g) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
h) Ejecute su programa.

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

int Base = 0x378; // Direccin del puerto paralelo

/* Variables globales */
unsigned char dato_adc;
int i, flag_int;
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 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* Vare el potencimetro 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 conversin

while (flag_int != 0x40) // INTR = 0? o termin conversin?
flag_int = _inp(Base+1)&0x40; /* Aqu no se usa xin, porque la lnea
IRQ7 va directamente al puerto 379h */
dato_adc = xin(0x6C); // Termin conversin, lee dato del ADC
xout(0x78, dato_adc); // Enva al PortA del PPI
voltios = ((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


Ing. Javier Barriga Hoyle 61
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
print_binario(dato_adc);
printf("\n); // Cambia lnea
Sleep(2000); // Espera 2 seg para tomar nueva muestra
}
} // Fin de main



Programa 12.3: (ADC_3.CPP) Tcnica de polling para leer el voltaje de un potencimetro y
mostrarlo en un LCD. Implemente el circuito mostrado y luego siga las instrucciones dadas en este
programa.

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
IRQ7
LIBRE ADC
J10
3 2 1
+
5
V
G
N
D
8 MHZ
Power E/S Timer SW Timer
LCD 2x16
HD 44780
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
LEYENDA:
D[7..0] Bus de datos
En Seal de habilitacin
R/W Seleccin de lectura (0) o escritura (1)
Rs Selector de registro (0 = Reg. Inst, 1 = Reg. Datos)
VCC Tensin de alimentacin, 5 V.
GND Entrada de alimentacin, 0 V.
VLC Entrada de control de constraste (unir al potenciometro)
+5V
5 K
+5V
1 K 1 K

Figura 12.2. Conexin Tarjeta - ADC - Potencimetro - PPI - LCD.

/*******************************************************************************
ADC_3.CPP: (Tcnica del Polling, LCD 2x16: Modo a 4 bits)
Este programa muestrea un voltaje analgico (0 V - 5 V) en un potencimetro y lo
muestra en un LCD conectado al PortA del PPI. El programa captura 20 muestras a
intervalos de 2 segundos.

Descripcin:
a) Las conexiones PPI - LCD es:
PORTA del PPI: PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0
LCD: D7 D6 D5 D4 EN RS X X
(La seal WR se conecta a tierra; este programa solo escribe en el LCD).
b) Implemente un circuito con un potencimetro entre 0 y 5V. El punto central de
ste conctelo al terminal (VI+) de la bornera azul o al molex.
c) El terminal VI-, conctelo a tierra;
d) El terminal AGND conctelo a tierra.
e) El terminal VREF puede conectarse a otro potencimetro con un voltaje de
salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en la
toma de muestras.
f) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
g) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
h) Ejecute su programa.

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


Ing. Javier Barriga Hoyle 62
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
#include <conio.h>
#include <stdio.h>
#include "BymWin.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin del puerto paralelo

#define CONTROL 0 // Constante para el display LCD
#define DATO 1 // Constante para el display LCD
#define DISPLAY_ON 0x0E // Display ON, cursor ON, blink OFF
#define BORRAR_LCD 0x01
#define UCHAR unsigned char

/* Prototipos LCD */
void PutcharLCD(UCHAR direc, UCHAR dato);
void BorraLCD(void);
void InitLCD(void);
void GotoxyLCD(UCHAR fila, UCHAR columna);
void PrintNumLCD(float numero, UCHAR fila, UCHAR columna);

/* Mensajes a enviar */
char Mensaje1[30] = {"TARJETA LPT BYM V2.0"}; // Ambas filas
char Mensaje2[20] = {" LECTURA DE ADC "}; // Fila 1
char Mensaje3[10] = {"X(vol)="}; // Fila 2

/* Variables globales */
unsigned char dato_adc;
int i, j, m, flag_int, num, divisor, cociente, residuo;
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)
InitLCD(); // Inicializa LCD

printf("\t****************************************************\n");
printf("\t* LECTURA DE UNA SENAL ANALOGICA USANDO EL ADC0804 *\n");
printf("\t* *\n");
printf("\t* Captura 20 muestras a intervalos de 2 segundos, *\n");
printf("\t* lo imprime en pantalla y en el LCD de 2x16. *\n");
printf("\t* Varie el potenciometro para muestras diferentes. *\n");
printf("\t****************************************************\n\n");

/* Enva mensaje1 a ambas filas del LCD */
while(j<20)
{
GotoxyLCD(1,2); // Posiciona cursor en la fila 1, columna 3
for(j=0; j<11; j++)
{
PutcharLCD(DATO, Mensaje1[j]); // Enva mensaje LCD
Sleep(200);
}
GotoxyLCD(2,4); // Posiciona cursor en la fila 2, columna 5
for(j=12; j<20; j++){
PutcharLCD(DATO, Mensaje1[j]); // Enva mensaje LCD
Sleep(200);
}
}
Sleep(2000); // Espera 2 segundos
BorraLCD();

/* Enva mensaje2 a la fila 1 del LCD */
for(j=0; j<16; j++){
PutcharLCD(DATO, Mensaje2[j]); // Enva mensaje LCD
Sleep(200);
}


Ing. Javier Barriga Hoyle 63
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/* Enva mensaje3 a la fila 2 del LCD */
GotoxyLCD(2,1); // Posiciona cursor al inicio de la fila 2
for(j=0; j<7; j++){
PutcharLCD(DATO, Mensaje3[j]); // Enva mensaje LCD
Sleep(200);
}
/* Proceso de lectura de 20 muestras del ADC a intervalos de 2 seg */
for(m=0; m<20; m++)
{
xout(0x6C, 0x00); // Inicia conversin

while (flag_int != 0x40) // INTR = 0? o termin conversin?
flag_int = _inp(Base+1)&0x40; /* Aqu no se usa xin, porque la lnea
IRQ7 va directamente al puerto 379h */

dato_adc = xin(0x6C); // Termin conversin, lee dato del ADC
voltios = ((float)dato_adc*5)/255; // Convierte a flotante

/* Muestra en pantalla y LCD en formato decimal el dato convertido */
printf("Valor ADC (%d) = %0.4f voltios\n",m,voltios); // 4 decimales
PrintNumLCD(voltios,2,9); // Imprime voltaje en LCD
Sleep(2000); // Espera 2 seg para tomar nueva muestra
}
} // Fin de main

/*-------------------------------------------------------------------------------
Funcin: void InitLcd(void)
Inicializa el display LCD.
-------------------------------------------------------------------------------*/
void InitLCD(void)
{
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
/* RS debe ser estable antes del flanco de subida de EN */
xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(5); // Demora superior a 4,1 ms

xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(1); // Demora superior a 100 s

xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(1); // Demora superior a 100 s
/* Selecciona interface de 4 bits */
xout(0x78, 0x28); // DB[7..4] EN RS X X
// 0010 1 0 0 0
xout(0x78, 0x20); // DB[7..4] EN RS X X
// 0010 0 0 0 0
/* Tras esta inicializacin el display queda en modo 4 bits */
Sleep(1); // Demora superior a 100 s
BorraLCD(); // Borra el LCD y lleva cursor al origen
} // FIN DE InitLcd

/*-------------------------------------------------------------------------------
Funcin: void PutcharLcd(UCHAR direc, UCHAR dato)
Envia al display LCD un "dato". Si:
direc = 0, se accede al registro de instrucciones
direc = 1, se accede al registro de datos
-------------------------------------------------------------------------------*/


Ing. Javier Barriga Hoyle 64
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
void PutcharLCD(UCHAR direc, UCHAR dato)
{
UCHAR temp, temp2;
temp2 = 0x08; // Para activar EN
if (direc == DATO){ // Es instruccin o dato?
temp2 |= 0x04; // Selecciona Dato/Control con RS
xout(0x78, 0x04); // DB[7..4] EN RS X X
} // 0000 0 1 0 0
else
xout(0x78, 0x00); // DB[7..4] EN RS X X
// 0000 0 0 0 0
/* RS debe ser estable antes del flanco de subida de EN */

/* Primero se enva el nibble alto */
temp = (dato & 0xf0) | temp2;
xout(0x78, temp); // Manda nibble alto con EN = 1
temp &= 0xf5;
xout(0x78, temp); // Desactiva EN

/* Despus se manda el nibble bajo */
temp = (dato << 4) | temp2;
xout(0x78, temp); // Manda nibble bajo con EN = 1
temp &= 0xf5;
xout(0x78, temp); // Desactiva EN
Sleep(1);
} // FIN DE PutcharLcd

/*-------------------------------------------------------------------------------
Funcin: void BorraLCD(void)
Establece control del LCD, Borra el LCD, establece Modo de entrada, y coloca
el cursor en el origen.
-------------------------------------------------------------------------------*/
void BorraLCD(void)
{
PutcharLCD(CONTROL, DISPLAY_ON); // Display on, cursor ON, blink off
PutcharLCD(CONTROL, BORRAR_LCD); // Borra el Display
PutcharLCD(CONTROL, 0x06); // Incremento automtico de AC al escribir
PutcharLCD(CONTROL, 0x02); // Cursor en la esquina izquierda
} // FIN DE BorraLCD

/*-------------------------------------------------------------------------------
Funcin: void GotoxyLCD(UCHAR fila, UCHAR columna)
Posiciona el cursor en la posicin especificada por fila, columna.
Si alguna de las coordenadas es invalida no se hace nada.
Coordenadas validas: fila = 1..2, columna = 1..16
-------------------------------------------------------------------------------*/
void GotoxyLCD(UCHAR fila, UCHAR columna)
{
UCHAR pos_fila, cursor;
if((fila<1 || fila>2) || (columna<1 || columna>16))
return;

switch(fila)
{
case 1:
pos_fila = 0x80; // Posicin de memoria 00h ---> 27h
cursor = pos_fila + columna;
PutcharLCD(CONTROL, cursor); // Posiciona cursor
break;
case 2:
pos_fila = 0xC0; // Posicin de memoria 40h ---> 67h
cursor = pos_fila + columna;
PutcharLCD(CONTROL, cursor); // Posiciona cursor
break;
}
}



Ing. Javier Barriga Hoyle 65
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/********************************************************************************
Funcion: void PrintNumLCD(float numero, UCHAR fila, UCHAR columna)
Imprime en el LCD un nmero en punto flotante con el formato
(x.xxxx), en la posicin especificada por fila y columna.
********************************************************************************/
void PrintNumLCD(float numero, UCHAR fila, UCHAR columna)
{
unsigned int cuenta;
GotoxyLCD(fila, columna); // Posiciona cursor al inicio de la fila 2

/* Se imprime en el LCD */
num = (int)( voltios * 10000 / 1);
cociente = num / 10000; // Divide y toma la parte entera
residuo = num % 10000; // Divide y toma el residuo
PutcharLCD(DATO, cociente + 0x30); // Convierte a ASCII e imprime en LCD
PutcharLCD(DATO, '.'); // Imprime punto decimal
divisor = 1000;
for(cuenta=2; cuenta<6; cuenta++){
cociente = (char)(residuo / divisor); // Divide y toma la parte entera
residuo = residuo % divisor; // Divide y toma el residuo
PutcharLCD(DATO, cociente + 0x30); // Convierte a ASCII e imprime en LCD
divisor = divisor /10;
}
}



Programa 12.4: (ADC_4.CPP) Control de la velocidad de un motor DC usando un potencimetro
y PWM. Para la conexin TIMER Motor ver Apndice E.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
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
Power
E/S Timer
SW Timer
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
74LS279
L293D
PWM
O
N
O
N
O
N
O
F
F
Motor DC
+5V
5 K
+5V
1 K 1 K

Figura 12.3. Conexin Tarjeta - ADC - Potencimetro - TIMER - Motor DC.


Ing. Javier Barriga Hoyle 66
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
El programa lee a travs del ADC el valor dado por un potencimetro y lo enva al TIMER para
generar la seal PWM, cuando el valor sea 0 el motor est parado y a medida que se aumenta ese
valor, el motor empezar a girar en sentido horario alcanzando la mxima velocidad cuando sea
255 o FFh. Siga las instrucciones dadas en este programa.

/********************************************************************************
ADC_4.CPP: (Tcnica del Polling y PWM)
Este programa controla la velocidad de un motor DC a travs de un potencimetro
conectado al ADC0804. El valor obtenido se enva al TIMER para generar la seal
PWM, que es la que regula la velocidad del motor.

Descripcin:
a) En el SW TIMER, coloque los bits de la siguiente manera:
G1(Gate 1)=ON, G2(Gate 2)=OFF, CLK1=ON (8MHz) y CLK2=ON (8 MHz).
b) Configure al CH1 en modo 2 a una frecuencia aproximada de 122 Hz.
c) Configure al CH2 en modo 5, este opera a una frecuencia variable ingresada por
el potencimetro conectado al ADC.
d) En la bornera azul TIMER, conecte las salidas del CH1 (OUT1) y CH2 (OUT2) al
pin5 y pin6 del 74LS279 respectivamente.
e) La salida PWM que se obtiene en el pin7 del 74LS279, conctela al pin 2 del
DRIVER L293D y de los pines 3 y 11 de ste al motor.
f) Recomiendo ver en un osciloscopio las formas de onda que se generan al variar
la velocidad en las salidas del CH1, CH2 y PWM.
g) Cree un proyecto en Visual C++ (modo consola) y escriba el programa.
h) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5).
i) Ejecute su programa y siga las instrucciones de la pantalla.

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

int Base = 0x378; // Direccin del puerto paralelo

/* Prototipos */
void EnvioDato(unsigned char NumCanal, unsigned char Data);
void AjusteFrecuenciaCanal2(unsigned char car);
void FrecCanal(unsigned char NumCanal);

/* Variables globales */
unsigned char Data, NumCanal, car, tecla, ncol, scan, car2;
unsigned int DataWord, DatoADC, Flag, Fin, ESC = 0x1B;

/* Inicia programa principal */
void main(void)
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0

printf("\n\t********* CONTROL DE UN MOTOR DC USANDO PWM *********\n\n");
printf("\t\t***** Contadores 1 y 2 para PWM *****\n\n");
printf("\nPara salir del programa pulse ...: (ESC)\n");
printf("\n\nPara variar la velocidad del motor mueva el potenciometro\n");
printf("\n(1) Posicion inicial (0): Motor parado\n");
printf("\n(2) Posicion final (255): Motor velocidad maxima\n\n");
printf("\nVariando frecuencia de contador 2 (Contador 1 = 122 Hz)\n\n");

/* Configura CH1 en modo 2 (Rate Generator) y CH2 en modo 5 (Hardware Triggered
Strobe - monoestable) */
xout(0x77, 0x74); // CH1 = 0111 0100 (palabra de control)
xout(0x77, 0xBA); // CH2 = 1011 1010 (palabra de control)

/* Inicializa Canal 1 */
DataWord = 0xFFFF; // Fija CH1 a frec = (8MHz/65535) = 122 Hz
FrecCanal(1); // Arranca Canal 1, para disparar al Canal 2


Ing. Javier Barriga Hoyle 67
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/* Espera que se vare el potencimetro para variar velocidad */
Fin = 0;
while(!Fin) // Espera ESC para terminar
{
/* Proceso de lectura de muestras del ADC a intervalos de 250 ms */
xout(0x6C, 0x00); // Inicia conversin
while (Flag != 0x40) // INTR = 0? o termin conversin?
Flag = _inp(Base+1)&0x40; /* Aqu no se usa xin, porque la lnea
IRQ7 va directamente al puerto 379h */

DatoADC = xin(0x6C); // Termin conversin, lee dato del ADC
AjusteFrecuenciaCanal2(DatoADC); // Ajusta frecuencia de canal 2
Sleep(250); // Retardo de 250 ms

if(kbhit()) // Se puls tecla?
{
car = getch(); // SI, entonces lee el teclado
if(car == 0x1B) Fin = 1; // Si es ESC, sale del programa
}
}
} // Fin de main

/*----------------------------------------------------------------------------
Funciones que trabajan con el TIMER.
-----------------------------------------------------------------------------*/
void FrecCanal(unsigned char NumCanal) // Enva 2 BYTES al canal
{
EnvioDato(NumCanal, DataWord & 0xff);
EnvioDato(NumCanal, DataWord >> 8);
}

void AjusteFrecuenciaCanal2(unsigned char muestra) // Calcula nueva frecuencia
{
DataWord = 1000 + muestra*250; // Incrementos cada 250*DatoAdc
printf("\tDATA WORD = %u \r",DataWord);
FrecCanal(2); // Enva DataWord
} // Fin de AjusteFrecuenciaCanal2

void EnvioDato(unsigned char NumCanal, unsigned char Data) // Enva al puerto
{
switch(NumCanal)
{
case 1:
xout(0x75, Data); // Enva dato al CH1
break;
case 2:
xout(0x76, Data); // Enva dato al CH2
}
} // Fin de EnvioDato


















Ing. Javier Barriga Hoyle 68
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
13. Aplicaciones con interrupciones: Pulsadores, ADC0804, TIMER, etc.
Para poder entender los programas que usan interrupciones, si UD no tiene conocimientos previos
es necesario que se revise el Apndice D.

13.1 Aplicaciones con interrupciones: Sistema Operativo Win2000 o WinXP.
Con estos Sistemas Operativos (SO), slo podemos hacer uso de la lnea de interrupcin IRQ0, la
IRQ7 del puerto paralelo est bloqueada por restriccin del SO. Adems es imprescindible tener
instalado el Borland C++ 3.0 para poder ejecutar los siguientes programas.


Programa 13.1: (IRQO_1.CPP)
/********************************************************************************
IRQ0_1.CPP
Este programa muestra como contar las interrupciones generadas por la IRQ0
conectada al canal 0 del TIMER de la PC. La frecuencia de entrada al CH0 del
TIMER de la PC es de 1.193.180 Hz, el cual es dividida entre 65,535 para
producir 18.2 Hz (interrupciones/seg). Se saldr del programa cuando se halla
transcurrido 5 segundos.

Descripcin:
a) Para producir 5 seg, se deber contar aproximadamente 91 interrupciones.
b) Cargue el programa con el TURBO C++ 3.0.
c) Compile con ALT + F9.
d) Ejecute con CRTL + F9.

Autor: Ing. Javier Barriga Hoyle
********************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos */
void interrupt (*old_timer)(...); // Vector antiguo
void interrupt new_timer(...); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Declaracin de variables globales */
unsigned char oldimr, newimr;
int num_int;

void main(void) // Inicia programa principal
{
clrscr(); // Borra pantalla
instala_imr_vector(); // Modifica IMR e instala vector
num_int = 0; // Contador de interrupciones = 0
while(num_int <= 91) // Cuenta 5 segundos (91 interrupciones)
{
gotoxy(25,5); // (Columna, fila)
printf("Interrupciones IRQ0: %d\r", num_int);
}
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main


Ing. Javier Barriga Hoyle 69
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
void interrupt new_timer(...) // Rutina de servicio de interrupcin
{
old_timer(); // Llama a la rutina antigua
num_int++; // Incrementa cada vez que ocurre una INTR
outportb(0x20,0x20); // Enva el EOI
}

void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = oldimr & 0xFE; // Activa IRQ0 = 1111 1110
outportb(0x21,newimr);
old_timer = getvect(0x08); // Lee vector original
setvect(0x08, new_timer); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable();
setvect(0x08, old_timer); // Restaura vector original
outportb(0x21,oldimr); // Restaura IMR original
enable();
}


Programa 13.2: (IRQO_2.CPP)
/********************************************************************************
IRQ0_2.CPP
Este programa muestra como utilizar las interrupciones generadas por la IRQ0
para producir retardos. En este caso, se har desplazar un bit de derecha a
izquierda y viceversa a intervalos de 200 ms. Los LEDS se conectan al PortA del
PPI. El programa termina cuando se pulse ESC.

Descripcin:
a) Con un cable flat, conecte 8 LEDS al PortA del PPI.
b) Para producir 200 ms, se deber contar aproximadamente 4 interrupciones.
c) Cargue el programa con el TURBO C++ 3.0.
d) Compile con ALT + F9.
e) Ejecute con CRTL + F9.

Autor: Ing. Javier Barriga Hoyle
********************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos */
void interrupt (*old_timer)(...); // Vector antiguo
void interrupt new_timer(__CPPARGS); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Variables globales */
unsigned char oldimr, newimr, dato;
int num_int, Fin, mseg200, sentido;


Ing. Javier Barriga Hoyle 70
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
void main(void) // Inicia programa principal
{
clrscr(); // Borra pantalla
inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI como PA = PB = PC = outs

printf("\t***********************************************************\n");
printf("\t* PROGRAMA QUE DESPLAZA UN BIT DE DERECHA A IZQUIERDA Y *\n");
printf("\t* VICEVERSA A INTERVALOS DE 200 ms POR EL PORTA DEL PPI *\n");
printf("\t* *\n");
printf("\t* El retardo de 200 ms se realiza usando la interrupcion *\n");
printf("\t* IRQ0 (4 interrupciones = 200 ms) *\n");
printf("\t***********************************************************\n\n");

printf("Por favor, espere mientras se ejecuta el programa\n\n");
printf("Para salir, pulse ESC(ape)");

instala_imr_vector(); // Modifica el IMR e instala la RSI
num_int = 0; // Inicializa contador de interrupciones
mseg200 = 0; // Contador de cada 200 ms
Fin = 0;
dato = 0x01;
sentido = 0; // Sentido: (0, izquierda) o (1, derecha)
xout(0x78, dato); // Inicializa desplazamiento

/* Espera que se genere las interrupciones */
while(!Fin) // Espera ESC para terminar
{
if(mseg200==1)
{
if(sentido==0) { // Desplaza a la izquierda
mseg200 = 0;
dato = dato << 1;
xout(0x78, dato); // Enva a los 8 leds del PortA del PPI
if(dato==0x80) sentido=1; // Cambia de sentido (derecha)
}
else {
mseg200 = 0;
dato = dato >> 1;
xout(0x78, dato); // Enva a los 8 leds del PortA del PPI
if(dato==0x01) sentido=0; // Cambia de sentido (izquierda)
}
}

if(kbhit()) // Se puls tecla?
{
car = getch(); // SI, entonces lee el teclado
if(car == 0x1B) Fin = 1; // Si es ESC, sale del programa
}
}
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main

void interrupt new_timer(...) // Rutina de servicio de interrupcin
{
old_timer(); // Llama a la rutina antigua
num_int++; // Incrementa cada vez que ocurre una INTR
if(num_int == 4) { // Cuatro interrupciones?
mseg200 = 1;
num_int = 0;
}
outportb(0x20,0x20); // Enva el EOI
}

void instala_imr_vector(void)
{


Ing. Javier Barriga Hoyle 71
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = oldimr & 0xFE; // Activa IRQ0 = 1111 1110
outportb(0x21,newimr);
old_timer = getvect(0x08); // Lee vector original
setvect(0x08, new_timer); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable();
setvect(0x08, old_timer); // Restaura vector original
outportb(0x21,oldimr); // Restaura IMR original
enable();
}


Programa 13.3: (IRQO_3.CPP)
/********************************************************************************
IRQ0_3.CPP
Este programa muestra como utilizar las interrupciones generadas por la IRQ0
para producir retardos. En este caso, la CPU siempre estar desplazando un bit
de derecha a izquierda y viceversa a intervalos de 100 ms. Los LEDS se conectan
al PortA del PPI. Adems, cada 1 seg se leer el voltaje analgico dado por el
potencimetro conectado al ADC0804. El programa termina cuando se alcance las 20
muestras.

Descripcin:
a) Con un cable flat, conecte 8 LEDS al PortA del PPI.
b) Conecte un potenciometro al ADC (Realice las conexiones de la figura 12.1)
c) Para producir 100 ms, se deber contar aproximadamente 2 interrupciones.
d) Para producir 1 seg, se deber contar aproximadamente 18 interrupciones.
e) Cargue el programa con el TURBO C++ 3.0.
f) Compile con ALT + F9.
g) Ejecute con CRTL + F9.

Autor: Ing. Javier Barriga Hoyle
********************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos */
void interrupt (*old_timer)(...); // Vector antiguo
void interrupt new_timer(__CPPARGS); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Variables globales */
unsigned char oldimr, newimr, dato, dato_adc;
int num_int_leds, num_int_adc, muestras, mseg100, seg1, flag_adc, sentido;
float voltios;

void main(void) // Inicia programa principal
{
clrscr(); // Borra pantalla


Ing. Javier Barriga Hoyle 72
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI como PA = PB = PC = outs

printf("\t************************************************************\n");
printf("\t* PROGRAMA QUE DESPLAZA UN BIT DE DERECHA A IZQUIERDA Y *\n");
printf("\t* VICEVERSA A INTERVALOS DE 100 ms POR EL PORTA DEL PPI. *\n");
printf("\t* ADEMAS, CADA 1 SEG CAPTURA UN DATO ANALOGICO DEL ADC *\n");
printf("\t* *\n");
printf("\t* El retardo de 100 ms se realiza usando la interrupcion *\n");
printf("\t* IRQ0 (2 interrupciones = 100 ms) *\n");
printf("\t************************************************************\n\n");

instala_imr_vector(); // Modifica el IMR e instala la RSI
num_int_leds = 0; // Contador de interrupciones de LEDS
num_int_adc = 0; // Contador de interrupciones de ADC
mseg100 = 0; // Contador de cada 100 ms
seg1 = 0; // Contador de cada 1 seg
muestras = 0; // Contador de nmero de muestras tomadas
dato = 0x01;
sentido = 0; // Sentido: (0, izquierda) o (1, derecha)
xout(0x78, dato); // Inicializa desplazamiento

/* Espera que se genere las interrupciones */
while(muestras <= 20) // Espera 20 muestras para terminar
{
if(mseg100==1) // Espera 100 ms para desplazar un bit
{
if(sentido==0) { // Desplaza a la izquierda
mseg100 = 0;
dato = dato << 1;
xout(0x78, dato); // Enva a los 8 leds del PortA del PPI
if(dato==0x80) sentido=1; // Cambia de sentido (derecha)
}
else {
mseg100 = 0;
dato = dato >> 1;
xout(0x78, dato); // Enva a los 8 leds del PortA del PPI
if(dato==0x01) sentido=0; // Cambia de sentido (izquierda)
}
}

if(seg1==1) // Espera 1 seg para tomar dato del ADC
{
while (flag_adc != 0x40) // INTR = 0? o termin conversin?
flag_adc = inportb(Base+1)&0x40; /* Aqu no se usa xin, porque la lnea
IRQ7 va directamente al puerto 379h */

dato_adc = xin(0x6C); // SI, lee dato del ADC
voltios = ((float)dato_adc*5)/255; // Convierte a flotante
printf("Valor ADC (%d) = %0.4f voltios\n",muestras,voltios);
seg1 = 0;
muestras++;
}
}
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main

void interrupt new_timer(...) // Rutina de servicio de interrupcin
{
old_timer(); // Llama a la rutina antigua
num_int_leds++; // Incrementa cada vez que ocurre una INTR
num_int_adc++; // Incrementa cada vez que ocurre una INTR
if(num_int_leds == 2) { // Dos interrupciones?
mseg100 = 1;
num_int_leds = 0;
}


Ing. Javier Barriga Hoyle 73
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
if(num_int_adc == 18) { // Dieciocho interrupciones?
xout(0x6C, 0x00); // Captura dato e inicia conversin
seg1 = 1;
num_int_adc = 0;
}
outportb(0x20,0x20); // Enva el EOI
}

void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = oldimr & 0xFE; // Activa IRQ0 = 1111 1110
outportb(0x21,newimr);
old_timer = getvect(0x08); // Lee vector original
setvect(0x08, new_timer); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable();
setvect(0x08, old_timer); // Restaura vector original
outportb(0x21,oldimr); // Restaura IMR original
enable();
}







































Ing. Javier Barriga Hoyle 74
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
13.2 Aplicaciones con interrupciones: Sistema Operativo Win98.
Con este Sistema Operativo, podemos usar las lneas de interrupciones IRQ0 y IRQ7 sin ningn
problema. Similar al caso anterior, es imprescindible tener instalado el Borland C++ 3.0 para
poder ejecutar los siguientes programas.

Programa 13.4: (IRQ7_1.CPP) Cuenta las interrupciones producidas por un pulsador sin rebotes
conectado a la lnea IRQ7. El programa termina cuando se alcance 10 interrupciones.
Realice la siguiente conexin.

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
IRQ7
LIBRE ADC
J10
3 2 1
+
5
V
G
N
D
8 MHZ
Salida digital (8 leds)
Power E/S Timer SW Timer
NOTA:
Quite el jumper del conector
J10, para dejar libre el pin3
(ADC) y el pin2 (IRQ7).
Ahora la salida del pulsador
conctelo al pin 1 para generar
interrupciones.


+5V
S1
START
+ C1
10uF
R2
10K
R1
330
PIN 1
74HC14

Figura 13.1. Conexin Tarjeta - Pulsador sin rebotes, para generar interrupciones.

Observar que cada vez que pulsa S1 (START), generar una interrupcin, incrementa el contador
y lo visualizar en la pantalla (sugerencia: analice el programa y trate de entenderlo para futuras
aplicaciones).

/********************************************************************************
IRQ7_1.CPP
Este programa cuenta las interrupciones generadas externamente por un pulsador
conectado a la lnea IRQ7 del puerto paralelo de la computadora, las imprime en
pantalla y las enva a 8 leds conectados al PortA del PPI de la tarjeta LPT V2.0

Descripcin:
a) Conecte un pulsador sin rebote a la lnea IRQ7 (pin 1 del J10).
b) Conecte 8 leds al PortA del PPI.
c) Cada vez que se active el pulsador, generara una interrupcin a la CPU.
d) El programa termina cuando se alcance 10 interrupciones.
e) Cargue el programa Turbo C++ 3.0 y abra el programa INTE_1.CPP, luego compile
con ALT+F9, y ejecute el programa con CTRL+F9.



Ing. Javier Barriga Hoyle 75
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Autor: Ing. Javier Barriga Hoyle
********************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos */
void interrupt (*old_irq7)(...); // Vector antiguo
void interrupt new_irq7(...); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Variables globales */
unsigned char oldimr, newimr;
int num_int;

void main(void) // Inicia programa principal
{
clrscr(); // Borra pantalla
inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI como PA = PB = PC = outs

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 tambin en el PortA del PPI. *\n");
printf("\t*********************************************************\n\n");

instala_imr_vector(); // Modifica el IMR e instala la RSI
num_int = 0; // Inicializa contador de interrupciones

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

/* Espera que se genere las interrupciones */
while(num_int <= 10) // Cuenta 10 interrupciones
{
xout(0x78, num_int); // Enva a los 8 leds del PortA del PPI
printf("\t\t\tInterrupciones IRQ7: %d\r", num_int);
}
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main

void interrupt new_irq7(...) // Rutina de servicio de interrupcin
{
old_irq7(); // Llama al vector antiguo
num_int ++; // Incrementa contador de interrupciones
outportb(0x20, 0x20); // Enva el EOI
}

void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR


Ing. Javier Barriga Hoyle 76
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
newimr = 0x7F & oldimr; // Activa IRQ7 = 0111 1111
outportb(0x21,newimr); // Enva nueva IMR al PIC
old_irq7 = getvect(0x0F); // Lee vector original
setvect(0x0F,new_irq7); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable(); // Deshabilita interrupciones
setvect(0x0F,old_irq7); // Restaura vector original
outportb(0x21,oldimr); // Restaura IMR original
enable(); // Habilita interrupciones
}


Programa 13.5: (IRQ7_2.CPP) Cada vez que se produce una interrupcin, lee el dato colocado en
el PortB del PPI (Dipswitch) y lo enva al PortA del PPI (Leds). El programa termina cuando se
alcance 10 interrupciones. Realice la siguiente conexin.

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


+5V
S1
START
+ C1
10uF
R2
10K
R1
330
PIN 1
74HC14

Figura 13.2. Conexin Tarjeta - Pulsador sin rebotes Dipswitch y Leds.

/******************************************************************************
IRQ7_2.CPP
Este programa cada vez que se active el pulsador, genera una interrupcion, se
lee el dipswitch conectado al PortB del PPI y el valor ledo se enva al
PortA del PPI.
El programa termina cuando se genere 10 interrupciones IRQ7.
Descripcin:
a) Conecte un pulsador sin rebote a la lnea IRQ7 (J10).
b) Conecte 8 leds al PortA del PPI de la tarjeta LPT V2.0.
c) Conecte un dipswitch de 8 bits al PortB del PPI de la tarjeta LPT V2.0.
d) Cargue el Turbo C++ 3.0, compile (ALT+F9) y ejecutelo (CTRL+F9).


Ing. Javier Barriga Hoyle 77
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
e) El programa termina cuando se alcance 10 interrupciones.

Autor: Ing. Javier Barriga Hoyle
**************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos */
void interrupt (*old_irq7)(...); // Vector antiguo
void interrupt new_irq7(...); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Variables globales */
unsigned char oldimr, newimr, dato;
int num_int;

void main(void) // Inicia programa principal
{
clrscr();
inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0
xout(0x7B, 0x82); // Configura PPI como PA=PC=out, PB=in

printf("\t*********************************************************\n");
printf("\t* PROGRAMA QUE MUESTRA LA UTILIDAD DE TRABAJAR CON *\n");
printf("\t* INTERRUPCIONES EXTERNAS (IRQ7) *\n");
printf("\t* *\n");
printf("\t* Al activarse el pulsador, se genera la interrupcion *\n");
printf("\t* se lee el dipswitch y el valor se envia a los leds. *\n");
printf("\t*********************************************************\n\n");

instala_imr_vector(); // Modifica el IMR e instala la RTI
num_int = 0; // Inicializa contador de interrupciones

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

/* Espera que se genere las interrupciones */
while(num_int <= 10); // Cuenta 10 interrupciones
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main

void interrupt new_irq7(...) // Rutina de servicio de interrupcin
{
old_irq7(); // Llama al vector antiguo
dato = xin (0x79); // Se lee del PortB del PPI
xout (0x78, dato); // Se enva al PortA del PPI
num_int++; // Incrementa contador de interrupciones
outportb(0x20, 0x20); // Se enva el EOI
}
void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = 0x7F & oldimr; // Activa IRQ7 = 0111 1111


Ing. Javier Barriga Hoyle 78
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
outportb(0x21,newimr); // Enva nueva IMR al PIC
old_irq7 = getvect(0x0F); // Lee vector original
setvect(0x0F,new_irq7); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable(); // Deshabilita interrupciones
setvect(0x0F,old_irq7); // Restaura vector original
outportb(0x21,oldimr); // Restaura IMR original
enable(); // Habilita interrupciones
}


Programa 13.6: (IRQ7_3.CPP) Cada vez que se produce una interrupcin, se enva a un LCD
conectado al PortA del PPI el nmero de interrupciones generadas, mientras la CPU por el PortC
realiza en todo instante un corrimiento de BITS por 8 leds. El programa termina cuando se pulse la
tecla ESC(escape). Realice la siguiente conexin.


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
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
Power E/S Timer SW Timer
INTERRUPCIONES
IRQ7 = 0


+5V
S1
START
+ C1
10uF
R2
10K
R1
330
PIN 1
74HC14

Figura 13.3. Conexin Tarjeta - Pulsador sin rebotes - LCD y Leds.

El programa principal siempre est realizando lo siguiente: En un inicio los leds estn apagados y
comienzan a prenderse desde los extremos hacia el centro; luego se van apagando desde el centro
hacia los extremos y as sucesivamente. Es muy vistosa e interesante la lgica empleada para
generarlo.



Ing. Javier Barriga Hoyle 79
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM


/******************************************************************************
IRQ7_3.CPP
Este programa tiene como rutina principal, prender secuencialmente los leds desde
los extremos hacia el centro, luego se irn apagando desde el centro hacia los
extremos y as sucesivamente. Los leds se conectan al PortC del PPI.
Cuando se genera una interrupcin por la lnea IRQ7, se incrementa la cuenta de
interrupciones (mximo 99) y se enva al LCD conectado al PortA del PPI.
El programa termina cuando se pulse ESC (escape).

Descripcin:
a) Conecte un pulsador sin rebote a la lnea IRQ7 (jumper J10).
b) Conecte 8 leds al Puerto C del PPI.
c) Conecte el LCD al Puerto A del PPI de la siguiente manera:
PortA : PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0
LCD : D7 D6 D5 D4 EN RS X X
nota: la seal WR, se pone a CERO porque solo se escribe.

e) Cargue el Turbo C++ 3.0, compile (ALT+F9) y ejectelo (CTRL+F9).

Autor: Ing. Javier Barriga Hoyle
******************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos para la interrupcin */
void interrupt (*old_irq7)(...); // Vector antiguo
void interrupt new_irq7(...); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Prototipos para el LCD */
void PutcharLCD(UCHAR direc, UCHAR dato);
void BorraLCD(void);
void InitLCD(void);
void GotoxyLCD(UCHAR fila, UCHAR columna);

/* Define constantes */
#define CONTROL 0 // Constante para el display LCD
#define DATO 1 // Constante para el display LCD
#define DISPLAY_ON 0x0E // Display ON, cursor ON, blink OFF
#define DIS_ON_CUR_OFF 0x0C // Display ON, cursor OFF, blink OFF
#define BORRAR_LCD 0x01
#define CURSOR_ORIGEN 0x80 // Apuntar al origen de la RAM de datos
#define CG_RAM_ORIGEN 0x40 // Apuntar al origen de la RAM gen de caract
#define UCHAR unsigned char



Ing. Javier Barriga Hoyle 80
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/* Define mensajes a enviar al LCD */
char Mensaje1[28] = {"ARQUITECTURA DE COMPUTADORAS"}; // ambas filas
char Mensaje2[16] = {" INTERRUPCIONES "}; // fila 1
char Mensaje3[9] = {" IRQ7 = "}; // fila 2

/* Define variables globales */
UCHAR oldimr, newimr, car, bit, y, z, MSB, LSB, num_dec, num_int;
int j, fin;

void main (void) // Inicia programa principal
{
clrscr(); // Borra pantalla
inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0
xout(0x7B, 0x80); // Configura PPI como PA = PB = PC = outs
InitLCD(); // Inicializa LCD

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 se envia al LCD *\n");
printf("\t* mientras se desplaza bits en el PortC del PPI. *\n");
printf("\t*********************************************************\n\n");

/* Enva mensaje de bienvenida al LCD */
while(j<28)
{
for(j=0; j<16; j++){
PutcharLCD(DATO, Mensaje1[j]);
delay(150);
}
GotoxyLCD(2,2); // Posiciona cursor en la fila 2, columna 2
for(j=16; j<28; j++){
PutcharLCD(DATO, Mensaje1[j]);
delay(150);
}
}
delay(2000); // Retardo de 2 seg.
BorraLCD(); // Borra el LCD

/* Enva mensaje para visualizar el nmero de interrupciones en el LCD */
for(j=0; j<16; j++)
{
PutcharLCD(DATO, Mensaje2[j]);
delay(150);
}
GotoxyLCD(2,1); // Posiciona cursor al inicio de la fila 2
for(j=0; j<8; j++)
{
PutcharLCD(DATO, Mensaje3[j]);
delay(150);
} // Fin de enviar mensajes

instala_imr_vector(); // Modifica el IMR e instala la RSI

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

/* Rutina principal que desplaza bits, mientras se espera que se genere las
interrupciones. Sale del programa cuando se pulse ESC */
fin = 0;
bit = 0;
num_int = 0;
num_dec = 0;
while( !fin ) // Se ejecuta mientras no se pulse ESC
{


Ing. Javier Barriga Hoyle 81
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
y = 0x01; // Rutina de desplazamientos
z = 0x80;
for(j=1; j<=8; j++){
xout(0x7A, bit); // Se enva al PortC
delay(200); // Retardo de 200 ms
bit = bit ^ y;
bit = bit ^ z;
y = y << 1;
z = z >> 1;
}
if(kbhit()){ // Se activ alguna tecla?
car = getch(); // SI, entonces se lee la tecla y si es ESC
if(car == 27) Fin=1; // salir del programa
}
}
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main

void interrupt new_irq7(...) // Rutina de servicio de interrupcin
{
old_irq7(); // Llama al vector antiguo
num_int ++; // Incrementa contador de interrupciones
if(num_int > 9){
num_int = 0; // Reinicia unidades
num_dec++; // Incrementa decenas
}
GotoxyLCD(2,9); // Posiciona cursor en la fila 2
LSB = num_int + 0x30; // Convierte a ASCII
MSB = num_dec + 0x30;
PutcharLCD(DATO, MSB); // Se enva al LCD
PutcharLCD(DATO, LSB); // Se enva al LCD
outportb(0x20, 0x20); // Se enva el EOI
}

void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = oldimr & 0x7F; // Activa IRQ7 = 0111 1111
outportb(0x21,newimr); // Enva nueva IMR al PIC
old_irq7 = getvect(0x0F); // Lee vector original
setvect(0x0F,new_irq7); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable(); // Deshabilita interrupciones
setvect(0x0F,old_irq7); // Restaura vector original
outportb(0x21,oldimr); // Restaura IMR original
enable(); // Habilita interrupciones
}

/******************************************************************
Funcin: void InitLcd(void)
Inicializa el display LCD.
******************************************************************/
void InitLCD(void)
{
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
/* RS debe ser estable antes del flanco de subida de EN */
xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0


Ing. Javier Barriga Hoyle 82
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Sleep(5); // Demora superior a 4,1 ms

xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(1); // Demora superior a 100 s

xout(0x78, 0x38); // DB[7..4] EN RS X X
// 0011 1 0 0 0
xout(0x78, 0x30); // DB[7..4] EN RS X X
// 0011 0 0 0 0
Sleep(1); // Demora superior a 100 s
/* Selecciona interface de 4 bits */
xout(0x78, 0x28); // DB[7..4] EN RS X X
// 0010 1 0 0 0
xout(0x78, 0x20); // DB[7..4] EN RS X X
// 0010 0 0 0 0
/* Tras esta inicializacin el display queda en modo 4 bits */
Sleep(1); // Demora superior a 100 s
BorraLCD(); // Borra el LCD y lleva cursor al origen
} // FIN DE InitLcd

/******************************************************************
Funcin: void PutcharLcd(UCHAR direc, UCHAR dato)
Envia al display LCD un "dato". Si:
direc = 0, se accede al registro de instrucciones
direc = 1, se accede al registro de datos
******************************************************************/
void PutcharLCD(UCHAR direc, UCHAR dato)
{
UCHAR temp, temp2;
temp2 = 0x08; // Para activar EN
if (direc == DATO) // Es instruccin o dato?
{
temp2 |= 0x04; // Selecciona Dato/Control con RS
xout(0x78, 0x04); // DB[7..4] EN RS X X
} // 0000 0 1 0 0
else
xout(0x78, 0x00); // DB[7..4] EN RS X X
// 0000 0 0 0 0
/* RS debe ser estable antes del flanco de subida de EN */

/* Primero se enva el nibble alto */
temp = (dato & 0xf0) | temp2;
xout(0x78, temp); // Manda nibble alto con EN = 1
temp &= 0xf5;
xout(0x78, temp); // Desactiva EN

/* Despus se manda el nibble bajo */
temp = (dato << 4) | temp2;
xout(0x78, temp); // Manda nibble bajo con EN = 1
temp &= 0xf5;
xout(0x78, temp); // Desactiva EN
Sleep(1);
} // FIN DE PutcharLcd

/*-------------------------------------------------------------------------------
Funcin: void BorraLCD(void)
Establece control del LCD, Borra el LCD, establece Modo de entrada,
y pone el cursor en el origen.
-------------------------------------------------------------------------------*/
void BorraLCD(void)
{
PutcharLCD(CONTROL, DISPLAY_ON); // Display on, cursor ON, blink off
PutcharLCD(CONTROL, BORRAR_LCD); // Borrar el Display
PutcharLCD(CONTROL, 0x06); // Incremento automtico de AC al escribir


Ing. Javier Barriga Hoyle 83
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
PutcharLCD(CONTROL, 0x02); // Cursor en la esquina izquierda
} // FIN DE BorraLCD

/*-------------------------------------------------------------------------------
Funcin: void GotoxyLCD(UCHAR fila, UCHAR columna)
Posiciona el cursor en la posicin especificada por fila, columna.
Si alguna de las coordenadas es invalida no se hace nada.
Coordenadas validas: fila = 1..2, columna = 1..16
-------------------------------------------------------------------------------*/
void GotoxyLCD(UCHAR fila, UCHAR columna)
{
UCHAR pos_fila, cursor;

if((fila<1 || fila>2) || (columna<1 || columna>16))
return;

switch(fila)
{
case 1:
pos_fila = 0x80; // Posicin de memoria 00h ---> 27h
cursor = pos_fila + columna;
PutcharLCD(CONTROL, cursor); // Posiciona cursor
break;

case 2:
pos_fila = 0xC0; // Posicin de memoria 40h ---> 67h
cursor = pos_fila + columna;
PutcharLCD(CONTROL, cursor); // Posiciona cursor
break;
}
}


Programa 13.7: (IRQ7_4.CPP) Uso de la tcnica de interrupciones (IRQ7) para leer el voltaje
analgico dado por el potencimetro a intervalos de 2 segundos. Realice la siguiente conexin:

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
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 lnea
INTR del ADC se conecte
con el pin 10 del conector
DB25 (bit 6 del puerto 379h).
+5V
5 K
+5V
1 K 1 K

Figura 13.4. Conexin Tarjeta - ADC - Potencimetro - PPI - Leds.



Ing. Javier Barriga Hoyle 84
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
/******************************************************************************
IRQ7_4.CPP: (Emplea la interrupcin IRQ7 para leer el ADC)
Este programa muestrea a intervalos de 2 seg. un voltaje analgico (0V-5V) de un
potencimetro y lo imprime en la pantalla, adems enva el dato en binario al
PortA (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 funcin delay.
El programa termina cuando se pulse ESC(escape)

Descripcin:
a) Implemente un circuito con un potencimetro entre 0 y 5V.
b) El punto central de ste conctelo al terminal (VI+) de la bornera azul o al
molex.
c) El terminal VI-, conctelo a tierra.
d) El terminal AGND conctelo a tierra.
e) El terminal VREF puede conectarse a otro potencimetro con un voltaje de
salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en la
toma de muestras.
f) Cargue el programa Turbo C++ 3.0 y abra el programa ADC_5, luego compile con
ALT+F9, y ejecute el programa con CTRL+F9.

Autor: Ing. Javier Barriga Hoyle
******************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera para la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
/* Prototipos */
void interrupt (*old_adc)(...); // Vector antiguo
void interrupt new_adc(...); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* 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.0
xout(0x7B,0x80); // Configura PPI como PA = PB = PC = outs
instala_imr_vector(); // Modifica IMR e instala vector de IRQ7

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

printf("\n");
printf("\t*********************************************************\n");
printf("\t* PROGRAMA QUE CAPTURA SEALES ANALOGICAS PROVENIENTES *\n");
printf("\t* DE UN POTENCIOMETRO, USANDO LA INTERRUPCION IRQ7 *\n");
printf("\t* *\n");
printf("\t* El valor obtenido se enva 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");

Fin = 0;


Ing. Javier Barriga Hoyle 85
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
muestras = 0;

while(!Fin) // El programa termina cuando se pulse ESC
{
xout(0x6C, 0x00); // Inicia conversin del ADC
if(datolisto == 1) // Termin conversin INT = 0?
{
dato_adc = xin(0x6C); // SI, procede a leerse el dato
xout(0x78, dato_adc); // Enva dato ledo al PortA del PPI
voltios = (float)dato_adc * 5 / 255; // Convierte a flotante
gotoxy(22,12);
printf("lectura ADC(%d) = %0.4f voltios",muestras,voltios); //4 decimales
datolisto = 0; // Borra flag para otra interrupcin
delay(2000); // Retardo de 2 segundos

if(kbhit()) // Se activ alguna tecla?
{
car = getch(); // SI, entonces se lee la tecla y si es ESC
if(car == 27) Fin=1; // salir del programa
}
}
}
restaura_imr_vector(); /* Termina el programa, recupera la mscara
y el vector original */
} // Fin de main

void interrupt new_adc(...) // Rutina de servicio de interrupcin
{
old_adc(); // Llama al vector original
datolisto = 1; // Flag, indica que se activ interrupcin
muestras++; // Incrementa nmero de muestras
outportb(0x20,0x20); // Enva el EOI
}

void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = 0x7F & oldimr; // Activa IRQ7 = 0111 1111
outportb(0x21,newimr); // Enva nueva IMR al PIC
old_adc = getvect(0x0F); // Lee vector original
setvect(0x0F,new_adc); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable(); // Deshabilita interrupciones
setvect(0x0F,old_adc); // Restaura vector original
outportb(0x21,oldimr); // Restaura IMR original
enable(); // Habilita interrupciones
}














Ing. Javier Barriga Hoyle 86
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Programa 13.8: (IRQ7_5.CPP) Uso de las interrupciones IRQ7 (ADC) e IRQ0 (TIMER de la PC).
Utilice el circuito del programa IRQ7_4.CPP

/******************************************************************************
IRQ7_5.CPP: (Emplea las interrupciones IRQ0 y IRQ7)
Este programa muestrea a intervalos de 1 seg. un voltaje analgico (0V-5V) de un
potencimetro y lo imprime en la pantalla, adems enva el dato en binario al
PortA (puede ser B o C) del PPI para que se vea en los 8 leds.
El retardo de 1 segundo se genera programando la interrupcin IRQ0.
La lnea INTR del ADC se conecta a la interrupcin IRQ7.
El programa termina cuando se pulse ESC(escape).

Descripcin:
a) Implemente un circuito con un potencimetro entre 0 y 5V.
b) El punto central de ste conctelo al terminal (VI+) de la bornera azul o al
molex;
c) El terminal VI-, conctelo a tierra.
d) El terminal AGND conctelo a tierra.
e) El terminal VREF puede conectarse a otro potencimetro con un voltaje de
salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en la
toma de muestras.

Autor: Ing. Javier Barriga Hoyle
******************************************************************************/
##include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera para la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos */
void interrupt (*old_adc)(...); // Vector antiguo IRQ7
void interrupt new_adc(...); // Nueva RSI
void interrupt (*old_timer)(...); // Vector antiguo IRQ0
void interrupt new_timer(...); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Variables globales */
unsigned char oldimr, newimr, datolisto, car, dato_adc;
int Fin, num_int, muestras;
float voltios;

void main(void) // Inicia programa principal
{
clrscr(); // Borra pantalla
inicio_tarjeta(); // Inicializa tarjeta de interfase LPT V2.0
instala_imr_vector(); // Modifica IMR e instala el vector de IRQ7
xout(0x7B,0x80); // Configura PPI como PA = PB = PC = out

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

printf("\n");
printf("\t*********************************************************\n");
printf("\t* PROGRAMA QUE CAPTURA SEALES ANALOGICAS PROVENIENTES *\n");
printf("\t* DE UN POTENCIOMETRO, USANDO LAS INTERRUPCIONES IRQ0-7 *\n");
printf("\t* *\n");


Ing. Javier Barriga Hoyle 87
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
printf("\t* El valor obtenido se enva 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 cero
num_int = 0; // Inicia Contador de interrupciones a cero
Fin = 0; // Flag de fin
xout(0x6C, 0x00); // Inicia conversin del ADC en t = 0 seg

while(!Fin) // Programa continua hasta que se pulse ESC
{
if(datolisto == 1) // Termin conversin INTR = 0?
{
dato_adc = xin(0x6C); // SI, procede a leerse el dato
xout(0x78, dato_adc); // Enva dato ledo al PortA del PPI
voltios = (float)dato_adc * 5 / 255; // Convierte a flotante
gotoxy(22,12);
printf("lectura ADC(%d) = %0.4f voltios",muestras,voltios); //4 decimales
datolisto = 0; // Borra flag para otra interrupcin

if(kbhit()) // Se activ alguna tecla?
{
car = getch(); // SI, entonces se lee la tecla
if(car == 27) Fin=1; // Salir del programa
}
}
}
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main

void interrupt new_timer(...) // Rutina de servicio de interrupcin
{
old_timer(); // Llama al vector original
num_int++; // Incrementa nmero de interrupciones
if(num_int == 18) // Pas 1 segundo?
{
num_int = 0; // Reinicia contador de interrupciones
xout(0x6C, 0x00); // Inicia conversin del ADC
muestras++; // Incrementa nmero de muestras
}
outportb(0x20,0x20); // Enva el EOI
}

void interrupt new_adc(...) // Rutina de servicio de interrupcin
{
old_adc(); // Llama al vector original
datolisto = 1; // Flag que indica que termino conversin
outportb(0x20,0x20); // Enva el EOI
}

void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = oldimr & 0x7E; // Activa IRQ7 e IRQ0 (0111 1110)
outportb(0x21,newimr); // Enva nueva IMR al PIC
old_timer = getvect(0x08); // Lee vector 8 original
setvect(0x08,new_timer); // Instala nuevo vector
old_adc = getvect(0x0F); // Lee vector 15 original
setvect(0x0F,new_adc); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{


Ing. Javier Barriga Hoyle 88
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
disable(); // Deshabilita interrupciones
setvect(0x08,old_timer); // Restaura vector 8 original
setvect(0x0F,old_adc); // Restaura vector 15 original
outportb(0x21,oldimr); // Restaura IMR original
enable(); // Habilita interrupciones
}


Programa 13.9: (IRQ7_6.CPP) Uso de las interrupciones IRQ7 (ADC) e IRQ0 (TIMER de la PC).
Los datos muestreados sern almacenados en un archivo muestreo.txt. Utilice el circuito del
programa IRQ7_4.CPP

/******************************************************************************
IRQ7_6.CPP: (Emplea las interrupciones IRQ0 y IRQ7)
Este programa muestrea a intervalos de 1/2 seg un voltaje analgico (0V-5V) de
un potencimetro y lo imprime en la pantalla, adems enva el dato en binario al
PORT 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 interrupcin IRQ0.
La lnea INT del ADC se conecta a la interrupcin IRQ7.
El programa termina cuando se alcance las 200 muestras. Los datos se almacenan
en el archivo muestreo.txt.

Descripcin:
a) Implemente un circuito con un potencimetro entre 0 y 5V.
b) El punto central de ste conctelo al terminal (VI+) de la bornera azul o al
molex;
c) El terminal VI-, conctelo a tierra.
d) El terminal AGND conctelo a tierra.
e) El terminal VREF puede conectarse a otro potencimetro con un voltaje de
salida aproximado de 2.5 voltios. Con esto se consigue mayor exactitud en la
toma de muestras.

Autor: Ing. Javier Barriga Hoyle
******************************************************************************/
#include <dos.h> // Librera DOS para el Turbo C++
#include <conio.h>
#include <stdio.h>
#include "BymDOS.h" // Librera para la tarjeta LPT V2.0

int Base = 0x378; // Direccin base del puerto paralelo

#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif

/* Prototipos */
void interrupt (*old_adc)(...); // Vector antiguo IRQ7
void interrupt new_adc(...); // Nueva RSI
void interrupt (*old_timer) (...); // Vector antiguo IRQ0
void interrupt new_timer(...); // Nueva RSI
void instala_imr_vector(void);
void restaura_imr_vector(void);

/* Declaracin de variables globales */
unsigned char oldimr, newimr, datolisto, car, dato_adc;
int Fin, num_int, muestras;
float voltios;

void main(void) // Inicia programa principal
{
FILE *archivo;
clrscr(); // Borra pantalla
inicio_tarjeta(); // Inicializa tarjeta LPT V2.0
xout(0x7B,0x80); // Configura PPI como PA = PB = PC = out


Ing. Javier Barriga Hoyle 89
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
printf("\n");
printf("\t**********************************************************\n");
printf("\t* PROGRAMA QUE CAPTURA SEALES ANALOGICAS PROVENIENTES *\n");
printf("\t* DE UN POTENCIOMETRO, USANDO LAS INTERRUPCIONES IRQ0-7 *\n");
printf("\t* *\n");
printf("\t* El valor obtenido se envia 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* El programa termina cuando se pulse ESC(escape) o *\n");
printf("\t* cuando se alcance las 200 muestras. *\n");
printf("\t**********************************************************\n\n");

instala_imr_vector(); // Modifica IMR e instala el vector de IRQ7

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

muestras = 0; // Inicia contador de muestras en cero
num_int = 0; // Inicia Contador de interrupciones a cero
Fin = 0; // Flag de fin

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

xout(0x6C,0x00); // Inicia conversin del ADC en t = 0
while(muestras <= 200) /* Programa contina hasta que se pulse ESC
cuando se alcance 200 muestras */
{
if(datolisto == 1) // Termin conversin INTR = 0?
{
dato_adc = xin(0x6C); // SI, procede a leerse el dato
xout(0x78, dato_adc); // Enva dato ledo al PortA del PPI
voltios = (float)dato_adc * 5 / 255; // Convierte a flotante
fprintf(archivo,"%f\n",voltios); // Almacena dato en el archivo
gotoxy(22,12);
printf("lectura ADC(%d) = %0.4f voltios",muestras,voltios); //4 decimales
datolisto = 0; // Borra flag para otra interrupcin
if(kbhit()) // Se activ alguna tecla?
{
car = getch(); // SI, entonces se lee la tecla
if(car == 27) Fin=1; // Salir del programa
}
}
}
fclose(archivo); // Cierra archivo muestreo.txt
restaura_imr_vector(); /* Termina el programa, recupera la mascara
y el vector original */
} // Fin de main

void interrupt new_timer(...) // Rutina de servicio de interrupcin
{
old_timer(); // Llama al vector original
num_int++; // Incrementa nmero de interrupciones
if(num_int == 9){ // Pas 1/2 segundo?
num_int = 0; // SI, reinicio contador de interrupciones
xout(0x6C,0x00); // Captura dato del ADC e inicia conversin
muestras++; // Incrementa nmero de muestras
}
outportb(0x20,0x20); // Enva el EOI
}

void interrupt new_adc(...) // Rutina de servicio de interrupcin
{
old_adc(); // Llama al vector original
datolisto = 1; // Flag que indica que termino conversin
outportb(0x20,0x20); // Enva el EOI
}


Ing. Javier Barriga Hoyle 90
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
void instala_imr_vector(void)
{
disable(); // Deshabilita interrupciones
oldimr = inportb(0x21); // Lee la mscara IMR
newimr = oldimr & 0x7E; // Activa IRQ7 e IRQ0 (0111 1110)
outportb(0x21,newimr); // Enva nueva IMR al PIC
old_timer = getvect(0x08); // Lee vector 8 original
setvect(0x08,new_timer); // Instala nuevo vector
old_adc = getvect(0x0F); // Lee vector 15 original
setvect(0x0F,new_adc); // Instala nuevo vector
enable(); // Habilita interrupciones
}

void restaura_imr_vector(void)
{
disable(); // Deshabilita interrupciones
setvect(0x08,old_timer); // Restaura vector 8 original
setvect(0x0F,old_adc); // Restaura vector 15 original
outportb(0x21,oldimr); // Restaura IMR original
enable(); // Habilita interrupciones
}











































Ing. Javier Barriga Hoyle 91
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
14. Aplicaciones del DAC 0830
Programa 14.1: (DAC_1.CPP) Programa de prueba del DAC. Se le enva datos binarios para
obtener voltajes de salida entre 0V hasta +5V. Realice la siguiente conexin.

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
IRQ7
LIBRE ADC
J10
3 2 1
+
5
V
G
N
D
8 MHZ
Power E/S Timer SW Timer
+
-
+
-
+5V
3
2
10K
10K
Inversor
+V
-V
El esquemtico completo puede verlo en la figura
E8, del apndice E.
LM741
LM741


Figura 14.1 Circuito simplificado de prueba del DAC0830 OPAMP 741.

/********************************************************************************
DAC_1.CPP
Este programa sirve para probar el funcionamiento del DAC. Se le enva valores
binarios desde 0 hasta 255 (00h - FFh), para obtener un voltaje de salida entre
0V y +5V aproximadamente.

Descripcin:
a) Realice las conexiones mostradas en la figura 14.1
b) El voltaje de Referencia del DAC0830 es +5V.
c) El primer OPAMP (U1) se conecta a la salida del DAC0830. El voltaje de salida
estar entre 0 y -5V.
d) Conecte a la salida del OPAMP (U1), el segundo OPAMP (U2) configurado para
operar en modo INVERSOR, el cual invierte el voltaje de salida negativo a
positivo (0V a +5V).
e) Escriba el programa en Visual C++ (modo consola)
f) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

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

int Base = 0x378; // Direccin del puerto paralelo

int i, Fin;
unsigned char car;

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
Fin=0;
i = 0;


Ing. Javier Barriga Hoyle 92
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
while(!Fin){
xout(0x5C, i); // Enva dato = i, al DAC
Sleep(100); // Pequeo retardo de 100 ms
printf("i = %d\n",i);
i++; // Incrementa valor de i
if(i == 256) Fin = 1;
if(kbhit()) // Pulso tecla?
{
car=getch(); // SI, leer tecla
if(car == 27) Fin=1; // Si es ESC, salir del programa
}
}
}


Programa 14.2: (DAC_2.CPP) Programa que lee un voltaje del ADC0804, lo convierte a digital y
luego lo enva al DAC0830 para que lo muestre el voltaje en un multmetro. Realice la siguiente
conexin.

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
IRQ7
LIBRE ADC
J10
3 2 1
+
5
V
G
N
D
8 MHZ
Power E/S Timer SW Timer
+
-
+
-
+5V
3
2
10K
10K
Inversor
+V
-V
El esquemtico completo puede verlo en las figuras
E8 y E9, del apndice E.
LM741
LM741
+5V
5 K
Vcc / 2


Figura 14.2 Circuito simplificado de ADC0804 y DAC0830.

/********************************************************************************
DAC_2.CPP
Este programa sirve para leer un valor analgico dado por un potencimetro y su
valor obtenido, se enva a un DAC para medir el voltaje dado por el ADC.

Descripcin:
a) Realice las conexiones mostradas en la figura 14.1 y 14.2
b) Vare el potencimetro para generar distintos niveles de voltaje que ingrese
al ADC0804.
c) Los valores obtenidos sern envados al DAC0830 para convertirlo a analgico.
El voltaje estar entre 0V y +5V.
d) El programa termina cuando pulse ESC.
e) Escriba el programa en Visual C++ (modo consola)
f) Compile (Ctrl + F7) -> Build (F7) -> Execute program (Ctrl + F5)

Autor: Ing. Javier Barriga Hoyle
********************************************************************************/


Ing. Javier Barriga Hoyle 93
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include "BymWin.h" // Librera usada por la tarjeta LPT V2.0

int Base = 0x378; // Direccin del puerto paralelo

int i, Fin, flag_int;
unsigned char car, dato_adc;
float voltios;

void main (void) // Inicia programa principal
{
inicio_tarjeta(); // Inicializa Tarjeta de interfase LPT V2.0
Fin=0;
while(!Fin)
{
xout(0x6C, 0x00); // Inicia conversin
while (flag_int != 0x40) // INTR = 0? o termin conversin?
flag_int = _inp(Base+1)&0x40; /* Aqu no se usa xin, porque la lnea
IRQ7 va directamente al puerto 379h */
dato_adc = xin(0x6C); // Termin conversin, leo dato del ADC

xout(0x5C, dato_adc); // Enva dato_adc al DAC

voltios = ((float)dato_adc*5)/255; // Convierte a flotante
/* Muestra en pantalla en formato decimal el dato convertido */
printf("Valor ADC = %0.4f voltios\n",voltios); // 4 decimales
if(kbhit()) // Pulso tecla?
{
car=getch(); // SI, leer tecla
if(car == 27) Fin=1; // Si es ESC, salir del programa
}
Sleep(500); // Retardo de 500 ms
}
}





























Ing. Javier Barriga Hoyle 94
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Apndice A. DRIVER L293D

El circuito L293D es un circuito lineal, su aplicacin principal es el funcionamiento para motores a
pasos y de corriente continua, tiene la caracterstica de que mediante entradas digitales, pueda
activar o desactivar el motor que se tiene conectado a la salida, la configuracin de este es la
siguiente.

1
L293D
2
3
4
5
6
7
8
16
15
14
13
12
11
10
9 VS
VSS
INPUT4
OUTPUT4
GND
OUTPUT3
INPUT3
ENABLE2
ENABLE1
INPUT1
OUTPUT1
GND
GND
OUTPUT2
INPUT2
GND
E1
IN1
IN2
IN3
IN4
E2
OUT1
OUT2
OUT3
OUT4
L293D


Figura A.1 Circuito Integrado L293D y su diagrama simplificado.

Este circuito incluye cuatro canales de salida capaces de suministrar hasta 600 mA por canal (1.2 A
de pico). Est diseado para atacar cargas inductivas (caso de un motor PAP o CC), dispone de
diodos de proteccin en las salidas y puede operar en aplicaciones de conmutacin (Ej. PWM) a
frecuencias de hasta 5 KHz.
Las patillas centrales 4, 5, 12, y 13 (GND), estn agrupados en el centro del encapsulado con objeto
de facilitar la conexin de disipadores de calor (disipa hasta 5 W con estas patillas a 80 C). Sus
caractersticas son: tensin de alimentacin de los canales de salida (Vs) hasta 36 V; Tensin de
alimentacin de la lgica TTL (Vss) hasta 36 V; tensin de las entradas (Vi) hasta 7 V; tensin de
las entradas de Enable (Ven) hasta 7 V. A continuacin se muestra la disposicin interna y la tabla
de funcionamiento.

V
S
V
S
V
S
V
S
2
1
7
4, 5, 12, 13 6 14
15
9
10
16 11 3 8
IN1
IN2
E1
IN3
IN4
E2
OUT2 OUT4
OUT1 OUT3 VS VSS
L293D
GND

Figura A.2 Diagrama de interno del driver L293D.


Tabla de funcionamiento del L293D
Enable Entrada Salida
L X Z
H L L
H H H






Ing. Javier Barriga Hoyle 95
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Apndice B. TIMER 8253 de la PC

Este temporizador aparece en la computadora personal decodificado en los puertos de E/S 40h
43h para realizar las siguientes funciones:
Generar una interrupcin bsica de temporizacin que ocurre aproximadamente a 18.2 Hz.
Refrescar el sistema de memoria DRAM (cada 15 S).
Proporcionar una fuente de temporizacin a la bocina interna y otros dispositivos. El
temporizador en la computadora personal es un 8253, en lugar de un 8254.
Todos los contadores van conectados a un reloj que oscila a una frecuencia de 1.193.180 ciclos
por segundo (casi 1,2 MHz).
El parlante se controla con la salida OUT del Canal 2 y con los dos primeros bits del PortB del PPI
(PB1 y PB0) ubicado en la direccin 62h del puerto de E/S. Es decir, para que el parlante suene el
bit PB0 que est conectado al GATE, debe estar en 1, as mismo, el bit PB1 que est conectado a
la compuerta AND, debe estar en 1.
Cuando este canal 2 se emplea slo para temporizar, el bit PB1 debe estar en 0 para evitar que el
parlante suene y el bit PB0 debe estar en 1 para habilitarlo.

CLK
GATE
OUT
CANAL 0
CLK
GATE
OUT
CANAL 1
CLK
GATE
OUT
CANAL 2
VCC
R
PB0
PB1
PPI
VCC
IRQ0 - Vector 8
Refresco de
Memoria DRAM
1193180 Hz

Figura B.1 TIMER 8253 dentro de la computadora personal.

















Ing. Javier Barriga Hoyle 96
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Apndice C. MODULACION POR ANCHO DE PULSOS (PWM)

Una manera de obtener una corriente continua cuyo valor medio se pueda variar es modular el
ancho o la frecuencia de una seal pulsatoria de onda cuadrada que vare entre 0 V. y un valor
mximo de tensin V
MAX
.
Estos circuitos reciben el nombre de Modulador de Pulsos (PWM), si lo que se vara es el tiempo
de duracin de pulso positivo, y Modulador de Frecuencia (PFM), si lo que se vara es el perodo
total de la seal.
Con cualquiera de estos dos sistemas se obtiene una seal cuadrada, cuyo valor medio es
fcilmente variable, seal con la que se puede regular la velocidad de un motor DC. Nosotros
veremos en esta aplicacin PWM.
En una onda cuadrada se vara el ancho del pulso positivo, manteniendo constante la frecuencia, ya
que de esta manera el valor medio de la onda resultante es variable dependiendo de la duracin del
pulso positivo de la misma.
La modulacin de anchura de pulsos (PWM) se consigue con circuitos electrnicos, de una de estas
formas:
Generando una seal triangular y comparndola con una tensin continua de referencia
(variable a voluntad), de manera que en la salida se obtiene una onda cuadrada con regulacin
del ancho del pulso positivo.
Mediante un circuito astable que controla el disparo de un monoestable, para obtener en la
salida una onda cuadrada de pulso positivo variable.
Mediante software, por programa para P o C, obteniendo en el puerto de salida una seal
cuadrada donde se puede variar el tiempo de pulso positivo.
Empleando dos canales (o contadores) del TIMER 82C54 en interfaz con el P, Bus ISA o con
el puerto paralelo de la PC.


C.1 Generacin de PWM con TIMER
La tarjeta de interfase LPT V2.0 para puerto paralelo tiene incluido un TIMER con su oscilador de
8 MHz, la siguiente figura muestra como se debe conectar las salidas de los canales 1 y 2 hacia el
Flip Flop RS 74LS279.
82C54
OUT0
OUT1
OUT2 CLK2
GATE2
CLK1
GATE1
CLK0
GATE0
D0 - D7
OSC
8 MHz
PWM
5
6
7
74LS279
+5v
10K

Figura C.1 Diagrama de conexin para obtener una seal PWM.





Ing. Javier Barriga Hoyle 97
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Su funcionamiento es como sigue:

Se configura al contador 1 (canal 1) en modo 2 (rate generator), el cual genera un tren de
pulsos continuos. Por ejemplo, si el contador es seteado con la cuenta de 1000, su salida estar
en 1 lgico durante 999 pulsos y en 0 lgico durante 1 pulso.
Se configura al contador 2 (canal 2) en modo 5 (hardware triggered strobe), en el cual la salida
del contador 1 (OUT1) se conecta a la entrada GATE 2, para producir los disparos y activar al
contador 2 (monoestable).
El software cambia el valor almacenado en el contador 2, cada vez que se pulsa una tecla (para
aumentar o disminuir el periodo). Como este nmero es cambiado, el tiempo entre la salida del
contador 1 y la salida del contador 2 tambin cambiar.
La salida OUT1 tambin se conecta a la entrada SETS, y la salida OUT2 se conecta a la
entrada RESET del FLIP FLOP RS (74LS279), en donde su salida (Q) del FLIP FLOP es una
seal PWM.
Considerar que el esquema debe trabajar teniendo en cuenta que el nmero almacenado en el
contador 2 debe ser un mnimo de 2 unidades menor que el nmero almacenado en el contador
1. Por ejemplo, si el contador 1 es programado con el nmero 1000, el contador 2 puede variar
entre 1 y 998. Esto asegura que las seales SET y RESET enviadas al FLIP FLOP no se
traslapen.
La siguiente figura, muestra las seales que se producen en las salidas de los contadores 1 y 2
del TIMER y la salida del F/F. En este ejemplo, al contador 1 se le ha enviado el valor de
65535 (FFFFh), y el contador 2 vara a intervalos de 4095 (FFFh).


CONTADOR 1
CONTADOR 2
(WORD = 32775)
CONTADOR 1
CONTADOR 2
SALIDA F/ F
(WORD = 57345)
SALIDA F/ F
(WORD = 4110)
CONTADOR 1
CONTADOR 2
SALIDA F/ F


Figura C.2 Formas de onda que se genera en las salidas de cada contador o canal.








Ing. Javier Barriga Hoyle 98
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
C.2 Driver L293D
Como controlador de motor de corriente continua (motor de CC), se ha empleado el circuito
integrado L293D (Apndice A). La siguiente figura muestra como conectar el motor con el CI
L293D.
A continuacin, se muestra el diagrama de cmo debe conectarse el motor DC al controlador
L293D. El programa G5_E6.CPP genera una seal PWM para el control de un motor DC.


V
S
V
S
V
S
V
S
2
1
7
4, 5, 12, 13 6 14
15
9
10
16 11 3 8
IN1 = PWM
E1 = +5 V
IN3 = Sentido de giro
E2 = +5 V
OUT1
OUT3
Vs = +5V o +12V Vss = +5V o +12 V
L293D
GND
MOTOR DC
+


Figura C.3 Ejemplo de conexin del driver L293D a un motor DC.









































Ing. Javier Barriga Hoyle 99
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Apndice D. INTERRUPCIONES

D.1 Conceptos
Una interrupcin se genera cuando se quiere que la CPU deje de ejecutar el proceso en curso y
ejecute una funcin especfica de quien produce la interrupcin. Cuando se ejecuta esta funcin
especfica decimos que la CPU est atendiendo la interrupcin. Podemos realizar una clasificacin
de las interrupciones, atendiendo a la fuente que las produce.
Interrupcin software, se produce cuando un usuario solicita una llamada del sistema. Se
tratan de procedimientos a los que llama un programa para la ejecucin de tareas ligadas, en su
mayora, al hardware de la computadora, tales como la adquisicin de una tecla, enviar
informacin a la pantalla, transmisin y recepcin de datos va un canal de comunicacin con
el exterior, etc. En realidad las interrupciones por software no interrumpen nada, ya que
cumplen una funcin 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 atencin
de la CPU para que se ejecute su manejador (rutina de interrupcin).
Internas: Son generadas dentro del CPU. Por ejemplo, un desbordamiento en la divisin,
un cdigo de operacin 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 algn
perifrico 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).


D.2 Interrupciones en la PC
La CPU 80x86 de una PC, posee tres seales 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 D.1 Lneas de interrupcin.
Donde:
Interrupt request (INTR): Solicitud de interrupcin, est disponible para ser utilizada por
dispositivos perifricos externos que necesiten ser atendidos por el CPU, el procesador 80x86
muestrea esta seal cada vez que va a iniciar una instruccin, si detecta que tiene un nivel
lgico 1, reconoce la interrupcin y salta a la rutina de servicio correspondiente para atender
dicho requerimiento. Esta lnea de interrupcin es enmascarable, puede ser habilitada
deshabilitada con la bandera de interrupcin (IF) del PSW. (CLI en Assembler y disable() 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 lnea).


Ing. Javier Barriga Hoyle 100
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Nonmaskable interrupt request (NMI): Esta disponible para ser utilizada por perifricos
externos que necesiten ser atendidos por el CPU, esta seal no es enmascarable, la peticin de
interrupcin en este caso es capturada dentro del CPU en el flanco de subida (transicin de 0 a
1 de NMI) de la seal NMI y se salta a la rutina de servicio cuando se completa la instruccin
en curso. Esta es utilizada frecuentemente para la deteccin de errores de paridad y otras fallas
mayores del sistema, tales como la falta de energa.
System reset (RESET): Es utilizada para generar una inicializacin completa del procesador
80x86, al pasar a nivel 1, se interrumpe la ejecucin de todo y s inicializan los registros
internos del procesador y cuando vuelve a 0 la seal, 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 interrupcin, 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 ejecucin de instrucciones en la localidad de memoria
FFFF0h (para el 8086) e inhabilita interrupciones futuras restaurando el bit de bandera IF.
INTA: La seal de reconocimiento de interrupcin, es una respuesta a la terminal de entrada
INTR. La terminal INTA es normalmente empleada para ubicar el nmero de vector de
interrupcin en el bus de datos, en respuesta a la solicitud de interrupcin.

INTA
INT
DATOS
80x86
INT
INTA
SP/ EN
DATOS
INT
INTA DATOS
BUS DE DATOS
IRQ0
IRQ1
IRQ3
IRQ4
IRQ5
IRQ6
IRQ7
IRQ8
IRQ9
IRQ10
IRQ11
IRQ12
IRQ13
IRQ14
IRQ15
SP/ EN
1 0
CAS 0
CAS 1
CAS 2
8259A 8259A
(master) (esclavo)

Figura D.2 Diagrama de conexin de la CPU y controladores de interrupciones en la PC.

Impresora
PIC
IRQ7
CPU
INT
INTA
00000H
Vector 0
Vector 1
Vector 15
00004H
Programa de
la RSI
MEMORIA
JMP printer
FFFFFH


Figura D.3 Secuencia de eventos que se generan debido a una interrupcin.

Las lneas de interrupcin (IRQx), estn conectadas a los perifricos tal como muestra la tabla
siguiente. Adems se indica el nivel de prioridades (IRQ0 es la de mayor prioridad)
PC


Ing. Javier Barriga Hoyle 101
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM

Lnea de
interrupcin Dispositivo conectado
* = Puede estar ubicado en otra lnea de IRQ (o podra no estar presente)
Nmero
de 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) 0Bh
IRQ 4 Puerto de comunicaciones serial #1 (COM1) 0Ch
IRQ 5 *Tarjeta de sonido (SOUND BLASTER) 0Dh
IRQ 6 Controlador estndar de disquetes (FDD) 0Eh
IRQ 7 Puerto paralelo (LPT1, tpicamente 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 numricos (FPU) 75h
IRQ 14 Controlador primario IDE 76h
IRQ 15 *Controlador secundario IDE 77h

Tabla D.1 Asignacin de interrupciones en la PC


D.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
RD
WR
82C59A
11
10
9
8
7
6
5
4
27
1
3
2
16
17
26
18
19
20
21
22
23
24
25
IR0
IR1
IR2
IR3
IR4
IR5
IR6
IR7
D0
D1
D2
D3
D4
D5
D6
D7
A0
CS
SP/EN
INT
INTA
12
13
15
CAS0
CAS1
CAS2

Figura D.4. Diagramas del Circuito Integrado 82C59A.

El 82C59 es un IC, diseado para manejar interrupciones, sus principales caractersticas son:
Puede manejar hasta 8 interrupciones.
Puede asignar prioridades a cada interrupcin.
Programable por software.
Permite su conexin con otros PICs (hasta 8 PICs esclavos) de modo que puede llegar a
manejar hasta 64 interrupciones.
Tiene la habilidad de aceptar seales de interrupcin por flancos (edge triggered) o por nivel
(level sensitive).
Tiene la capacidad de indicar al CPU la direccin de la rutina asociada al dispositivo que
genera la interrupcin.
Tiene capacidad de habilitacin o inhabilitacin individual de cada entrada de interrupcin.




Ing. Javier Barriga Hoyle 102
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
D.4 Vectores de interrupcin
Un vector de interrupcin es un conjunto de dos valores, almacenados en 4 bytes del espacio de
memoria, que representan la direccin de memoria donde se encuentra almacenada la rutina de
servicio de interrupcin asociada a una interrupcin. En los primeros dos bytes de un vector, se
encuentra el desplazamiento, y en los dos bytes siguientes se encuentra el segmento de dicha
direccin.

CS_255
IP_255
VECTOR 255
0000 : 03FE h
0000 : 03FC h
CS_254
IP_254
VECTOR 254
0000 : 03FA h
0000 : 03F8 h
CS_1
IP_1
VECTOR 1
0000 : 0006 h
0000 : 0004 h
CS_0
IP_0
VECTOR 0
0000 : 0002 h
0000 : 0000 h
Segmento : Offset

Tabla D.2 Tabla de vectores de interrupcin en la PC.

Despus de que se genera una interrupcin, el CPU debe proceder a ejecutar la rutina de servicio
que atender dicha interrupcin, para esto se dispone de una tabla de vectores de interrupcin. Esta
tabla en el caso de la PC es capaz de soportar hasta 256 interrupciones, cuando se produce una
interrupcin, se necesita el segmento (CS) y el desplazamiento (IP) de la primera instruccin de la
rutina de servicio, estos datos son almacenados en la tabla de vectores de interrupcin:
Al producirse la interrupcin, el CPU determina el nmero del vector asociado a la interrupcin y
salta a la direccin contenida dentro del vector, observe que cada vector utiliza 4 bytes (tabla D.2).

D.5 Instalacin de vectores de interrupcin
Para leer e instalar un vector de interrupcin de una manera cmoda y prctica se hace uso de la
INT 21h del DOS, tal como muestra la siguiente tabla.

14.1 25H 14.2 ESTABLECER EL VECTOR
Entrada AH = 25h
AL = nmero del vector de interrupcin.
DS:DX = Direccin del nuevo procedimiento para el vector de interrupcin.


Notas
Antes de cambiar el vector de interrupcin, se sugiere que el vector de interrupcin
actual sea primero guardado utilizando la funcin 35H del DOS. Esto permite un
vnculo para que el vector original pueda ser posteriormente restaurado.
35H LEER EL VECTOR DE INTERRUPCION
Entrada AH = 35h
AL = nmero del vector de interrupcin.
Salida ES:BX = Direccin archivada en el vector.
Notas Esta funcin del DOS es usada con la funcin 25H para instalar/retirar los
identificadores de los interrupciones.


Ing. Javier Barriga Hoyle 103
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
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 guarda
MOV AH, 35H
MOV AL, 08H ; num. vector 08h
INT 21H
MOV oldvec8_off, BX
MOV oldvec8_seg, ES
; se instala la rutina de interrupcin UPC
MOV DX, OFFSET UPC
MOV AX, SEG UPC
PUSH DS
MOV DS, AX
MOV AH, 25H
MOV AL, 08H ; instala vector
INT 21H
POP DS
/* se lee vector y se guarda */

oldvec8 = getvect (0x08);



/* se instala la rutina de interrupcin UPC */

setvect (0x08, UPC);


D.6 Mscara de interrupcin (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
0 1 2 3 4 5 6 7
IMR (21h):


PIC Esclavo (A0h A1h):
IRQ15 IRQ14 IRQ13 IRQ12 IRQ11 IRQ10 IRQ9 IRQ8
0 1 2 3 4 5 6 7
IMR (A1h):


Ejemplo: Escriba las instrucciones para habilitar la interrupcin del COM1 (IRQ4).

void main()
{
unsigned char oldimr, newimr;
oldimr = inportb(0x21); // lee mascara IMR del PIC
newimr = oldimr & 0xEF; // habilita la IRQ4 (1110 1111b)
outportb(0x21, newimr); // se enva al PIC la nueva IMR
}

Consideraciones previas: Al implementar su RSI, deber tener en cuenta lo siguiente:
La instalacin de vectores de interrupcin y la habilitacin 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-implementacin de bucles
en el interior de la RTI.
Al terminar el programa, deber enviar el EOI: outportb(0x20,0x20);
Tngase en cuenta los niveles de prioridad.





Ing. Javier Barriga Hoyle 104
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
D.7 Instalacin de rutinas de servicio de interrupcin (RSI)
Es la rutina (o procedimiento) asociada a una interrupcin, y ser ejecutada en caso se encuentre
habilitada. Su estructura es similar a un procedimiento convencional, con la salvedad que la
instruccin de retorno es IRET.
Dicha rutina, al estar en memoria, tiene un offset (desplazamiento), y un segmento. Ambos valores
debern ser almacenados en la tabla de vectores de interrupcin (instalacin de los vectores de
interrupcin).

Pasos a seguir para la instalacin / desinstalacin de la RSI: (Suponga la IRQ1 y vector 9h)
Programa principal:
Instalacin:
a) Deshabilitar interrupciones.
b) Leer y Guardar IMR.
c) Modificar el IMR para que permita las interrupciones de la lnea 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 ejecucin del programa (bucle infinito)
Desinstalacin: (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 direccin 20H del espacio de
E/S.


NOTA: Para ejecutar los programas que hagan uso de interrupciones, es necesario que se
utilice el Sistema Operativo Windows 98, ya que los dems (Win2000 y WinXP) no permiten
generar interrupciones, an usando el UserPort.


















Ing. Javier Barriga Hoyle 105
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
Apndice E. ESQUEMATICOS DE ALGUNOS CIRCUITOS

E.1 Salida de datos por LEDS

R2
330
D5
VCC
D1
R6
330
D5
VCC
D6
R0
330
R4
330
D7
D2
D0
D1
D2 D0
D4
R5
330
R3
330
U1
ULN2803A
1
2
3
4
5
6
7
18
17
16
15
14
13
12
9
11 8
10
D0
D1
D2
D3
D4
D5
D6
O0
O1
O2
O3
O4
O5
O6
GND
O7 D7
+V
D7
R7
47
VCC
R1
330
D3
D6 D4
D3
J2
PORT_A
1
2
3
4
5
6
7
8
9
10


E.2 Entrada de datos de 8 bits usando un dipswitch

I4
VCC
I6
I5
J1
PORT_B
1
2
3
4
5
6
7
8
9
10
R1
10K
I7
I1
I3
I2
I0
ON
S1
DIP/SW-8
1
2
3
4
5
6
7
8
16
15
14
13
12
11
10
9
VCC


E.3 Displays (cuatro) multiplexados en BCD

D
6
U2
ULN2003
1
2
3
4
5
6
7
16
15
14
13
12
11
10
8 9
I0
I1
I2
I3
I4
I5
I6
S0
S1
S2
S3
S4
S5
S6
GND X
1K 1K
VCC
D0
Q0
VCC
D3
U1
74LS48
7
1
2
6
4
5
3
13
12
11
10
9
15
14
1
2
4
8
BI/RBO
RBI
LT
A
B
C
D
E
F
G
1K
47
a
b
c
d
e
f
g
Q3
D5
D1
D
5
1K
DIS_2
VCC
D
4
VCC
R1
DIS_0
VCC
D4
D
7
Q1
VCC
DIS_3
D7
VCC
D0
D2
D3
D6
D2
Q2
DIS_1
D1
J1
PORT_A PPI
1
2
3
4
5
6
7
8
9
10
NOTA: LOS DISPLAYS
SON DE ANODO COMUN



Ing. Javier Barriga Hoyle 106
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
E.4 Displays (cuatro) multiplexados en HEXADECIMAL

D0
Q1
DIS_2
1K
Q2
VCC
D4
D
4
1K
DIS_1
D7
D2
Q0
D2
Q3
DIS_0
47
VCC
a
b
c
d
e
f
g
1K NOTA: LOS DISPLAYS
SON DE ANODO
COMUN
D1 D3
D6
VCC
1K
J1
PORT_A PPI
1
2
3
4
5
6
7
8
9
10
DIS_3
U1
MC14495P
5
6
9
10
11
7
12
13
14
15
1
2
3
4
A
B
C
D
I
LE
a
b
c
d
e
f
g
H+I
VCC
D1
D5
VCC
D0
D
6
D3
R1
U2
ULN2003
1
2
3
4
5
6
7
16
15
14
13
12
11
10
8 9
I0
I1
I2
I3
I4
I5
I6
S0
S1
S2
S3
S4
S5
S6
GND X
D
5
VCC
D
7



E.5 Displays (ocho) multiplexados en salida binaria codificada en software

DIS4
R1
1K
VCC
Q1
D5
DIS6
47
Q3 Q2
1K
D
1
1K
D7
Q4
J2
PORT_B PPI
1
2
3
4
5
6
7
8
9
10
D2
DIS5
Q6
NOTA: LOS DISPLAYS SON DE ANODO COMUN
VCC
D1
VCC
D5
D6
Q0
D
4
DIS0 DIS7
1K
VCC VCC
D6
D4
D3
D4
D
2
D
3
1K
D
0
D
5
J1
PORT_A PPI
1
2
3
4
5
6
7
8
9
10
DIS3 DIS2
D3
VCC
D
6
VCC
a
b
c
d
e
f
g
D0
1K
VCC
D2
1K 1K
Q5
VCC
U2
ULN2003
1
2
3
4
5
6
7
16
15
14
13
12
11
10
8 9
I0
I1
I2
I3
I4
I5
I6
S0
S1
S2
S3
S4
S5
S6
GND X
VCC
D
7
DIS1
D0
Q7
VCC
D1



E.6 Control de un motor de pasos con el PORTA del PPI

D3
D3
VCC
D0
VCC
D1
D2
D2
U1
L293D
2
7
10
15
1
9
3
6
11
14
8
16
4
5
13
12
1A
2A
3A
4A
1,2EN
3,4EN
1Y
2Y
3Y
4Y
VS
VSS
GND
GND
GND
GND
VCC
VCC
D0
D1
MG1
MOTOR STEPPER
1
2
3
456
J1
PORT_A PPI
1
2
3
4
5
6
7
8
9
10




Ing. Javier Barriga Hoyle 107
sol_bym@viabcp.com
Soluciones Electrnicas Integradas BYM
E.7 Control de un motor DC usando el TIMER y el PPI (PWM)

ON
SW TIMER
G1
U1
74LS279
1
2
3
5
6
10
11
12
14
15
4
7
9
13
1R
1S1
1S2
2R
2S
3R
3S1
3S2
4R
4S
1Q
2Q
3Q
4Q
GND
+5V
OUT2
VCC
G1
OUT1
PWM
U2
L293D
2
7
10
15
1
9
3
6
11
14
8
16
4
5
13
12
1A
2A
3A
4A
1,2EN
3,4EN
1Y
2Y
3Y
4Y
VS
VSS
GND
GND
GND
GND
Bit0 PortB del PPI
A
-
+
MOTOR DC
1
2
G2
CLK1
SENTIDO
CLK2
CLK1
VCC
G2
CLK2





Bibliografa:

Los Microprocesadores Intel: Arquitectura, programacin e interfaz de los procesadores
8086/8088, 80186/80188, 80286, 80386, 80486, Pentium, Pentium Pro y Pentium II.
Barry B. Brey
Prentice Hall.
ISBN: 970-17-0424-X

Prcticas con Microcontroladores de 8 bits: Aplicaciones industriales
Javier Martnez Prez Mariano Barrn Ruiz
McGraw Hill
ISBN: 84-481-0101-4

Microcontroladores PIC: Diseo prctico de aplicaciones
Jos Ma Angulo Usategui Ignacio Angulo Martnez
McGraw Hill
ISBN: 84-841-2496-0

Amplificadores Operacionales y Circuitos Integrados Lineales
Robert F. Coughlin Frederick F. Driscoll
Prentice Hall
ISBN: 968-880-284-0