CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Simple SPI routines for LCD display using MCP23S08

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

Simple SPI routines for LCD display using MCP23S08
PostPosted: Tue Jun 18, 2013 10:02 am     Reply with quote

This is a simple routine to convert a standard alpha-numeric LCD display as a serial interface. I wrote it just for the exercise just to see how it will work using the MCP23S08 SPI I/O expander. I have tried it both in simulation as well as testing it on real hardware and it works quite well. Don't really know how practical this approach would be rather than using an existing SPI LCD module commercially available. I have tried it with a 2X20 and a 4X20 LCD module that use the generic HD44780 instruction set, both appear to work.

I have pasted the code for the following modules here:
MCP23S08.C
SerLCD.C
SerLCDdemo.c
SerLCDdemo.h
Code:

//CODE FOR  SerLCDdemo.h

#include <24FJ128GA010.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES ICSP1                    //ICD uses PGC1/PGD1 pins
#FUSES NOJTAG                   //JTAG disabled
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES PR                       //Primary Oscillator

#use delay(clock=8000000)


Code:

//CODE FOR  SerLCDdemo.c

#include <SerLCDdemo.h>
#include <SerLCD.c>

void Init(void);

void Init(void){
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4);
setup_spi2( FALSE );
setup_timer1(TMR_DISABLED);
SETUP_ADC_PORTS(NO_ANALOGS);
output_high(CS);
output_high(IORST);
}


void main()
{
   unsigned char i;
 
   Init();

   Init23S08();
   LCD_init();
   lcd_gotoxy(1,1);
   Display_On_Blink;
   printf(lcd_putc,"Hello World");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"We Have done it!");   
   delay_ms(2000);
   lcd_putc("\f");
   Display_No_Cursor;
   lcd_gotoxy(1,1);
   printf(lcd_putc,"And now we count");
   
   while(1){
     for(i=0; i<256; i++){
     lcd_gotoxy(1,2);
     printf(lcd_putc,"Count = %u  ",i);
     delay_ms(500);}
   
      }
}


Code:

//CODE FOR  SerLCD.c

/*******************************************************************************
* SerLCD.C
* Serial routines using a MCP23S08 to write to a 2X16,2X20,4X16 or 4X20
* alphanumeric LCD display using generic HD44780 compatible intruction set.
* Adapted from various LCD routines from CCS,PCM programmer and Oleg's article
* (Interfacing LCD using SPI and 74HC595)
*
* C. Barberis
* Bartek Technologies
* June 18, 2013
********************************************************************************
Notes:
 This driver uses a six wire connection to the LCD display where the RW signal is
 always tied low, therefore we are only doing writes to the module as having to do
 reads would add quite a bit of addittional timing for these serial routines.
 The SPI should be set to mode 0,0 or 1,1 (0,0 is used here)

********************************************************************************/

#include <MCP23S08.c>

// Function prototypes
void LCD_init(void);
void LCD_sendbyte(BYTE tosend);
void lcd_gotoxy(unsigned char x, unsigned char y);
void lcd_putc(char c);

#define TWO_LINE        // for 2X16 or 2X20 displays
//#define FOUR_LINE     // for 4X16 or 4X20 displays

unsigned char LCDpins;   // in this case we asign the data nibble (LCDpins) to GP4 to GP7 on the MCP23S08

#define RS 0x04 // RS pin         // in this case we asign the RS control to GP2 on the MCP23S08
#define E  0x08 // E pin          // in this case we asign the RS control to GP3 on the MCP23S08

#define SET_RS LCDpins |= RS      // how to set RS using a OR mask of data and control pin
#define CLR_RS LCDpins &= ~RS      // how to clear RS using a OR mask of data and control pin
#define SET_E LCDpins |= E         // how to set E using a OR mask of data and control pin
#define CLR_E LCDpins &= ~E         // how to clear E using a OR mask of data and control pin

