Logo Studenta

Laboratorio 7-ARQUITECTURA DE COMPUTADORAS-2020-II

¡Este material tiene más páginas!

Vista previa del material en texto

Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
1 
 
 
 
 
 
 
 
 
UNIVERSIDAD 
 
 NACIONAL DE LA 
 
 AMAZONIA PERUANA 
 
 
 
 
FACULTAD DE INGENIERIA 
 
DE SISTEMAS E INFORMATICA 
 
LABORATORIO DE ARQUITECTURA DE COMPUTADORAS 
 
 
GUIA - INFORME Nº 7 
CURSO : ARQUITECTURA DE COMPUTADORAS 
 TEMA : Buses de Datos 
 PROFESOR : 
 GRUPO : 
 ALUMNO : 
 CODIGO : 
 
 NOTA: 
 
 FECHA EXPE.: SEMEST. ACADÉ. 2020 - II 
 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
2 
 
 
 
7mo LABORATORIO 
Tema: Buses de Datos 
Objetivo: Hacer que el alumno aprenda la comunicación del Arduino con los dispositivos 
conectados a él, como son los protocolos I2C (bus de circuito integrado) y el SPI 
(Interfaz serie de periféricos) 
Material y Equipo: 
 Dispositivos Diversos 
Diodos LED 
 Resistencias 
 Un Protoboard 
 Cablecitos de Conexión 
 Una Tarjeta Arduino Uno 
 Cable USB 
EXPERIENCIA 1: EL BUS I2C 
El bus 12C también conocido como interfaz de dos hilos (two Wire Interface) o abreviadamente: 
bus TWI es una forma simple de comunicar estos dispositivos mediante dos cables. El Arduino 
proporciona este tipo de bus a través de dos de sus patillas llamados SDA y SCL (Figura 1) 
 
 
 
 
 
 
 
 
 
 Figura 1.- Bus I2C 
 
SDA: LINEA DE DATOS 
 
SCL: LINEA DE RELOJ 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
3 
 
 
En el protocolo 12C el Arduino es considerado como dispositivo maestro (master) y cada uno de 
los otros dispositivos externos 12C como esclavos (slaves). Cada esclavo tiene su propia dirección 
expresada como un número hexadecimal que permite al Arduino direccionarlo para comunicarse 
con él. Cada dispositivo tiene un rango posible de direcciones dadas por su fabricante. La dirección 
particular que escogemos es determinada a nivel de conexionado, estableciendo el estado lógico 
de los pines de dirección como se verá más adelante. 
Para usar el bus 12C necesitamos, como en otras ocasiones, incluir en nuestro sketch una librería. 
En este caso será: Wire.h (viene incluida en el iDE). 
#include <Wire.h> 
Después, en el bucle de configuración, activamos el bus I2C mediante la función: 
Wire.begin( ); 
El dato es transmitido en paquetes de un byte. Para enviar un byte de datos desde el Arduino al 
bus precisamos tres funciones: 
La primera inicializa la comunicación con la dirección del dispositivo esclavo. 
Wire.beginTransmission(dirección); 
La segunda función envía un byte (dato) desde nuestro Arduino al dispositivo esclavo previamente 
direccionado. 
Wire.write(dato); 
Finalmente, una vez que hemos de enviar datos al esclavo, utilizamos la siguiente función para 
acabar la trasmisión. 
Wire.endTransmission(); 
Si ahora queremos solicitar datos desde el dispositivo esclavo al Arduino, debemos escribir las 
siguientes dos funciones: 
Wire.beginTransmission(dirección) 
Wire.requestFrom(dirección,x) 
Donde x es el número de bytes que deseamos leer. Para leer los datos que vienen es necesario 
utilizar una variable de la siguiente manera: 
Dentrada = Wire.read(); 
Donde Dentrada es la variable que almacenará ese dato. Finalizaremos la trasmisión utilizando: 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
4 
 
 
Wire.endTransmission(); 
La mejor manera de entender y asimilar lo expuesto es realizar un proyecto para clarificar el uso 
de este protocolo de comunicación tan extendido 
EXPERIENCIA 1.1.- UTILIZACIÓN DE LA MEMORIA I2C 24LC512 
El Arduino tiene una memoria EEPROM interna para guardar datos de forma segura. Sin embargo, 
esta memoria solo puede guardar 1.024 bytes como máximo. En muchas aplicaciones esta 
capacidad es insuficiente. Por ello, podemos echar mano de una memoria externa EEPROM de 
tipo I2C.En esta práctica usaremos la EEPROM 24LC512 (Figura 2) fabricada por Microchip 
Technology. Presenta una capacidad de 64 kB (65,536 bytes) que es más que suficiente en 
proyectos de nivel básico o medio. 
 
 
 
 
 
 
 
 
 Figura 2.- MEMORIA EEPROM 24LC512 
