LCD Driving with MCP23S17 I/O Expander Interface????

Hello all,

My question was about how to drive LCD with an I/O expander MCP23S17 by using SPI from my Arduino UNO. I have an SPI interface between Arduino and MCP23S17. Everything works well. But the problem is I cannot drive LCD with MCP23S17 i/o pins. Standard library allows me to use only Arduino's i/o pins.

Please help me about this!!!

Thanks,

Which LCD?

However this should get you started: Gammon Forum : Electronics : Microprocessors : Connecting a graphical LCD via a I2C/SPI using a 16-bit port expander

Thanks for the reply,

I am now trying to drive my LCD which is 16x2 big Characters LCD(TC1602B-06). But I could not make it work. Maybe, it is because of connection problem between MCP23S17 and LCD. So, here are the pins LCD have:

First 5 pins are for power connections of LCD
1 BLK
2 BLA
3 VSS
4 VDD
5 V0

6 RS //data-instruction register
7 R/W //read / write since I will only use write function of LCD. I directly connected this to ground
8 E //enable
9-16 D0-D7 //data pins

According to your source files, I connected the data pins starting from B0-B7 to LCD data pins. Also, I connected pin 28(A7) to enable of LCD and pin 26(A5) to RS(data-instruction register). My code is;

#include <Wire.h>
#include <SPI.h>
#include <I2C_graphical_LCD_display.h>

I2C_graphical_LCD_display lcd;

void setup ()
{
lcd.begin (0x20,0,10);
lcd.letter ('x');
}

void loop()
{
}

Actually, LCD works with Arduino UNO if it is connected directly. But, I really need to make it work through MCP23S17 with SPI protocol. What is the problem about my condition ?

Thanks again.

That page was for a graphical LCD not a character one.

I think someone has done a driver for a character LCD using SPI, but I can't spot it. Maybe someone else remembers?

I understand. Actually, I found some libraries implemented for SPI connection LCD driving but they are using 74HC595. I tried to make some changes in source codes and use for MCP23S17. But it didnt work. Other than SPI, there are lots of libraries implemented for I2C. Since it is actually slow and I want to use remaining expander pins for other purposes. I2C is not my solution.

Why there is no-one using SPI with MCP23S17 to drive LCD ???

By the way, I came up with a different solution but it is just an idea. Actually standard Liquid Crystal library only accepts digital pins of Arduino. So, is there a way to show MCP23S17 pins as Arduino's standard pins so that I can use Liquid Crystal library. For example, once I wrote 14 it understands that A0 of MCP23S17 will be used. Is this possible ?

Why there is no-one using SPI with MCP23S17 to drive LCD ???

Well, I did, and that was with a graphical LCD.

All I can suggest right now is taking one of the I2C libraries that use the MCP23017 and modify them to use SPI. The changes I had to make to my graphical library were quite small, you could compare the few places that my code decides whether to use SPI or I2C.

All I can suggest right now is taking one of the I2C libraries that use the MCP23017 and modify them to use SPI. The changes I had to make to my graphical library were quite small, you could compare the few places that my code decides whether to use SPI or I2C.

That is how I made a library for driving an LCD through I2C.
There are only one or two places where the LCD library accesses the output pins. Just substitute a call to your SPI output routines.

Grumpy_Mike:

All I can suggest right now is taking one of the I2C libraries that use the MCP23017 and modify them to use SPI. The changes I had to make to my graphical library were quite small, you could compare the few places that my code decides whether to use SPI or I2C.

That is how I made a library for driving an LCD through I2C.
There are only one or two places where the LCD library accesses the output pins. Just substitute a call to your SPI output routines.

Actually, I tried but it was little bit hard for me to re-shape the code for SPI. Since it is an object oriented, you have to jump between classes this makes you crazy a few minutes later. :slight_smile: Anyway, I'm now considering to use a graphical lcd instead of character one or if I can dare to jump into codes, I will add SPI feature to lcd library.

Hello,

Finally, I wanted to use a graphical lcd instead of a character one with your library in my project. Here is my next question:

I will use LCD in my term project. And we have a budget limit. So, can you suggest me some type of graphical lcd's that work well with your library and not costy? Actually, I had bought a 16x2 character lcd and it was enough for my task. So, your suggestions can be something like that.

Thanks,

Changing your hardware just because you can't get your head round the much simpler task of driving a character LCD is not going to win you any assignment points, well not if I was marking it.

