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.
..
Apuntes teoría sensores y material de prácticas para la asignatura del curso Informática Industrial
Mostrando entradas con la etiqueta Programación C. Mostrar todas las entradas
Mostrando entradas con la etiqueta Programación C. Mostrar todas las entradas
29 de enero de 2011
7 de noviembre de 2010
Poner un bit a "0" con AND
En este video se explica la operación que debe realizarse para poner a cero algún bit en un registro.
30 de octubre de 2010
Añadir un formulario al proyecto
Cuando trabajo en un proyecto Borland C++, puedo necesitar más formularios además del principal "Form1". Para añadirlo sólo hay que seleccionar la opción del menú "File/New/Form".
Lo que ocurre entonces es que Borland crea una unidad nueva asociada al formulario. Ambos objetos forman un conjunto. En el formulario se añaden los elementos gráficos y en la unidad el código de cada objeto, función, etc.
Para verlo en HD activa "Pantalla completa" después de iniciar la reproducción.
Lo que ocurre entonces es que Borland crea una unidad nueva asociada al formulario. Ambos objetos forman un conjunto. En el formulario se añaden los elementos gráficos y en la unidad el código de cada objeto, función, etc.
Para verlo en HD activa "Pantalla completa" después de iniciar la reproducción.
18 de octubre de 2010
Prácticas con Builder C
Aquí tenéis dos artículos sencillos que os vendrán bien para repasar las prácticas que realizaremos en el laboratorio con Borland C++ Builder.
Introducción al uso de las unidades (1 página, formato PDF)
Uso de las propiedades de los objetos (2 páginas, formato PDF)
En el primero se introduce el uso de las unidades, que nos permitirán separar el código en bloques independientes. Esta metodología permite acercarnos a la programación modular.
En el segundo artículo, se hace una introducción al uso de las propiedades de los objetos utilizando el panel "Inspector de objetos". Lo utilizarás siempre que tengas que modificar alguna propiedad de los objetos de tu aplicación como botones, cajas de texto, imágenes, etc.
Introducción al uso de las unidades (1 página, formato PDF)
Uso de las propiedades de los objetos (2 páginas, formato PDF)
En el primero se introduce el uso de las unidades, que nos permitirán separar el código en bloques independientes. Esta metodología permite acercarnos a la programación modular.
En el segundo artículo, se hace una introducción al uso de las propiedades de los objetos utilizando el panel "Inspector de objetos". Lo utilizarás siempre que tengas que modificar alguna propiedad de los objetos de tu aplicación como botones, cajas de texto, imágenes, etc.
4 de junio de 2010
Problema de puertos con sentencias "if"
Usando un sistema MCS-51, se pretende controlar un sistema de entradas y salidas según la tabla siguiente:

Observa que las entradas están asociadas al puerto “P0” y corresponden a los bits 5, 6 y 7 (los tres de la parte alta). Las salidas están asociadas al puerto “P1” y corresponden a los bits 0, 1 y 4. Puedes resolver el problema usando “sbits” o desplazando la posición de los bits.
Se pide escribir un programa en C que resuelva el requerimiento. Define los registros “sfr” necesarios y el bloque principal del programa. Comprueba con Keil que funciona.
El procedimiento para resolverlo va a ser definir los “sbits” necesarios (entradas y salidas). Puedes ver como se han definido los "sfr" y "sbits" necesarios:

Para detectar cada una de las combinaciones de entrada, utilizamos sentencias “if”. Como hay sólo cuatro casos, no es excesivamente complicado hacerlo de esta manera:
En la figura anterior tienes cuatro condiciones “if” que supervisan los cuatro estados a detectar en las entradas. Son sentencias independientes, cada una “vigila” una combinación única. Si en las entradas aparece una entrada no contemplada en alguna sentencia “if” sencillamente, el programa no hace absolutamente nada, no la tiene en cuenta. Esta acción de omisión puede generar un problema.
Imagina que se ha detectado la entrada “000”, el programa la detecta con el primer “if” y activa las salidas “000”. Ahora las entradas cambian a “011”, una combinación que no detecta ningún “if”, el programa no hace nada y las salidas mantienen la activación anterior. Aquí está el problema, nuestro programa está manteniendo activas unas salidas cuando detecta una combinación de entradas inexistente, es decir, se activan las salidas cuando no toca.
Para resolver este problema, hay que asegurarse de que el programa detecte el caso “ninguno de los anteriores”. Esto se consigue agrupando las sentencias “else if” en un bloque único donde se comprueban una a una las condiciones y si ninguna cumple, se activa la sentencia “else” final. La condición final pondrá una determinada combinación en las salidas (a determinar). Esto contesta a la nota que se plantea al final del problema:

