correct logic hazard in latch and load nybble; was transitioning control lines at the same time as enable, causing spurious behaviour on less-tolerant displays
improve timing parameters in init sequences for better display compatibility correct (row,col) -> address calculation; affects 4-line displays update comments in header and readme
This commit is contained in:
parent
4cc722aa1a
commit
4643fcdfd8
@ -63,9 +63,9 @@
|
||||
|
||||
/* timing characteristics of the LCD interface */
|
||||
|
||||
#define DELAY_US_NYBBLE0 200
|
||||
#define DELAY_US_NYBBLE1 100
|
||||
#define DELAY_US_WRITE 35
|
||||
#define DELAY_US_NYBBLE0 20
|
||||
#define DELAY_US_NYBBLE1 10
|
||||
#define DELAY_US_WRITE 40
|
||||
#define DELAY_US_HOMECLEAR 1500
|
||||
|
||||
/* HD44780 commands */
|
||||
@ -259,7 +259,7 @@ static inline uint8_t rc2addr(FAR struct pcf8574_lcd_dev_s *priv,
|
||||
* of first line, and fourth line is a continuation of second.
|
||||
*/
|
||||
|
||||
return (row - 2) * 0x40 + (col - priv->cfg.cols);
|
||||
return (row - 2) * 0x40 + (col + priv->cfg.cols);
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,9 +383,14 @@ static void latch_nybble(FAR struct pcf8574_lcd_dev_s *priv, uint8_t nybble,
|
||||
en_bit = 1 << priv->cfg.en;
|
||||
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
|
||||
|
||||
/* Put the nybble, preserving backlight, reset R/~W and set EN and maybe RS */
|
||||
/* Put the nybble, preserving backlight, reset R/~W and maybe RS */
|
||||
|
||||
lcddata = prepare_nybble(priv, nybble) | priv->bl_bit | en_bit | rs_bit;
|
||||
lcddata = prepare_nybble(priv, nybble) | priv->bl_bit | rs_bit;
|
||||
pca8574_write(priv, lcddata);
|
||||
|
||||
/* Now set EN */
|
||||
|
||||
lcddata |= en_bit;
|
||||
pca8574_write(priv, lcddata);
|
||||
up_udelay(DELAY_US_NYBBLE0); /* setup */
|
||||
|
||||
@ -419,9 +424,14 @@ static uint8_t load_nybble(FAR struct pcf8574_lcd_dev_s *priv, bool rs)
|
||||
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
|
||||
rw_bit = 1 << priv->cfg.rw;
|
||||
|
||||
/* Put highs on the data lines, preserve, set R/~W and set EN and maybe RS */
|
||||
/* Put highs on the data lines, preserve, set R/~W and maybe RS */
|
||||
|
||||
lcddata = prepare_nybble(priv, 0x0f) | priv->bl_bit | en_bit | rw_bit | rs_bit;
|
||||
lcddata = prepare_nybble(priv, 0x0f) | priv->bl_bit | rw_bit | rs_bit;
|
||||
pca8574_write(priv, lcddata);
|
||||
|
||||
/* Now set EN */
|
||||
|
||||
lcddata |= en_bit;
|
||||
pca8574_write(priv, lcddata);
|
||||
up_udelay(DELAY_US_NYBBLE0); /* setup */
|
||||
|
||||
@ -538,7 +548,7 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
|
||||
{
|
||||
/* Wait for more than 15 ms after Vcc for the LCD to stabilize */
|
||||
|
||||
usleep(20000);
|
||||
usleep(50000);
|
||||
|
||||
/* Perform the init sequence. This sequence of commands is constructed so
|
||||
* that it will get the device into nybble mode irrespective of what state
|
||||
@ -548,7 +558,7 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
|
||||
* the remainder of operations.
|
||||
*/
|
||||
|
||||
/* Send Command 0x30, set 8-bit mode, and wait > 4.1 ms*/
|
||||
/* Send Command 0x30, set 8-bit mode, and wait > 4.1 ms */
|
||||
|
||||
latch_nybble(priv, 0x30>>4, false);
|
||||
usleep(5000);
|
||||
@ -556,15 +566,17 @@ static void lcd_init(FAR struct pcf8574_lcd_dev_s *priv)
|
||||
/* Send Command 0x30, set 8-bit mode, and wait > 100 us */
|
||||
|
||||
latch_nybble(priv, 0x30>>4, false);
|
||||
usleep(200);
|
||||
usleep(5000);
|
||||
|
||||
/* Send Command 0x30, set 8-bit mode */
|
||||
|
||||
latch_nybble(priv, 0x30>>4, false);
|
||||
usleep(200);
|
||||
|
||||
/* now Function set: Set interface to be 4 bits long (only 1 cycle write for the first time). */
|
||||
|
||||
latch_nybble(priv, 0x20>>4, false);
|
||||
usleep(5000);
|
||||
|
||||
/* Function set: DL=0;Interface is 4 bits, N=1 (2 Lines), F=0 (5x8 dots font) */
|
||||
|
||||
|
@ -225,7 +225,7 @@ Example of programming a character image:
|
||||
Now character '\x04' will display as an 'up arrow'.
|
||||
|
||||
Note, you might consider avoiding the use of code point 0x00 unless
|
||||
absolutely needed, because the embedded nul character can cause
|
||||
you absolutely need it, because the embedded nul character can cause
|
||||
problems. The driver, and write() apis are binary, and unaffected,
|
||||
but things like printf() and puts() assume C-style strings, and are
|
||||
affected.
|
||||
@ -237,9 +237,16 @@ Troubleshooting
|
||||
bus timeouts that suggest a non-responsive slave.
|
||||
* Check your board wiring and configuration specification. Buzz
|
||||
out the lines if you have to.
|
||||
* Con't forget to check the 'contrast' potentiometer. The voltage
|
||||
at the central wiper should be approximately 0.29 V. The useful
|
||||
range of voltages at this pin is very narrow, and outside that
|
||||
range there will be nothing visible on the display, so most of the
|
||||
turn range of the pot is non-useful. Much of human life has been
|
||||
wasted in the rediscovery of this farcically idiotic
|
||||
* Remember to set the (ros,cols) geometry in pcf8574_lcd_backpack_config_s
|
||||
before registration of the driver, since this cannot be determined
|
||||
programmatically.
|
||||
* If the driver registration step seems to 'hang' it could be the I2C
|
||||
driver performing retries due to no response from the LCD backpack. Check
|
||||
the address. Turning on debug output for I2C can help make this visible.
|
||||
* Don't forget to check the 'contrast' potentiometer. The voltage at the
|
||||
central wiper should be approximately 0.3 V - 2.4 V, but the actual value
|
||||
is is dependent on the physics of the attached LCD module. The useful
|
||||
range of voltages at this pin for any given LCD is quite narrow, and
|
||||
outside that range there will be nothing visible on the display, so most
|
||||
of the turn range of the pot is non-useful. It's less 'contrast' and
|
||||
more 'LCD segment drive bias'.
|
||||
|
@ -58,12 +58,15 @@
|
||||
* Pretty much anything on the market except 4x40, which really consists of two
|
||||
* separate 2x40 controllers, and the I2C backpack doesn't support those due
|
||||
* to the second 'E' line being needed.
|
||||
* Additionally, you still need to set the (row,col) geometry explicitly, since
|
||||
* there is not a means of determining this dynamically.
|
||||
* Consider these 'informative'.
|
||||
* XXX Note, actual testing has been done on LCD_I2C_BACKPACK_CFG_MJKDZ only,
|
||||
* the others come from online research.
|
||||
* XXX Note, actual testing has been done on LCD_I2C_BACKPACK_CFG_MJKDZ
|
||||
* and LCD_I2C_BACKPACK_CFG_SAINSMART only, the others come from online
|
||||
* research.
|
||||
*/
|
||||
|
||||
/* board marked 'mjkdz' */
|
||||
/* board marked 'mjkdz' and Arduino-IIC-LCD GY-LCD-V1 */
|
||||
|
||||
#define LCD_I2C_BACKPACK_CFG_MJKDZ {0x20,4,5,6,0,1,2,3,7,false,0,0}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user