Actually, I tried but it was little bit hard for me to re-shape the code for SPI. Since it is an object oriented, you have to jump between classes this makes you crazy a few minutes later.

This is just plane rubbish. Object orientation has absolutely nothing to do with it. You don't have to jump between classes.

Grumpy_Mike:
Changing your hardware just because you can't get your head round the much simpler task of driving a character LCD is not going to win you any assignment points, well not if I was marking it.

This is just plane rubbish. Object orientation has absolutely nothing to do with it. You don't have to jump between classes.

You are right. But it is not that I didn't make enough research to solve this problem on the internet even trying to rewrite the library by myself. But I couldnt do it. Also, my major is electrical enginnering and this doesnt mean that I can do such assignments. This is actually a big project and this task is just for an extra feature on the robot. So, I dont want to spend too much time. Due to these reasons, I though to buy a graphical lcd and I will also use the character one for other purposes in the project.

I don't see what the complexity is. In my library, the part that chooses whether to write using I2C or SPI looks like this:

// send a byte via SPI or I2C
void I2C_graphical_LCD_display::doSend (const byte what)   
{
  if (_ssPin)   // if using SPI
    SPI.transfer (what);
  else
    Wire.write (what);
}

It's hardly complex or "jumping through classes". (My original code was slightly more complex because it allowed for pre-1.0 versions of the IDE, but the above is all it should take).

I was really fed up with looking for codes or dealing with coding about lcd driving with SPI thru MCP23S17. If it is such an easy task, I expect people to do it. Because, I cannot solve this issue.

karanlikcag:
I was really fed up with looking for codes or dealing with coding about lcd driving with SPI thru MCP23S17. If it is such an easy task, I expect people to do it. Because, I cannot solve this issue.

That is a very regrettable attitude. Just to look for code for something so simple and not to want to understand anything. And for an assignment as well.
Why do you not want to learn how to do it?
Given Nick's spoon feeding of you can you not even string two lines of code together? If not then that project is too hard for you. If that is the case do some learning before tackling it.

Grumpy_Mike:

karanlikcag:
I was really fed up with looking for codes or dealing with coding about lcd driving with SPI thru MCP23S17. If it is such an easy task, I expect people to do it. Because, I cannot solve this issue.

That is a very regrettable attitude. Just to look for code for something so simple and not to want to understand anything. And for an assignment as well.
Why do you not want to learn how to do it?
Given Nick's spoon feeding of you can you not even string two lines of code together? If not then that project is too hard for you. If that is the case do some learning before tackling it.

I didnt say that i dont want to learn how to do it. I tried but i couldnt. And this doesnt mean that i cannot do well in this project. If it is such an easy solution ( just for two lines of code), then please write this very simple solution. I will appreciate for that.

sorry this thread is probably old but have you tried this Arduino Playground - HomePage
I modified the original library for SPI but using 74HC595, it shouldn't be that difficult to modify it for the MCP23S17
take a look at it.

// Rough example (full code) to understand the operation of LCD interfaced with MCP23S17 using SPI (ported from PICDEM example, Check the schematics attached)

// MOSI: pin 11
// MISO: pin 12
// SCK: pin 13
// CS: pin 10
//For 2 line and 16 character LCD. The address from 0x80 to 0x8F are visible on first line and 0xC0 to 0xCF is visible on second line
#include <SPI.h>
int i=0;
const int slaveSelectPin = 10;

