Mostrando entradas con la etiqueta vuestras dudas. Mostrar todas las entradas
Mostrando entradas con la etiqueta vuestras dudas. Mostrar todas las entradas

21 de abril de 2011

Como buscar información sobre microcontroladores

Un alumno (Óscar) me plantea la siguiente pregunta por correo: "Buenas Luis, tengo que prestar ayuda a un compañero de trabajo ex-alumno tuyo. Necesita encontrar información detallada sobre micros, en concreto de 8 bits, para realizar su proyecto final de carrera. Sería de Motorola e Intel. Si puedes facilitarme algún enlace o archivos pdf de consulta te lo agradecería".

Aprovecho para publicar mi respuesta por si a alguien le resulta de interés:

Bueno, yo creo que la primera opción es entrar en las páginas de los fabricantes. Supongo que estará buscando algunos micros en concreto, allí podrá encontrar los datasheets correspondientes.

Otra opción es buscar estos micros en un proveedor de componentes electrónicos como Farnell, RS, Digikey u otros, allí encontrará información detallada.

En este blog, en la columna de la derecha y abajo hay una lista de sitios web de componentes electrónicos que podría servir.

También puede mirar en sitios como Scribd  o Slideshare  donde se comparten ppts y documentos de todo tipo, también de electrónica, micros, informática..

Por último se me ocurre que Youtube es una opción muy interesante donde los aficionandos a la electrónica publican sus experimentos y donde se puede aprender, buscando como lo harías en Google, poniendo el tipo de micro en el cuadro de búsqueda y navegando por los resultados.

Si alguien quiere recomendar algún sitio web, que ponga un comentario en este post.

19 de abril de 2011

Access violation..Error al depurar un programa en Keil

Cuando ejecutas en Keil paso a paso un programa para un microcontrolador y no has incluido el bucle "while(1){..}" tu programa se ejecutará sólo una vez y al llegar al final, continuará buscando instrucciones, produciendo un error. Supongamos que tenemos un programa así:


Debes añadir un bucle "while(1)" para que no termine su ejecución. Quedaría así:



Descarga el programa aquí.

Bucle "while" con dos condiciones

En ocasiones necesitamos controlar la ejecución de ciertas instrucciones. Se pùede hacer utilizando sentencias tipo "while". Este tipo de sentencias permiten ejecutar las instrucciones del bucle (aquellas que están entre las llaves), mientras la condición sea cierta (flecha verde).

Cuando dicha condición no se cumple (flecha roja), se sale del bucle y se ejecutan las instrucciones que están fuera del mismo.

Si deseamos controlar 15 desbordamientos, nuestro bucle sólo tendrá una condición >> que el número de desbordes sea menor que quince:


El bucle anterior ejecutará las instrucciones mientras la condición sea cierta (desbordes<15). Como se ejecutan las instrucciones del bucle, se comprueba si el temporizador desborda mirando "TF0" e incrementando la variable. Cuando llegue a quince, el bucle termina. En este caso sólo hay una condición.

  Pero ¿cómo haríamos para detener el temporizador si el usuario pulsa "P0_0"?

OPCIÓN I
Si incluimos otra condición que compruebe el puerto, conseguiremos que el temporizador no llegue a la cuenta especificada, ya que saldrá del bucle, pero habrá que detenerlo incluyendo la instrucción "TR0=0":


La explicación es sencilla. El bucle se ejecuta si se cumplan las dos condiciones: que no llegue al máximo de desbordes Y que NO se pulse P0_0.

Cuando se pulse P0_0, al estar negado, su valor en la condición será "0" y la condición será "FALSE" (es una AND) y se terminará el bucle saltando a las instrucciones que haya detrás del mismo, en este caso, la instrucción que desactiva el temporizador (TR0=0).

OPCIÓN 2 (mejor)
También podemos incluir dentro del bucle la comprobación del puerto, de este modo, podemos detener el temporizador, pero nos mantenemos en el bucle, pudiendo reanudar la temporización cuando se deje de pulsar "P0_0". Es una gran diferencia.




17 de abril de 2011

Leer los bits 0 y 4 del puerto "P0"


