Mostrando entradas con la etiqueta Multimedia. Mostrar todas las entradas
Mostrando entradas con la etiqueta Multimedia. Mostrar todas las entradas

sábado, 2 de marzo de 2013

Ejemplos MMB. Acelerómetro SPI + Bluetooth UART.

Siguiendo con la entrada anterior, en la que os mostré como configurar el módulo SPI del PIC32 para enviar y recibir datos del acelerómetro, lo siguiente que nos quedaba era utilizar esos datos de aceleraciones que hemos recibido para algo. Lo más sencillo, y que además nos servirá para depurar un poco la aplicación, será mostrar por la pantalla de la MMB. Para ello, utilizamos la libreria LCDTerminal.h, y el código seria el siguiente:
sprintf(s,"Eje X:\t 0d \n", (AccX));
LCDPutString( s);
sprintf(s,"Eje Y:\t 0d \n", AccY);
LCDPutString( s);
sprintf(s,"Eje Z:\t 0d \n", AccZ);
LCDPutString( s);
Como veis el código es extremadamente sencillo, y el resultado es bastante bueno, aunque podemos hacer cosas más interesantes.
Una vez desarrollada la aplicación, y mostradas las aceleraciones en los 3 ejes en la pantalla, se me ocurre que lo siguiente que podríamos hacer, es enviar esos datos al PC, y procesarlos desde un programa en VB.NET.
Para ello lo primer que debemos hacer es convertir los datos que nos devuelven las funciones de lectura del acelerómetro, ya que como os comenté, nos puede devolver tanto valores positivos como negativos, además de un valor que numéricamente no significa nada, ya que el valor que leemos va desde –260 cuando la aceleración es –g, y 260 cuando la aceleración es +g. Estos valores los podemos convertir en un valor que vaya, por ejemplo desde 0 a 180, de forma que nos devuelva el ángulo que tenemos girada la placa en cada dirección. para ello, debemos realizar las siguientes operaciones:
AccX_tx= (AccX + 260) / 2.88;
AccY_tx= (AccY + 260) / 2.88;
AccZ_tx= (AccZ + 260) / 2.88;
Sumándole un offset para obtener valores solo positivos, y multiplicándolo por una ganancia, obtenemos los valores que queremos. Lo siguiente es enviar estos 3 valores, que ahora nos caben en un byte, por el puerto serie del PIC32. Configurar el puerto UART es muy sencillo, y lo hacemos de la siguiente forma. Lo primero nos creamos una definiciones generales que nos pueden servir para cualquier puerto UART de nuestro PIC.
// definiciones RS232
#define BAUDRATE 9600
#define BRGDATA (GetPeripheralClock()/4/BAUDRATE-1)
#define U_ENABLE 0x8008 // enable,BREGH=1, 1 stop, no parity
#define U_TX 0x1400 // enable tx & rx, clear all flags
Para luego configurar el puerto que queramos de forma más sencilla.
//CONFIGURAMOS EL MODULO USART
U2MODE = U_ENABLE; // initialize the UART module
U2STA = U_TX; // enable the Transmitter and Receiver
U2BRG = BRGDATA;
Una vez configurado, solo nos queda enviar los datos, pero para que el PIC no esté enviando los datos de forma continua, lo que hacemos es esperar a recibir un carácter, por ejemplo la ‘e’, desde el PC, y entonces el PIC32 le responde con los 3 valores de los ángulos
if( U2STAbits.URXDA){ //esperamos que llegue un dato nuevo
  if(U2RXREG == 'e'){
      LD2 = !LD2;
      U2TXREG = AccX_tx;
       while(!U2STAbits.TRMT);  //esperamos a que se envíe el dato
       U2TXREG = AccY_tx;
       while(!U2STAbits.TRMT);  //esperamos a que se envíe el dato
       U2TXREG = AccZ_tx;
       while(!U2STAbits.TRMT);  //esperamos a que se envíe el dato
       }
}
En este momento, ya tenemos los datos en el PC, y lo que queda es procesarlos. Buscándo por internet encontré un aplicación que es bastante llamativa. Se trata de un programa en visual basic, que dibuja un cubo 3d en el formulario, y este cubo va girando de forma automática en sus 3 ángulos. El programa lo encontré en la página CodeNTronix. Si a este código lo añadimos en primer lugar la comunicación UART, mediante un objeto SerialPort, le añadimos un Timer que mande al microcontrolador cada 100ms la letra ‘e’, un par de botones que nos permitan conectar y desconectar la placa, y le pasamos los datos que recibimos a los ángulos del cubo, nos podría quedar algo bonito… y así fué! este es el resultado.
Espero que os haya resultado interesante!! en breve subiré todos los archivos para que os lo podáis descargar.

