I2C commands to LCD
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 1:23 PM
I am learning this new 32-bit from my 8-bit world as well as new IDE on top of re-learning C. So be gentle....
I am trying to use the CubeIDE to talk to an I2C LCD. I am following a tutorial but the LCD does not respond at all.
Some of the code below:
/* LCD Commands */
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
/* Commands bitfields */
//1) Entry mode Bitfields
#define LCD_ENTRY_SH 0x01
#define LCD_ENTRY_ID 0x02
//2) Display control
#define LCD_DISPLAY_B 0x01
#define LCD_DISPLAY_C 0x02
#define LCD_DISPLAY_D 0x04
//3) Shift control
#define LCD_SHIFT_RL 0x04
#define LCD_SHIFT_SC 0x08
//4) Function set control
#define LCD_FUNCTION_F 0x04
#define LCD_FUNCTION_N 0x08
#define LCD_FUNCTION_DL 0x10
/* I2C Control bits */
#define LCD_RS (1 << 0)
#define LCD_RW (1 << 1)
#define LCD_EN (1 << 2)
#define LCD_BK_LIGHT (1 << 3)
/* Library variables */
static I2C_HandleTypeDef* lcd16x2_i2cHandle;
static uint8_t LCD_I2C_SLAVE_ADDRESS=0;
#define LCD_I2C_SLAVE_ADDRESS_0 0x4E
#define LCD_I2C_SLAVE_ADDRESS_1 0x7E
/* Private functions */
static void lcd16x2_i2c_sendCommand(uint8_t command)
{
const uint8_t command_0_3 = (0xF0 & (command<<4));
const uint8_t command_4_7 = (0xF0 & command);
uint8_t i2cData[4] =
{
command_4_7 | LCD_EN | LCD_BK_LIGHT,
command_4_7 | LCD_BK_LIGHT,
command_0_3 | LCD_EN | LCD_BK_LIGHT,
command_0_3 | LCD_BK_LIGHT,
};
HAL_I2C_Master_Transmit(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS, i2cData, 4, 200);
}
static void lcd16x2_i2c_sendData(uint8_t data)
{
const uint8_t data_0_3 = (0xF0 & (data<<4));
const uint8_t data_4_7 = (0xF0 & data);
uint8_t i2cData[4] =
{
data_4_7 | LCD_EN | LCD_BK_LIGHT | LCD_RS,
data_4_7 | LCD_BK_LIGHT | LCD_RS,
data_0_3 | LCD_EN | LCD_BK_LIGHT | LCD_RS,
data_0_3 | LCD_BK_LIGHT | LCD_RS,
};
HAL_I2C_Master_Transmit(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS, i2cData, 4, 200);
}
I have a logic analyzer set to display I2C on the SCL and SDA pins and the results after a reset are:
write to 0x1F nak
read to 0x1F ack
read to 0x1F ack
read to 0x1F ack data:0x3F
read to 0x1E ack data: 0x6D
read to 0x79 ack
read to 0x36 nak
read to 0x36 nak
I have checked with a different tutorial for using the I2C LCD and the defines seem to match.
There are no jumpers on the A0 A1 or A2 lines which suggest it is at address 0x4E for write and 0x4F for read.
I suspect this may be simple but I have been looking for sometime and it seems to evade me.
Any suggestions would be greatly appreciated.
Regards to All.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 5:56 PM
The original Youtube video showed the author using a STM32 Discovery board and I am using a Nucleo-H723ZG board.
Could I be missing something in the way I set up the chip in the IOC?
Feeling frustrated as this code apparently does work - perhaps not easily on my board however?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 6:01 PM
Right here:
bool lcd16x2_i2c_init(I2C_HandleTypeDef *pI2cHandle)
{
HAL_Delay(50);
lcd16x2_i2cHandle = pI2cHandle;
if(HAL_I2C_IsDeviceReady(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS_0, 5, 500) != HAL_OK)
{
if(HAL_I2C_IsDeviceReady(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS_1, 5, 500) != HAL_OK)
{
return false;
}
else
{
LCD_I2C_SLAVE_ADDRESS = LCD_I2C_SLAVE_ADDRESS_1;
}
}
else
{
LCD_I2C_SLAVE_ADDRESS = LCD_I2C_SLAVE_ADDRESS_0;
}
...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 6:16 PM
I feel so stupid. I have looked at this code for quite a while and did not see that.
To your question, how would I know if HAL_OK?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 6:39 PM
* Put some breakpoints in the code in relevant spots. Infer the return value from which one gets hit.
* Rewrite the code to save the return value, and view that variable in the debugger.
These are pretty basic debugging skills. If you want to develop programs, you'll need to get comfortable there.
You should also be able to find examples that look for all I2C devices on the bus. Here is one of many:
https://deepbluembedded.com/stm32-i2c-scanner-hal-code-example/
I2C should work on the STM32H7 the same as the other families. The HAL does the lower level work to make the user-facing functions the same on all families. Basic rules still apply. I2C needs external pullups, or internal pullups with a very low clock speed. If you can see SDA/SCL signals, and they have clear edges, and the clock speed is correct, it's probably wired correctly. Still need to power the external device, and provide ground.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 6:44 PM
Thanks TDK. In my 8-bit world I would push data to a serial port and use it for debug.
I have tried
bool lcd16x2_i2c_init(I2C_HandleTypeDef *pI2cHandle)
{
HAL_Delay(50);
lcd16x2_i2cHandle = pI2cHandle;
if(HAL_I2C_IsDeviceReady(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS_0, 5, 500) != HAL_OK)
{
if(HAL_I2C_IsDeviceReady(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS_1, 5, 500) != HAL_OK)
{
return false;
}
else
{
LCD_I2C_SLAVE_ADDRESS = LCD_I2C_SLAVE_ADDRESS_1;
printf("** Addr=1 ** \n\r");
}
}
else
{
LCD_I2C_SLAVE_ADDRESS = LCD_I2C_SLAVE_ADDRESS_0;
printf("** Addr=0 ** \n\r");
}
However, it does not print to the console feature pf the IDE. I am sure I don't yet have a grasp on it.
I will look at your example given to see if I can get some insight.
Should I be able to print directly to the console for debug purposes?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 6:54 PM
TDK, I will use a couple of LEDs to let me know if addr0 or addr1 is used.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 7:14 PM
TDK, I have tried several ways to get an LED to fire based on which address.
How would you do it with the following code?
My attempt has been commented out:
bool lcd16x2_i2c_init(I2C_HandleTypeDef *pI2cHandle)
{
HAL_Delay(50);
lcd16x2_i2cHandle = pI2cHandle;
if(HAL_I2C_IsDeviceReady(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS_0, 5, 500) != HAL_OK)
// HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); //GREEN LED
{
if(HAL_I2C_IsDeviceReady(lcd16x2_i2cHandle, LCD_I2C_SLAVE_ADDRESS_1, 5, 500) != HAL_OK)
{
return false;
}
else
{
LCD_I2C_SLAVE_ADDRESS = LCD_I2C_SLAVE_ADDRESS_1;
}
}
else
{
LCD_I2C_SLAVE_ADDRESS = LCD_I2C_SLAVE_ADDRESS_0;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-08-15 7:49 PM

- « Previous
-
- 1
- 2
- Next »