Gary Richardson
/
testLCD
Test of LCD code
Diff: lcd_i2c.cpp
- Revision:
- 0:a4d44dfd2f03
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcd_i2c.cpp Fri May 30 12:24:56 2014 +0000 @@ -0,0 +1,148 @@ +#include "mbed.h" +#include "lcd_i2c.h" +/* + LCD (Optrex DCM16230, DCM20261, etc.) via I2C using a PCF8574 + + Frequency (clks/sec) Frequency + Transfer rate = ------------------------------------------------ = ---------------- (characters/sec) + 9 clks/write * 3 writes/nibble * 2 nibbles/character 54 +*/ +I2C i2c(p9, p10); // (sda, scl) +Serial pc2(USBTX, USBRX); // tx, rx + +// PCF8574 output bits Px +#define RS BIT1 +#define RW BIT2 +#define E BIT3 +#define DB4 BIT4 +#define DB5 BIT5 +#define DB6 BIT6 +#define DB7 BIT7 + +char update[NUPDATE]; +char cw, address; + +int updateDisplay(char *str, int nchars) +{ +char w, ch, *p; +int n, k, rc; + + if (nchars > 20) + return 1; + n = 0; + p = update; + for (k = 0; k < nchars; k++) + { + // write most significant nibble + ch = *str++; + w = (ch & 0xf0) | cw; + *p++ = w; + *p++ = w | E; + *p++ = w; + + // write least significant nibble + w = (ch << 4) | cw; + *p++ = w; + *p++ = w | E; + *p++ = w; + n += 6; + } + rc = i2c.write(address, update, n); // rc == 0 ==> ACK + return rc; +} + +int write4Bits(char data) +{ +char w; +int rc; + + w = (data & 0xf0) | cw; // grab the left nibble + update[0] = w; + update[1] = w | E; + update[2] = w & ~ E; + rc = i2c.write(address, update, 3); + return rc; +} + +int initLcd(int i2cAddress, int frequency) +{ +typedef struct { + char cmd; + char numNibbles; + char delayMs; + //char testBF; +} INIT; +static const INIT initData[] = { + {3, 1, 5}, + {3, 1, 1}, + {3, 1, 1}, + {2, 1, 1}, // Function set: 4-bit interface + {0x28, 2, 2}, // Function set: 2 lines, 5x7 + {0x08, 2, 2}, // Display off + {0x01, 2, 16}, // Clear display + {0x06, 2, 2}, // Entry mode set: No increment, shift cursor + {0x0e, 2, 2}}; // Display on: cursor on, blink off +#define NINITD (sizeof(initData)/sizeof(initData[0])) +INIT *p; +int k, rc; + // Initialization must start at least 16 ms after power up. + i2c.frequency(frequency); + address = i2cAddress; + cw = 0; + p = (INIT *)initData; + for (k = 0; k < NINITD; k++) + { + //p = (INIT *)&initData[k]; + if (p->numNibbles == 1) + rc = write4Bits(p->cmd << 4); + else + { + rc = write4Bits(p->cmd); // output the most significant nibble + wait_us(10); // this will need to be adjusted when printf stmts are removed + rc |= write4Bits(p->cmd << 4); // output the least significant nibble + } + if (rc) + break; + wait_ms(p->delayMs); + p++; + } + return rc; +} + +int lcdWriteMsg(char *msg) +{ // msg must be a null-terminated string +char rc; + cw |= RS; // data + cw &= ~RW; // write + rc = updateDisplay(msg, strlen(msg)); + return rc; +} + +int lcdWriteCmd(char cmd, int delayMs) +{ +int rc; + cw &= ~RS; // command + rc = write4Bits(cmd); + wait_us(10); + rc |= write4Bits(cmd << 4); + if (delayMs) + wait_ms(delayMs); + return rc; +} + +int lcdPositionCursor(char row, char col) +{ +// Code may not be correct for displays larger than 20 x 2 +int x, rc; + x = 0x80 | ((row & 1)<<6) | (col & 0xf); + rc = lcdWriteCmd(x, 1); + return rc; +} + +int lcdClearDisplay(void) +{ + return lcdWriteCmd(1, 16); +} + + +