#define LCD_sendcmd(a)  CLR_RS; LCD_sendbyte(a)      // this macro sends a control command to the LCD
#define LCD_sendchar(a) SET_RS; LCD_sendbyte(a)      // this macro sends a character to be printed by the LCD

#define LCD_TYPE 2       // 0=5x7, 1=5x10, 2=2 lines
#define FOUR_BIT_MODE 0x20
#define FUNCSET    FOUR_BIT_MODE | (LCD_TYPE << 2)
#define LCD_LINE_TWO 0x40 // LCD RAM address for the 2nd line
#define DISP_ON 0x0C
#define CLEAR_DISP 0x01
#define INCREMENT_CURSOR 0x06

//////// Special Display Macro Functions you can call /////////////////////////////////////////////////////////////////////////
#define   Write_Inc_LtoR              LCD_sendcmd(0x06)   // increments the cursor after writing data from L to R **(normal)
#define   Write_Inc_RtoL              LCD_sendcmd(0x07)   // increments the cursor after writing data from R to L
#define   Write_Dec_LtoR              LCD_sendcmd(0x05)   // decrements the cursor after writing data from R to L
#define   Write_Dec_RtoL              LCD_sendcmd(0x04)   // decrements the cursor after writing data from R to L
#define   Display_Blank_No_Clr        LCD_sendcmd(0x08)   //display off, without clearing
#define   Display_No_Cursor           LCD_sendcmd(0x0C)   //display on, cursor off
#define   Display_Cursor_On           LCD_sendcmd(0x0E)   //display on, cursor on
#define   Display_On_Blink            LCD_sendcmd(0x0F)   //display on, blinking cursor
#define   MoveCursorLeft              LCD_sendcmd(0x10)   //Move cursor one char to the left, same as '\b'
#define   MoveCursorRight             LCD_sendcmd(0x14)   //Move cursor one char to the right
#define   MoveCursorHome              LCD_sendcmd(0x02)   //Move cursor to top left char position (1,1)
#define   ClearScreen                 LCD_sendcmd(0x01)   //clears the screen an alternate to '\f'
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/***************************************************************************
* LCD initialization by instruction
* Must be called before making any function calls
***************************************************************************/
void LCD_init(){
CLR_RS;
delay_ms(100);
LCDpins = 0x30;
SET_E;
WriteToExpanderPort(LCDpins);
CLR_E;
WriteToExpanderPort(LCDpins);
delay_ms(10);
SET_E;         
WriteToExpanderPort(LCDpins);
CLR_E;
WriteToExpanderPort(LCDpins);
delay_ms(10);
SET_E;
WriteToExpanderPort(LCDpins);
CLR_E;
WriteToExpanderPort(LCDpins);
delay_ms(1);
LCDpins =  FOUR_BIT_MODE;    // send 0x20 - switch to 4-bit
SET_E;
WriteToExpanderPort(LCDpins);
CLR_E;
WriteToExpanderPort(LCDpins);
 /* regular transfers start here */
delay_ms(2);
LCD_sendcmd(FUNCSET);      //4-bit 2-line 5x7-font
delay_ms(1);
LCD_sendcmd(CLEAR_DISP);   //clear display
delay_ms(10);
LCD_sendcmd (DISP_ON);  //turn off cursor, turn on display
delay_ms(10);
LCD_sendcmd (INCREMENT_CURSOR); //Increment cursor automatically
}


/***************************************************************************
* Sends a byte to LCD in 4-bit mode by sending the upper nibble followed
* by the lower nibble using the MCP23S08 serial expander device
***************************************************************************/
void LCD_sendbyte(unsigned char tosend)
{
LCDpins &= 0x0f; //prepare place for the upper nibble
LCDpins |= ( tosend & 0xf0 ); //copy upper nibble to LCD variable
SET_E; // send upper nibble
WriteToExpanderPort(LCDpins);
CLR_E;
WriteToExpanderPort(LCDpins);
LCDpins &= 0x0f; //prepare place for the lower nibble
LCDpins |= ( tosend << 4 ) & 0xf0; //copy lower nibble to LCD variable
SET_E; // send lower nibble
WriteToExpanderPort(LCDpins);
CLR_E;
WriteToExpanderPort(LCDpins);
}


