Tuto. 6 - Graphic LCD

PIC tutorial 6 - Graphic LCD

Print
Category: PIC Tutorials
Published Date Written by Francois

Tutorial 6a

Fig. 1a Board 4 with graphic LCD display

Description:

The 6th tutorial in the series, we'll look at using LCD display, alphanumeric or graphic. The graphic display is taken from an old Nokia 3310 mobile phone.
You will need a processor board, a power supply, the alphanumeric and the graphic LCD display.

The tutorial will build a library to be able to control and use the graphic display. The alphanumeric library was already built in previous tutorial.
It also shows with a simple example how a program can be configured to run on different boards.

It displays a counter on the display, either alphanumeric or graphic. It shows how to easily switch between display types.

You can download the files for this tutorial in the zip file pic_tutorial6.zip.

The boards can be powered by one of the PSU boards (powered from USB port), or between 2.7 to 5V.

Requirements:

Processor boardAny board (board 4 in example)

Extension(s)Alphanumeric and graphic LCD Display

Power supplyPSU 1, 2 or 3. Depends on board used.

LanguageCCS C

ProgrammerPicKIT 2


Program:

#define board_id 4
#include "lib\mainboard.c" // Load board module
#if (board_id == 1) // Load alphanumeric or graphic lcd library
  #include "lib\lcd_lib.c"
#else
  #include "lib\nok3310_lib.c"
#endif
int8 counter;
void main() {
  boot_up();
  counter = 0;
  init_display();
  while (true) {
    printf(display_putc, "\fH=%X, D=%u", counter, counter);
    counter ++;
    delay_ms(250);
  }
}

The program defines the processor board used and load the display library. If using board 1, it loads the alphanumeric library, else the graphical one.

Once all libraries are loaded, the processor board, the counter and LCD display are initialised.

The main loop is then entered: we display the counter after clearing the screen (with the \f character) in 2 different format: hexa and decimal. The counter is incremented anda delay of 250ms is inserted.
The counter is incremented 4 times a second.

Now to the graphic LCD display library.

