Lo primero que se debe hacer a la hora de escribir un código de comunicación SPI es revisar la hoja de especificaciones del dispositivo con el que vamos hacer la comunicación y buscar el diagrama de tiempos y la tabla de direcciones. Para el LTC1661 tenemos este diagrama:
Recordemos que aún con la librería SPI.h de Arduino sólo podemos enviar paquetes de 8 bits a la vez. Cuando visualizamos esta secuencia nos damos una buena idea de lo que tenemos que hacer en el código. En este caso habrá que dividir la "palabra" de 16 bits que deseamos enviar en dos paquetes de 8 bits cada uno. Así, la secuencia binaria de un 512 (en binario 1000000000) que se traducirá como la mitad del voltaje de referencia para la salida A es:
1001100000000000
(dirección, dato y bits "don't care")
y debe ser divido como:
10011000 y 00000000
Para esto tomaremos una variable que llamaremos "valor" que representará a un dato de 10 bits como valor de voltaje. Es importante recordar que esta variable se declara como entero sin signo que en Arduino es un dato de 16 bits. Para obtener el primer byte será necesario utilizar una variable de tipo char (que es de 8 bits) que llamaremos "temp" y que igualaremos a la variable "valor" después de hacer un corrimiento de 6 bits a la derecha de manera que el entero sin signo 0000001000000000 se convierta en 0000000000001000 y finalmente en el char 00001000. Para agregar la dirección 1001 habrá que sumar simplemente 1001000 a nuestra variable "temp". Toda esta operación en lenguaje Arduino (y también en C) queda:
temp = (valor >> 6) & 0x0F; // Corrimiento a la derecha
temp = 0x90 + temp; // dirección y parte del dato
Teniendo este numero cargado en "char" queda listo para ser enviado con la fusión SPI.transfer(). Para el segundo byte lo único que falta hacer es aplicar un corrimiento de dos bits a la izquierda e igualar a "temp" y volver a enviar con SPI.transfer():
temp = valor << 2;
Como había escrito al principio, es posible que los dispositivos que estén utilizando trabajen con datos de 8 o 12 bits y no 10 como en este ejemplo. Pero en esos casos lo único que habrá que hacer es ajustar el valor de los corrimientos. Si es la primera vez que conectas un dispositivo SPI a un Arduino es importante que sepas cuales son los pines para este tipo de comunicación.
Código completo:
#include <SPI.h>; #include < math.h>;
Aquí pueden encontrar el código para comunicar un PIC18F2550 con un DAC LTC1660.int ss = 10; float t; unsigned valor = 0; void setup(){ pinMode(ss, OUTPUT); SPI.begin(); } void enviar( unsigned int valor_dac){ char temp; digitalWrite(ss, LOW); // CS o SS en bajo temp = (valor_dac << 6) & 0x0F; // Corrimiento a la derecha temp = 0x90 + temp; // dirección y parte del dato SPI.transfer(temp); // envio del primer byte temp = valor_dac << 2; // Corriemiento a la izquierda SPI.transfer(temp); // envío del segundo byte digitalWrite(ss,HIGH); // CS o SS en alto } void loop(){ for (int i; i < 80; i++){ // función de prueba t = t + 0.078; valor = (unsigned int) 511*sin(t)+511; enviar(valor); delay(1); if (t > 2*3.14) t = 0; } }
2 comentarios:
Muy interesante. Un proceso similar se aplicaría a una conexión ADC+Arduino Due por SPI?
Nunca he hecho recepción de datos por SPI pero debe ser más sencillo porque la función debe combinar los dos bytes por si misma.
Publicar un comentario