sábado, 23 de febrero de 2013

Ejemplos MMB. Acelerómetro SPI

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!!

viernes, 23 de noviembre de 2012

Ejemplos MMB. Lectura de temperatura.

Como comenté ya hace algún tiempo, en las navidades pasadas me compré la placa MMB for PIC32 de Mikroe. Esta placa monta un PIC32MX460f512 que funciona a 80MHz. La placa lleva un buen puñado de periféricos como son memoria FLASH y EEPROM, acelerometro de 3 ejes, sensor de temperatura analógico… así que he decidido crear un mini sección en el blog dedicada a esta placa. En esa sección iré  colgando diferentes ejemplos en los que se utilicen los distintos periféricos que trae la placa. En una entrada anterior ya os presenté la librería LCDTerminal.h, la cual nos permitía utilizar la pantalla TFT que trae la placa de una forma muy sencilla como si de un terminal se tratase, cosa que nos vendrá muy bien para visualizar diferentes datos.
En la primera de esta serie de entradas, he diseñado un programa que, como no podía ser de otra manera para ser el primero, hace una lectura del sensor de temperatura de la placa y lo muestra por pantalla. La programación que he utilizado es una “especie” de programación orientada a objetos por dos razones, la primera es que el código es más entendible, y la segunda es que muchas de las funciones que utilicemos las podremos luego meter en una librería y reutilizarlas. Cabe decir que con la placa ya viene una librería con funciones para todos los periféricos, pero en mi caso, he preferido crearme yo una librería propia. Así pues, empecemos.
El sensor de temperatura que leva la placa es un MCP9700A, el cual nos da una tensión de 10mV/ºC, con un offset de 0,5 voltios, lo que hace que podamos medir también temperaturas negativas. Para leer esta tensión necesitamos utilizar el módulo ADC del PIC32, por lo que será lo primero que configuremos. Para ello creamos la función initADC().
void initADC( int amask)
{
   AD1PCFG = amask;    // selección de pines analógicos
   AD1CON1 = 0x00E0; // conversión automática despues del muestreo
   AD1CON2 = 0;     // utilizamos MUXA, vdd y vss como referencias
   AD1CON3 = 0x1F3F;  // Tsamp = 32 x Tad;
   AD1CON1bits.ADON = 1;  // ponemos en marcha el ADC

} //initADC
A esta función le debemos pasar la mascara en la que configuramos los pines como analógicos o digitales. La siguiente función que vamos a crear es la que nos va a devolver el valor leído del ADC.
int readADC( int ch)
{
   AD1CHSbits.CH0SA = ch; // 1. select input channel
   AD1CON1bits.SAMP = 1; // 2. start sampling
   while (!AD1CON1bits.DONE); // 3. wait conversion complete
   return ADC1BUF0; // 4. read conversion result
} // readADC
A esta función le debemos pasar el canal analógico que queremos leer, y esta nos devuelve un entero entre 0 y 1024. Una vez tenemos este valor digital, debemos calcular a partir de el la temperatura, la cual almacenaremos en una variable float. Esto lo haremos mediante la función siguiente.
float readTemp(){
 
   float temp;
   temp = readADC(8);
   temp = temp * 330 / 1024;
   temp = temp - 50;
   return temp;

}
Una vez definidas las funciones auxiliares nos queda tan solo escribir el código del main(), en la que llamaremos a las funciones auxiliares. El código es el siguiente.
void main( void)
{
   float temp;
   char s[5];

// INICIALIZAMOS LA PLACA Y EL LCD
   MMBInit();          
   LCDInit();
   BacklightOn();

// SELECCIONAMOS UN COLOR PARA LAS LETRAS
   SetColor( LIGHTBLUE);     

// CONFIGURAMOS EL MÓDULO ADC
   initADC(0xFEFF); 

// MENSAJE
   LCDPutString( "Termometro LCD\nMIPS AND CHIPS\nP. Trujillo");
   LCDSetXY(0,5);

   while( 1){
  
      LCDPutString( "Temperatura:\t");
      temp = readTemp();  
      sprintf( s, "%.2f degC\n", temp);
      LCDPutString( s); 
      delay();
      LCDSetXY(0,5);

 }   
} 
Al código main se han añadido otras funciones para la configuración de la placa, además de todo el código de la visualización. En próximas entradas os podré el código para empezar a almacenar datos en la EEPROM y en la FLASH.