Observa que la parte del programa principal es "void main(void)" porque no devuelve ningún valor. Sólo realiza una tarea: comprobar los bits 0 y 4 del puerto "P0", pero no devuelve ningún dato.
 Descargar programa.

Puedo poner sólo void main (void)

En el ejercicio del examen, se pedía que se leyeran los bits "b0" y "b4" del puerto "P0" y si alguno de ellos fuera "1" entonces se pusiera a "1" todos los bits del puerto "P1".

Algunos de vosotros en el programa habéis puesto "int main (void)" en el punto de entrada al programa. Recuerda que sólo si el programa devuelve un dato, debes utilizar "int". En nuestro caso, el programa controla unos bits de entrada y activa unos bits de salida, pero no devuelve ningún valor.

El caso en que sí se haría, por ejemplo sería en el caso del cálculo del área de un círculo. Al programa se le pasa el radio y devolvería un entero con el valor del área.

11 de febrero de 2011

SimSeny no se lleva bien con el tratamiento de errores..

Un alumno me envía un problema que tiene al intentar activar una salida. Parece que la tarjeta de inicializa bien, pero al hacer clic en el botón "Activar calefactor" se muestra el siguiente error:


La solución es sencilla, debes ir a la función que genera el error (en este caso "proceso_escribir_calefactor()" y comentar la línea correspondiente a la llamada de la función "proceso_error" (resaltada en color rojo en la imagen de abajo):


Una vez hecho, al activar la salida, podrás ver en el simulador como cambian los niveles y así comprobar que lo estás haciendo bien (que se activa sólo una salida y no todo el puerto por ejemplo):

Con el simulador abierto puedes ir haciendo clic en los botones activar/desactivar calefactor/válvula de tu programa y comprobar si cambian los niveles en las salidas (H/L). Es una manera magnífica de ver si lo estás haciendo bien.

Recuerda que estamos en un entorno de simulación que nos permite trabajar sin tener el "HW". En situaciones reales, deberás tener muy presente el tratamiento de errores para poder determinar, en caso de error, donde puede estar el fallo.
..
..

Diferencias entre el modo manual y el automático

Hay que tener clara la diferencia entre el modo manual y el automático.

En el modo manual, será el usuario el que pueda encender o apagar la válvula, calefactor o cualquier otra salida disponible. En la figura la esfera representa el sistema y las piezas blancas el usuario. Dos salidas, en color azul, están controladas por el usuario en modo manual. Las otras dos salidas siguen estando supervisadas por el sistema (según estrategias y diseño, el modo manual puede no permitir tener el control de todas las salidas).


En el modo manual, no es necesario un temporizador y deberá estar desactivado.
Para ello puedes escribir la siguiente instrucción en tu programa:
"Form1->Timer1->Enabled=false;"

En el modo automático, el temporizador del sistema será el "encargado" de comprobar las entradas y ajustar automáticamente las salidas, a una frecuencia dada. En la figura, la esfera representa el sistema y las cajas los dispositivos a controlar. El color indica que todos los dispositivos están supervisados.


En el modo automático, el usuario pasa a un segundo plano. El temporizador deberá estar encendido.
Para ello puedes escribir la siguiente instrucción en tu programa:
"Form1->Timer1->Enabled=false;"

Al iniciar el programa..los temporizadores deberían estar apagados

En los proyectos se debe incluir uno o varios temporizadores para controlar la frecuencia de refresco de las entradas/salidas. Un alumno me envía un correo comentando los errores que se muestran al iniciar el programa:


Son dos mensajes, uno en el fondo con el título "SimSenyII" y otro delante "ssDAQmxReadAnalogScalarF64()..". Esta claro que el primero es del simulador, que intenta arrancar (cuando se llama a alguna función de la tarjeta) y el segundo corresponde a una función de la tarjeta de adquisición..Estos errores aparecen sin intervención del usuario, nada más arrancar, ésto sugiere que es debido a un temporizador que debería estar parado.

Lo que sucede aquí es bastante frecuente, arrancar la aplicación con los temporizadores ENCENDIDOS. Como el timer se dispara antes de poder inicializar el simulador y la tarjeta, todo salta por los aires, no se puede empezar a usar una función de la tarjeta si antes no se ha inicializado..

Solución: Busca el temporizador en el formulario y desactívalo cambiando su propiedad "Enabled=false", de este modo, al arrancar el programa, el timer estará apagado:


De esta manera el sistema estará inicializado pero detenido hasta que el usuario determine los valores deseados y el modo (manual o automático) .

Si se usa el modo automático, habrá que activar el temporizador:
"Form1->Timer1->Enabled=1" (el timer es el "encargado" de controlar el sistema)

Si se usa el modo manual, habrá que detener el temporizador:
"Form1->Timer1->Enabled=0" (el usuario controla las salidas, el timer no hace falta)

Por último, yo añadiría un botón nuevo con el que puedas inicializar la tarjeta, añade uno al formulario, cámbiale el nombre y haz doble clic en para escribir el código que deberá ejecutarse al pulsarlo:
"proceso_inicializar_proceso();" (inicia la tarjeta y el simulador)

De este modo, cuando arranques la aplicación, pulsa primero en el botón y tendrás las tarjeta lista para usar. A partir de este momento ya puedes llamar a las funciones que quieras.

Esto es una parte de la solución.
Ahora el programa permite inicializar la tarjeta y elegir el modo de funcionamiento, sin errores.
..

10 de febrero de 2011

Funciones mal borradas..funciones desaparecidas

Durante la creación de un programa creas y borras funciones. Cuando borras, como es tan fácil hacerlo, puede ser un arma de doble filo si no lo haces correctamente. Si borras una función también deberás borrar su definición en la cabecera del módulo.

Si no lo haces, el compilador encontrará la definición de una función que le dirá "aquí se ha creado una función con estos argumentos y que puedes encontrar aquí al lado.." y...cuando se va a mirar el código de la función, resulta que no está porque la hemos borrado, así de golpe..

El error es parecido al que sale cuando no se encuentra alguna función de la tarjeta.
Podría ser algo así:


Aparecen un par de errores "[Linker Error] Unresolved external__" que hacen referencia a funciones que fueron creadas por el usuario: "CalentadorClick" y "Button2Click". Estas funciones se crean automáticamente cuando el usuario hace doble clic en algún botón. Si más adelante las borras, porque has eliminado el botón o por cualquier otro motivo DEBES BORRARLAS BIEN.

Para hacerlo correctamente, debes ir al módulo que indica el error y mostrar la cabecera del mismo. Haz clic con el botón derecho sobre el título de la unidad y selecciona "Open Source/Header File":




Una vez hecho, podrás ver el contenido de la cabecera, con todas las definiciones de las funciones usadas en el programa. Podría ser algo así:



Recordando un poco, en la cabecera aparecen todas las definiciones de las funciones creadas. Aquí sólo están sus nombres, argumentos que usarán (void, int, double..) y los datos que devolverán. Para cada función creada en ".cpp" aquí habrá una definición única.

Si borras una función de ".cpp" debes borrarla también de la cabecera ".h". Si no lo haces, el compilador encontrará una definición de la función en la cabecera pero no encontrará la función en el cuerpo del programa y se quejará..con un error tipo "[Link Error]"

La solución pasa por borrar de la cabecera aquellas funciones que el usuario creyó haber borrado (aquellas que aparecen referenciadas en el error).

El error también podría generarse al olvidar algún "include" que impediría encontrar las funciones buscadas, pero lo normal es que sea por el motivo anterior, de hecho si en la cabecera está definida la función y no está en el cuerpo, es casi seguro que la borraste así "de golpe".

Si olvidaras un "include" verías un error de este tipo:


Recuerda: una vez hayas eliminado las definiciones de la cabecera, no olvides volver al cuerpo de la unidad con la misma operación (botón derecho sobre el nombre de la unidad).
.

Cannot convert 'int (*)() to 'int'

Cuando accedemos a las variables del módulo de datos, por ejemplo durante la inicialización del sistema, usamos funciones creadas por el usario. Recuerda que para cada variable asociada a un sensor o actuador, has creado funciones de lectura y escritura. Nos encontramos este error:



En la figura anterior, aparece un error de conversión. Esto puede suceder cuando al llamar a una función, ésta no entiende muy bien los datos que se le pasan o se le devuelve un dato que no coincide con lo esperado. Por ejemplo podría darse el caso de esperar un entero (int) y le ha venido de golpe un doble (double) u otro tipo.

En la instrucción marcada en rojo de la figura, lo que se trata de hacer es actúar sobre la válvula, abriéndola o cerrándola físicamente. El valor que se le pasará será aquel que el usuario haya decidido, haciendo clic en un botón o de cualquier otro modo en el interfaz gráfico. Cuando lo haga, este valor se guardará en el módulo de datos para mantener la imagen del proceso.

Aquí es donde está el problema, en la llamada a la función, se le pasa como parámetro "VerVálvula" pero debería ser "VerVálvula()" ya que es la función del módulo de datos que consulta la variable.

Al olvidar los paréntesis, el compilador busca una variable llamada "VerVálvula" y genera el error porque lo que encuentra es una función.

Recuerda: aunque la función no tenga argumentos - void VerVálvula(void) - al llamarla siempre hay que incluirlos.

No encuentra las funciones de la tarjeta DAQ

Cuando se compila un programa, pueden aparecer muchos errores relacionado con las funciones de la tarjeta de adquisición. Los errores que aparecen pueden parecerse a los siguientes:


Los errores tipo: "[C++ Warnings]", son advertencias pero no detienen la ejecución. La compilación se va a parar en seco cuando encuentre errores de tipo: "[Link Error]". En una de las líneas con este error, dice que no puede encontrar una función externa "DAQmxReadAnalogScalar64..".

Aunque hayamos copiado la librería (fichero.lib) de la tarjeta DAQ en la carpeta del proyecto, quizá no le hayamos indicado al compilador que está allí. El compilador es un poco perezoso y no va a mirar a menos que se lo indiques.

Para resolverlo, activa la opción "View/Project manager", verás la estructura del proyecto:


Lo que ves en la figura anterior es una lista de los ficheros que "mirará" el compilador. Si algo no está en esta "lista", es como si no existiera (aunque físicamente esté copiado en la carpeta del proyecto). Puedes ver todas las unidades del proyecto (ficheros.cpp) y la cabecera de la librería (NIDAQmx.h), pero NO la librería (NIDAQmx.lib). Búscala y añadela.

Selecciona la opción "Project/Add to project", localiza la librería y selecciónala:


Ahora comprueba de nuevo desde "View/Project manager" que la librería ya está en la lista. De este modo, el compilador ya sabe donde se encuentran todas las funciones que necesita para compilar tu programa.


Cuando compiles de nuevo, los errores generados por las funciones de la tarjeta habrán desaparecido, pero nos quedarán otros asociados con las funciones que ha creado el usuario (eso en otro artículo).

29 de enero de 2011

Pregunta de examen

Pregunta de examen (Test Enero 2010):
7. Observa detenidamente el siguiente código en C y determina el valor de la variable “z” una vez ejecutadas todas las sentencias.

int x,y,z;
x=8;
y=4;
if(x=y){z=x*y;}
else{z=x+y;}
a) 0x12
b) 0x0C
c) 0x10