/***************************************************************************
* Command to set cursor position at any given line of the LCD display
* will work from 1 line to 4 line displays based on the defined #define
***************************************************************************/
void lcd_gotoxy(unsigned char x, unsigned char y)
{
unsigned char address;
#ifdef FOUR_LINE
     switch(y) {
     case 1 : address=0x80;break;
     case 2 : address=0xc0;break;
     case 3 : address=0x94;break;
     case 4 : address=0xd4;break;
address += x-1;
LCD_sendcmd(address);
#endif

#ifdef TWO_LINE
if(y != 1)
   address = LCD_LINE_TWO;
else
address=0;
address += x-1;
LCD_sendcmd(0x80 | address);
#endif

}


/***************************************************************************
* Sends a character to be printed to LCD or a command function to the LCD
*
***************************************************************************/
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      LCD_sendcmd(CLEAR_DISP);
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1,2);
       break;
   
    case '\b':
       LCD_sendcmd(0x10);
       break;
   
    default:
       LCD_sendchar(c);
       break;
   }
}


Code:

//CODE FOR  MCP23S08.c

void Init23S08(void);

/*************************************************************
MCP23X08.h

**************************************************************/
#define IODIR      0x00
#define IPOL        0x01
#define GPINTEN   0x02
#define DEFVAL    0x03
#define INTCON       0x04
#define IOCON        0x05
#define GPPU        0x06
#define INTF         0x07
#define INTCAP       0x08
#define GPIO        0x09
#define OLAT         0x0A
/**************************************************************/ 

#define CS PIN_B0
#define IORST PIN_B1

#define CONTROL_REG_VAL 0x40  //// these two defines are used here
#define GPIO_CONFIG_VAL 0x09  //// just to do very simple serial to parallel output transfer


void Init23S08(){
output_low(IORST);
delay_ms(200);
output_high(IORST);
delay_ms(200);
output_low(CS);
delay_us(100);
spi_write(CONTROL_REG_VAL); // control register setup
spi_write(0x00); // GPIO set to all outputs
spi_write(0x00); // Set all I/O to low
delay_us(100);
output_high(CS);
}


void WriteToExpanderPort(unsigned char data){
output_low(CS);
delay_us(100);
spi_write(CONTROL_REG_VAL); // control register setup
spi_write(GPIO_CONFIG_VAL); // GPIO configuration
spi_write(data); // value to I/O
delay_us(100);
output_high(CS);
}


/////////////////// Enjoy!!
crocu



Joined: 02 Nov 2009
Posts: 5

View user's profile Send private message

PostPosted: Sat Sep 28, 2013 6:44 am     Reply with quote

Hello

I've tried your code but i'm experiencing problems :

When the program starts, my 2x16 LCD display shows squares on the 1st
line, 2sd line does not show anything. ( see attached picture )



I think there is an issue during the LCD init process.
How could i debug and find out the problem ?

I'm using PIC18F2620 and i have Microchip ICD3 programmer.

Any suggestion will be much appreciated.
Best regards,
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Sat Sep 28, 2013 8:27 am     Reply with quote

Hi, Unfortunately I am traveling overseas and do not have very good access to the internet or much of my other material. The first thing I would ask is whether your LCD module is truly compatible with the HD44780 instruction set ? It appears to me that for some reason the module is not getting initialized. Also, it may be a wiring issue somewhere in the circuit I don't recall if I had posted the schematic and unfortunately I don't have one with me here to send to you at the moment but I could when I return to the US.
All I can tell you is that I had wired and prototyped this circuit and it worked quite well with most generic alpha-numeric LCD modules. I did have other tried this and they seem to have had successful results
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group