Utilizaremos esta memoria para guardar y recuperar posteriormente 20 datos aleatorios. Se trata 
de observar simplemente cómo funciona este protocolo. 
En cuanto al hardware que necesitamos: 
Una memoria I2C EEPROM 24LC512. 
Dos resistencias de 4.7 kΩ (pull-up). 
Un condensador cerámico de 100 nf. 
Las resistencias pull-up son necesarias siempre que utilicemos este tipo de bus. 
Antes de nada, vamos a echar un vistazo al esquema (Figura 6) porque en este caso es importante 
estudiarlo antes de examinar el sketch. 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
5 
 
 
En el circuito diseñado bajo Proteus observamos que hemos añadido dos instrumentos virtuales 
que nos permiten profundizar en el funcionamiento del bus I2C.Setrata de un instrumento virtual 
(Figura 3) para visualizar en tiempo real el estado lógico del bus, lo que simplifica mucho su 
lectura. El analizador del protocolo I2C te permite controlar e interactuar con el bus I2C.El 
analizador tiene dos propósitos: primero, permitir que veamos los datos enviados por el bus I2C; 
y segundo, proporciona una forma de enviar datos al bus, ya sea como maestro o como dispositivo 
esclavo. Esto hace que sea muy valioso, tanto como instrumento de depuración sino también, para 
desarrollar y probar nuestras propias rutinas de I2C. 
 
 
 
 
 
 
 
 Figura 3.- Instrumento Virtual de Proteus: “I2C” 
 
 
 
 
 
 
 
 Figura 4.- Instrumento Virtual de Proteus: “Terminal Virtual”. 
Como segundo instrumento virtual tenemos el terminal virtual serie (Figura 4) que conectado a las 
líneas serie TX y RX, visualiza mensajes de comprobación de funcionamiento del programa. La 
localización de estos dos instrumentos virtuales se detalla en la siguiente figura 5. 
 
 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
6 
 
 
 
 
 
 
 
 
 
 
 
 Figura 5.- Localización de Instrumentos Virtuales en Arduino 
En la red existe un nuevo modelo de Arduino (Versión 3), el cual presenta importantes mejoras 
gráficas con respecto a loa librería anterior. Se puede descargar gratuitamente del siguiente 
enlace: 
http://blogembarcado.blogspot.com.es/2012/02/simulino-simulando-arduino.html 
Descárgalo e intégralo en Proteus reemplazando la otra librería. Sin duda, está bastante bien 
elaborado a nivel gráfico. Aunque nuestra EEPROM externa puede almacenar hasta 64 kB de 
datos, nuestra práctica tiene solo la intención de demostrar un poco su uso, así que vamos a 
almacenar y recuperar bytes solo en las primeras 20 posiciones de memoria de la EEPROM. 
 
 
 
 
 
 
 
 
 Figura 6.-Diagrama del circuito de uso de la Memoria I2C 24LC512 
 
