Laboratorio de Estructuras de Computadores. Lab 07. 02/99 Se

Anuncio
Laboratorio de Estructuras de Computadores. Lab 07.
Se dispone del siguiente programa:
02/99
#include <reg51.h>
/* P1.3 Se le da nombre a un bit determinado */
sbit at 0x93 reloj ;
/*Forma de definir la rutina de servicio del timer 0, usando banco de registros 2 */
void timer0(void) interrupt 1 using 2
{
if (reloj == 0) reloj=1 ; else reloj=0;
TH0 = 0xFF;
/* set timer period valor real= 0x63C0*/
TL0 = 0xFC;
/*para simular se coloca valor bajo */
/* 65536-40000=25536=0x63C0 Cálculo de cuenta regresiva del timer en modo 1*/
}
void main(void)
{
/* setup timer 0 interrupt. Inicialización del timer con interrupciones.*/
TMOD = 0x01; /* select mode 1 */
TR0 = 1;
/* start timer 0 */
ET0 = 1;
/* enable timer 0 interrupt */
EA = 1;
/* global interrupt enable */
TCON = 0x30; /* timer on and force interrupt */
/* program main routine, do forever */
while (1) {;}
}
1. Simular, visualizando el timer y la puerta 1. Usar modo animación.
2. Dibujar la forma de onda del reloj, de acuerdo al programa.
3. Escribir programa que genere dos relojes ( P1.3 y P1.4)
P1.3: Está en uno durante 50 mseg y en cero 150 mseg.
P1.4: De ciclo 50 %, se coloca en uno en el canto de bajada de P1.3
Laboratorio de Estructuras de Computadores I. Segundo Semestre 1999.
1
Solución.
1. Para poder observar la salida del puerto1 o del timer 0 fuimos al menú View-Hardware –
y aquí podemos elegir las dos opciones para ver en pantalla.
En port1 se pueden observar los niveles de las 8 salidas, variando en este caso sólo la 3, que
cambiaba de nivel cada vez que se leía el ‘if’.
En el Timer0 se puede apreciar como varía THLO, mostrando su estado, y al producirse un
over-flow, se activa TCON en 0x30, con lo cual el programa se va a la interrupción.
2. Para dibujar la forma de onda debemos ir al menú View-Simbols-(aquí seleccionamos
P1.3 – add watch, luego vamos a View-Trace, donde elegimos en opciones modo continuo, para
poder ver la señal pedida en pantalla.
La señal vista en Proview32 es la siguiente:
3.El programa creado en el laboratorio es el siguiente:
#include <reg51.h>
/*P1.3 Se le da nombre a un bit determinado */
sbit at 0x93 reloj ;
sbit at 0x94 reloj1;
int j=0;
/*Forma de definir la rutina de servicio del timer 0, usando banco de
registros 2 */
void timer0(void) interrupt 1 using 2
{
if (j == 0)
{
reloj=1 ;
reloj1=0;
/*para simular se coloca valor bajo */
/* 65536-40000=25536=0x63C0 Cálculo de cuenta regresiva del timer en
modo 1*/
}
Laboratorio de Estructuras de Computadores I. Segundo Semestre 1999.
2
if (j == 1)
{
reloj = 0;
reloj1 = 1;
}
if (j == 2)
{
reloj = 0;
reloj1 = 1;
}
if (j == 3)
{
reloj=0;
reloj1 = 0;
j=-1;}
else;
TH0 = 0xff;
TL0 = 0xe8;
j++;
}
void main(void)
{
/* setup timer 0 interrupt. Inicialización del timer con
interrupciones.*/
TMOD = 0x1; /* select mode 1 */
TR0 = 1;
/* start timer 0 */
ET0 = 1;
/* enable timer 0 interrupt */
EA = 1;
/* global interrupt enable */
TCON = 0x30; /* timer on and force interrupt */
/* program main routine, do forever */
while (1) {;}
}
La idea principal del programa es dividir la rutina en 4 partes, de modo de setear los niveles
de ambos relojes en tiempos discretos, y no dedicarse todo el tiempo a controlar solamente los
relojes.
Debido a que los tiempos de simulación no permiten trabajar con los valores propuestos en
la pauta, decidimos ocupar valores de manera de mantener la relación en los relojes.
Laboratorio de Estructuras de Computadores I. Segundo Semestre 1999.
3
Otra solución.
Desarrollo experiencia de laboratorio Nº7.
Se dispone del siguiente programa:
#include <reg51.h>
/* P1.3 Se le da nombre a un bit determinado */
sbit at 0x93 reloj ;
/*Forma de definir la rutina de servicio del timer 0, usando banco de registros 2 */
void timer0(void) interrupt 1 using 2 ;
/* Define una rutina de servicio llamada timer0, está asociada a la interrupción uno que
corresponde, en este caso, a una interrupción interna, por hardware, esto es, es el contador quien
llama la interrupción.
Cuando se inicia la ejecución del programa, de inicializan los registros de control con
valores apropiados.
TMOD indica que el contador cuenta en modo de 16 bits.
TR0 = 1 Timmer Ram 1 indica al contador que cuente
ET0 = 1 habilita particularmente a timmer 0 como “generador” de interrupciones. ( ET0
corresponde a un bit del registro IE)
EA = 1 habilita a todas aquellas interrupciones que hayan sido previamente validadas con
los bits demás de control del registro EA.
TCON = 0x30 esta instrucción fuerza la primera interrupción. */
{
if (reloj == 0) reloj=1 ; else reloj=0;
/* Al iniciar la rutina de servicio, se setea o resetea la variable reloj, que en este caso corresponde al
bit 3 de la puerta uno, según la definición que se hace previamente. */
TH0 = 0xFF;
/* set timer period valor real= 0x63C0*/
TL0 = 0xFC;
/*para simular se coloca valor bajo */
/* En estas dos instrucciones, se inicializa el byte alto y el byte bajo del registro contador, que ya se
encuentra preparado para contar en modo de 16 bits, ( TH0 y TL0 son ambos de ocho bits. El
registro contiene entonces 0xFFFC que es el inicio del conteo ascendente, el cual se realiza hasta
que el contador se rebalsa, sobrepasando el valor 0xFFFF.
Si tenemos que el contador cuenta instrucciones ejecutadas (del assembler, no de C), y cada
instrucción tiene un tiempo aproximado de ejecución de un microsegundo, al definir estos valores,
definimos el tiempo que permanecerá en alto ( 1 ) el bit reloj, y cuanto tiempo permanecerá en bajo.
El rebalse ocurre si contador>0xFFFF, luego, nosotros tenemos que el tiempo en alto de la
señal reloj esta dado por la diferencia entre el Primer numero no representable en cuatro bits HEX
y el valor que se pasa al registro contador, el tiempo está expresado en microsegundos, pues cada
incremento de contador tarda un microsegundo
Notar que en este caso, el tiempo que esta reloj en uno es igual al tiempo que permanece en
cero.
Laboratorio de Estructuras de Computadores I. Segundo Semestre 1999.
4
Si se hubiesen considerado los valores indicados en comentarios precedentes, se habría
tenido una señal de período igual a 80 milisegundos ( 40 [ms] en alto y 40 [ms] en bajo ).*/
/* 65536-40000=25536=0x63C0 Cálculo de cuenta regresiva del timer en modo 1*/
}
void main(void)
{
/* setup timer 0 interrupt. Inicialización del timer con interrupciones. */
TMOD = 0x01; /* select mode 1 */
TR0 = 1;
/* start timer 0 */
ET0 = 1;
/* enable timer 0 interrupt */
EA = 1;
/* global interrupt enable */
TCON = 0x30; /* timer on and force interrupt */
/* Al pasar por estas líneas, se inicializan los bits necesarios del control de las interrupciones, como
se indicó anteriormente, */
/* program main routine, do forever */
while (1) {;} /* Al entrar a while, evalúa la condición uno es igual a uno, y como es
siempre verdadera, ejecuta este lazo indefinidamente.
Sin embargo, el contador que se encontraba previamente inicializado con el valor indicado
anteriormente, se incrementa con cada ciclo de reloj hasta el momento en que se produce el rebalse.
En ese momento, se genera la interrupción que invoca a la rutina timmer0, que hace variar al bit
reloj entre uno y cero.
}
1. Simular, visualizando el timer y la puerta 1. Usar modo animación.
Se copia el segmento de texto en el editor del PROVIEW32, se graba como archivo .c, y se
ejecuta.
Timmer0 y puerta uno se encuentran seleccionando el menú VIEW, hardware. Una vez que
se tienen a la vista, nos permite visualizar la evolución de las variables que representan. El modo
animación permite la ejecución paso a paso del programa, ya sea dejándolo correr con una
velocidad regulable desde el panel o paso a paso mediante la tecla F7.
2. Dibujar la forma de onda del reloj, de acuerdo al programa.
Para dibujar la forma de onda, se debe realizar la traza de las variables que nosotros
queremos graficar. La traza se ve en el menú VIEW, TRACE, habiendo previamente agregado al
watch las variables de interés y seteando las opciones de la traza para visualización continua, que se
borre el contenido al reinicializar. La forma de onda se aprecia en la parte inferior de la ventana de
la traza, haciendo clic en el casillero en que se indica el nombre de la variable. En este caso, la señal
corresponde a una onda cuadrada que tiene la características de periodo y ciclo de trabajo antes
mencionados.
3. Escribir programa que genere dos relojes ( P1.3 y P1.4)
P1.3: Está en uno durante 50 mseg y en cero 150 mseg.
P1.4: De ciclo 50 %, se coloca en uno en el canto de bajada de P1.3
#include <reg51.h>
Laboratorio de Estructuras de Computadores I. Segundo Semestre 1999.
5
/* P1.3 Se le da nombre a un bit determinado */
sbit at 0x93 reloj ; /* Bit 0x93, corresponde a la puerta uno, tercer bit.*/
sbit at 0x94 reloj1 ; /* Bit 0x94 corresponde a la puerta uno, cuarto bit.*/
int k=0;
/*Se declara una variable auxiliar k, la cual será usada como un contador */
/*en la rutina de interrupción.*/
/*Con la rutina de servicio se pretende generar las señales en los bits correspondientes de la
siguiente forma:
Primero tenemos que hacer que la rutina de interrupción dure 50 milisegundos, para lo cual
modificamos los valores de TH0 y TL0 con el número correspondiente como se explicó en el punto
anterior. El cálculo nos queda:
0x10000 – 0xc350 = 0x3cb0 ; en donde 0xc350 = 50000 (para lograr tiempo de
50milisegundos=50000 microsegundos) y 0x3cb0 que es el valor que debemos usar para inicializar
el contador( TH0=0x3c , TL0=0xb0 ).
Como cada rutina de interrupción dura 50 milisegundos nuestro programa debe lograr la
siguiente secuencia en cada bit antes definido:
Tiempo en
milisegundos
50
100
150
200
250
300
350
400
Valor de k
Reloj
Reloj1
0
1
2
4
0
1
2
Etc...
0
1
0
0
0
1
0
0
0
1
1
0
0
1
Con el programa que se muestra a continuación se da solución a lo planteado; k es
una variable usada para contar y controlar el ciclo de ejecución del programa.
Notar que se obtiene la sincronización pedida, es decir, cuando el bit 0x93 tiene un canto de
bajada, en el bit 0x94 se tiene un canto de subida .*/
void timer0(void) interrupt 1 using 2
{
if (k == 4) k=0;
if (k == 0)
{
reloj=1 ;
reloj1=0;
k=1;
}
else
{
reloj=0;
if (k==1) reloj1=1;
if (k==3) reloj1=0;
Laboratorio de Estructuras de Computadores I. Segundo Semestre 1999.
6
k=k+1;
}
TH0 = 0x3c;
TL0 = 0xb0;
}
void main(void)
{
/* setup timer 0 interrupt. Inicialización del timer con interrupciones.*/
TMOD = 0x01; /* select mode 1; Registro 81h: indica Timer 0 como contador de 16 bit*/
TR0 = 1;
ET0 = 1;
EA = 1;
P1=0;
TCON = 0x30
while (1) {;}
Laboratorio de Estructuras de Computadores I. Segundo Semestre 1999.
7
Descargar