Respuesta:
En la sentencia de comparación "if(x=y) {z=x*y}" es donde está la clave.
Como sabes, una sentencia "if" compara un valor con otro y si se cumple la condición, ejecuta la sentencia que le sigue. Pero la sentencia "if" puede funcionar de manera diferente...si nos olvidamos algo..

En este problema, hay un fallo, la sentencia correcta sería "if(x==y)".
Recuerda que en una comparación siempre deben incluirse dos signos "=".

Por lo tanto al incluir sólo un signo "=", la sentencia NO COMPARA, ASIGNA:

if (x=y) >> ASIGNA EL VALOR DE "y" A "x" (ambas valen ahora 4).
A continuación, se ejecuta la sentencia "{z=x*y}"  z=4*4=16=0x10.

Si tienes curiosidad y quieres comprobarlo, puedes abrir un proyecto en Builder y probarlo.
Añade un objeto tipo "Label" y asígnale el valor de z. Comprobarás que al poner sólo un signo "=" el la etiqueta aparece 16, pero si lo haces correctamente con "==" en la etiqueta aparecerá 12.

..

8 de diciembre de 2010

Duda con una función del módulo de proceso

Un alumno envía una función del módulo de proceso:

int Proceso_leer_rebose(void) {
int32 errdaq;
uInt32 data;
errdaq = DAQmxStartTask(en_dig); //
errdaq = DAQmxReadDigitalScalarU32(en_dig,0.0,&data,NULL);
errdaq = DAQmxStopTask(entradas_digitales);
if ((data & 0x00000001) == 0){
return(REBOSE_HAY);}
else{
return(REBOSE_NO_HAY);
}

Esta función "Proceso_leer_rebose" lee físicamente los pines de la tarjeta para detectar niveles de tensión, usa para ello tres funciones de la tarjeta NI USB-6008 (aparecen resaltadas). Este valor es almacenado en la variable "data".

Como esta variable tiene el valor del puerto completo y queremos mirar sólo un bit, aplicamos una máscara (línea resaltada en verde) para quedarnos con el bit de interés.

De este modo podemos detectar el estado del bit y almacenarlo en el módulo de datos, para que esté a disposición de otras funciones, por lo tanto yo modificaría esta última parte de la función:

if ((data & 0x00000001) == 0){
Datos_escribir_rebose(0);
else
{
Datos_escribir_rebose(1);
}

Por lo tanto la función no devuelve nada, sólo almacena el valor que lee del sensor en el módulo de datos. Esta función "Proceso_leer_rebose" está haciendo uso de la función "Datos_escrbir_rebose" del módulo de datos para guardar esta información. El último cambio que habría que hacer sería redefinir la cabecera de la función para que devuelva "void":

void Proceso_leer_rebose(void) {

Se indica "void" porque la función no devuelve ningún valor. Lo hace a través de las funciones del módulo de datos.

26 de marzo de 2010

Error "Access violation at"...al depurar

Diego (curso 2009-2010) escribe un programa, lo compila con Keil y comienza la depuración. Empieza a usar "F11" para ejecutar paso a paso y encuentra el siguiente error:








El código es el siguiente:

sfr P1=0x90;
sfr P2=0xA0;
void main(void)
{int i;
i=P1&0x07;
switch(i){
case 0:P2=0x3f; break;
case 1:P2=0x06; break;
case 2:P2=0x5b; break; }
}

Cuando se graba un programa en el micro, empieza a ejecutarse inmediatamente desde el punto de entrada (main). Si te fijas, en el programa del ejemplo, sólo se ejecuta una vez ya que no está dentro de ningún bucle.

En un microcontrolador hay que 'encerrar' al programa en un bucle infinito (dentro de un "while"). El motivo es que al grabar el programa en la memoria y comienza la ejecución si no tiene un bucle rápidamente llega al final, pero no se detiene y sigue buscando instrucciones en las posiciones de memoria siguientes, pero como no encuentra nada 'coherente' se genera un error de ejecución. Por lo tanto el programa escrito correctamente sería:

sfr P1=0x90;
sfr P2=0xA0;
void main(void)
{
int i;
while(1) {
i=P1&0x07;
switch(i){
case 0:P2=0x3f; break;
case 1:P2=0x06; break;
case 2:P2=0x5b; break; }
}
}

23 de marzo de 2010

No olvides el punto de entrada al programa

Intenta compilar este programa utilizando Keil:

sfr P1 = 0x90;
sbit e0 = P1^0;
sbit e1 = P1^1;
sbit s0 = P1^4;
sbit s1 = P1^5;
while (1) {
if (e0==0 && e1==0){s0=1;s1=1;}
}

En un programa escrito en Keil, tenemos dos bloques:
1.- La definición de los registros a utilizar (sfr) y
2.- Punto de entrada del programa (main).

En el código anterior, no se ha incluido el segundo bloque, por lo tanto al intentar compilar el programa se produce un error. Recuerda que todo programa debe tener un punto de arranque, por donde empieza la ejecución. Si no incluyes el "main", nuestro programa no funcionará. La versión correcta del programa sería:

// definición de registros
sfr P1 = 0x90;
sbit e0 = P1^0;
sbit e1 = P1^1;
sbit s0 = P1^4;
sbit s1 = P1^5;

// punto de entrada del programa
void main(void) {
while (1) {

if (e0==0 && e1==0)
{s0=1;s1=1;}

}}

22 de marzo de 2010

No tengo claro cuando usar "if" o "while"...

Es una pregunta que me habéis hecho algunos alumnos. El caso es que hay veces que al programar surge la duda. Cuando compruebo una condición puedo utilizar ambas sentencias pero el funcionamiento del programa puede verse afectado si tomo una decisión equivocada.

Pongamos un supuesto. Imagina un comedor. Muchos clientes levantando la mano solicitando atención. Tenemos a un camarero muy especial. Tiene la sorprendente capacidad de poder moverse a la velocidad de la luz. Si algún cliente le llama, se dirige al cliente y le pregunta lo que desea tomar.

El camarero se dirige al cliente y se queda inmóvil esperando. Algunos clientes son rápidos, saben lo que quieren y le entregan al instante la información al camarero. Cuando el camarero recibe la petición, la procesa y la entrega al cliente de manera inmediata.

Algunos clientes se piensan un poco el pedido, están dubitativos, no lo tienen claro o bien han cambiado de opinión. En este caso nuestro supercamarero se queda inmóvil mirando al cliente y espera...

Imagina que el cliente se entretiene. El camarero está inmóvil pendiente del cliente.
Si el cliente no se decide, el camarero seguirá inmóvil esperando. Otros clientes pueden haber levantado la mano, pero el camarero no puede atenderlos porque está bloqueado hasta que el cliente decida que ya no necesita atención.

Este caso descrito representa el uso del "While". Cuando utilizamos esta sentencia, el programa queda bloqueado y "secuestra" el control hasta que la condición del "While" se libera. Con el uso de esta condición, el control del programa queda controlado por las condiciones. Si la condición no se libera (el cliente no se decide a pedir...) el programa (nuestro camarero) quede enganchado dentro de este bucle y no puede hacer nada más.

El problema en esta circunstancia es que mientras el programa está encerrado en el bucle, NO puede hacer otra cosa (aunque otros clientes soliciten atención, nuestro camarero está ocupado). Por lo tanto, de esta manera, nuestro programa se queda aislado frente a otros eventos.

En ciertas circunstancias, no hay más remedio que hacerlo de esta manera. Por ejemplo cuando el camarero atiende al cliente, espera cobrar por ello, por lo tanto, en este caso es obligado incluir una sentencia "While" (el camarero no se irá del lugar hasta que cobre).

Cuando necesitamos que nuestro programa no siga adelante hasta que se cumpla una determinada condición usaremos "While" aún a riesgo de que el programa quede bloqueado hasta que se libere la condición.

Si hubiéramos utilizado la sentencia "if", nuestro camarero hubiera podido atender a otros clientes si alguno no se decide. Como es muy rápido, mientras un cliente se piensa lo que desea tomar, es capaz de atender a muchos porque la sentencia "if" no es bloqueante.

También puedes entenderlo con el siguiente ejemplo. Imagina un pasillo de un hospital, desde un extremo puedes ver todas las puertas de las habitaciones, incluso las más alejadas. También puedes ver los indicadores luminosos en la parte superior del marco de las puertas. Con una sentencia "if" puedes comprobar si algún paciente solicita atención porque puedes ver todos los indicadores luminosos. Sin embargo, si entras en una habitación para atender a un cliente, no podrás ver el resto de indicadores y no podrás atender al resto de clientes hasta que no salgas de la habitación (este caso sería usando "While").

24 de marzo de 2009

Pregunta: Cuando escribes un programa para el microcontrolador de la placa EASY8051B y utlizas los puertos, ¿tienes que definir si son entradas o salidas? ¿puedo utilizar algunos bits del puerto P2 como salidas y el resto como entradas?

Respuesta: Los puertos del 8051 son "quasibidireccionales", esto quiere decir que los puedes usar al mismo tiempo como entradas y como salidas. Solo hay que tener la precaución de poner sus latchs a "1" para que se puedan leer sin problemas o leerás siempre un "0".

28 de junio de 2008

¿Qué son los registros DPL y DPH?

Una pregunta de Francisco:

"Hola Luis: Tengo unas dudas respecto al problema de ensamblador de Junio 2006. Copio el programa literalmente aqui:

org 5000h
Etiqueta1:
MOV R0,30h
Etiqueta2:
MOV DPL, 31h
MOV DPH,32h
MOVX A,@DPTR
INC DPTR
MOV 31h,DPL
MOV 32h,DPH
MOV DPL,33h
MOV DPH,34h
MOVX @DPTR,A
INC DPTR
MOV 33h,DPL
MOV 34h,DPH
DJNZ R0,Etiqueta2end

"Vale pues mi pregunta es la siguiente: cuando pone DPL y DPH ¿cómo lo tengo que considerar?, así a simple vista puedo entender que uno es la parte alta y otro la baja, pero ¿cómo busco eso en las tablas? Saludos y Gracias."

Respuesta del profesor:

El microcontrolador visto en clase dispone de un registro de 16 bits llamado DPTR, pero como no dispone de una instrucción para cargarlo de una vez, debemos hacerlo con dos instrucciones MOV, primero cargando la parte baja (MOV DPL,31h) y luego la parte alta (MOV DPH,32h). Ambos registros puedes verlos en las tablas, te los pongo señalados en la figura siguiente:

Mucho ánimo!!

24 de junio de 2008

Dudas de un problema de examen

En el examen de Junio de 2006, sobre el siguiente problema:

"Se desea controlar un proceso industrial que temporice un tiempo t1 de 1 segundo,
posteriormente otro tiempo t2 de medio segundo y cuando finalice t2 escriba en el puerto
P2 el valor 0xF1 y así sucesivamente. Para ello se utilizará el Timer 0 del microcontrolador Atmel y se programará en modo 16 bits atendido por interrupciones. Para temporizar los tiempos t1 y t2 se utilizará el conteo de desbordamientos. Reloj de 12 Mhz."


Pregunta1: En el enunciado, nos dicen sacar por el puerto P2 el valor en hexadecimal de F1 y sucesivamente. ¿Qué quieren que hagamos?

-R: lo que quería decir (yo puse el problema) es que se enviara dicho valor por el puerto y volviera a comenzar el proceso de nuevo...

Pregunta2: Para calcular los valores de THO y TLO tenemos que calcular el tiempo del ciclo de maquina ¿Qué fórmula se utiliza?

-R: por supuesto, es lo primero que debes hacer porque todos los cálculos se basan en el ciclo de máquina y éste depende de la velocidad de la máquina, a mayor frecuencia, el ciclo de máquina es más 'rápido' (el tiempo que tarda en ejecutar una instrucción es más pequeño ya que el reloj va más rápido). Por lo tanto lo primero es calcular vuestro CM (ciclo máquina) en función de la frecuencia que os den.

Un ejemplo: Supongamo un problema en el que te dan una frecuencia de 12Mhz...

- Primero calcula el inverso para sacar el periodo: 1/12Mhz=0,8333microsegundos.

- Después mira la documentación del micro para ver cuantos ciclos de reloj tiene un ciclo de máquina (Atmel tiene 12CLK por CM, Microchip tiene 4CLK por CM).

- En nuestro caso (Atmel) si ves las transparencias tiene 12, por lo tanto un ciclo de máquina en este micro tardará en ejecutarse: 12x0,8333...= 1microsegundo.

Fíjate que ésto es lo primero que tienes que hacer en un problema, ya que todos los cálculos están basados en el tiempo de ciclo de máquina. Prueba a hacerlo para otras frecuencias como 2Mhz, 10Mhz o 40Mhz.

Pregunta3: Una vez calculado el TCM calculamos el número de cuentas necesarias. Si el número de cuentas es superior a 2^número de bits del temporizador se tiene que obtener el resto que introducimos en THO y TLO. ¿Tiempo total = TCM x Cuentas?

-R: Imagina que te sale una cuenta de 65.781 (una cuenta completa de 65.536 más una parcial de 245), en este caso tendrás que cargar primero el resto 245 en TL0 (TH0=0) para contabilizarlo primero y después dejar que se desborde una vez para completar la cuenta...

Puedes hacerlo al revés, primero la cuenta completa y después la parcial. En ambos casos necesitas una variable que te cuente los desbordamientos.

Resumiendo: cuando la cuenta supera el valor máximo del registro, hay que hacer varias pasadas o desbordamientos para ir 'acumulando', por lo tanto el tiempo total será: TCMxCuentas.