#ifndef _NOK3310_LIB
  #define _NOK3310_LIB
  // To modify accordingly to your hardware
  #byte nokia3310_port = pb // Port where graphic LCD is connected
  #byte tris_nokia3310 = trisb
  #bit nokia3310_sck = nokia3310_port.3
  #bit nokia3310_sdi = nokia3310_port.6
  #bit nokia3310_dc = nokia3310_port.5
  #bit nokia3310_cs = nokia3310_port.4
  #bit nokia3310_res = nokia3310_port.2
  // End of zone to modify
  // variables used by library
  int8 charsel;
  // function prototypes
  void Init_Nok3310(void);
  void Nok3310_clean_ddram(void);
  void Nok3310_wr_data(int8 bytefornokia_data);
  void Nok3310_wr_cmd(int8 bytefornokia_command);
  void Nok3310_wr_dorc(int8 bytefornokia);
  void Nok3310_gotoxy(int8 xnokia, int8 ynokia);
  void Nok3310_erase_y(int8 ynokia);
  void Nok3310_erase_x(int8 xnokia);
  void Nok3310_putc(int8 cvar);
  void table_to_Nok3310(int8 charsel);
  void Nok3310_print_degree(void);
  void Nok3310_wr_data_inv(int8 bytefornokia_data_inv);
  void Nok3310_plot(int8 xnokia,int8 plot_value8, int8 plot_type);
  // Character/font table. Each character takes 5 bytes (5 columns of 8 pixels): 96 rows * 5 bytes= 480 bytes
  int8 const TABLE5[240]= {0x00,0x00,0x00,0x00,0x00, // 20 space
    0x00,0x00,0x5f,0x00,0x00, // 21 !
    0x00,0x07,0x00,0x07,0x00, // 22 "
    0x14,0x7f,0x14,0x7f,0x14, // 23 #
    0x24,0x2a,0x7f,0x2a,0x12, // 24 $
    0x23,0x13,0x08,0x64,0x62, // 25 %
    0x36,0x49,0x55,0x22,0x50, // 26 &
    0x00,0x05,0x03,0x00,0x00, // 27 '
    0x00,0x1c,0x22,0x41,0x00, // 28 (
    0x00,0x41,0x22,0x1c,0x00, // 29 )
    0x14,0x08,0x3e,0x08,0x14, // 2a *
    0x08,0x08,0x3e,0x08,0x08, // 2b +
    0x00,0x50,0x30,0x00,0x00, // 2c ,
    0x08,0x08,0x08,0x08,0x08, // 2d -
    0x00,0x60,0x60,0x00,0x00, // 2e .
    0x20,0x10,0x08,0x04,0x02, // 2f /
    0x3e,0x51,0x49,0x45,0x3e, // 30 0
    0x00,0x42,0x7f,0x40,0x00, // 31 1
    0x42,0x61,0x51,0x49,0x46, // 32 2
    0x21,0x41,0x45,0x4b,0x31, // 33 3
    0x18,0x14,0x12,0x7f,0x10, // 34 4
    0x27,0x45,0x45,0x45,0x39, // 35 5
    0x3c,0x4a,0x49,0x49,0x30, // 36 6
    0x01,0x71,0x09,0x05,0x03, // 37 7
    0x36,0x49,0x49,0x49,0x36, // 38 8
    0x06,0x49,0x49,0x29,0x1e, // 39 9
    0x00,0x36,0x36,0x00,0x00, // 3a :
    0x00,0x56,0x36,0x00,0x00, // 3b ;
    0x08,0x14,0x22,0x41,0x00, // 3c <
    0x14,0x14,0x14,0x14,0x14, // 3d =
    0x00,0x41,0x22,0x14,0x08, // 3e >
    0x02,0x01,0x51,0x09,0x06, // 3f ?
    0x32,0x49,0x79,0x41,0x3e, // 40 @
    0x7e,0x11,0x11,0x11,0x7e, // 41 A
    0x7f,0x49,0x49,0x49,0x36, // 42 B
    0x3e,0x41,0x41,0x41,0x22, // 43 C
    0x7f,0x41,0x41,0x22,0x1c, // 44 D
    0x7f,0x49,0x49,0x49,0x41, // 45 E
    0x7f,0x09,0x09,0x09,0x01, // 46 F
    0x3e,0x41,0x49,0x49,0x7a, // 47 G
    0x7f,0x08,0x08,0x08,0x7f, // 48 H
    0x00,0x41,0x7f,0x41,0x00, // 49 I
    0x20,0x40,0x41,0x3f,0x01, // 4a J
    0x7f,0x08,0x14,0x22,0x41, // 4b K
    0x7f,0x40,0x40,0x40,0x40, // 4c L
    0x7f,0x02,0x0c,0x02,0x7f, // 4d M
    0x7f,0x04,0x08,0x10,0x7f, // 4e N
    0x3e,0x41,0x41,0x41,0x3e // 4f O
  };
  int8 const TABLE6[240]= {0x7f,0x09,0x09,0x09,0x06, // 50 P
    0x3e,0x41,0x51,0x21,0x5e, // 51 Q
    0x7f,0x09,0x19,0x29,0x46, // 52 R
    0x46,0x49,0x49,0x49,0x31, // 53 S
    0x01,0x01,0x7f,0x01,0x01, // 54 T
    0x3f,0x40,0x40,0x40,0x3f, // 55 U
    0x1f,0x20,0x40,0x20,0x1f, // 56 V
    0x3f,0x40,0x38,0x40,0x3f, // 57 W
    0x63,0x14,0x08,0x14,0x63, // 58 X
    0x07,0x08,0x70,0x08,0x07, // 59 Y
    0x61,0x51,0x49,0x45,0x43, // 5a Z
    0x00,0x7f,0x41,0x41,0x00, // 5b [
    0x02,0x04,0x08,0x10,0x20, // 5c /
    0x00,0x41,0x41,0x7f,0x00, // 5d ]
    0x04,0x02,0x01,0x02,0x04, // 5e
    0x40,0x40,0x40,0x40,0x40, // 5f --
    0x00,0x01,0x02,0x04,0x00, // 60
    0x20,0x54,0x54,0x54,0x78, // 61 a
    0x7f,0x48,0x44,0x44,0x38, // 62 b
    0x38,0x44,0x44,0x44,0x20, // 63 c
    0x38,0x44,0x44,0x48,0x7f, // 64 d
    0x38,0x54,0x54,0x54,0x18, // 65 e
    0x08,0x7e,0x09,0x01,0x02, // 66 f
    0x0c,0x52,0x52,0x52,0x3e, // 67 g
    0x7f,0x08,0x04,0x04,0x78, // 68 h
    0x00,0x44,0x7d,0x40,0x00, // 69 i
    0x20,0x40,0x44,0x3d,0x00, // 6a j
    0x7f,0x10,0x28,0x44,0x00, // 6b k
    0x00,0x41,0x7f,0x40,0x00, // 6c l
    0x7c,0x04,0x18,0x04,0x78, // 6d m
    0x7c,0x08,0x04,0x04,0x78, // 6e n
    0x38,0x44,0x44,0x44,0x38, // 6f o
    0x7c,0x14,0x14,0x14,0x08, // 70 p
    0x08,0x14,0x14,0x18,0x7c, // 71 q
    0x7c,0x08,0x04,0x04,0x08, // 72 r
    0x48,0x54,0x54,0x54,0x20, // 73 s
    0x04,0x3f,0x44,0x40,0x20, // 74 t
    0x3c,0x40,0x40,0x20,0x7c, // 75 u
    0x1c,0x20,0x40,0x20,0x1c, // 76 v
    0x3c,0x40,0x30,0x40,0x3c, // 77 w
    0x44,0x28,0x10,0x28,0x44, // 78 x
    0x0c,0x50,0x50,0x50,0x3c, // 79 y
    0x44,0x64,0x54,0x4c,0x44, // 7a z
    0x00,0x08,0x36,0x41,0x00, // 7b {
    0x00,0x00,0x7f,0x00,0x00, // 7c |
    0x00,0x41,0x36,0x08,0x00, // 7d }
    0x10,0x08,0x08,0x10,0x08, // 7e ~
    0x78,0x46,0x41,0x46,0x78 // 7f
  };
  void Init_Nok3310(void) { // Initialise graphic lcd module
    tris_nokia3310 =0x00; // bits are all outputs
    delay_us(200);
    nokia3310_dc=1; // bytes are stored in the display data ram, address counter, incremented automatically
    nokia3310_cs=1; // chip disabled
    delay_us(200);
    nokia3310_res=0; // reset chip during 250ms
    delay_ms(250);
    nokia3310_res=1;
    Nok3310_wr_cmd(0x21); // set extins extended instruction set
    Nok3310_wr_cmd(0xc8); // Vop v1: 0xc8 (for 3V)// v2: 0xa0 (for 3V)
    Nok3310_wr_cmd(0x13); // bias
    Nok3310_wr_cmd(0x20); // horizontal mode from left to right, X axe are incremented automatically , 0x22 for vertical addressing
    Nok3310_wr_cmd(0x09); // all on
    delay_ms(50);
    Nok3310_clean_ddram(); // reset DDRAM, otherwise the lcd is filled with random pixels
    delay_ms(10);
    Nok3310_wr_cmd(0x08); // mod control
    delay_ms(10);
    Nok3310_wr_cmd(0x0c);
  }
  #define Init_display Init_Nok3310 // Init function for screen (LCD or graphic)
  void Nok3310_clean_ddram(void) { // Clean screen
    int16 ddram;
    Nok3310_gotoxy(0,0); // 84*48/8 = 504 bytes to clear
    for (ddram=504;ddram>0;ddram--){
      Nok3310_wr_data(0x00);
    }
  }
  #define Clear_display Nok3310_clean_ddram
  void Nok3310_wr_data(int8 bytefornokia_data) { // Send data to display
    nokia3310_dc=1; // set display to receive data
    nokia3310_cs=0; // chip enale
    Nok3310_wr_dorc(bytefornokia_data); // clock byte in
    nokia3310_cs=1; // chip disabled
  }
  void Nok3310_wr_cmd(int8 bytefornokia_command) { // Send command to display
    nokia3310_dc=0; // set display to receive command
    nokia3310_cs=0;
    Nok3310_wr_dorc(bytefornokia_command);
    nokia3310_cs=1;
  }
  void Nok3310_wr_dorc(int8 bytefornokia) { // clock byte in display
    char caa;
    for (caa=8;caa>0;caa--) { // clock in 8 bits of byte
      nokia3310_sck=0; // clock low
      delay_us(2);
      if ((bytefornokia&0x80)==0){nokia3310_sdi=0;} // set bit accordingly
      else {nokia3310_sdi=1;}
      nokia3310_sck=1; // clock high to clock bit in display
      bytefornokia=bytefornokia<<1; // shift byte for next bit
    }
  }
  void Nok3310_gotoxy(int8 xnokia, int8 ynokia) { // Nokia LCD 3310 Position cursor (0,0 top left corner)
    Nok3310_wr_cmd(0x40|(ynokia&0x07)); // Y axe initialisation: 0100 0yyy
    Nok3310_wr_cmd(0x80|(xnokia&0x7f)); // X axe initialisation: 1xxx xxxx
  }
  #define display_gotoxy Nok3310_gotoxy // gotoxy function for screen
  void Nok3310_erase_y(int8 ynokia) { // Erase a ligne (84x8 pixels)
    Nok3310_gotoxy(0,ynokia);
    printf(Nok3310_putc,"              ");
  }
  void Nok3310_erase_x(int8 xnokia) { // Erase a column (6x48 pixels)
    int8 column;
    for (column=0;column!=6;column++) { // repeat for 6 lines (or bytes)
      Nok3310_gotoxy(xnokia,column);
      Nok3310_wr_data(0x00); // blank pixels in 6 rows
      Nok3310_wr_data(0x00);
      Nok3310_wr_data(0x00);
      Nok3310_wr_data(0x00);
      Nok3310_wr_data(0x00);
      Nok3310_wr_data(0x00);
    }
  }
  void Nok3310_putc(int8 cvar) { // Write 1 character to LCD
    switch (cvar) {
      case '\f':
        Nok3310_clean_ddram(); // Clear screen
        delay_ms(20);
        break;
      default : table_to_Nok3310(cvar);
    }
  }
  #define display_putc Nok3310_putc // Putc function for output to screen
  void table_to_Nok3310(int8 charsel) { // extract ascii character from tables & write to LCD
    int8 char_row, charpos, chardata;
    if (charsel<0x20)return; // check character are in the table
    if (charsel>0x7f)return;
    for (char_row=0;char_row<5;char_row++) { // 5 bytes
      if (charsel<0x50) { // use TABLE5
        charpos=(((charsel&0xff)-0x20)*5);
        chardata=TABLE5[(charpos+char_row)];
      } else if (charsel>0x4f) { // use TABLE6
        charpos=(((charsel&0xff)-0x50)*5);
        chardata=TABLE6[(charpos+char_row)];
      }
      Nok3310_wr_data(chardata); // send data to nokia
    }
    Nok3310_wr_data(0x00);
  }
  void Nok3310_print_degree(void) { // Writes degree character to display
    Nok3310_wr_data(0x00);
    Nok3310_wr_data(0x06);
    Nok3310_wr_data(0x09);
    Nok3310_wr_data(0x09);
    Nok3310_wr_data(0x06);
    Nok3310_wr_data(0x00);
  }
  #define display_print_degree Nok3310_print_degree
  void Nok3310_wr_data_inv(int8 bytefornokia_data_inv) { // Writes inverted data white pixels on black background
    int8 caa;
    nokia3310_dc=1;
    nokia3310_cs=0;
    for (caa=8;caa>0;caa--) {
      nokia3310_sck=0;
      delay_us(2);
      if ((bytefornokia_data_inv&0x01)==0){
        nokia3310_sdi=0;
      } else {
        nokia3310_sdi=1;
      }
      nokia3310_sck=1;
      bytefornokia_data_inv=bytefornokia_data_inv>>1;
    }
    nokia3310_cs=1;
  }
  void Nok3310_plot(int8 xnokia,int8 plot_value8, int8 plot_type) { // plot_type: 1=dot grap, 0=bar graph
    int8 i;
    int32 plot_value32, plot_umsb,plot_lmsb,plot_ulsb,plot_llsb;
    plot_value32=0;
    if (plot_type) {
      plot_value32|=1; // dotgraph
    }
    for (i=0;i!=plot_value8;i++) {
      if (!plot_type) {
        plot_value32|=1; // bargraph
      }
      plot_value32<<=1;
    }
    plot_value32|=2; // bottom line is always filled
    plot_llsb=(plot_value32&0xff);
    plot_ulsb=((plot_value32>>8)&0xff);
    plot_lmsb=((plot_value32>>16)&0xff);
    plot_umsb=((plot_value32>>24)&0xff);
    Nok3310_gotoxy(xnokia,1);
    Nok3310_wr_data_inv(plot_umsb);
    Nok3310_gotoxy(xnokia,2);
    Nok3310_wr_data_inv(plot_lmsb);
    Nok3310_gotoxy(xnokia,3);
    Nok3310_wr_data_inv(plot_ulsb);
    Nok3310_gotoxy(xnokia,4);
    Nok3310_wr_data_inv(plot_llsb);
  }
