前言
I.MX6ULL的板子未选配RGB的屏幕,无法在板子上进行GUI的开发调试,不过手头上有块控制器为ST7789V3的LCD屏幕(1.3inch),通过简易接线后可以很方便进行驱动的移植
如有异议,欢迎留言指正
ST7789 LCD控制器
ST7789是一款单芯片TFT-LCD控制器,支持并口与SPI通信方式文章来源:https://www.toymoban.com/news/detail-405706.html
特性
- 控制器支持显示区域340x320(LCD屏幕实际为240X240)
- RGB565、16bit、65K真彩
- 支持SPI通信
- LCD控制引脚
NO. | 引脚 | 描述 |
---|---|---|
1 | BLK | 背光调节亮度 |
2 | CS | 片选 |
3 | RES | 复位 |
4 | SDA | 数据引脚 |
5 | SCL | 串行时钟 |
6 | DC | 数据命令选择 |
修改设备树
修改&ecspi1
- 板子上通过SPI1接到LCD上,设备树路径
arch/arm/boot/dts/100ask_imx6ull-14x14.dts
,修改&ecspi1
,增加cs-gpios
、dc-gpios
、rst-gpio
引脚(dc与rst也可以单独放到root节点下)
&ecspi1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ecspi1>;
fsl,spi-num-chipselects = <1>;
cs-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
dc-gpios = <&gpio4 21 GPIO_ACTIVE_HIGH>;
rst-gpio = <&gpio4 23 GPIO_ACTIVE_HIGH>;
status = "okay";
spidev: st7789s@0{
compatible = "100ask, st7789s";
spi-max-frequency = <25000000>;
reg = <0>;
};
};
修改pinctrl
- 修改设备树中
pinctrl_ecspi1
,增加dc
、rst
的IO配置(dc与rst的配置也可以单独放到root节点下,需要屏蔽掉其他地方复用防止引起的冲突)
pinctrl_ecspi1: spi_st7789s {
fsl,pins = <
MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x000010B1/*sclk*/
MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x000010B1/*mosi*/
MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x000010B1/*miso*/
MX6UL_PAD_CSI_DATA03__GPIO4_IO24 0x000010B0/*cs*/
MX6UL_PAD_CSI_DATA00__GPIO4_IO21 0x000010B0/*dc*/
MX6UL_PAD_CSI_DATA02__GPIO4_IO23 0x000010B0/*rst*/
>;
};
SPI驱动框架
注册spi
- Linux内核使用
spi_driver
标识spi设备驱动(匹配方式、probe、remove函数),通过spi_register_driver
向内核进行注册
/* SPI驱动结构体 */
static struct spi_driver st7789s_driver = {
.probe = st7789s_probe,
.remove = st7789s_remove,
.driver = {
.owner = THIS_MODULE,
.name = ST7789S_NAME,
.of_match_table = st7789s_of_match,
},
.id_table = st7789s_id,
};
/*
* @description : 驱动入口函数
* @param : 无
* @return : 无
*/
static int __init st7789s_init(void)
{
return spi_register_driver(&st7789s_driver);
}
数据发送
- 将待发送数据添加到
spi_message
队列中,并使用同步(堵塞方式)发送
static int st7789_write_regs(struct st7789_dev *dev,unsigned char *buf, int len)
{
int ret;
struct spi_message m;
struct spi_transfer *t;
struct spi_device *spi = (struct spi_device *)dev->private_data;
t = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL); /* 申请内存 */
t->tx_buf = buf; /* 要写入的数据 */
t->len = len; /* 写入的字节数 */
spi_message_init(&m); /* 初始化spi_message */
spi_message_add_tail(t, &m);/* 将spi_transfer添加到spi_message队列 */
ret = spi_sync(spi, &m); /* 同步发送 */
kfree(t); /* 释放内存 */
return ret;
}
probe函数
- 设备与驱动匹配成功后,在probe中注册设备并进行刷屏
static int st7789s_probe(struct spi_device *spi)
{
int ret = 0;
printk("st7789 probe \n");
/* 1、构建设备号 */
if (st7789sdev.major) {
st7789sdev.devid = MKDEV(st7789sdev.major, 0);
register_chrdev_region(st7789sdev.devid, ST7789S_CNT, ST7789S_NAME);
} else {
alloc_chrdev_region(&st7789sdev.devid, 0, ST7789S_CNT, ST7789S_NAME);
st7789sdev.major = MAJOR(st7789sdev.devid);
}
/* 2、注册设备 */
cdev_init(&st7789sdev.cdev, &st7789s_ops);
cdev_add(&st7789sdev.cdev, st7789sdev.devid, ST7789S_CNT);
/* 3、创建类 */
st7789sdev.class = class_create(THIS_MODULE, ST7789S_NAME);
if (IS_ERR(st7789sdev.class)) {
return PTR_ERR(st7789sdev.class);
}
/* 4、创建设备 */
st7789sdev.device = device_create(st7789sdev.class, NULL, st7789sdev.devid, NULL, ST7789S_NAME);
if (IS_ERR(st7789sdev.device)) {
return PTR_ERR(st7789sdev.device);
}
/* 获取设备树中cs片选信号 */
st7789sdev.nd = of_find_node_by_path("/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02008000");
if(st7789sdev.nd == NULL) {
printk("ecspi1 node not find!\r\n");
return -EINVAL;
}
/* 2、 获取设备树中的gpio属性,得到BEEP所使用的BEEP编号 */
st7789sdev.cs_gpio = of_get_named_gpio(st7789sdev.nd, "cs-gpios", 0);
if(st7789sdev.cs_gpio < 0) {
printk("can't get cs-gpio");
return -EINVAL;
}
st7789sdev.res_gpio = of_get_named_gpio(st7789sdev.nd, "rst-gpios", 0);
if(st7789sdev.res_gpio < 0) {
printk("can't get res-gpio");
return -EINVAL;
}
st7789sdev.dc_gpio = of_get_named_gpio(st7789sdev.nd, "dc-gpios", 0);
if(st7789sdev.dc_gpio < 0) {
printk("can't get dc-gpio");
return -EINVAL;
}
/* 3、设置GPIO为输出,并且输出高电平 */
ret = gpio_direction_output(st7789sdev.cs_gpio, 1);//
if(ret < 0) {
printk("can't set cs gpio!\r\n");
}
gpio_set_value(st7789sdev.cs_gpio,1);
ret = gpio_direction_output(st7789sdev.res_gpio, 1);
if(ret < 0) {
printk("can't set res gpio!\r\n");
}
ret = gpio_direction_output(st7789sdev.dc_gpio, 1);
if(ret < 0) {
printk("can't set dc gpio!\r\n");
}
/*初始化spi_device */
spi->mode = SPI_MODE_2; /*MODE0,CPOL=0,CPHA=0 */
spi_setup(spi);
st7789sdev.private_data = spi; /* 设置私有数据 */
/* 初始化st7789s内部寄存器 */
st7789s_reginit(&st7789sdev);
return 0;
}
编译运行
模块拷贝到板子中,由于在加载内核驱动中增加了刷图代码,所以加载驱动后LCD会显示如下图
文章来源地址https://www.toymoban.com/news/detail-405706.html
后续章节贴完整源码
到了这里,关于linux驱动开发 ST7789 LCD驱动移植(I.MX6ULL平台)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!