This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430G2553: Interfacing LCD via I2C

Part Number: MSP430G2553
Other Parts Discussed in Thread: PCF8574, , PCF8574A

Tool/software: Code Composer Studio

Hi, I am new at this. I am trying to interfacing 1602A LCD display with MSP430G2553 via PCF8574. When I run the code, nothing happens:

#include <msp430.h>

unsigned int *ptxData;
unsigned int count = 0;
// [0..3] -> power on, [4..5] -> function set, [6..7] -> display off, cursor off, blink off
// [8..9] -> clear screen, [10..11] -> right, do not shift, [12..13] -> display on, cursor on
// [14..15] -> write char 'B'
unsigned int txData[] = {0x03, 0x03, 0x03, 0x02, 0x02, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x0F, 0x24, 0x22};

void main() {
    WDTCTL = WDTPW | WDTHOLD;

    // for i2c pins
    P1SEL = 0xC0;
    P1SEL2 = 0xC0;

    // i2c config
    UCB0CTL1 |= UCSWRST;
    UCB0CTL0 = UCMST | UCMODE_3 | UCSYNC;
    UCB0CTL1 = UCSSEL_3;
    UCB0BR0 = 12;
    UCB0BR1 = 0;
    UCB0I2CSA = 0x27;   // slave address
    UCB0CTL1 &= ~UCSWRST;

    // enable tx interrupt
    IE2 |= UCB0TXIE;
    _enable_interrupts();

    // start to transmit data
    ptxData = txData;
    UCB0CTL1 |= UCTR + UCTXSTT;

    while (1);
}

#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void){
    // send txData elements one by one
    UCB0TXBUF = *ptxData;
    count++;
    *ptxData++;

    // if txData ends, start from beginning
    if (count == 16) {
        count = 0;
        ptxData -= 16;
    }
}

What am I missing, can you help me?

  • What is the origin of your TxData[] array? I expect it's a sequence of pin settings based on how the LCD is wired to the PCF8574. Since I don't know those settings, I don't know exactly how to interpret them.

    One thing that comes to mind is that the controller (HD44780 I presume) requires delays at certain points in the sequence, and this code doesn't seem to do that.

    Also, take a look at the chip on your board, to see if it's a PCF8574 or a PCF8574A. The former has an address in the 0x20-0x27 range and the latter in 0x38-0x3F.

  • I updated my code and added comments. TxData array contains LCD instructions such as function set, display on/off etc. The slave address is correct. But I can not add delays. I try  this:

    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void){
        // send txData elements one by one
        UCB0TXBUF = *ptxData;
        count++;
        *ptxData++;
    
        for (int i=0; i<10000; i++) { }
    
        // if txData ends, start from beginning
        if (count == 16) {
            count = 0;
            ptxData -= 16;
        }
    }

    When I debugged this code, I saw that for loop is skipped.

  • I don't recommend doing a delay with a for-loop. Use __delay_cycles(uint32_t) instead. Since you haven't changed the clock, one cycle is roughly 1 usec.

    If you're certain the address and data stream are correct, I defer. But (a) I don't see anything that wiggles the EN pin (b) some/most of the examples over on github seem to think the data nybble is in the high bits of the port, not the low bits (c) PCF8574 data sheet (SCPS068J) Sec 8.3.1 seems to say that only the first byte of a transaction is operative, and the rest are ignored..

  • How can I toggle E?

    Can you add link here for some exapmles on github? I could not found any.

  • Each write to the PCF is equivalent to writing a port register (byte). I would expect to see 4x transactions for each byte: (a) (high bits + En=1) (b) (high-bits + En=0) (c) (low-bits + En=1) (d) (low-bits + En=0). [Edit: The D/C bit fits in here somewhere as well.]

    Your first stop should probably be the manufacturer's web site. Some of these are better than others, but at minimum you should be able to find a schematic/diagram showing how the pins are wired. (I don't know how many variants there are on the market.)

    I searched github for "LCD1602 I2C" and got a collection of hits. Here's one:

    https://github.com/Szpillmann/LCD1602A/blob/master/LCD1602a.CPP

    None that I looked at had the lower (I2C) layer, merely calls into it (at the "i2c_write" level).

    I didn't find any specifically for the MSP430. This person over here was working with the F5529 but the I2C units are somewhat similar. I thought I recalled that he had succeeded, but re-reading the final sentence apparently he didn't. I now wonder whether he was encountering the 1-byte-per-transaction limitation. Anyway, it had the pieces I would expect (both LCD and I2C layers), they may just need a little re-packaginng.

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/907530

    The examples are over here. "i2c_02" appears to work with a cousin of your PCF chip.

    http://dev.ti.com/tirex/explore/node?node=ALFfIDtjUH-HwRytz.WJPQ__IOGqZri__LATEST

  • I have written code for the character LCDs in a few ways but always with direct GPIO connections and not using a I2C I/O expander. That makes it a lot harder.

    Further I can't say because while you said you are using an I/O expander to interface to the LCD, you provide no details on the connections. Are the control signals connected?

  • I recommend a divide and conquer approach: first get the I/O expander working. You need a function that will write a byte to the output. Once you get that working you can worry about talking to the LCD.

  • 5V to VCC, GND to GND, P1.7 to SDA, P1.6 to SCL. Theese are the only connections.

    Thanks for advices, I will read documentations more carefully and analyze the codes that you given. I hope I can print 'Hello World' on screen eventually.

  • No pullup resistors to 3.3V on SDA and SCL? (MSP430 Vcc) No connections to the LCD?

  • Do I have to add resistor to SDA and SCL?

  • I have no idea. You bought that display with its I2C interface so you know what you have. I don't. You will have to read the documentation that came with it because I don't have it.

  • Sunfounder (among others) markets an LCD1602 with QAPASS on the back of the LCD and MH on the backpack. Its Wiki page points to an Arduino library, which includes:

    #define LCD_BACKLIGHT 0x08
    #define En B00000100  // Enable bit
    #define Rw B00000010  // Read/Write bit
    #define Rs B00000001  // Register select bit
    

    http://wiki.sunfounder.cc/index.php?title=I%C2%B2C_LCD1602

    This has an actual schematic which matches in the things I can check. It includes pullups on the I2C. These pullups would be to 5V, which may or may not be good for the MSP430, but I suppose if you haven't fried anything yet you can get away with it.

    It also shows D7-D4 in the high bits of the port.

    https://www.playembedded.org/blog/hd44780-backpack-stm32/

**Attention** This is a public forum