Tutoriales

Librería LCD Nokia 6100 para PIC32

Esta librería se puede emplear para controlar una LCD de celular Nokia 6100 mediante un PIC32MX y 4 líneas de control. Te será útil para dibujar imágenes y texto en la pantalla. Para este ejemplo se utilizó la Color LCD - Breakout Board de Sparkfun y la ya antes revisada tarjeta MiE32U para PIC32MX de Microingenia. La librería surge a partir de la mezcla de 2 librerías proporcionadas por Sparkfun: una librería escrita para un microcontrolador LPC y otra para un Atmel.

 

Características de la pantalla Nokia 6100

+ 131 x 131 pixeles
+ Compatible con diversos celulares (6100, 6610, 7210, 7250, and 5100)
+ Comunicación SPI de 9 bits
+ Iluminación integrada (funcional a 7V)
+ 4,096 colores disponibles

La pantalla cuenta con un conector SMD muy pequeño que llega a ser difícil de soldar. Cuento con una pantalla a la que le hice su propia PCB y pude soldar el conector. Sólo bastó proporcionarle una alimentación de 7V, la cual armé con una fuente step-up usando un TC962CPA de Microchip. Posteriormente compré la breakout board de Sparkfun, la cual ya incluye la LCD soldada, 2 tact switches, un LED tricolor, la fuente step-up de 7V a partir de 3.3V y un header para conexiones. Me resultó bastante práctica ya que para cuestiones de prueba es muy versátil.

 


Comunicación SPI

La pantalla usa la interfaz SPI de 9 bits para comunicarse con un microcontrolador. Se emplean 4 líneas para controlarla:

+ Reset
+ DIO, data input output
+ SCK, reloj
+ CS, chip select

Los pulsos para la interfaz SPI pueden generarse por hardware o por software y en la librería que he mezclado se usa el modo software (bit banging).


La librería Nokia_LCD_driver

Esta librería cuenta con 3 archivos:

+ Nokia_LCD_driver.c
Contiene las funciones principales para inicializar la librería, enviarle pixeles y trazar texto
+ Nokia_LCD_driver.h
Contiene defines útiles como los códigos de cada color
+ fonts.c
Contiene 3 tablas con caracteres en tamaños pequeño, mediano y grande

Para utilizar la librería basta con incluir los 3 archivos anteriores mediante una línea #include y definir qué pines se usarán en el PIC32. Nótese la posición del bit en cada define. La librería hace uso perfecto de los registros atómicos del PIC32.

//Librería para la LCD
#define LCD_RES 1      //RB0
#define LCD_DIO 2      //RB1
#define LCD_SCK 4      //RB2
#define LCD_CS     8      //RB3
#include "./lcd_nokia/Nokia_LCD_driver.c"

Los 4 pines se declararán con TRIS de salida.

 


Embebiendo una imagen

Para insertar una imagen a la pantalla se debe hacer pixel a pixel. El contenido de la imagen debe exportarse de archivo .BMP a un archivo .H. Para lograr esto existe la aplicación C Code Image Generator escrito por Jamie Samayoa. Se debe abrir un BMP de 131 x 131 pixeles y exportar el código. Después se guarda el archivo .H en el proyecto. Se debe comentar la primera línea de datos ya que puede resultar inconviente para el código.

// Image format {Width, Height, Bit Depth, Byte Count , Max Frame, ...
// Bit Depth:
//          12b bit: 0x04
//               0000RRRR GGGGBBBB