TERMINAL 
VIRTUAL 
I2C 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
7 
 
 
Programa: Utilizando una memoria I2C: 
/* Ejemplo básico del uso de la EEPROM 24LC512 */ 
/* Aumentando la capacidad de la memoria interna del Arduino */ 
#include <Wire.h> 
#define memoria 0x50 
unsigned int pointer; 
byte d=0; 
void setup() 
{ 
 Serial.begin(9600); 
 Wire.begin(); 
} 
void writeDato(int dispo, unsigned int address, byte dato) 
{ 
 Wire.beginTransmission(dispo); 
 Wire.write((byte)(address>> 8)); 
 Wire.write((byte)(address & 0xFF)); 
 Wire.write(dato); 
 Wire.endTransmission(); 
 delay(10); 
} 
byte readDato(int dispo, unsigned int address) 
{ 
 byte result; 
 Wire.beginTransmission(dispo); 
 Wire.write((byte)(address >> 8)); 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
8 
 
 
 Wire.write((byte)(address & 0xFF)); 
 Wire.endTransmission(); 
 Wire.requestFrom(dispo,1); 
 result = Wire.read(); 
 return result; 
} 
void loop() 
{ 
 Serial.println("Escribiendo Datos..."); 
 for (int a=0; a<20; a++) 
 { 
 writeDato(memoria, a, a); 
 } 
 Serial.println("Leyendo Datos..."); 
 for (int a=0; a<20; a++) 
 { 
 Serial.print("Posicion de la EEPROM "); 
 Serial.print(a); 
 Serial.print("Guarda "); 
 d=readDato(memoria, a); 
 Serial.println(d, DEC); 
 } 
} 
Examinamos el listado anterior. Primero activamos la librería y definimos la dirección del bus I2C 
de la EEPROM como memoria. 
#include <Wire.h> 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
9 
 
 
#define memoria 0x50 
Las entradas A0, Al y A2 son utilizadas por la 2LC512 para establecer la dirección única del 
dispositivo dentro del bus I2C.Los niveles lógicos de estos pines definen parte de la dirección 
elegida por el usuario. La otra parte de la dirección viene establecida de fábrica. En nuestro caso, 
la parte fija es 1010 y como los pines A0, Al y A2 están a cero (porque así lo cableamos), la 
dirección completa es: 1010 000. En la figura 7 se observa el formato completo. 
 
 
 
 
 
 
 
 
 
 
 Figura 7.- Formato del Byte de Control 
También vemos que utiliza un bit de comienzo (Star Bit): bit que indica si queremos leer o escribir 
en el dispositivo (R/W). Otro bit llamado de reconocimiento nos indicará si la trasmisión ha ido 
bien (Acknowledge Bit). 
Por si te pierdes un poco, o para profundizar más en este tipo de protocolo, te recomiendo que 
acudas al siguiente enlace: 
http://www.comunidadelectronicos.com/articulos/i2c.htm 
Las dos funciones personalizadas WriteDato() y readDato() se incluyen para ahorrar tiempo y las 
podremos reutilizar siempre que utilicemos este tipo de memorias. Sirven para escribir y leer datos. 
La función WriteDato() inicia la transmisión con la EEPROM y envía la dirección en donde 
almacenar el byte de datos en la EEPROM. La función readDato() opera en el bus I2Cde la misma 
manera que WriteDato(), pero en lugar de enviar un byte de datos a la EEPROM, se utiliza la 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
10 
 
 
función Wire.requestFrom() para consultar los datos. Por último, el byte de datos enviado desde 
la EEPROM es recibido en una variable (result) y se convierte en el retorno de la función. 
Prestar especial atención a estas dos líneas de código que actualizan constantemente la dirección 
de la memoria: 
Wire.write((byte)(address >> 8)); 
 Wire.write((byte)(address & 0xFF)); 
En el bucle principal se escribe 20 veces el valor o dato en direcciones consecutivas de la 
memoria EEPROM.A continuación se realiza un bucle de nuevo, recuperando los valores y 
mostrándolos en el instrumento terminal virtual (Figura 8) 
En la figura 9 se observa al analizador 12C funcionado. Nos presenta mucha información valiosa 
de la comunicación I2C. Es una herramienta fabulosa para analizar este tipo de circuitos. No 
quiero pensar en lo que tendríamos que gastarnos para adquirir su equivalente en hardware. 
 
 
 
 
 
 
 
 Figura 8.- Terminal Virtual 
 
 
 
 
 
 
 
 Figura 9.- Analizador I2C 
 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
11 
 
 
Por último, bajo Proteus tenemos la posibilidad de examinar el contenido de la memoria EEPROM 
y comprobar si los 20 datos se han guardado correctamente (Figura 10). 
 
 
 
 
 
 
 
 
 
 
 
 
 Figura 10.- Contenido de la Memoria EEPROM 
EXPERIENCIA 1.2.- EXPANDIENDO LOS PUERTOS CON EL I2C MCP23017 
Un «expansor» de puertos es otro integrado útil que se controla a través del bus I2C.Está diseñado 
para ofrecer más salidas digitales. En este proyecto, vamos a utilizar el MCP23017(Figura 11) que 
permite expandir las salidas digitales de tu Arduino (y así no gastarás dinero en comprarte un 
Arduino Mega). 
 
 
 
 
 
 
 Figura 11.- El MCP23017 
 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
