Hace ya un tiempo que empecé una serie de entradas en las que quería ir mostrándoos cada una de las aplicaciones que podemos desarrollar con la placa de desarrollo MMB for PIC32, de Mikroe. En la primera de ellas, os mostré como utilizando la pantalla tft que lleva incorporada, y el sensor de temperatura, podíamos mostrar la lectura del sensor por el TFT. En esta ocasión , os quiero mostrar una aplicación que utiliza 2 tipos de comunicaciones diferentes. En primer lugar, vamos a utilizar la comunicación SPI (Serial Peripheral Interface), el cual se basa en una comunicación serie síncrona, parecida al I2C (Inter Initegrated Circuits), pero con algunas diferencias significativas. En primer lugar, en general utilizamos 3 hilos para la comunicación, uno para la transmisión de datos (SDO), otro para la recepción (SDI), y otro para enviar la señal de reloj (SCK), mientras que en el I2C, utilizamos tan solo dos, uno bidireccional para datos, y otro para el reloj, con lo que nos limitamos a una comunicación del tipo half-duplex, mientras que con el SPI podemos hacer comunicaciones del tipo full-duplex, aunque no es lo habitual. El sistema de direccionamiento del SPI respecto al I2C, cambia drásticamente, mientras que en el I2C, la dirección del receptor la metemos dentro de la trama de datos, en el SPI debemos utilizar una línea extra (CS), por cada receptor, de esta forma, poniendo la línea CS del receptor con el que queremos comunicarnos a nivel bajo, es este el que empieza a escuchar al bus. Y por ultimo, otra diferencia entre ambos buses es el número de bits que mandamos, mientras que en el I2C, el número máximo de bits que podemos transmitir es de 8 de una vez, el protocolo SPI nos permite mandar, en el caso de PIC32, hasta 32 bits.
Configurar el módulo SPI es sencillo, pero para hacerlo más sencillo todavía, voy a utilizar una libreria para PIC32, que facilita muchísimo las cosas, la plib.h. La línea de configuración quedaría de la siguiente manera:
OpenSPI2( PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | CLK_POL_ACTIVE_LOW | SPI_SMP_ON , SPI_ENABLE); SPI2BRG = 3;
Con este trozo de código, y mediante los OR, vamos poniendo a 1 diferentes bits de los registros SPIxCON y SPIxSTAT. Las dos primeras opciones hacen referencia al registro SPI2BRG, que en la configuración se deja a 0, para luego configurarlo en 3, que corresponde con una frecuencia del SPI de 1MHz.
Una vez configurado el módulo, debemos leer y escribir en el bus, para ello debemos leer o escribir en el registro SPI2BUF. Para hacerlo más entendible, declaramos estos dos #defines#define ReadSPI2() (SPI2BUF) #define WriteSPI2(data_out) (SPI2BUF=(data_out))
Una vez definidas las funciones, no nos queda más que probar nuestro invento, y para ello voy a utilizar el acelerómetro que lleva incorporado la MMB, el cual se comunica con el PIC32 mediante SPI. Lo primero que tenemos que hacer es configurar el acelerómetro, y para ello hay que leer su datasheet, pero básicamente lo que configuramos es el formato de los datos de salida, y la resolución, y queda así:
// Read DEVID register (test) CS_ACC_LAT_BIT = 0; WriteSPI2( 0x80 | 0x00 ); // read DEVID register while( !DataRdySPI2()); w = ReadSPI2(); // dummy WriteSPI2( 0); // dummy while( !DataRdySPI2()); w = ReadSPI2(); // read DEVID CS_ACC_LAT_BIT = 1; if ( w != 0xE5) return 0; // Failed // enable measurement CS_ACC_LAT_BIT = 0; WriteSPI2( 0x00 | 0x2D ); // write to POWER_CTL register while( !DataRdySPI2()); w = ReadSPI2(); // dummy WriteSPI2( 0x08); // set Measure bit ON while( !DataRdySPI2()); w = ReadSPI2(); // dummy CS_ACC_LAT_BIT = 1;
Como veis, siempre se hacen operaciones de lectura y escritura, de esta forma simplificamos el código ya que siempre hacemos las mismas operaciones. En primer lugar mandamos el byte, y una vez enviado leemos el buffer, este dato no nos proporciona información, es un byte dummy. Cuando el acelerómetro nos debe mandar los datos, esta vez enviamos desde el micro un byte dummy, y en esta ocasión, el dato que recibimos si que es válido. Utilizando esta misma forma, podemos también, una vez configurado el módulo SPI, leer los registros de las aceleraciones X, Y y Z. Para ello mandamos la dirección del registro y el acelerómetro nos devuelve su valor. Como en acelerómetro nos devuelve un valor de 12 bits, para cada dirección leemos 2 bytes, X1 y X0, Y1 e Y0 y Z1 y Z0.
void MMBAccRead( int* x, int* y, int*z) { int w; // read acceleration values CS_ACC_LAT_BIT = 0; WriteSPI2(0xC0 | 0x32 ); // read DataX0/X1/Y0/Y1/Z0/Z1 while( !DataRdySPI2()); w = ReadSPI2(); // dummy WriteSPI2(0x00); while( !DataRdySPI2()); *x = ReadSPI2(); // read lsb WriteSPI2(0x00); while( !DataRdySPI2()); *x |= ReadSPI2()<<8; // read msb if (*x >32767) *x-=65536; WriteSPI2(0x00); while( !DataRdySPI2()); *y = ReadSPI2(); // read lsb WriteSPI2(0x00); while( !DataRdySPI2()); *y |= ReadSPI2()<<8; // read msb if (*y >32767) *y-=65536; WriteSPI2(0x00); while( !DataRdySPI2()); *z = ReadSPI2(); // read lsb WriteSPI2(0x00); while( !DataRdySPI2()); *z |= ReadSPI2()<<8; //read msb if (*z >32767) *z-=65536; CS_ACC_LAT_BIT = 1; }
Con este código, almacenamos los valores de X Y y Z en los punteros *x, *y y *z. En cada lectura, como veis, se comprueba si el valor es mayor a 32767, y si lo es se le resta 65536, de esta forma centramos la medida en 0, y obtenemos valores negativos y positivos de aceleración.
Tengo preparada una aplicación con el módulo SPI y la placa MMB, pero como esta entrada me ha quedado bastante larga dejo la aplicación y su vídeo para la próxima. ya veréis que interesante!!
No hay comentarios:
Publicar un comentario