viernes, 6 de julio de 2012

LCDTerminal.h. TFT muy sencillo.

Cuando me compré la placa MMB for PIC32 de Mikroelektronica, de la cual hablé aquí, algo que eché en falta es una interfaz visual que fuera sencilla de utilizar, tipo un LCD de 16x2, para, por ejemplo, mostrar una temperatura, o que nos indique que todo está funcionando bien, al igual que encontramos en la placa EXPLORER16 de Microchip. Esta placa, como la comenté, monta un TFT de 320x240 puntos, lo cual es un periférico muy potente, y por tanto, algo tedioso de manipular, hasta que trabajé con la librería LCDTerminal.h.
La librería en cuestión, nos facilita mucho la labor de mostrar cadenas de texto en la pantalla TFT como si de un terminal se tratara. Esta librería viene en el CD que traen las placas MMB, aunque también la podéis encontrar en la página de Mikroe, y vale para muchos tipos de pantallas TFT con diferentes controladores. Para crear nuestro proyecto, a parte de añadir los archivos LCDTerminal.h, y LCDTerminal.c, hay que añadir las librerias referentes al control de pantallas que encontramos en las Microchip Aplication Libraries/ Graphics, como son graphics.h, Primitive.h y DisplayDriver.h, a parte de sus correspondientes archivos .c.
Como en el caso del STACK TCPIP, disponemos también de un archivo de configuración llamado GraphicsConfig.h, en el cual le decimos que elementos queremos tener disponibles y cuales no, de forma que ahorremos espacio en el micro. Para el caso de utilizar solo la pantalla como terminal, la configuración es la siguiente, que como veréis, es la más sencilla posible.
   1: #ifndef _GRAPHICSCONFIG_H
   2: #define _GRAPHICSCONFIG_H
   3:  
   4: //////////////////// COMPILE OPTIONS AND DEFAULTS ////////////////////
   5:  
   6: /*********************************************************************
   7: * Overview: Blocking and Non-Blocking configuration selection. To
   8: *            enable non-blocking configuration USE_NONBLOCKING_CONFIG
   9: *            must be defined. If this is not defined, blocking 
  10: *            configuration is assumed.
  11: *
  12: ********************************************************************/
  13: //#define USE_NONBLOCKING_CONFIG // Comment this line to use blocking configuration
  14:  
  15: /*********************************************************************
  16: * Overview: Keyboard control on some objects can be used by enabling
  17: *            the GOL Focus (USE_FOCUS)support. 
  18: *
  19: *********************************************************************/
  20: //#define USE_FOCUS
  21:  
  22: /*********************************************************************
  23: * Overview: Input devices used defines the messages that Objects will
  24: *            process. The following definitions indicate the usage of 
  25: *            the different input device:
  26: *            - USE_TOUCHSCREEN - enables the touch screen support.
  27: *            - USE_KEYBOARD - enables the key board support.
  28: *
  29: *********************************************************************/
  30: //#define USE_TOUCHSCREEN            // Enable touch screen support.
  31: //#define USE_KEYBOARD            // Enable key board support.
  32:  
  33: /*********************************************************************
  34: * Overview: To save program memory, unused Widgets or Objects can be 
  35: *            removed at compile time. 
  36: *
  37: *********************************************************************/
  38: //#define USE_GOL                 // Enable Graphics Object Layer.
  39: //#define USE_BUTTON                // Enable Button Object.
  40: // USE_WINDOW                // Enable Window Object.
  41: //#define USE_CHECKBOX            // Enable Checkbox Object.
  42: //#define USE_RADIOBUTTON            // Enable Radio Button Object.
  43: //#define USE_EDITBOX                // Enable Edit Box Object.
  44: //#define USE_LISTBOX                // Enable List Box Object.
  45: //#define USE_SLIDER                 // Enable Slider or Scroll Bar Object.
  46: //#define USE_PROGRESSBAR            // Enable Progress Bar Object.
  47: //#define USE_STATICTEXT            // Enable Static Text Object.
  48: //#define USE_PICTURE                // Enable Picture Object.
  49: //#define USE_GROUPBOX            // Enable Group Box Object.
  50: //#define USE_ROUNDDIAL            // Enable Dial Object.
  51: //#define USE_METER                // Enable Meter Object.
  52: //#define USE_CUSTOM                // Enable Custom Control Object (an example to create customized Object).
  53:  
  54: /*********************************************************************
  55: * Overview: To enable support for unicode fonts, USE_MULTIBYTECHAR  
  56: *            must be defined. This changes XCHAR definition. See XCHAR 
  57: *            for details.
  58: *
  59: *********************************************************************/
  60: //#define USE_MULTIBYTECHAR
  61:  
  62: /*********************************************************************
  63: * Overview: Font data can be placed in two locations. One is in 
  64: *            FLASH memory and the other is from external memory.
  65: *            Definining one or both enables the support for fonts located
  66: *            in internal flash and external memory. 
  67: *    - USE_FONT_FLASH - Font in internal flash memory support.    
  68: *    - USE_FONT_EXTERNAL - Font in external memory support.    
  69: *
  70: *********************************************************************/
  71: #define USE_FONT_FLASH             // Support for fonts located in internal flash
  72: //#define USE_FONT_EXTERNAL        // Support for fonts located in external memory
  73:  
  74: /*********************************************************************
  75: * Overview: Similar to Font data bitmaps can also be placed in 
  76: *            two locations. One is in FLASH memory and the other is 
  77: *            from external memory.
  78: *            Definining one or both enables the support for bitmaps located
  79: *            in internal flash and external memory. 
  80: *    - USE_BITMAP_FLASH - Font in internal flash memory support.    
  81: *    - USE_BITMAP_EXTERNAL - Font in external memory support.    
  82: *
  83: *********************************************************************/
  84: #define USE_BITMAP_FLASH        // Support for bitmaps located in internal flash
  85: //#define USE_BITMAP_EXTERNAL        // Support for bitmaps located in external memory
  86:  
  87: /*********************************************************************
  88: * Overview:
  89: *   Graphics on the MMB Board 
  90: *                                        
  91: ********************************************************************/
  92: #define LCD_WRAP
  93: #define LCD_SCROLL
  94: //#defin LCD_OVERLAY
  95: #define LCD_BACK    BLACK
  96: #define LCD_FORE    WHITE
  97:  
  98: #endif // _GRAPHICSCONFIG_H