#endif


Tutorial 5b

Fig. 1b Board 1 with LCD display

First we need to setup the hardware connections to the display. The library needs to know which port the display will be connected to, and then just assign the various signals to specific bits of the 8 bits bus.
Each function then gets its prototype defined.

Next is the character table (equivalent to a bitmap font). Each character is displayed on 6x8 pixels. The last column is blank, so each character is separated by a blank column. Which means we actually need 5 bytes per character (5 columns). Each byte in a character has the pixels to show (when the bit is set to one) or blank in the column. The lsb bit is always blank, so each line is separated by a blank pixel.

For example, the character 0x7e,0x11,0x11,0x11,0x7e would display as A: first column as 7e, second 11...

       
                        
         
         
         
         
         
         

It is therefore easy to design custom made symbols or fonts, like in the Nok3310_Print_degree function.

Then a list of functions is available to control the display:

  • Init_Nok3310: Reset and initialise the Nokia 3310 display.
  • Nok3310_clean_ddram: Clear the screen: all pixels are blanked.
  • Nok3310_wr_data: send a byte to data register of Nokia 3310
  • Nok3310_wr_cmd: send a byte to command register of Nokia 3310
  • Nok3310_wr_dorc: output a byte to the Nokia 3310 display using a software emulation of SPI
  • Nok3310_gotoxy: position the pointer on the display. x and y are in pixels. 0,0 is upper left corner.
  • Nok3310_erase_y: clears a row character
  • Nok3310_erase_x: clears a column of character
  • Nok3310_putc: send a character at the current pointer of Nokia 3310
  • table_to_Nok3310: send a character from the font table to the display
  • Nok3310_print_degree: print the degree symbol
  • Nok3310_wr_data_inv: display in inverted mode a character
  • Nok3310_plot: draw a plot of data (bargraph or dot type)

Compile the project and program the target with a PicKIT 2 programmer for example. Connect the processor board to the graphic LCD display board on port B.

Power up the boards.
The display will show a counter incrementing 4 times a second on the 1st line.

To change display type, just use board 1 or change the condition that load the display library and recompile. The program is then set for an alphanumeric LCD display.


Files and links:

Tutorial 6 source files.
Processor board 4.
LCD Display board.
Graphic LCD board.

Post your comments...

    Copyright 2011. Poker Games. Copyright © 2012 riaDesign