12 
 
 
En esta práctica, vamos a conectar el MCP23017 a nuestro Arduino y demostrar cómo controlar 
las 16 salidas de expansión del puerto. Cada una de las salidas del expansor de puertos puede ser 
tratada como un pin digital normal de salida del Arduino. 
En cuanto al hardware que necesitamos: 
• Un MCP23017(es barato: < 3 Euros). 
• Dos resistencias de 4.7 kΩ 
• Algunos diodos leds y resistencias de 200Ω 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Figura 12.- Diagrama del circuito con el I2c MCP23017 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
13 
 
 
Los dieciséis puertos de E/S se distribuyen en dos puertos A y el B. Las resistencias pull-up 
externas de 4.7 K deben utilizarse en el bus I2C obligatoriamente. Por otra parte tenemos la 
dirección de hardware de los tres pines (15 a 17). Estos se utilizan para determinar la dirección del 
bus I2C.Si todos ellos se conectan a GND, la dirección del dispositivo que nosotros elegimos es: 
0x20(hexadecimal). 
Ahora examinaremos cómo utilizar este integrado. La mayoría de los dispositivos I2C tienen 
varios registros que se pueden configurar. Cada dirección contiene un byte de datos que 
determina varias opciones. Así que antes de usarlo necesitamos establecer si cada puerto es una 
entrada o una salida. Vamos a establecer los dos puertos como salidas. Para ello escribimos: 
Wire.beginTransmission(Ox20); 
Wire.beginTransmission(0x20); 
Wire.write(0xoo); // Acceso a Registro A I0DIRA 
Wire.write(0x00); // Pone todos los pines del puerto A 
como salidas. 
Wire.endTransmission(); 
Wire.beginTransmission(0x20); 
Wire.write(0x01); //Acceso a Registro B I0DIRB 
Wire.write(0x00); //Pone todos los pines del puerto B 
 Como salidas. 
 Wire.ednTransmission(); 
Dentro del bucle principal controlamos directamente los pines de cada puerto utilizando el 
siguiente trozo de programa: 
Wire.beginTransmission(0x20); 
Wire.write(0x12); //Dirección del puerto A. 
Wire.write(valor); //valor de envío. 
Wire.endTransmission(); 
 
Wire.beginTransmission(0x20); 
Wire.write(0x13); //Dirección del puerto B 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
14 
 
 
Wire.write(valor); //Valor de envío 
Wire.endTransmission(); 
Las sireccones de los dos registros internos A y B son la 0x12 y 0x13. 
El siguiente sketc reúne todo lo anterior para realizar un encendido secuencial y curios de los 16 
diodos leds conectados a nuestro Arduino tal y como se observa en a figura 12. 
PROGRAMA: Ampliando los pines digitales del Arduino 
/* Utilización básica del MCP2307 */ 
/* Por pines que no sea…..*/ 
#include<Wire.h> 
void setup() 
{ 
Wire.begin(); 
Wire.beginTransmission(0x20); 
Wire.write(0x00); 
Wire.endTransmission(); 
Wire.beginTransmission(0x20); 
Wire.write(0x01); 
Wire.endTransmission(); 
} 
void ContajeBina() 
{ 
for(byte a= 0; a<256; a++) 
{ 
Wire.beginTransmission(0x20);Wire.write(0x12); 
Wire.write(a); 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
15 
 
 
Wire.endTransmission(); 
Wire.beginTransmission(0x20); 
Wire.write(0x13); 
Wire.write(a); 
Wire.endTransmission(); 
} 
} 
void loop() 
{ 
ContajeBina(); 
delay(500); 
} 
Como podrás observar el código muestra un contaje secuencial en los diodos LED mediante la 
estructura for. 
EXPERIENCIA 1.3.- MIDIENDO EL TIEMPO CON EL I2C DS1307 
Cuando necesitemos utilizar el dato del tiempo en nuestros proyectos con Arduino tendremos que 
usar un integrado especializado en esta tarea. Se me ocurre plantear una medida de temperaturas 
que se muestre junto al tiempo en que se ha realizado para proporcionar una mayor información y 
contrastarla en un histograma 
El integrado RTC DS1307 es un reloj de tiempo real con batería de respaldo (RTC= Real Time 
Clock) que permite al Arduino mantener tiempo; hora y fecha, aun si el circuito electrónico en el 
que se encuentra se queda sin energía. Es perfecto para llevar registro de datos, de tiempo, 
temporizadores y alarmas, etc. 
Un reloj de tiempo real (RTC)es básicamente un reloj que funciona con una batería y mantiene la 
hora, incluso cuando hay un corte de energía. El uso de un RTC puede realizar un seguimiento 
durante largos plazos de tiempo. 
Arduino tiene incorporado un reloj interno llamado millis que es utilizado por la función millis(). 
Esta función solo realiza un seguimiento del tiempo transcurrido desde la última vez que se usó 
Arduino. Esto significa que cuando la alimentación se enciende, el temporizador de milisegundos 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
16 
 
 
se ajusta a 0. Nuestro Arduino no sabe que es «lunes» o «09 de abril»: lo único que puede decir es 
«Hace 14.000 milisegundos desde la última vez que me encendí». Si deseamos ajustar la hora en 
el Arduino sin tener el módulo DS1307, tendríamos que establecer y programar la fecha y hora 
para que empiece a contar desde ese momento. Pero dejamos sin la alimentación al Arduino, no 
nos quedaría más remedio que reajustar la hora. Al igual que los relojes de alarma muy baratos: 
cada vez que pierden la alimentación quedan parpadeando con la hora en 12:00. Si bien este tipo 
de cronometraje básico está bien para algunos proyectos, algunos proyectos tales como 
registradores de datos, relojes, etc. tendrán que tener un cronometraje consistente que no se 
desprograme cuando dejamos al Arduino sin alimentación. El integrado RTC se especializa en 
mantener la noción del tiempo. Se pueden contar años bisiestos y saber en qué día o mes estamos. 
Una desventaja es que no puede registrar el cambio de hora por el horario de verano o invierno. 
En la figura 12 y 13 se muestra una plaquita que trae incorporada el integrado DS1307 
(www.bricogeek.com) junto con la batería necesaria (la pila dura unos 9 años con lo que no 
debemos preocuparnos demasiado por ella). Es muy útil adquirirla de esta manera para evitar 
conexionado. 
 
 
 
 
 
 
 
 Figura 12.- DS1307 
 
 
 
 
 
 Figura 13.- Diagrama de conexionado del DS1307 
 
 
