i2c是最常用的通信接口或协议,在龙芯2k0300中蜂鸟开发板上,引出了4路i2c,相对来说,还是比较充足的,本文使用i2c2来驱动lcd模块
硬件电路
i2c电路
![QQ_1724683173944.png](//file1.elecfans.com/web2/M00/05/30/wKgaombMk_6AVuBAAAF03h7cAWY511.png)
![QQ_1724683859821.png](//file1.elecfans.com/web2/M00/05/30/wKgaombMll6APstZAAFh7dT7Wrw318.png)
lcd模块
采用Grove - 16x2 LCD模块,如下图所示,它是i2c接口,支持显示16x2个字符,
![QQ_1724683481018.png](//file1.elecfans.com/web2/M00/04/43/wKgZombMlOCAMwjjAAGCcjE3kpE156.png)
Grove - 16x2 LCD | Seeed Studio Wiki
Grove - 16X2 LCD RGB Backlight - Seeed Studio
驱动适配
设备树
无,使用传统或原始的方法适配
驱动代码
板级文件
#define I2C_BUS_AVAILABLE (2)
#define LCD_ADDRESS 0x3E
#define RGB_ADDRESS 0x62
static struct i2c_client *rgb_client;
static struct i2c_board_info lcd_board_info = {
I2C_BOARD_INFO("lcd", LCD_ADDRESS)
};
static struct i2c_board_info rgb_board_info = {
I2C_BOARD_INFO("rgb", RGB_ADDRESS)
};
probe
static int i2c_driver_probe(struct i2c_client *client, const struct i2c_device_id *id) {
pr_info("Grove LCD RGB Backlight V4.0 driver probe\n");
if (client->addr == RGB_ADDRESS) {
pr_info("client->addr is RGB\n");
initialize_rgb(client);
rgb_client = client;
} else if (client->addr == LCD_ADDRESS) {
pr_info("client->addr is LCD\n");
initialize_lcd(client);
lcd_write_string(client, lcd_text);
lcd_client = client;
}
return 0;
}
static const struct i2c_device_id i2c_driver_id[] = {
{ "lcd", 0 },
{ "rgb", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, i2c_driver_id);
static struct i2c_driver etx_i2c_driver = {
.driver = {
.name = "grove_lcd_rgb",
.owner = THIS_MODULE,
},
.probe = i2c_driver_probe,
.remove = i2c_driver_remove,
.id_table = i2c_driver_id,
};
控制代码
static void initialize_rgb(struct i2c_client *client) {
pr_info("Initilize of RGB starting...\n");
i2c_write_data(client, rgb_reg_reset, rgb_val_reset);
i2c_write_data(client, rgb_reg_clock, rgb_val_clock);
i2c_write_data(client, rgb_reg_led, rgb_val_led);
i2c_write_data(client, rgb_reg_red, rgb_val_red);
i2c_write_data(client, rgb_reg_green, rgb_val_green);
i2c_write_data(client, rgb_reg_blue, rgb_val_blue);
pr_info("Initilize of RGB Completed\n");
}
static void lcd_write_string(struct i2c_client *client, const char *str) {
pr_info("Writing is start on display\n");
i2c_write_data(client, COMMAND_MODE, 0x80);
i = 0;
while ((i < LCD_MAX_CHARS_PER_LINE) && (*str)) {
i2c_write_data(client, DATA_MODE, *str++);
i++;
}
if (*str) {
i2c_write_data(client, COMMAND_MODE, 0xC0);
while (*str) {
i2c_write_data(client, DATA_MODE, *str++);
}
}
pr_info("Writing is completed on display\n");
}
应用测试
while (1) {
printf("\nChoose an operation:\n");
printf("1. Read RGB values\n");
printf("2. Write RGB values\n");
printf("3. Read LCD text value\n");
printf("4. Write LCD text value\n");
printf("5. Exit\n");
printf("Enter your choice: ");
scanf("%d", &option);
switch (option) {
case 1:
// Read RGB values from driver
printf("Reading RGB Values from Driver...\n");
ioctl(fd, RD_RGB_VALUE, (struct rgb_value*) &read_data);
printf("RGB Values are R: %d, G: %d, B: %d\n", read_data.red, read_data.green, read_data.blue);
break;
case 2:
// Write RGB values to driver
printf("Enter the RGB values (0-255) to send: \n");
printf("Red: ");
scanf("%d", &Red);
printf("Green: ");
scanf("%d", &Green);
printf("Blue: ");
scanf("%d", &Blue);
if(Red > 255 || Red < 0){
printf("Red > 255\nTaking default value of Red : 255\n");
rgb_data.red = 255;
} else {
rgb_data.red = Red;
}
if(Green > 255 || Green < 0){
printf("Green > 255\nTaking default value of Green : 255\n");
rgb_data.green = 255;
} else {
rgb_data.green = Green;
}
if(Blue > 255 || Blue < 0){
printf("Blue > 255\nTaking default value of Blue : 255\n");
rgb_data.blue = 255;
} else {
rgb_data.blue = Blue;
}
// Print RGB values before writing to driver
printf("RGB Values to write: R: %d, G: %d, B: %d\n", rgb_data.red, rgb_data.green, rgb_data.blue);
printf("Writing RGB Values to Driver...\n");
ioctl(fd, WR_RGB_VALUE, (struct rgb_value*) &rgb_data);
break;
case 3:
// Read LCD text from driver
printf("Reading LCD Text from Driver...\n");
ioctl(fd, RD_LCD_TEXT, read_lcd_text);
printf("LCD Text is: %s\n", read_lcd_text);
break;
case 4:
// Get LCD text from user
printf("Enter the LCD text to send: \n");
getchar(); // Clear newline character left by previous scanf
fgets(lcd_text, sizeof(lcd_text), stdin);
lcd_text[strcspn(lcd_text, "\n")] = 0; // Remove newline character
// Print LCD text before writing to driver
printf("LCD Text to write: %s\n", lcd_text);
// Write LCD text to driver
printf("Writing LCD Text to Driver...\n");
ioctl(fd, WR_LCD_TEXT, lcd_text);
break;
case 5:
printf("Exiting...\n");
close(fd);
return 0;
default:
printf("Invalid option. Please try again.\n");
break;
}
}
验证效果
加载驱动
[root@LS-GD home]# insmod i2clcd.ko [ 46.470496] audit: type=1334 audit(1612279826.283:6): prog-id=8 op=UNLOAD
[ 46.478288] audit: type=1334 audit(1612279826.283:7): prog-id=7 op=UNLOAD
[ 53.668027] i2clcd: loading out-of-tree module taints kernel.
[ 53.686544] Major = 242 Minor = 0
[ 53.698072] Grove LCD RGB Backlight V4.0 driver probe
[ 53.718396] client->addr is LCD
[ 53.725472] Initilize of LCD starting...
[ 53.786414] Sending data to I2C device: register=0x00, data=0x28
[ 53.792549] send bytes 2
[ 53.844383] Sending data to I2C device: register=0x00, data=0x08
[ 53.853055] send bytes 2
[ 53.904395] Sending data to I2C device: register=0x00, data=0x01
[ 53.913068] send bytes 2
[ 53.964392] Sending data to I2C device: register=0x00, data=0x06
[ 53.973063] send bytes 2
[ 54.026405] Sending data to I2C device: register=0x00, data=0x0C
[ 54.041318] send bytes 2
[ 54.094400] Initilize of LCD Completed
[ 54.106413] Writing is start on display
[ 54.112216] Sending data to I2C device: register=0x00, data=0x80
[ 54.118883] send bytes 2
[ 54.118890] Sending data to I2C device: register=0x40, data=0x48
[ 54.127889] send bytes 2
[ 54.127896] Sending data to I2C device: register=0x40, data=0x65
[ 54.136886] send bytes 2
[ 54.136892] Sending data to I2C device: register=0x40, data=0x6C
[ 54.166404] send bytes 2
[ 54.166417] Sending data to I2C device: register=0x40, data=0x6C
[ 54.185393] send bytes 2
[ 54.185406] Sending data to I2C device: register=0x40, data=0x6F
[ 54.204449] send bytes 2
[ 54.204463] Sending data to I2C device: register=0x40, data=0x2C
[ 54.218419] send bytes 2
[ 54.218429] Sending data to I2C device: register=0x40, data=0x20
[ 54.237657] send bytes 2
[ 54.237671] Sending data to I2C device: register=0x40, data=0x57
[ 54.246956] send bytes 2
[ 54.246963] Sending data to I2C device: register=0x40, data=0x6F
[ 54.255949] send bytes 2
[ 54.255956] Sending data to I2C device: register=0x40, data=0x72
[ 54.264947] send bytes 2
[ 54.264953] Sending data to I2C device: register=0x40, data=0x6C
[ 54.273941] send bytes 2
[ 54.273948] Sending data to I2C device: register=0x40, data=0x64
[ 54.282929] send bytes 2
[ 54.282936] Sending data to I2C device: register=0x40, data=0x21
[ 54.292053] send bytes 2
[ 54.292059] Writing is completed on display
[ 54.311541] Grove LCD RGB Backlight V4.0 driver probe
[ 54.320552] client->addr is RGB
[ 54.324138] Initilize of RGB starting...
[ 54.328254] Sending data to I2C device: register=0x00, data=0x00
[ 54.334548] send bytes 2
[ 54.334554] Sending data to I2C device: register=0x01, data=0x00
[ 54.343553] send bytes 2
[ 54.343560] Sending data to I2C device: register=0x08, data=0xAA
[ 54.352582] send bytes 2
[ 54.352588] Sending data to I2C device: register=0x04, data=0xFF
[ 54.371555] send bytes 2
[ 54.371569] Sending data to I2C device: register=0x03, data=0xFF
[ 54.380868] send bytes 2
[ 54.380874] Sending data to I2C device: register=0x02, data=0xFF
[ 54.389834] send bytes 2
[ 54.389839] Initilize of RGB Completed
[ 54.400809] Driver Added!!!
运行应用
[root@LS-GD home]# ./i2clcd-app
Opening Driver..[ 68.766573] Device File Opened...!!!
.
Choose an operation:
1. Read RGB values
2. Write RGB values
3. Read LCD text value
4. Write LCD text value
5. Exit
Enter your choice: 2
Enter the RGB values (0-255) to send:
Red: 255
Green: 0
Blue: 0
RGB Values to wr[ 80.754240] Initilize of RGB starting...
ite: R: 255, G: [ 80.759637] Sending data to I2C device: register=0x00, data=0x00
0, B: 0
Writing[ 80.767984] send bytes 2
RGB Values to D[ 80.767991] Sending data to I2C device: register=0x01, data=0x00
river...
[ 80.778808] send bytes 2
[ 80.778814] Sending data to I2C device: register=0x08, data=0xAA
[ 80.788212] send bytes 2
[ 80.788219] Sending data to I2C device: register=0x04, data=0xFF
[ 80.797205] send bytes 2
[ 80.797212] Sending data to I2C device: register=0x03, data=0x00
[ 80.806215] send bytes 2
[ 80.806221] Sending data to I2C device: register=0x02, data=0x00
[ 80.825188] send bytes 2
[ 80.825199] Initilize of RGB Completed
Choose an operation:
1. Read RGB values
2. Write RGB values
3. Read LCD text value
4. Write LCD text value
5. Exit
Enter your choice: 4
Enter the LCD text to send:
hello elecfans,hello loongson
LCD Text to writ[ 91.184806] Initilize of LCD starting...
e: hello elecfans,hello loongson
Writing LCD Text to Driver...
[ 91.242396] Sending data to I2C device: register=0x00, data=0x28
[ 91.248529] send bytes 2
[ 91.300437] Sending data to I2C device: register=0x00, data=0x08
[ 91.309196] send bytes 2
[ 91.360426] Sending data to I2C device: register=0x00, data=0x01
[ 91.369768] send bytes 2
[ 91.421389] Sending data to I2C device: register=0x00, data=0x06
[ 91.430061] send bytes 2
[ 91.482509] Sending data to I2C device: register=0x00, data=0x0C
[ 91.497159] send bytes 2
[ 91.548506] Initilize of LCD Completed
[ 91.558420] Writing is start on display
[ 91.564048] Sending data to I2C device: register=0x00, data=0x80
[ 91.570684] send bytes 2
[ 91.570691] Sending data to I2C device: register=0x40, data=0x68
[ 91.579699] send bytes 2
[ 91.579707] Sending data to I2C device: register=0x40, data=0x65
[ 91.588690] send bytes 2
[ 91.588697] Sending data to I2C device: register=0x40, data=0x6C
[ 91.597687] send bytes 2
[ 91.597693] Sending data to I2C device: register=0x40, data=0x6C
[ 91.606663] send bytes 2
[ 91.606669] Sending data to I2C device: register=0x40, data=0x6F
[ 91.625655] send bytes 2
[ 91.625669] Sending data to I2C device: register=0x40, data=0x20
[ 91.634937] send bytes 2
[ 91.634943] Sending data to I2C device: register=0x40, data=0x65
[ 91.644088] send bytes 2
[ 91.644094] Sending data to I2C device: register=0x40, data=0x6C
[ 91.653094] send bytes 2
[ 91.653100] Sending data to I2C device: register=0x40, data=0x65
[ 91.662148] send bytes 2
[ 91.662154] Sending data to I2C device: register=0x40, data=0x63
[ 91.671143] send bytes 2
[ 91.671149] Sending data to I2C device: register=0x40, data=0x66
[ 91.680125] send bytes 2
[ 91.680131] Sending data to I2C device: register=0x40, data=0x61
[ 91.699214] send bytes 2
[ 91.699229] Sending data to I2C device: register=0x40, data=0x6E
[ 91.708579] send bytes 2
[ 91.708586] Sending data to I2C device: register=0x40, data=0x73
[ 91.717576] send bytes 2
[ 91.717582] Sending data to I2C device: register=0x40, data=0x2C
[ 91.726581] send bytes 2
[ 91.726587] Sending data to I2C device: register=0x40, data=0x68
[ 91.735574] send bytes 2
[ 91.735580] Sending data to I2C device: register=0x00, data=0xC0
[ 91.744527] send bytes 2
[ 91.744534] Sending data to I2C device: register=0x40, data=0x65
[ 91.763547] send bytes 2
[ 91.763561] Sending data to I2C device: register=0x40, data=0x6C
[ 91.772813] send bytes 2
[ 91.772819] Sending data to I2C device: register=0x40, data=0x6C
[ 91.781802] send bytes 2
[ 91.781809] Sending data to I2C device: register=0x40, data=0x6F
[ 91.790764] send bytes 2
[ 91.790771] Sending data to I2C device: register=0x40, data=0x20
[ 91.799732] send bytes 2
[ 91.799738] Sending data to I2C device: register=0x40, data=0x6C
[ 91.808726] send bytes 2
[ 91.808732] Sending data to I2C device: register=0x40, data=0x6F
[ 91.817846] send bytes 2
[ 91.817853] Sending data to I2C device: register=0x40, data=0x6F
[ 91.836783] send bytes 2
[ 91.836797] Sending data to I2C device: register=0x40, data=0x6E
[ 91.846079] send bytes 2
[ 91.846086] Sending data to I2C device: register=0x40, data=0x67
[ 91.855079] send bytes 2
[ 91.855085] Sending data to I2C device: register=0x40, data=0x73
[ 91.864069] send bytes 2
[ 91.864076] Sending data to I2C device: register=0x40, data=0x6F
[ 91.873033] send bytes 2
[ 91.873040] Sending data to I2C device: register=0x40, data=0x6E
[ 91.882004] send bytes 2
[ 91.882010] Writing is completed on display
效果