Nota: Como última consideración, ¿qué pasaría si después de detectar la combinación “000”, en las entradas apareciera un “011”, una entrada no contemplada?

Observa que las entradas están asociadas al puerto “P0” y corresponden a los bits 5, 6 y 7 (los tres de la parte alta). Las salidas están asociadas al puerto “P1” y corresponden a los bits 0, 1 y 4. Puedes resolver el problema usando “sbits” o desplazando la posición de los bits.
Se pide escribir un programa en C que resuelva el requerimiento. Define los registros “sfr” necesarios y el bloque principal del programa. Comprueba con Keil que funciona.
El procedimiento para resolverlo va a ser definir los “sbits” necesarios (entradas y salidas). Puedes ver como se han definido los "sfr" y "sbits" necesarios:

Para detectar cada una de las combinaciones de entrada, utilizamos sentencias “if”. Como hay sólo cuatro casos, no es excesivamente complicado hacerlo de esta manera:
En la figura anterior tienes cuatro condiciones “if” que supervisan los cuatro estados a detectar en las entradas. Son sentencias independientes, cada una “vigila” una combinación única. Si en las entradas aparece una entrada no contemplada en alguna sentencia “if” sencillamente, el programa no hace absolutamente nada, no la tiene en cuenta. Esta acción de omisión puede generar un problema.
Imagina que se ha detectado la entrada “000”, el programa la detecta con el primer “if” y activa las salidas “000”. Ahora las entradas cambian a “011”, una combinación que no detecta ningún “if”, el programa no hace nada y las salidas mantienen la activación anterior. Aquí está el problema, nuestro programa está manteniendo activas unas salidas cuando detecta una combinación de entradas inexistente, es decir, se activan las salidas cuando no toca.
Para resolver este problema, hay que asegurarse de que el programa detecte el caso “ninguno de los anteriores”. Esto se consigue agrupando las sentencias “else if” en un bloque único donde se comprueban una a una las condiciones y si ninguna cumple, se activa la sentencia “else” final. La condición final pondrá una determinada combinación en las salidas (a determinar). Esto contesta a la nota que se plantea al final del problema:

Nota: Como última consideración, ¿qué pasaría si después de detectar la combinación “000”, en las entradas apareciera un “011”, una entrada no contemplada?
1 de junio de 2010
Ejemplo de temporizadores sin usar calculadora
Temporiza 6 segundos con el timer T0 (v.1.1)
Se desea supervisar un sensor (S0) con un microcontrolador compatible 8051. El sensor “S0” está conectado al bit 4 del puerto “P1”. Cuando se detecta un nivel bajo en el sensor “S0”, el bit 7 del puerto “P0” deberá ponerse a nivel alto e iniciarse una temporización de 6 segundos. Cuando finalice este tiempo, el bit 7 del puerto “P0” deberá ponerse a nivel bajo.

Se pide:
Realizar un programa en C que implemente la especificación anterior. Para ello, se deberá contemplar la programación de los registros involucrados (“sfr”), los bits necesarios y la utilización de las variables. La temporización se realizará por encuestas (sin utilizar interrupciones). Considérese que el reloj del sistema funciona a 12 Mhz.
Solución:
Como nos piden una temporización grande, usaremos el modo 1 (16 bits).
desbordamientos_enteros: 6000000/65536=91
resto: 6000000-(91*65536)=36224 (un desborde parcial).
Por lo tanto debemos realizar:
- 91 desbordamientos completos (timer empieza en cero) y
- 1 desbordamiento parcial (timer no empieza en cero).