http://www.bricogeek.com/
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
17 
 
 
Vamos con la práctica que consistirá en mostrar la fecha y la hora en un LCD utilizando nuestro 
Arduino. Lo primero que tenemos que hacer es descargarnos e instalar la librería RTClib para 
hacernos la vida más fácil 
https://github.com/adafruit/RTClib 
El siguiente paso es configurar nuestro RTC con la fecha y hora actual. En este punto, es necesario 
tener la fecha correcta de nuestro PC, ya que será la que se establecerá en el RTC. Para esto, 
compilaremos y cargaremos el siguiente código. Es de vital importancia que compilemos y 
carguemos el código con la mayor rapidez posible entre un paso y otro, porque cuando compilamos 
se genera un archivo ".hex" con su fecha de modificación y es esta fecha la que se cargará en el 
RTC. 
Programa 1.3.a: Ajuste del RTC 
/* Ajuste de la fecha actual en el RTC DS1307*/ 
/* Igualito que en el desperatdor de nuestro dormitorio */ 
#include<Wire.h> 
#include "RTClib.h" 
RTC_DS1307 rtc; 
void setup() 
{ 
 Wire.begin(); 
 rtc.begin(); 
 rtc.adjust(DateTime(F(__DATE__), F( __TIME__))); 
// rtc.setDate(byte day, byte month, byte year); 
// rtc.setTime(byte hours, byte minutes, byte seconds); 
} 
void loop() 
{ 
 } 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
18 
 
 
La función rtc.adjust(DateTime(F(__DATE__), F( __TIME__))); es la que toma la fecha de tu 
PC y la ajusta en el D51307. Una vez cargado el código anterior, cargamos lo que es código de 
funcionamiento propiamente dicho. 
Programa 1.3.b: El DS1307 mostrando la fecha y la hora en un LCD 
/* Mostrando la fecha y la hora actual en el LCD */ 
/* Ya tenemos construido un reloj básico...*/ 
#include <Wire.h> 
#include <RTClib.h> 
#include <LiquidCrystal.h> 
RTC_DS1307 rtc; 
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 
void setup() 
{ 
 lcd.begin(16, 2); 
 Serial.begin(9600); 
 Wire.begin; 
 rtc.begin; 
} 
void loop() 
{ 
 lcd.clear(); 
 DateTime now = rtc.now(); 
 lcd.setCursor(1,1); 
 lcd.print(now.year(), DEC); 
 lcd.print('/'); 
 lcd.print(now.month(), DEC); 
 lcd.print('/'); 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
19 
 
 
 lc.print(now.day(), DEC); 
 lcd.print('/'); 
 lcd.print(now.hour(), DEC); 
 lcd.print(':'); 
 lcd.print(now.minute(), DEC); 
 lcd.print(':'); 
 lcd.print(now.second(), DEC); 
 lcd.println(); 
 delay(1000); 
} 
Como vemos en el listado anterior, todo se reduce a utilizar la función RTC.now() que nos 
averigua la fecha actual contenida en el D51307 para después mostrarla ordenadamente en el LCD. 
El esquema en Proteus se muestra en la Figura 14. 
 
 
 
 
 
 
 
 
 
 
 
