mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 20:08:15 +08:00
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:
@@ -63,9 +63,9 @@
|
|||||||
|
|
||||||
/* timing characteristics of the LCD interface */
|
/* timing characteristics of the LCD interface */
|
||||||
|
|
||||||
#define DELAY_US_NYBBLE0 200
|
#define DELAY_US_NYBBLE0 20
|
||||||
#define DELAY_US_NYBBLE1 100
|
#define DELAY_US_NYBBLE1 10
|
||||||
#define DELAY_US_WRITE 35
|
#define DELAY_US_WRITE 40
|
||||||
#define DELAY_US_HOMECLEAR 1500
|
#define DELAY_US_HOMECLEAR 1500
|
||||||
|
|
||||||
/* HD44780 commands */
|
/* 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.
|
* 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;
|
en_bit = 1 << priv->cfg.en;
|
||||||
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
|
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);
|
pca8574_write(priv, lcddata);
|
||||||
up_udelay(DELAY_US_NYBBLE0); /* setup */
|
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;
|
rs_bit = rs ? (1 << priv->cfg.rs) : 0;
|
||||||
rw_bit = 1 << priv->cfg.rw;
|
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);
|
pca8574_write(priv, lcddata);
|
||||||
up_udelay(DELAY_US_NYBBLE0); /* setup */
|
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 */
|
/* 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
|
/* Perform the init sequence. This sequence of commands is constructed so
|
||||||
* that it will get the device into nybble mode irrespective of what state
|
* 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.
|
* 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);
|
latch_nybble(priv, 0x30>>4, false);
|
||||||
usleep(5000);
|
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 */
|
/* Send Command 0x30, set 8-bit mode, and wait > 100 us */
|
||||||
|
|
||||||
latch_nybble(priv, 0x30>>4, false);
|
latch_nybble(priv, 0x30>>4, false);
|
||||||
usleep(200);
|
usleep(5000);
|
||||||
|
|
||||||
/* Send Command 0x30, set 8-bit mode */
|
/* Send Command 0x30, set 8-bit mode */
|
||||||
|
|
||||||
latch_nybble(priv, 0x30>>4, false);
|
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). */
|
/* now Function set: Set interface to be 4 bits long (only 1 cycle write for the first time). */
|
||||||
|
|
||||||
latch_nybble(priv, 0x20>>4, false);
|
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) */
|
/* 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'.
|
Now character '\x04' will display as an 'up arrow'.
|
||||||
|
|
||||||
Note, you might consider avoiding the use of code point 0x00 unless
|
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,
|
problems. The driver, and write() apis are binary, and unaffected,
|
||||||
but things like printf() and puts() assume C-style strings, and are
|
but things like printf() and puts() assume C-style strings, and are
|
||||||
affected.
|
affected.
|
||||||
@@ -237,9 +237,16 @@ Troubleshooting
|
|||||||
bus timeouts that suggest a non-responsive slave.
|
bus timeouts that suggest a non-responsive slave.
|
||||||
* Check your board wiring and configuration specification. Buzz
|
* Check your board wiring and configuration specification. Buzz
|
||||||
out the lines if you have to.
|
out the lines if you have to.
|
||||||
* Con't forget to check the 'contrast' potentiometer. The voltage
|
* Remember to set the (ros,cols) geometry in pcf8574_lcd_backpack_config_s
|
||||||
at the central wiper should be approximately 0.29 V. The useful
|
before registration of the driver, since this cannot be determined
|
||||||
range of voltages at this pin is very narrow, and outside that
|
programmatically.
|
||||||
range there will be nothing visible on the display, so most of the
|
* If the driver registration step seems to 'hang' it could be the I2C
|
||||||
turn range of the pot is non-useful. Much of human life has been
|
driver performing retries due to no response from the LCD backpack. Check
|
||||||
wasted in the rediscovery of this farcically idiotic
|
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
|
* 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
|
* separate 2x40 controllers, and the I2C backpack doesn't support those due
|
||||||
* to the second 'E' line being needed.
|
* 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'.
|
* Consider these 'informative'.
|
||||||
* XXX Note, actual testing has been done on LCD_I2C_BACKPACK_CFG_MJKDZ only,
|
* XXX Note, actual testing has been done on LCD_I2C_BACKPACK_CFG_MJKDZ
|
||||||
* the others come from online research.
|
* 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}
|
#define LCD_I2C_BACKPACK_CFG_MJKDZ {0x20,4,5,6,0,1,2,3,7,false,0,0}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user