* Sin calculadora, se deja indicado:
desbordamientos_enteros: 6000000/65536 (91)
resto: 6000000 % 65536 (36224)
El desbordamiento parcial debe temporizar resto (36224 microsegundos).
Para cargar “TH0” y “TL0” con esta cuenta inicial, debemos, como siempre, restar del valor total del temporizador:
cuenta_inicial=65536-36224 = 29312 = 0x7280
TH0 = 0x72;
TL0 = 0x80;
* Sin calculadora, se deja indicado:
cuenta_inicial=65536-resto
TH = cuenta_inicial/256;
TL= cuenta_inicial % 256;
Esta operación anterior “separa” un valor de 16 bits en dos registros de 8 bits. Se hace así porque este micro no permite la asignación de un registro de 16 bits en una operación única.
Ejemplo del programa:
void main (void){
TR1=0;
P0=0x01; // configura línea 0 del puerto P0 como entrada
TMOD=0x01; // modo temporizador, gate=0, modo 16 bits
while (1){
desbordes=92;
if (s0 == 0) {
salida = 1;
TH0 = 29312/256; // carga parcial
TL0= 29312 % 256; // carga parcial
TR0=1;// puesta en marcha del timer
…terminarlo y probarlo…
Se desea supervisar un sensor (S0) con un microcontrolador compatible 8051. El sensor “S0” está conectado al bit 4 del puerto “P1”. Cuando se detecta un nivel bajo en el sensor “S0”, el bit 7 del puerto “P0” deberá ponerse a nivel alto e iniciarse una temporización de 6 segundos. Cuando finalice este tiempo, el bit 7 del puerto “P0” deberá ponerse a nivel bajo.

Se pide:
Realizar un programa en C que implemente la especificación anterior. Para ello, se deberá contemplar la programación de los registros involucrados (“sfr”), los bits necesarios y la utilización de las variables. La temporización se realizará por encuestas (sin utilizar interrupciones). Considérese que el reloj del sistema funciona a 12 Mhz.
Solución:
Como nos piden una temporización grande, usaremos el modo 1 (16 bits).
desbordamientos_enteros: 6000000/65536=91
resto: 6000000-(91*65536)=36224 (un desborde parcial).
Por lo tanto debemos realizar:
- 91 desbordamientos completos (timer empieza en cero) y
- 1 desbordamiento parcial (timer no empieza en cero).

* Sin calculadora, se deja indicado:
desbordamientos_enteros: 6000000/65536 (91)
resto: 6000000 % 65536 (36224)
El desbordamiento parcial debe temporizar resto (36224 microsegundos).
Para cargar “TH0” y “TL0” con esta cuenta inicial, debemos, como siempre, restar del valor total del temporizador:
cuenta_inicial=65536-36224 = 29312 = 0x7280
TH0 = 0x72;
TL0 = 0x80;
* Sin calculadora, se deja indicado:
cuenta_inicial=65536-resto
TH = cuenta_inicial/256;
TL= cuenta_inicial % 256;
Esta operación anterior “separa” un valor de 16 bits en dos registros de 8 bits. Se hace así porque este micro no permite la asignación de un registro de 16 bits en una operación única.
Ejemplo del programa:
void main (void){
TR1=0;
P0=0x01; // configura línea 0 del puerto P0 como entrada
TMOD=0x01; // modo temporizador, gate=0, modo 16 bits
while (1){
desbordes=92;
if (s0 == 0) {
salida = 1;
TH0 = 29312/256; // carga parcial
TL0= 29312 % 256; // carga parcial
TR0=1;// puesta en marcha del timer
…terminarlo y probarlo…
11 de mayo de 2010
Definir puertos como entradas o salidas
Cuando vamos a utilizar los puertos para leer sensores o manejar actuadores debemos especificar si estos puertos serán entradas o salidas, es decir, definir la dirección de los datos.
Para definir todas las líneas del puerto "P0" como entradas:
P0 = 0xFF; // todos los bits del puerto cero como entradas
Para definir un puerto como salidas, no hace falta hacer nada, en este micro, por defecto están configurados como salidas.
Puedes ver un ejemplo en el siguiente código.
Este programa lee un bit del puerto "P0" y activa una salida en el puerto "P1":
sfr P0=0x80;
sfr P1=0x90;
sbit P0_0=P0^0;
sbit P1_7=P1^7;
void main(void){
P0=0xFF; // definimos todo el puerto P0 como entradas
// el puerto P1 configurado como salida por defecto
while (1){
if (P0_0==0) P1_7=1; // comprueba nivel bit P0.0
else P1_7=0;
}}
Nota: Si no tienes en cuenta este paso definiendo la dirección de los datos, cuando simules en el compilador Keil, tendrás un error y en ocasiones el programa podrá terminar inesperadamente.
Prueba a compilar y simular este programa sin definir la dirección de los puertos y observa como al cambiar el estado de los bits en los puertos, el programa se bloquea (trabajando con la versión 2 de Keil).
Para definir todas las líneas del puerto "P0" como entradas:
P0 = 0xFF; // todos los bits del puerto cero como entradas
Para definir un puerto como salidas, no hace falta hacer nada, en este micro, por defecto están configurados como salidas.
Puedes ver un ejemplo en el siguiente código.
Este programa lee un bit del puerto "P0" y activa una salida en el puerto "P1":
sfr P0=0x80;
sfr P1=0x90;
sbit P0_0=P0^0;
sbit P1_7=P1^7;
void main(void){
P0=0xFF; // definimos todo el puerto P0 como entradas
// el puerto P1 configurado como salida por defecto
while (1){
if (P0_0==0) P1_7=1; // comprueba nivel bit P0.0
else P1_7=0;
}}
Nota: Si no tienes en cuenta este paso definiendo la dirección de los datos, cuando simules en el compilador Keil, tendrás un error y en ocasiones el programa podrá terminar inesperadamente.
Prueba a compilar y simular este programa sin definir la dirección de los puertos y observa como al cambiar el estado de los bits en los puertos, el programa se bloquea (trabajando con la versión 2 de Keil).
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;}
}}
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").
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 noviembre de 2008
Uso de unidades en Borland C++
Este mini documento explica muy brevemente el uso de las unidades en los proyectos con Borland C++.
Puedes descargarlo aquí.
Puedes descargarlo aquí.
8 de junio de 2008
Cuestionario Programación en C y uso de máscaras
Estimados alumnos, aquí publico la solución al cuestionario sobre Programación en C y algunos ejercicios del uso de máscaras. Se explica de manera sencilla los conceptos, no obstante, si alguna respuesta no quedase clara, os invito a participar enviándome un correo a fin de poder ampliar la explicación.
También he incluido archivos de audio (mp3) con las respuestas.
Cuestionario resuelto en PDF:
Nota: he detectado que desde Firefox parece que no se abre el PDF, puedes descargarlo poniendo el ratón sobre la imagen y utilizando la opción del botón derecho "Guardar enlace como...".

Audio: Los archivos mp3 son un complemento al documento de texto, te recomiendo que leas primero el documento pdf y después escuches los archivos mp3.
Archivos para escuchar directamente desde la web:
(puede tardar un poco en iniciar la reproducción, ten paciencia)
Pregunta 1, haz clic en 'Play':
Pregunta 2:
Pregunta 3:
Pregunta 4:
Pregunta 5:
Archivos en mp3 para descargar:
Audio pregunta 1
Audio pregunta 2
Audio pregunta 3
Audio pregunta 4
Audio pregunta 5
También he incluido archivos de audio (mp3) con las respuestas.
Cuestionario resuelto en PDF:
Nota: he detectado que desde Firefox parece que no se abre el PDF, puedes descargarlo poniendo el ratón sobre la imagen y utilizando la opción del botón derecho "Guardar enlace como...".

Audio: Los archivos mp3 son un complemento al documento de texto, te recomiendo que leas primero el documento pdf y después escuches los archivos mp3.
Archivos para escuchar directamente desde la web:
(puede tardar un poco en iniciar la reproducción, ten paciencia)
Pregunta 1, haz clic en 'Play':
Pregunta 2:
Pregunta 3:
Pregunta 4:
Pregunta 5:
Archivos en mp3 para descargar:
Audio pregunta 1
Audio pregunta 2
Audio pregunta 3
Audio pregunta 4
Audio pregunta 5
Suscribirse a:
Entradas (Atom)