void setup()
{
// set the slaveSelectPin as an output:
pinMode(slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
Serial.begin(9600);
delay(1000);
LCDInit();
}

void loop() {

if (i==0)
{
i=i+1;// Execute only once

//LCDLine_1(); // Write the cammand to start on line 1

LCDline_pos(1,1); // Select LCD position to line 1, 1st position
d_write('h'); // Write the data one char at a time.
delay(500);
LCDClear(); //Celear LCD
s_write("Hello World");
delay(500);
LCDClear();
delay(500);
s_write("string print");//Write the data by string.
delay(1000);
}
if (Serial.available())
{
LCDline_pos(2,2); // Select LCD position to line 2, 2nd position
d_write(Serial.read()); // Write the data input from serial port
}
}
//*****************************************************************
// LCD busy delay
//*****************************************************************
void LCDBusy(void)
{
delay(10);
}
//*****************************************************************
// Write to MCP923S17 Port A
//*****************************************************************
void WritePortA(char b)
{
digitalWrite(slaveSelectPin, LOW);
SPI.transfer (0x40);
SPI.transfer (0x12);
SPI.transfer (b);
digitalWrite(slaveSelectPin, HIGH);
}
//*****************************************************************
// Write to MCP923S17 Port B
//*****************************************************************
void WritePortB(char b)
{
digitalWrite(slaveSelectPin, LOW);
SPI.transfer (0x40);
SPI.transfer (0x13);
SPI.transfer(b);
digitalWrite(slaveSelectPin, HIGH);
}
//*****************************************************************
// Write the data to the display
//*****************************************************************
void d_write(char b)
{
WritePortA(0x80);
LCDBusy();
WritePortB(b);
delay(0);
WritePortA(0xC0);
delay(0);
WritePortA(0x00);

}
//*****************************************************************
// Send a instruction to the display
//*****************************************************************
void i_write(char b)
{
WritePortA(0x00);
LCDBusy();
WritePortB(b);
delay(100);
WritePortA(0x40);
delay(100);
WritePortA(0x00);
}
//*****************************************************************
// Write to line 1 of the display
//*****************************************************************
void LCDLine_1(void)
{
i_write(0x80);
}
//*****************************************************************
// Write to line 1 of the display
//*****************************************************************
void LCDLine_2(void)
{
i_write(0xC0);
}
//*****************************************************************
// To clear the display
//*****************************************************************
void LCDClear(void)
{
i_write(0x01);
}
//******************************************************************
// Function to write to the PORT
//******************************************************************
void InitWrite(char b)
{
WritePortA(0);
WritePortB(b);
delay(100);
WritePortA(0x40);
delay(100);
WritePortA(0);
}
//*****************************************************************
// Initialize MCP923S17 Port A
//*****************************************************************
void InitPortA_SPI(char b)
{
digitalWrite(slaveSelectPin, LOW);
SPI.transfer (0x40);
SPI.transfer (0x00);
delay(100);
SPI.transfer (b);
delay(100);
digitalWrite(slaveSelectPin, HIGH);
}
//*****************************************************************
// Initialize MCP923S17 Port B
//*****************************************************************
void InitPortB_SPI(char b)
{
digitalWrite(slaveSelectPin, LOW);
SPI.transfer (0x40);
SPI.transfer (0x01);
SPI.transfer(b);
digitalWrite(slaveSelectPin, HIGH);
}

//******************************************************************
// LCD Initialization function
//******************************************************************
void LCDInit(void)
{
// take the SS pin low to select the chip:
digitalWrite(slaveSelectPin, HIGH);
InitPortA_SPI(0);
InitPortB_SPI(0);
WritePortA(0);
delay(500);
InitWrite(0x3C); //0011NFxx
delay(500);
InitWrite(0x0C); //Display Off
delay(500);
InitWrite(0x01); //Display Clear
delay(500);
InitWrite(0x06); //Entry mode
}
//*****************************************************************
// Point to the display writing position
//*****************************************************************
void LCDline_pos(int a,int b)
{
if (a==1)
{
if (b>=0 && b<16)
{
int a;
a= 0x80+b,HEX;
Serial.print(a,HEX);
i_write(a);
}
}
if (a==2)
{
if (b>=0 && b<16)
{
int a;
a= 0xC0+b,HEX;
Serial.print(a,HEX);
i_write(a);
}
}

}
//*****************************************************************
// Write the string to the display
//*****************************************************************
void s_write(char data[])
{
int i;
int j;
for(i = 0; data != '\0';i++);
//Serial.print("i=:",i);
for (j=0;j<i;j++)
{
Serial.print("i am in data\n");
//Serial.print("j=:",data[j]);
WritePortA(0x80);
LCDBusy();
WritePortB(data[j]);
delay(0);
WritePortA(0xC0);
delay(0);
WritePortA(0x00);
}
}


16x2LCD ported from PICDEM updated.txt (5.99 KB)

If one is still interested, I have developed a modified version of the SPI library that works with the MCP23S17 port expander.

You can download the library at GitHub - Electronza/MCP23S17_LCD: MCP23S17 - LCD Arduino library

For connection diagram and some explanations regarding the use of the library visit Arduino: a code library for MCP23S17 LCD | Electronza