How to run LCD display using I2C on Zephyr? #72745
Unanswered
hanabudimlic
asked this question in
Q&A
Replies: 2 comments
-
Hi @hanabudimlic! We appreciate you submitting your first issue for our open-source project. 🌟 Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙 |
Beta Was this translation helpful? Give feedback.
0 replies
-
CC @erwango @ajarmouni-st @FRASTM @gautierg-st @GeorgeCGV |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Describe the bug
I am trying to use 1602 display via I2C communication protocol in Zephyr using stm32f3 discovery board. The program fails during initialization and it prints on serial monitor "Status -5" i.e. I/O error. The 'lcdInit()' function calls 'lcdSendCommand()' function that calls Zephyr's 'i2c_write()' function who ultimately returns the error code. The similar code was used to establish desired behaviour using uVision and it worked with no errors, so I believe I am missing some kind of configuration here.
I didn't change anything in the device tree, so my overlay file looks like this:
i2c1: &i2c1 {
pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb7>;
pinctrl-names = "default";
status = "okay";
clock-frequency = <I2C_BITRATE_FAST>;
};
This is my main:
/*
*/
#include <stdbool.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
#include <string.h>
#include <zephyr/drivers/i2c.h>
#include "../inc/i2c_lcd.h"
#define I2C_INST DT_NODELABEL(i2c1)
//static const struct i2c_dt_spec i2c = I2C_DT_SPEC_GET(i2c1);
const struct device *const i2c = DEVICE_DT_GET(I2C_INST);
int main(){
if (!device_is_ready(i2c)) {
printf("i2c is not ready!\n");
} else {
printf("i2c is ready\n");
}
lcdInit(i2c);
k_sleep(K_MSEC(1000));
printf("Checkpoint\n");
k_sleep(K_MSEC(1000));
char buf[] = "hello";
lcdSendString(i2c, buf);
while (1){
printk("Hello world\n");
k_sleep(K_MSEC(1000));
}
return 0;
}
And lastly my .c file for i2c communication to lcd:
#include "i2c_lcd.h"
#include <zephyr/sys/printk.h>
// LOG_MODULE_REGISTER(i2c_lcd);
#define SLAVE_ADDRESS_LCD 0x4E
void lcdSendCommand(const struct device *const i2c_dev, char cmd){
char data_u, data_l;
uint8_t data_t[4];
data_u = (cmd & 0xf0);
data_l = ((cmd << 4) & 0xf0);
data_t[0] = data_u | 0x0C; // en=1, rs=0
data_t[1] = data_u | 0x08; // en=0, rs=0
data_t[2] = data_l | 0x0C; // en=1, rs=0
data_t[3] = data_l | 0x08; // en=0, rs=0
int ret;
ret = i2c_write(i2c_dev, data_t, 4, SLAVE_ADDRESS_LCD);
printk("Status %d\n", ret);
}
void lcdSendData(const struct device *const i2c_dev, char data){
char data_u, data_l;
uint8_t data_t[4];
data_u = (data & 0xf0);
data_l = ((data << 4) & 0xf0);
data_t[0] = data_u | 0x0D; // en=1, rs=0
data_t[1] = data_u | 0x09; // en=0, rs=0
data_t[2] = data_l | 0x0D; // en=1, rs=0
data_t[3] = data_l | 0x09; // en=0, rs=0
i2c_write(i2c_dev, data_t, 4, SLAVE_ADDRESS_LCD);
}
void lcdClear(const struct device *const i2c_dev){
lcdSendCommand(i2c_dev, 0x80);
for (int i = 0; i < 70; i++)
{
lcdSendData(i2c_dev, ' ');
}
}
void lcdPutCur(const struct device *const i2c_dev, int row, int col){
switch (row){
case 0:
col |= 0x80;
break;
case 1:
col |= 0xC0;
break;
}
}
void lcdInit (const struct device *const i2c_dev){
// 4 bit initialization
k_sleep(K_MSEC(50)); // wait for >40ms
lcdSendCommand(i2c_dev, 0x30);
k_sleep(K_MSEC(5)); // wait for >4.1ms
lcdSendCommand(i2c_dev, 0x30);
k_sleep(K_USEC(100)); // wait for >100us
lcdSendCommand(i2c_dev, 0x30);
k_sleep(K_MSEC(10));
lcdSendCommand(i2c_dev, 0x20); // 4bit mode
k_sleep(K_MSEC(10));
// display initialization
lcdSendCommand(i2c_dev, 0x28); // Function set --> DL=0 (4 bit mode), N = 1 (2 line display) F = 0 (5x8 characters)
k_sleep(K_MSEC(1));
lcdSendCommand(i2c_dev, 0x08); // Display on/off control --> D=0,C=0, B=0 ---> display off
k_sleep(K_MSEC(1));
lcdSendCommand(i2c_dev, 0x01); // clear display
k_sleep(K_MSEC(1));
k_sleep(K_MSEC(1));
lcdSendCommand(i2c_dev, 0x06); // Entry mode set --> I/D = 1 (increment cursor) & S = 0 (no shift)
k_sleep(K_MSEC(1));
lcdSendCommand(i2c_dev, 0x0C); // Display on/off control --> D = 1, C and B = 0. (Cursor and blink, last two bits)
}
void lcdSendString(const struct device *const i2c_dev, char *str){
while (*str)
lcdSendData(i2c_dev, *str++);
}
Expected behavior
I expect the program to print 'hello' on LCD display.
Impact
This issue stopped the progress with my current work.
Environment (please complete the following information):
OS: Ubuntu
Board: STM32F3 DISCOVERY
Beta Was this translation helpful? Give feedback.
All reactions