Para ahorrar la faena de añadir los archivos .c y .h, os recomiendo que os descarguéis los ejempos de MMBforPIC34MX4, y ahi dentro encontrareis uno que se llama TEST, ese proyecto utiliza la pantalla como terminal, además de utilizar muchos de los periféricos que trae a placa, por lo que es muy sencillo, a partir de este ejemplo, empezar a crear nuestros proyectos.
Las funciones básicas que encontramos en la libreria LCDTerminal son las siguientes :
  • LCDCenterString( n, cadena): Muestra un texto centrado horizontamente en la pantalla. El valor n, es el numero de lineas por encima o por debajo de la linea central horizontal donde aparecerá nuestro texto.
  • LCDPutString( cadena): Muestra un texto con alineación a la izquierda.
  • SetColor( color): Establece el color del texto siguiente.
  • LCDSetXY( x, y): Mueve el cursor hasta la posición X, Y seleccionada.
  • LCDClear(): Borra el contenido de la pantalla y lleva el cursr a la posición X = 0, Y = 0.
  • LCDHome(): Lleva el cursor a la posición X = 0, Y = 0.
  • LCDLineHome(): Mueve el cursor al valor X = 0, el valor Y lo deja como está.
Con todo esto ya podemos crear un pequeño ejemplo para ver el funcionamiento de la librería. El ejemplo que he creado nos muestra una pantalla inicial, y cuando movemos el joystick hacia cualquier posición, pasamos a un menú desde el cual podemos encender o apagar los leds. Veréis que aparecen otras funciones como MMBGetKey(), la cual nos devuelve la posición a la que se ha movido el joystick.

   1:  
   2: #include "MMB.h"
   3: #include "LCDTerminal.h"
   4: #include "Graphics\Graphics.h"
   5: //#include "MDD File System\FSIO.h"
   6: //#include "SerialFLash.h"
   7:  
   8: // Configuration bits 
   9: #pragma config POSCMOD = XT, FNOSC = PRIPLL, FSOSCEN = ON
  10: #pragma config FPLLIDIV = DIV_2, FPLLMUL = MUL_20, FPLLODIV = DIV_1, FPBDIV = DIV_1
  11: #pragma config OSCIOFNC = ON, CP = OFF, BWP = OFF, PWP = OFF
  12:  
  13: // fonts
  14: extern const FONT_FLASH TerminalFont;
  15:  
  16: int main( void)
  17: {
  18:     char opc = 0, sel = 0;
  19:     int i = 0;
  20:     char dir = 0;
  21:  
  22:     MMBInit();          // Inicialización de la placa MMB
  23:     LCDInit();            // Inicialización de la libreria gráfica.
  24:  
  25: //---- TEXTO DE LA PANTALLA INICIAL.
  26:  
  27:     SetColor( LIGHTBLUE);     
  28:  
  29:     LCDCenterString( -5, "EJEMPLO MENU LCD");
  30:     LCDCenterString( -3, "P.Trujillo");
  31:     LCDCenterString( -2, "MIPS AND CHIPS");
  32:     SetColor( BRIGHTYELLOW);
  33:     LCDCenterString( 0, "www.mipsandchips.blogspot.com.es");
  34:     SetColor( WHITE);
  35:     LCDCenterString(  2, "(Mueva el joystick ");  
  36:     LCDCenterString(  3, "para continuar) ");  
  37:     MMBFadeIn( 250);    
  38:     MMBGetKey();    //esperamos a que se pulse un botón.
  39:     LCDClear();     
  40:     
  41:     LCDSetXY(3,2);
  42:     LCDPutString("Selecciona una opcion:\n");
  43:     LCDSetXY(0,5);
  44:     LCDPutString(" > Encender LEDs.\n   Detener LEDs.");
  45:     while( 1)
  46:     {      
  47:         LCDSetXY(0,5);
  48:  
  49:         switch(MMBGetKey()){
  50:     
  51:             case JOY_UP:
  52:                 LCDPutString(" > Encender LEDs.\n   Detener LEDs.");
  53:                 opc = 1;
  54:                 break;
  55:             case JOY_DOWN:
  56:                 LCDPutString("   Encender LEDs.\n > Detener LEDs.");
  57:                 opc = 2;
  58:                 break;
  59:             case JOY_SELECT:
  60:                 sel = opc;
  61:                 break;
  62:                 
  63:         }
  64:             if (sel == 1)
  65:                 LATA = 0x0;
  66:             else
  67:                 LATA = 0xf;    
  68:     
  69:     } 
  70: } 
Aquí tenéis unas imágenes de las dos pantallas que tenemos en el proyecto, ya que en el video no se ve demasiado bien.
IMG_1965

IMG_1966

Y a continuación un video demostrativo.


Haré más proyectos con esta librería ya que resulta muy sencillo hacer un proyecto que, a simple vista, parecen muy complejos.