const unsigned char bmp[] = {
//0x83, 0x83, 0x04, 0x02, 0x00, //comentada
0xF, 0xFF, 0xF, 0xFF, 0xF, 0xFF, 0xF, 0xFF, 0xF


El programa

En este ejemplo se mostrará una pantalla y sobre ella se escribirá texto con una medición del ADC del PIC32MX440F512H directamente en Volts y posteriormente unos saludos. El código es muy simple y creo que no hace falta explicarlo. Si tienes dudas te recomiendo que leas mis 2 tutoriales anteriores sobre PIC32. La conexión PIC32 <-> LCD, del PWM y del ADC es como sigue:

+ RB0 Reset
+ RB1 DIO
+ RB2 SCK
+ RB3 CS
+ RB4 a una señal de 0V a 3.3V (ADC)
+ RD0 a cualquier LED

La LCD se alimenta por los pines VBAT y 3.3V directamente a 3.3V y su línea GND. No hace falta usar una fuente de 7V.


Los archivos fuente del programa se pueden descargar a continuación
La contraseña de descarga es PIC32MXLCD

(Descarga)


/*
Demo de LCD Nokia 6100
MigSantiago.com
*/
#include <p32mx440f512h.h>
#include <plib.h>

////////////////////////////////////////////////////////////////////////////////////////////
//Configurando los osciladores

//Entrada de cristal a 8MHz
//Para CPU será elevada a 80Mhz
#define SYS_FREQ             (80000000L)

//CPU
//XT es de 8MHz y hay que elevarlo a 80MHz
#pragma config FPLLIDIV = DIV_2, FPLLMUL = MUL_20, FPLLODIV = DIV_1
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
#pragma config FSOSCEN = OFF //sin oscilador secundario
////////////////////////////////////////////////////////////////////////////////////////////

//Delays
#define GetInstructionClock()  (80000000L)
#include "TimeDelay.c"

//Librería para la LCD
#define LCD_RES 1      //RB0
#define LCD_DIO 2      //RB1
#define LCD_SCK 4      //RB2
#define LCD_CS     8      //RB3
#include "./lcd_nokia/Nokia_LCD_driver.c"
//Pines a usar
#define TRIS_AD4 TRISBbits.TRISB4 //adc
#define TRIS_PWM TRISDbits.TRISD0

#define SYS_FREQ             (80000000L)
#define PB_DIV                 1
#define PRESCALE               1

//Logotipo
#include "logo.h"

char texto[30];

//////////////////////////////////////////////////////////////////////////////////////////
//tiempo * 250us
void DelayPWM(unsigned int tiempo)
{
BOOL sentido=1;
while(tiempo--)
   {
   Delay10us(25);
   if(sentido)
      {
      ++OC1RS;
      if(OC1RS==1999)
         sentido=0;
      }
   else
      {
      --OC1RS;
      if(OC1RS==0)
         sentido=1;
      }
   }
}
//////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////
//Programa principal
int main()
{
   int i, j, k;
   int pix;
   float voltaje;

   SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

   //disable JTAG port
   DDPCONbits.JTAGEN = 0;

   //Configura pines
   TRIS_PWM = 0; //Salida PWM
   TRIS_AD4 = 1;

    AD1CON2 = 0;
    AD1CON3 = 0x000F; //512 Tpb
    AD1PCFG = 0xFFFF; //todo digital
    AD1PCFGbits.PCFG4 = 0; //menos AN4
    AD1CSSL = 0;          
    AD1CHS=0;
    AD1CHSbits.CH0SA = 4;
    AD1CON1 = 0x8000; //adc on

   //Pines RB0 a RB3 serán para controlar la LCD
   PORTSetPinsDigitalOut(IOPORT_B, LCD_RES | LCD_DIO | LCD_SCK | LCD_CS);

   //Inicializa la pantalla
   LCDInit();

   //Configura OC1 junto con TIMER2 para generar PWM en RD0
   //Duty cycle (es el que cambiara constantemente)
   OC1R = 0; //sólo se debe escribir al inicio
   OC1RS = 0;
   //Modo de operación PWM sin Fault Pin
   OC1CONbits.OCM = 0b110;
   //Elige TIMER2 como origen de comparaciones
   OC1CONbits.OCTSEL = 0;
   //Arranca PWM
   OC1CONbits.ON = 1;
   //TIMER2 corriendo 1:1, 80MHz generará evento cada 25us
   //Periodo PWM = 25us = 40kHz
   //(1999+1)(1/80MHz)=25us
   OpenTimer2(T2_ON | T2_SOURCE_INT | T2_PS_1_1, 1999);

   while(1)
      {
      //Logo
      k=0;
      for(i=0; i<131; ++i)
         for(j=0; j<131; ++j)
            {
            pix=(int)(bmp[k*2]<<8);
            pix|=(int)bmp[k*2+1];
            LCDSetPixel(pix, i, j);
            ++k;
            }

      //Medir ADC
      AD1CON1bits.SAMP = 1; 
      Delay10us(1);
      AD1CON1bits.SAMP = 0; 
      while(!AD1CON1bits.DONE);

      voltaje=(float)ADC1BUF0*0.003225806452; //10 bits @ 3.3V
     
      sprintf(texto, "ADC: %0.2fV", voltaje);
      LCDString(texto, GRA, 5, 34, RED, WHITE);

      sprintf(texto, "Saludos desde");
      LCDString(texto, PEQ, 5, 51, BLUE, WHITE);

      sprintf(texto, "MigSantiago.com");
      LCDString(texto, MED, 5, 66, GREEN, WHITE);

      sprintf(texto, "Nokia LCD 6100");
      LCDString(texto, GRA, 5, 82, BLUE, WHITE);

      sprintf(texto, "PIC32MX440F512H");
      LCDString(texto, GRA, 5, 98, RED, WHITE);

      sprintf(texto, "MiE32U V1.0");
      LCDString(texto, GRA, 5, 114, GREEN, WHITE);

      DelayPWM(5000);
      }
}
//////////////////////////////////////////////////////////////////////////////////////////

Los resultados

El programa dibuja la imagen y el texto correctamente. Además se usa la salida PWM con efecto de desvanecimiento para iluminar uno de los 3 LEDs de la tarjeta de Sparkfun. Prácticamente se puede escribir cualquier cosa en la pantalla ya que la tabla de caracteres contiene todos los caracteres ASCII disponibles.