Trabajo Encargado 
Diseña un proyecto que muestre en un LCD, la temperatura medida con un sensor lM35 junto con 
la fecha y la hora en que se ha realizado. 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
20 
 
 
EXPERIENCIA 2.- EL BUS SPI 
El bus SPI difiere del bus I2C en que se puede utilizar para enviar los datos y recibirlos desde un 
dispositivo de forma simultánea y a diferentes velocidades. La comunicación, sin embargo, es 
también del tipo maestro-esclavo. El Arduino actúa como maestro y determina qué dispositivo 
(el esclavo) se comunicará con él a la vez. Cada dispositivo SPI utiliza cuatro pines (Figura 15) 
para comunicarse con un maestro: MOSI (Master-Out, Slave-In), MISO (Master-In, Slave-Out), 
SCK (reloj), y SS o SC (Slave Select o Selección de chip). Estos pines SPI están dispuestos en el 
Arduino como se muestra en la Figura 16. 
 
 
 
 
 
 
 
 
 
 
 
Figura 15.- Pines en Arduino del Bus SPI 
 
 
 
 
 
 
 
 Figura 16.- Conexión Master - Slave 
 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
21 
 
 
Una típica conexión de un dispositivo SPI con el Arduino es las que se muestra en la Figura 7. los 
pines D11, D12 y D13 están reservados para la comunicación SPI, pero el pin SS se puede utilizar 
como cualquier otro pin digital. 
Veamos ahora cómo implementar este protocolo en Arduino. En primer lugar, añadimos la librería 
SPI.h (incluida con el IDE de Arduino). 
#include "SPI.h" 
A continuación,tenemos que elegir un pin que se utilizará para SS y configurarlo como un pin 
digital de salida. Debido a que estamos utilizando solo un dispositivo SPI en nuestro ejemplo, 
vamos a utilizar D10 y configurarlo HIGH primero, porque la mayoría de los dispositivos SPI 
tienen un pin SS activo LOW. 
pinMode (10, OUTPUT) 
digitalWrite (10, HIGH) 
Esta es la función para activar el bus SPI: 
SPI.begin () 
Por último, tenemos que establecer la forma de enviar y recibir datos. Algunos dispositivos SPI 
requieren que sus datos sean enviados junto con el bit más significativo (MSB) en primer lugar, y 
otros requieren que este bit MSB se envíe al final del dato. Por lo tanto, usaremos la siguiente 
función después SPI.begin(): 
SPI.setBitOrder (orden) 
Aquí, el parámetro orden es bien MSBFIRSTo MSBlAST. 
Para enviar datos a un dispositivo SPI, primero establecemos el pin SS en bajo (LOW) que advierte 
al Arduino que desea comunicarse con él. A continuación, enviaremos bytes de datos al dispositivo 
utilizando la función siguiente: 
SPI.transfer(byte) 
Después de que se haya terminado la comunicación con el dispositivo, establecemos el pin SS a 
HIGH para indicar al dispositivo SPI que el Arduino ha finalizado la comunicación con él. 
EXPERIENCIA 2.1.- UTILIZANDO EL POTENCIOMETRO DIGITAL SPI AD5206 
Los potenciómetros digitales son útiles cuando se necesita variar la resistencia en un circuito 
electrónicamente, en lugar de manualmente. Existen multitud de aplicaciones como el 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
22 
 
 
acondicionamiento de señales de audio y de generación de tonos en las que se utilizan los 
potenciómetros digitales. En esta práctica vamos a utilizar un potenciómetro digital de seis canales 
para controlar el brillo de seis LED. Los pasos que cubriremos para implementar la comunicación 
SPI pueden ser modificados para su uso con la mayoría de los otros dispositivos SPI. 
El AD5206 es un potenciómetro digital de 6 canales. Esto significa que tiene seis resistores 
variables (potenciómetros) en un circuito integrado. Hay tres pines en el circuito integrado por 
cada uno de los seis resistores variables internos. Los pines de cada resistor variable están 
etiquetados como AX. BX y WX. Ejemplo: Al, B1 y W1. 
En esta práctica usaremos cada resistor variable como un divisor de tensión; en un lado se conecta 
el pin de tensión alta (pin B), en el otro lado el pin de tensión baja (pin A). El pin central (pin W) 
se conexiona como salida de la tensión variable. 
 
 
 
 
 
 
 
 
 
 Figura 17.-SPI AD5206 
