1
\$\begingroup\$

I'm at my wits end with this at the moment.

I need to interface my MSP430G2553 with the PCF8574 I2C expander in order to drive an LCD display. So far I've had not much luck at all. There is very little support on the manufacturer's website in terms of code examples and so on:

This is the LCD - http://modtronix.com/lcd204a-biw.html

This is the I2C daughter board - http://modtronix.com/mod-lcdi2c-bb1.html

I've soldered them together as per the pictures on the website above and connected the board to my launchpad correctly. Jumper on P1.6 has been removed. Pull-up resistors of 10K on both SCL and SDA lines. The LCD backlight is on when the launchpad is connected to a USB port.

The issue I'm fairly sure is a code-based one. On the manufacturer's website it says that the board comes with the slave address 0x3F and the MSP430 example code I've used does recognize the board over I2C using this address. The problem I'm having now is writing to the board using this code, as I really don't understand what's going on. The User Guide for the MSP430 is not much help at all and I'm not sure what I should be writing to the daughter board for it to work properly with the LCD. Here are the pertinent parts of my code:

void TI_USCI_I2C_transmitinit(unsigned char slave_address,
                      unsigned char prescale){
  P3SEL |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0
  UCB0CTL1 = UCSWRST;                        // Enable SW reset
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;              // Use SMCLK, keep SW reset
  UCB0BR0 = prescale;                         // set prescaler
  UCB0BR1 = 0;
  UCB0I2CSA = slave_address;                  // Set slave address
  UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
  UCB0I2CIE = UCNACKIE;
  IE2 = UCB0TXIE;                            // Enable TX ready interrupt
}

//------------------------------------------------------------------------------
// unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)
//
// This function is used to look for a slave address on the I2C bus.
//
// IN:   unsigned char slave_address  =>  Slave Address
// OUT:  unsigned char                =>  0: address was not found,
//                                        1: address found
//------------------------------------------------------------------------------
unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address){
  unsigned char ie2_bak, slaveadr_bak, ucb0i2cie, returnValue;
  ucb0i2cie = UCB0I2CIE;                      // restore old UCB0I2CIE
  ie2_bak = IE2;                              // store IE2 register
  slaveadr_bak = UCB0I2CSA;                   // store old slave address
  UCB0I2CIE &= ~ UCNACKIE;                    // no NACK interrupt
  UCB0I2CSA = slave_address;                  // set slave address
  IE2 &= ~(UCB0TXIE + UCB0RXIE);              // no RX or TX interrupts
  __disable_interrupt();
  UCB0CTL1 |= UCTR + UCTXSTT + UCTXSTP;       // I2C TX, start condition
  while (UCB0CTL1 & UCTXSTP);                 // wait for STOP condition

  returnValue = !(UCB0STAT & UCNACKIFG);
  __enable_interrupt();
  IE2 = ie2_bak;                              // restore IE2
  UCB0I2CSA = slaveadr_bak;                   // restore old slave address
  UCB0I2CIE = ucb0i2cie;                      // restore old UCB0CTL1
  return returnValue;                         // return whether or not
                                              // a NACK occured
}

//------------------------------------------------------------------------------
// void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field)
//
// This function is used to start an I2C commuincation in master-transmit mode.
//
// IN:   unsigned char byteCount  =>  number of bytes that should be transmitted
//       unsigned char *field     =>  array variable. Its content will be sent.
//------------------------------------------------------------------------------
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field){
  TI_transmit_field = field;
  byteCtr = byteCount;
  UCB0CTL1 |= UCTR + UCTXSTT;                 // I2C TX, start condition
}

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Disable Watchdog
_EINT(); // enable interrupts
TI_USCI_I2C_transmitinit(0x3F,0x20); // initialize USCI
i = TI_USCI_I2C_slave_present(0x3F);
while ( TI_USCI_I2C_notready() ); // wait for bus to be free
TI_USCI_I2C_transmit(1, array); // transmit a byte-long array
LPM0; // put CPU to sleep during
// communication
}

I'm sorry if this is a confusing post - I'm very confused by the whole task I'm trying to achieve here. I have a friend who did this using UART and is suggesting I give on I2C and buy parts to change over to that protocol, but I thought I'd look for help from those who might have a bit of experience in I2C.

\$\endgroup\$
  • \$\begingroup\$ On mobile so excuse the typos. The lcd is a standard hd4xxx type character display so that's how you address it. The i2c backpack datasheet has the physical to logical pinout for specifics. And I have a similar project on the 43oh.com forums with the same parts (scratch built) under the username cde, along with many other similar projects. Its a msp430 centric \$\endgroup\$ – Passerby Oct 6 '14 at 18:14
  • \$\begingroup\$ Hi, do you mean this? forum.43oh.com/topic/126-i2c-explorer/page-2#entry25918 It seems the code is for USI. What kind of differences are there in programming for USCI? \$\endgroup\$ – Nick Oct 7 '14 at 1:40
  • \$\begingroup\$ the difference is in layers. There is three layers in an i2c lcd setup. One is the i2c layer (in this case, usi or usci or bit banged). Two is the device layer (in this case, the pcf8574 pinout). Three is the LCD layer, the specifics on how to address the LCD. Once you have the i2c layer working, the rest is simple. \$\endgroup\$ – Passerby Oct 7 '14 at 1:55
  • \$\begingroup\$ I believe that the code I've posted above works for my setup. I'm just confused as to how the PCF8574 is connected to the LCD. When I send through a byte of data from the controller to the PCF8574 over i2c, is this immediately placed on pins 7-14 of the LCD? The daughter board I've soldered on then automatically enables the screen and sets its other registers to their appropriate values? The data sheet only explains the chip itself - there is no info on the actual daughter board which is what has me stuck. \$\endgroup\$ – Nick Oct 7 '14 at 4:49
  • \$\begingroup\$ The daughterboard is wired according to the Arduino i2c lcd library. see playground.arduino.cc/Code/LCDi2c \$\endgroup\$ – Passerby Oct 7 '14 at 5:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.