la librería spi - eldesvandejose.com

Transcripción

la librería spi - eldesvandejose.com
This page was exported from - El desván de Jose
Export date: Fri Dec 23 9:55:54 2016 / +0000 GMT
LA LIBRERÍA SPI
En este artículo vamos a hablar sobre una librería específicamente diseñada para gestionar la transmisión de datos en serie entre una
placa Arduino y un dispositivo cualquiera, como pueda ser una pantalla TFT, una tarjeta shield Ethernet, una SD, o cualquier otro
que admita datos en serie.
Sin embargo, para que, llegado el momento, podamos sacarle partido a esta librería, vamos a conocer, previamente, algunos detalles
sobre las comunicaciones en serie y el protocolo SPI en general, y el puerto ICSP de Arduino en particular.
COMUNICACIONES SERIE Y SPI
SPI (Serial Peripheral Interface, Interface para Periféricos Serie) es un protocolo de transferencia de datos serie sincronizados,
utilizado por microcontroladores para comunicaciones rápidas con uno o más dispositivos. También puede usarse para comunicar
dos microcontroladoras entre sí.
En una conexión SPI siempre hay un dispositivo maestro (normalmente una microcontroladora) que controla los dispositivos
periféricos (conocidos como esclavos). La configuración típica establece tres líneas comunes a todos los dispositivos:
MISO] (Master In Slave Out, Entrada al Maestro, Salida del Esclavo). Es la línea por la que el dispositivo esclavo envía datos al
maestro.
MOSI] (Master Out Slave In, Salida del Maestro, Entrada al Esclavo). Es la línea por la que el dispositivo maestro envía datos al
esclavo.
SCK (Serial Clock). Es la línea por la que se envían los pulsos de reloj con los que el maestro sincroniza las transmisiones.
También existe una línea específica para cada dispositivo esclavo:
SS (Slave Select, Selección de Esclavo). El pin de cada dispositivo esclavo que el maestro emplea para activar o desactivar ese
dispositivo específico. Cuando este pin está a LOW el esclavo está en comunicación con el maestro. Si se pone en HIGH, no existe
dicha comunicación. Esto permite que un mismo maestro se comunique con varios esclavos, usando las mismas líneas MISO, MOSI
y SCK.
Para escribir código para un nuevo dispositivo SPI debes tener en cuenta algunos detalles:
¿Cúal es la máxima velocidad SPI que puede usar tu dispositivo? Esto se controla mediante el primer parámetro en SPISettings (ver
más adelante, en la descripción de la librería). Si estás usando un chip a 15 MHz, establece 15000000. Arduino seleccionará,
automáticamente, la mayor velocidad posible que sea igual o inferior al valor establecido.
¿Los datos se transmiten empezando por el Bit Más Significativo (MSB) o el Bit Menos Significativo (LSB)? Esto se controla en el
segundo parámetro de SPISettings, que puede ser MSBFIRST o LSBFIRST. La mayoría de los chips SPI usan MSB.
¿El reloj está en reposo con nivel HIGH o LOW? ¿Hay muestras de flanco de subida o de bajada de los pulsos de reloj? Estos modos
se controlan con el tercer parámetro de SPISettings.
El estándar SPI es flexible y cada dispositivo lo implementa con pequeñas diferencias. Esto significa que tienes que poner especial
atención a la datasheet de tu dispositivo cuando programes el código.
En general, existen cuatro modos de transmisión. Estos modos controlan cuando se desplazan los datos de entrada y salida, en los
flancos de subida o bajada de la señal de reloj (lo que se llama fase de reloj). Y si el reloj está activo en nivel alto o bajo (lo que se
llama polaridad de reloj).
Los cuatro modos combinan la fase y la polaridad de acuerdo a la siguiente tabla:
Modo
Output as PDF file has been powered by [ Universal Post Manager ] plugin from www.ProfProjects.com
| Page 1/6 |
This page was exported from - El desván de Jose
Export date: Fri Dec 23 9:55:54 2016 / +0000 GMT
Polaridad de reloj (CPOL)
Fase de reloj (CPHA)
SPI_MODE0
0
0
SPI_MODE1
0
1
SPI_MODE2
1
0
SPI_MODE4
1
1
Una vez establecidos los parámetros, usa SPI.beginTransaction() para empezar a usar el puerto SPI, que se configurará con los ajustes
que hayas indicado. La forma más simple y eficiente para establecer los ajustes de SPI es en el propio método SPI.beginTransaction(),
así:
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0));
Si otras librerías están usando interrupciones SPI no podrán acceder a SPI hasta que llames a SPI.endTransaction(). Este método no
cambia los ajustes SPI establecidos. Si tu código, u otra librería, vuelve a iniciar SPI (SPI.beginTransaction() de nuevo), se mantendrán
los ajustes anteriores, a menos que, en la segunda inicialización se cambien explícitamente. Ten esto en cuenta si tu código emplea
más de una librería que use SPI.
Con la mayoría de los dispositivos SPI, después de SPI.beginTransaction(), pondrás el pin SS en LOW, llamarás a SPI.transfer() las veces
que sea necesario para enviar tus datos, pondrás el pin SS en HIGH y cerrarás la conexión con SPI.endTransaction().
CONEXIONES
La siguiente tabla muestra que pines de las distintas tarjetas Arduino se emplean como SPI. En las que la conexión se puede
establecer en un pin digital, o bien en uno específico del puerto ICSP de la tarjeta, aparece así especificado.
Tarjeta Arduino / Genuino
MOSI
MISO
SCK
Output as PDF file has been powered by [ Universal Post Manager ] plugin from www.ProfProjects.com
| Page 2/6 |
This page was exported from - El desván de Jose
Export date: Fri Dec 23 9:55:54 2016 / +0000 GMT
SS (slave)
SS (master)
Nivel
Uno o Duemilanove
11 o ICSP-4
12 o ICSP-1
13 o ICSP-3
10
5V
Mega1280 o Mega2560
51 o ICSP-4
50 o ICSP-1
52 o ICSP-3
53
5V
Leonardo
ICSP-4
ICSP-1
ICSP-3
5V
Due
ICSP-4
ICSP-1
ICSP-3
4, 10, 52
3.3V
Zero
ICSP-4
ICSP-1
ICSP-3
3.3V
Output as PDF file has been powered by [ Universal Post Manager ] plugin from www.ProfProjects.com
| Page 3/6 |
This page was exported from - El desván de Jose
Export date: Fri Dec 23 9:55:54 2016 / +0000 GMT
101
11 o ICSP-4
12 o ICSP-1
13 o ICSP-3
10
10
3.3V
MKR1000
8
10
9
3.3V
Conector ISCP de Arduino
Observa que los pines MISO, MOSI y SCK están disponibles en un conector físico en ICSP. Esto es útil para el diseño de shields que
se adapten a cualquier placa, o para usar estos pines para conectar los correspondientes de cualquier dispositivo SPI. En la imagen se
ve la disposición de los pines en el conector ISCP.
EL PIN SS EN PLACAS BASADAS EN AVR
Todas las placas basadas en microcontroladores de la serie AVR (cómo, p.e. los de Arduino) tienen un pin SS que resulta útil cuando
actúan como esclavos controlados por un maestro externo. Dado que la librería sólo soporta el modo maestro, este pin debería estar
configurado siempre como de salida (OUTPUT). En otro caso la interface SPI podría configurar por hardware el maestro como
esclavo, volviéndose inoperante.
Sin embargo, es posible usar cualquier pin como SS en los dispositivos. Por ejemplo, el shield Ethernet utiliza el pin 4 para controlar
la conexión SPI del slot SD incorporado, y el pin 10 para controlar la conexión del controlador Ethernet.
LA LIBRERÍA SPI
Ahora que ya tenemos algunas ideas claras sobre la comunicación de datos en serie, vamoss a detallar la operativa de la librería SPI.
EL CONSTRUCTOR
El constructor de esta librería es SPISettings. Se emplea para crear un objeto con los ajustes de los que hablábamos anteriormente.
La sintaxis genérica es:
SPISettings objetoSPI (VelMax, OrdenBits, ModoDeDatos);
Los argumentos, que ya hemos comentado antes, son:
VelMax. La velocidad máxima a la que puede transmitir o recibir datos tu dispositivo.
OrdenBits. Si en los bloques de bits que se envían o reciben se transmite primero el bit más significativo (MSB_FIRST) o el menos
significativo (LSB_FIRST).
ModoDeDatos. Establece la fase de reloj y la polaridad de reloj, según la tabla que vimos más arriba.
Estos tres datos debes consultarlos en la datasheet de tu dispositivo.
Output as PDF file has been powered by [ Universal Post Manager ] plugin from www.ProfProjects.com
| Page 4/6 |
This page was exported from - El desván de Jose
Export date: Fri Dec 23 9:55:55 2016 / +0000 GMT
EL MÉTODO begin()
Este método no recibe argumentos. Se emplea en la sección setup (normalmente) para inicializar el bus SPI de la tarjeta Arduino. Su
sintaxis general es la siguiente:
SPI.begin();
EL MÉTODO beginTransaction()
Se emplea para iniciar una comunicación SPI. Si se empleó el constructor la sintaxis será pasándole cómo argumento el objeto de la
clase SPISettings, así:
SPI.beginTransaction(objetoSPI);
Si no se usó SPISettings, o se desea iniciar la comunicación con otros parámetros, la sintaxis será:
SPI.beginTransaction(VelMax, OrdenBits, ModoDeDatos);
EL MÉTODO end()
No recibe ningún argumento. Desactiva el bus SPI. Se emplea cuando nuestro sketch no va a usar más este modo de comunicación.
La sintaxis general es la siguiente:
SPI.end();
EL MÉTODO endTransaction()
Se emplea para indicar la finalización de una transmisión, tras poner a HIGH el pin correspondiente a SS (también llamado CS, en
algunos textos), lo que desactiva la comunicación con el dispositivo esclavo. El uso de ambas operaciones permite que el bus SPI
quede disponible para otras librerías que necesiten usarlo. El método no recibe argumentos y la sintaxis es:
SPI.endTransaction();
EL MÉTODO setBitOrder()
Este método se emplea para cambiar el orden de transferencia de los datos, permitiendo indicar que estos empiezan por el bit más
significativo o el menos. Para ello, recibe como argumento una de las dos constantes Arduino que se emplean para este fin (
MSB_FIRST o LSB_FIRST). La sintaxis genreal es la siguiente:
SPI.setBitOrder(MSB_FIRST);
o bien
SPI.setBitOrder(LSB_FIRST);
Dado que este dato puede establecerse, con carácter general, con SPISettings, o con carácter particular para una transacción concreta
con SPI.beginTransaction(), el método SPI.setBitOrder() está cayendo en desuso, y la documentación oficial lo desaconseja, lo que
induce a pensar que en el futuro quedará obsoleto y podría no ser aceptado por futuras versiones del IDE.
EL MÉTODO setClockDivider()
Este método es una alternativa para establecer la velocidad de transferencia de datos (la velocidad del reloj, que es el que marca los
pulsos, en realidad). Su sintais general es la siguiente:
SPI.setClockDivider(CONSTANTE_DE_DIVISION);
En esta sintaxis, CONTANTE DE DIVISION es una constante de Arduino que establece un divisor sobre la velocidad estándar del
reloj de las placas Arduino, que es de 16 MHz. Así, si le decimos que divida por 2, estaremos estableciendo la velocidad en 8 MHz.
Las divisiones posibles son 2, 4, 8, 16, 32, 64 y 128. Si queremos, por ejemplo, establecer la velocidad en 8 MHz, usaremos la
siguiente sintaxis específica:
SPI.setClockDivider(SPI_CLOCK_DIV2);
En el caso concreto de la placa Arduino Due, la velocidad estándar del reloj es de 84 MHz, en vez de los 16 MHz de otras placas, y el
valor del divisor se puede establecer con un valor entre 1 y 255. Por ejemplo, un valor de 10 fijaría una velocidad de transmisión SPI
de 8,4 MHz.
El uso de este método está desaconsejado por las mismas razones que SPI.setBitOrder().
EL MÉTODO setDataMode()
Establece la fase y polaridad del reloj, mediante una de las constantes que ya conocemos (SPI_MODE0, SPI_MODE1, SPI_MODE2 y
SPI_MODE3). También está desaconsejado, ya que se puede establecer este modo en SPISettings o en SPI.beginTransaction().
EL MÉTODO shiftIn()
Este método es, realmente, una función independiente, es decir, no es parte de la librería SPI. Se usa para leer un byte disponible en
un pin de la placa. Su uso está destinado a leer bit a bit una secuencia de bits, por lo que entre los argumentos de esta función se
establece si esta secuencia empezará por el bit más significativo o el menos. La sintaxis general es la siguiente:
byte entrada = shiftIn(dataPin, clockPin, bitOrder);
Output as PDF file has been powered by [ Universal Post Manager ] plugin from www.ProfProjects.com
| Page 5/6 |
This page was exported from - El desván de Jose
Export date: Fri Dec 23 9:55:55 2016 / +0000 GMT
Los argumentos son los siguientes:
dataPin. Es el pin por el que entran los datos.
clockPin. Es el pin en el que está la señal de reloj. Arduino lo pone a HIGH antes de recibir cada bit y a LOW inmediatamente
después. No tenemos que hacer nada específico para que esto ocurra. La gunción shiftIn() se encarga de gestionar esto.
bitOrder. Es una de las dos constantes, MSB_FIRST o LSB_FIRST.
EL MÉTODO shiftOut()
Es la contraparte de la función anterior. Al igual que esta, no es un método propio de la librería SPI. Su uso es el mismo que la
función anterior, pero para enviar un byte, en lugar de recibirlo. La sintaxis es ligeramente diferente:
shiftOut(dataPin, clockPin, bitOrder, byte);
Los tres primeros argumentos ya los conocemos. El cuarto es el byte que vamos a enviar. La función se encarga de enviarlo bit a bit.
LOS MÉTODOS transfer() y transfer16()
Estos métodos se usan para recibir un byte (el primero) o dos bytes (el segundo). La sintaxis general es:
palabra = SPI.transfer(valor);
dónde palabra sería una variable con un byte de tamaño, o bien
palabra = SPI.transfer16(valor);
dónde palabra sería una variable con 16 bits de tamaño.
Para enviar datos, en lugar de recibirlos, usamos sólo el método SPI.transfer(). La sintaxis general, en este caso, es la siguiente:
SPI.transfer(matriz, tamaño);
Los argumentos son los siguientes:
matriz. Es una matriz de datos para transferir. Los datos son de un byte cada uno (pueden ser byte, o char, por ejemplo).
tamaño. Es el tamaño en bytes que tiene la matriz.
EL MÉTODO usingInterrupt()
Este método permite que, si se usa la librería SPI en un sketch que maneja interrupciones, evitemos conlictos al usar
SPI.beginTransaction(). La sintaxis general es la siguiente:
SPI.usingInterrupt(interrupcion);
En breve publicaremos un artículo sobre interrupciones para entender como funcionan.
Output as PDF file has been powered by [ Universal Post Manager ] plugin from www.ProfProjects.com
| Page 6/6 |

Documentos relacionados