El AD5206 (Figura 17) es controlado digitalmente usando SPI. El dispositivo es habilitado 
poniendo el pin Chip Select (CS) a nivel bajo. Las instrucciones se envían en códigos de 
operaciones (opcodes) de 10 bits con los tres bits más significativos (10-8) definiendo la dirección 
del potenciómetro a ajustar y los ocho bits menos significativos (7-0) estableciendo qué valor 
poner al potenciómetro entre 0 y 255. La transferencia del código de operación empieza con el bit 
más significativo MSB en el flanco de subida de la señal de reloj. En este caso, el AD5206 
proporciona una resistencia máxima de 10 kΩ, entregados en 255 pasos (255 siendo el máximo, 
siendo 0 el mínimo). 
 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
23 
 
 
En esta práctica vamos a variar el brillo de seis leds de forma secuencial, cambiando el valor de 
la resistencia de las patillas W1,W2,W3,W4,W5 y W6 del integrado AD5206. 
En cuanto al hardware necesario: 
• Un potenciómetro SPI AD5206 de 10 kΩ 
• 6 diodos LED 
PROGRAMA: Manejando un Potenciómetro Digital 
/* El potenciometro SPI y Arduino */ 
/* Una manera de esquivar las resistencias */ 
#include<SPI.h> 
const int slaveSelectPin = 10; 
void setup() 
{ 
 pinMode (slaveSelectPin, OUTPUT); 
 SPI.begin(); 
 SPI.setBitOrder(MSBFIRST); 
} 
void loop() 
{ 
 for(int channel = 0; channel < 6; channel++) 
{ 
 for (int level = 0; level < 255; level++) 
 { 
 digitalPotWrite(channel,level); 
 delay(10); 
 } 
 delay(100); 
 for(int level = 0; level < 255; level++) 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
24 
 
 
 { 
 digitalPotWrite(channel, 255 - level); 
 delay(10); 
 } 
 } 
} 
void digitalPotWrite(int address, int value) 
{ 
 digitalWrite(slaveSelectPin, LOW); 
 SPI.transfer(address); 
 SPI.transfer(value); 
 delay(100); 
 digitalWrite(slaveSelectPin, HIGH); 
} 
Después de incluir e inicializar la librería Spi.h, entramos en dos bucles for que van seleccionado 
cada canal y, progresivamente primero, envían valores entre 0 y 255 y, después, entre 255 y cero. 
Con ello, la resistencia aplicada a los diodos varía en intervalos de 10 ms. la función clave de 
este programa es la que se muestra a continuación: 
void digitalPotWrite(int address, int value) 
Activamos el chip mediante la patilla 10 del Arduino conectada al pin SS del ADS206. A 
continuación, le enviamos por SPI la dirección del canal sobre el que deseamos actuar y el valor 
que debe tener su resistencia asociada. Finalmente cerramos comunicación con el dispositivo 
enviando un nivel bajo por el pin SS. 
El esquema de la práctica simulada con Proteus se muestra en la figura 18. 
Trabajo Encargado 
Diseña un proyecto basado en el sensor de temperatura SPI TC72 y un LCD Serial. Puedes 
encontrar su hoja de características en el siguiente enlace: 
http://ww1.microchip.com/downloads/en/DeviceDoc/21743B.pdf 
Universidad Nacional de la Facultad de Ingeniería de 
 Amazonia Peruana Sistemas e Informática 
25 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Figura 18.- Arduino y Potenciómetro Digital 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
	LABORATORIO DE ARQUITECTURA DE COMPUTADORAS

Continuar navegando