IMX6ULL + SPI LCD(驱动IC ILI9341)显示简单的QT界面

2023-05-16

1. 硬件:

使用正点原子的IMX6ULL Linux开发板

开发板底板原理图版本:V2.1

核心板原理图版本:V1.6

LCD :MSP2402 (IC ILI9341)

2. 查找可用引脚

开发板上引出的引脚是在JP6上,只看JP6会发现没有可用的SPI引脚,但是查看底板原理图中与核心板相连的位置会发现其实JP6上的UART2的TX/RX/CTS/RTS 四个引脚正好可以复用为ECSPI3的 MISO/MOSI/CLK/SS0四个引脚,SPI LCD还需要三个IO口作为Reset/DC/背光的控制引脚,如

下图所示(但是我是偷懒了,将背光引脚直接接的V3.3)

3.添加支持SPI LCD的设备树节点(不废话,直接上干货)

    pinctrl_ecspi3: ecspi3grp {

            fsl,pins = <

                    MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO        0x100b1  /* MISO*/

                    MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI        0x100b1  /* MOSI*/

                    MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK      0x100b1  /* CLK*/

                    MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20       0x100b0  /* CS*/

                    MX6UL_PAD_GPIO1_IO00__GPIO1_IO00          0x17059  /*back light*/

                    MX6UL_PAD_GPIO1_IO03__GPIO1_IO03          0x17059  /*data&command*/

                    MX6UL_PAD_GPIO1_IO08__GPIO1_IO08          0x17059 /* Reset IO */

            >;

    };


 

&ecspi3 {

        fsl,spi-num-chipselects = <1>;

        cs-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;    ###特别注意,ATK出厂的设备树这里有问题,原有的cs-gpio 需要改成cs-gpios不然SPI将无法工作

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_ecspi3>;

        status = "okay";

    spidev: icm20608@0 {

        compatible = "alientek,icm20608";

            spi-max-frequency = <8000000>;

            reg = <0>;

    };

    spi_lcd_msp2402@0 {

        compatible = "spi_lcd_msp2402";

        spi-max-frequency = <8000000>;  

        reg = <0>;            

        msp2402-bl-gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;          

        msp2402-dc-gpio = <&gpio1 3 GPIO_ACTIVE_HIGH>;    

        msp2402-rst-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>;                

    };

4.关键代码:

1.请先分析一下IMX6ULL的SPI设备驱动,网上太多了此处不再赘述

2. LCD初始化命令:

    命令序列是从淘宝客服给的单片机代码里摘出来的(没有去看ILI的芯片手册,太长了,五的初衷是学习驱动,而不是研究LCD,因此请不要问我命令都是实现什么功能的,因为我不知道)

struct spi_lcd_cmd{

    u8  reg_addr; // command

    u8  len;  //需要从spi_lcd_datas数组里发出数据字节数

    int delay_ms; //此命令发送数据完成后,需延时多久

}cmds[] = {

    {0xCF, 3, 0},

    {0xED, 4, 0},

    {0xE8, 3, 0},

    {0xCB, 5, 0},

    {0xF7, 1, 0},

    {0xEA, 2, 0},

    {0xC0, 1, 0},    

    {0xC1, 1, 0},

    {0xC5, 2, 0},    

    {0xC7, 1, 0},

    {0x36, 1, 0},

    {0x3A, 1, 0},

    {0xB1, 2, 0},

    {0xB6, 2, 0},

    {0xF2, 1, 0},

    {0x26, 1, 0},

    {0xE0, 15, 0},

    {0xE1, 15, 0},

    {0x2B, 9, 0},

    {0x11, 0, 120},  

    {0x29, 0, 0},  

};


 

u8 spi_lcd_datas[] = {

    0x00, 0xD9, 0x30,                       // command: 0xCF

    0x64, 0x03, 0x12, 0x81,                 // command: 0xED

    0x85, 0x10, 0x7A,                       // command: 0xE8

    0x39, 0x2C, 0x00, 0x34, 0x02,           // command: 0xCB

    0x20,                                   // command: 0xF7

    0x00, 0x00,                             // command: 0xEA

    0x1B,                                   // command: 0xC0      

    0x12,                                   // command: 0xC1

    0x08, 0x26,                             // command: 0xC5

    0xB7,                                   // command: 0xC7

    0x08,                                   // command: 0x36

    0x55,                                   // command: 0x3A

    0x00, 0x1A,                             // command: 0xB1

    0x0A, 0xA2,                             // command: 0xB6

    0x00,                                   // command: 0xF2

    0x01,                                   // command: 0x26

    0x0F, 0x1D, 0x1A, 0x0A, 0x0D, 0x07, 0x49, 0x66, 0x3B, 0x07, 0x11, 0x01, 0x09, 0x05, 0x04, //command: 0xE0

    0x00, 0x18, 0x1D, 0x02, 0x0F, 0x04, 0x36, 0x13, 0x4C, 0x07, 0x13, 0x0F, 0x2E, 0x2F, 0x05, //command: 0xE1

    0x00, 0x00, 0x01, 0x3F, 0x2A, 0x00, 0x00, 0x00, 0xEF, //command: 0x2B

};

3.大名鼎鼎的probe函数:

static int msp2402_probe(struct spi_device *spi)

{

    int ret =0;

    struct fb_info *fb;

    /*初始化spi_device */

    printk("File:%s Function:%s Line:%d \n",__FILE__,__FUNCTION__,__LINE__);

    if (msp2402_gpio_parse_dt(&msp2402lcd, &spi->dev) < 0) {

        printk(KERN_ERR "msp2402lcd gpio parse dt fail!\n");

        goto params_parse_fail;

    }

    /*

    Mode 0 CPOL=0, CPHA=0

    Mode 1 CPOL=0, CPHA=1

    Mode 2 CPOL=1, CPHA=0

    Mode 3 CPOL=1, CPHA=1

    */

    spi->mode = SPI_MODE_0; /*MODE0,CPOL=0,CPHA=0*/

    spi->bits_per_word = 8;

   // spi->dev.platform_data = msp2402lcd;

    ret = spi_setup(spi);

    if (ret < 0)

    {

        printk("spi_setup failed.\n");

    }

    /* 初始化msp2402内部寄存器 */

    msp2402lcd.spi = spi;

    msp2402_reginit(spi);

   lcd_fill_rect(spi,0, 0,LCD_W,LCD_H,RED);

   LCD_DrawLine(spi,0, 50, 240,50);

//至此,LCD的驱动部分就初始化完成了,屏幕上应该是红色背景,然后显示一条横线

// 下边是为了实现Framwbuffer的必要步骤:

   /*填充frambuffer对应项目 */

    fb = framebuffer_alloc(0, NULL);

    if (!fb) {

        printk(KERN_ERR "msp2402 lcd framebuffer alloc fail!\n");

        goto dma_alloc_fail;

    }

    //LCD基本参数设置

    fb->var.xres   = LCD_W;

    fb->var.yres   = LCD_H;

    fb->var.xres_virtual = LCD_W;

    fb->var.yres_virtual = LCD_H;

    fb->var.bits_per_pixel = 32;

    //LCD RGB格式设置, RGB888

    fb->var.red.offset = 16;

    fb->var.red.length = 8;

    fb->var.green.offset = 8;

    fb->var.green.length = 8;

    fb->var.blue.offset = 0;

    fb->var.blue.length = 8;

    //设置固定参数

    strcpy(fb->fix.id, "MSP2402,spilcd");

    fb->fix.type   = FB_TYPE_PACKED_PIXELS;

    fb->fix.visual = FB_VISUAL_TRUECOLOR;

    //设置显存

    fb->fix.line_length = LCD_W * 32 / 8;

    fb->fix.smem_len    = LCD_W * LCD_H * 32 / 8;

    printk("fb->fix.smem_len is %d\n", fb->fix.smem_len);

    dma_set_coherent_mask(&spi->dev, DMA_BIT_MASK(32));

    fb->screen_base = dma_alloc_coherent(&spi->dev, fb->fix.smem_len, (dma_addr_t*)&fb->fix.smem_start, GFP_KERNEL);

    if (!fb->screen_base) {

        printk(KERN_ERR "dma_alloc_coherent %d bytes fail!\n", fb->fix.smem_len);

        goto dma_alloc_fail;

    }

    printk("fb->screen_base is 0x%08x\n", (uint32_t)fb->screen_base);

    fb->screen_size = LCD_W * LCD_H * 32 / 8;

    printk("fb->screen_size is %ld\n", fb->screen_size);

    //操作函数集

    fb->fbops = &msp2402_fb_ops;

    spi_set_drvdata(spi, fb);

    ret = register_framebuffer(fb);

    if (ret < 0) {

        printk(KERN_ERR "register framebuffer fail!\n");

        goto register_fail;

    }

    msp2402lcd.thread = kthread_run(msp2402_refresh_kthread_func, fb, spi->modalias);

    printk("probe run successfully ...%s\n", spi->modalias);

    return 0;

register_fail:

    dma_free_coherent(&spi->dev, fb->fix.smem_len, fb->screen_base, fb->fix.smem_start);

dma_alloc_fail:

    framebuffer_release(fb);

params_parse_fail:

    gpio_free(msp2402lcd.data_command_io);

    gpio_free(msp2402lcd.reset_io);

    gpio_free(msp2402lcd.backlight_io);

return -1;

}

4. 清屏代码:

有两种写法建议都尝试以下就会发下差异(我就郁闷了一会)

方法一(这种方法清屏比较慢,需要7s左右,根本无法接受):

void LCD_Clear(struct spi_device *spi,u16 Color)

{

    unsigned int i,m;    

    LCD_SetWindows(spi,0, 0,LCD_W - 1,LCD_H - 1);

    gpio_set_value(msp2402lcd.reset_io, 1);

    for(i=0;i<LCD_H-1;i++){

        for(m=0;m<LCD_W-1;m++){

            Lcd_WriteData_16Bit(spi,Color);

        }

    }

}

方法二:

static void lcd_fill_rect(struct spi_device *spi,uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)

{

    uint32_t size, i;

    uint8_t data[] = {0};

    uint8_t *mem;

    size = (x2 - x1 + 1) * (y2 - y1 + 1) * 2;   // RGB888 3个字节

    data[1] = color >> 8;

    data[0] = color;

    mem = (uint8_t *)kzalloc(size, GFP_KERNEL);

    if (!mem) {

        printk(KERN_ERR "lcd_fill_rect: alloc %d bytes mem fail!\n", size);

    }

    for (i = 0; i < size/2 ; i++) {

        mem[i * 2] =  data[1];

        mem[i * 2 + 1] =  data[0];

    }

    LCD_SetWindows(spi,0, 0,LCD_W - 1,LCD_H - 1);

    gpio_set_value(msp2402lcd.data_command_io, 1);

    spi_write(spi,mem, size);

    kfree(mem);

}

完整源码地址(如果硬件相同可直接运行):

(48条消息) IMX6ULL+SPILCDMSP2402(驱动ICILI9341)显示简单的QT界面-C文档类资源-CSDN文库

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

IMX6ULL + SPI LCD(驱动IC ILI9341)显示简单的QT界面 的相关文章

  • LVGL V8

    本文适用于LVGL V8版本 LVGL simulator vs2019 官方工程 lv sim visual studio 使用注意事项 1 将官方工程从github上下载下来 最好使用git 将整个工程clone下来 因为工程内部有依赖
  • SPI基础概念

    文章目录 目的 物理接线 极性和相位 信号时序 总结 目的 SPI Serial Perripheral Interface 是一种非常常用的全双工接口 这个接口在非常简单的机制下达到了比较高的通讯速度 比它通讯速度更高的常见的要不是并口
  • Android中LCD背光驱动

    分类 Linux驱动 Android系统 2013 06 17 16 28 287人阅读 评论 0 收藏 举报 目录 Android的Setting Android的背光JNI层 Android的背光HAL层 Linux的背光内核层 Lin
  • 100ask_imx6ull视频监控项目-内网穿透(六)

    100ask imx6ull视频监控项目 内网穿透 六 在前面的课程 Ffmpeg和Nginx都运行在开发板上 拉流端只能在同一个局域网内 不能通过局域网外的互联网访问Ngnix 想在任何地方 都可以通过互联网访问Nginx 怎么办 方法1
  • RT-Thread记录(十六、SFUD组件 — SPI Flash的读写)

    从本文开始 测试学习一些 RT Thread 常用的组件与软件包 先从刚学完的 SPI 设备开始 目录 前言 一 SFUD 组件简介 1 1 基本简介 1 2 SFUD 对 Flash 的管理 二 SFUD 组件操作函数 2 1 初始化相关
  • 沁恒CH32V307使用记录:SPI基础使用

    文章目录 目的 基础说明 使用演示 其它补充 总结 目的 SPI是单片机中比较常用的一个功能 这篇文章将对CH32V307中相关内容进行说明 本文使用沁恒官方的开发板 CH32V307 EVT R1沁恒RISC V模块MCU赤兔评估板 进行
  • 关于IKEv2中安全策略索引SPI的生成

    首先引入一个PF key的概念 PF KEY Key Management API 提供IKE模块和IPSec核心之间的接口 在RFC 2367中 有一个SADB GETSPI消息 这个消息就是实现允许一个进程获取SPI值 该值标识所给的s
  • Java SPI机制

    一 SPI机制简介 SPI的全名为Service Provider Interface java spi机制的思想 系统里抽象的各个模块 往往有很多不同的实现方案 在面向的对象的设计里 一般推荐模块之间基于接口编程 模块之间不对实现类进行硬
  • 迅为i.MX6ULL开发板Platform设备驱动运行测试

    文章目录 1 编译驱动和设备程序 2 编译应用测试程序 3 运行测试 1 编译驱动和设备程序 和前面章节中驱动测试程序一样需要一个Makefile文件 只是将obj m的值改为led device o led driver o Makefi
  • micropython-SPI通讯

    micropython SPI通讯 1 什么是SPI 2 SPI通讯原理 3 Micropython中的SPI 4 ZTMR测试SPI 1 ZTMR中SPI引脚 2 ZTMRSPI自测 2 SPI 2板之间通讯测试 1 什么是SPI SPI
  • IMX6学习记录(18)-分析官方镜像制作文件

    上面是我的微信和QQ群 欢迎新朋友的加入 1 源码 打开 home jun i mx6 sdk SDK 2 2 MCIM6ULL tools imgutil evkmcimx6ull下面的mkimage sh文件 bin bash func
  • LCD和LED屏幕的工作原理总结

    1 点阵取模原理之横向取模与纵向取模 1 1 针式打印机 针式打印机16针是纵向排列 每次打印垂直的16bit 然后右移一bit 继续下列打印 字节的MSB表示最上面的点 字节LSB表示最下面的点 由于汉字字模的点阵是横向排列的 而提供给打
  • IMX6学习记录(8)-更换linux配置,加速启动

    上面是我的微信和QQ群 欢迎新朋友的加入 之前启动的时候将近是1分钟 这个时间太浪费了 更新一下内核的配置 让启动速度更快一些 更新之后 启动时间大概10秒左右 一共三个内容 来源是板子附带源码里面的文件 1 配置文件 2 设备树文件 3
  • I2C与SPI通信总线协议

    仅以寄存器地址为8Bit的器件为例 例如MPU6500 LSM6DS3 I2C通信协议 I2C 的要点是了解I2C通信帧的组成部分 START起始位 STOP停止位 ACK NACK信号 从机器件地址 从机寄存器地址 I2C读的时序比较繁琐
  • imx6ull驱动开发经验

    1 背景 imx6ull驱动开发基于正点原子的开发板 上面运行linux 4 1 15内核 根文件系统为ubuntu 16 05 5 LTS 2 加载驱动文件chrdevbase ko文件时 先使用depmod生成依赖文件时 提示无modu
  • SD卡系列之---SD初始化(SPI)

    SD卡分为SDIO模式与SPI模式 SDIO模式使用SD总线协议 使用4根数据线进行数据传输 SPI使用1收1发2根数据线数据传输 理论上SDIO模式会比SPI模式速度快4倍 但SDIO模式还牵扯到CRC校验位的计算 所以 如果使用CPU有
  • 谁在驱动程序代码中调用“probe”函数?

    我试图理解thisomap2 panda 板的 mcspi 驱动程序代码 我不明白谁打电话probe函数以及调用链是什么this驱动代码 设备连接时如何通知驱动程序 探针函数由spi omap2 mcspi c保存在static struc
  • Arm 板上有两个以上的 SPI 设备,但只支持两个?

    我们其中一块板上的 Arm 处理器有一个 spi 端口 带有两条片选线 该处理器的数据表中提到它最多可以控制两个 spi 设备 是否可以使用 GPIO 作为附加 spi 设备的从选择 如何修改现有的库 设备驱动程序以支持此更改 到目前为止
  • Python - 如何使用 ioctl 或 spidev 从设备读取输入?

    我有一个提供它的供应商提供了一些 C 代码来监听按钮按下 该代码使用ioctl 该设备具有 SSD1289 控制器 按钮不需要额外的引脚 可以通过 SPI 读取其状态 这就是我想要的 读取按下了哪个按钮 我试图在 Python 中为我自己的
  • STM32F4 板上的 SPI 从机设置

    我正在尝试通过主从配置中的 SPI 在两个 STM32F4 发现板之间进行通信 我已经有了主设备的代码 但我对需要对从设备的 SPI 初始化进行的更改感到有点困惑 我还想在主机发送数据时实现中断 而不是让从机一直轮询 RXNE 寄存器 但是

随机推荐

  • 从x86到ARM,代码移植指北

    最近ARM架构的处理器从云到端全面开花 xff0c 比如苹果MAC上的ARM架构处理器M1 MAX就堪称王炸 xff0c 华为的鲲鹏系列ARM处理器也已经稳定服务了很长时间 xff0c 目前业内有口皆碑 xff0c 因此基于x86环境编写的
  • AGV车载控制系统搭建(初学者入门)

    本文转载 xff1a 博主 robinvista的http blog csdn net robinvista article details 78349627 目的 本文介绍 AGV 车载控制系统的实现过程 xff0c 可以分为硬件搭建和软
  • 激光无轨导航AGV,未来智能工厂的必需品

    这篇文章结合一家激光无轨导航AGV公司 xff0c 开启了进入AGV领域的学习与总结 随着国家政策大力支持 xff0c 智能制造 工业4 0 人工智能等等成为了风口 xff0c 热门话题 智能制造中重要的一环 xff0c 物流搬运 分拣和智
  • 【FreeRTOS源码阅读】<2> task.c (1) 任务创建以及TCB、List的结构

    上篇讲述了list c关于链表操作的源码阅读 xff0c 此片文章将开始阅读task c task h相关结构体 由eTaskGetState返回的任务状态 typedef enum eRunning 61 0 一个任务查询自己的状态 xf
  • github仓库添加指定commit版本的子模块

    添加子模块 git submodule add repository url local path 进入子模块目录 xff0c 将子模块回滚到指定commit版本 git reset hard commit number
  • 使用阿里云的k8s部署访问环境

    阿里云推出的kubernetes版本是1 97的 xff0c docker的版本是17 06 2 ce 3 xff0c 用的都是比较新的 xff0c 相比自己搭建集群 xff0c 使用阿里这个还是比较省事的 xff0c 不需要自己研究怎么写
  • 阿里云Ubuntu服务器图形界面配置(详细步骤,萌新看过来)

    刚买完阿里云Ubuntu服务器后 xff0c 发现并没有图形界面 xff0c 就想办法在网上搜集了一些资料配置 xff0c 结果发现一些资料配置过程并不适用于萌新 所以写这篇博客 xff0c 一为记录 xff0c 二为让萌新更快更方便的配置
  • STL简单了解

    STL xff08 Standard Template Library xff0c 标准模板库 xff09 xff1a 是一种类型参数 xff08 type parameterized xff09 的程序设计方法 xff0c 基于模板的标准
  • ROS编译D435i过程中的问题及解决

    请确保已经正确安装了ROS OPENCV realsense viewer 编译出现第一个问题 96 traversing 5 packages in topological order realsense2 camera msgs pla
  • 本科毕业设计 基于ORB SLAM3的多从机SLAM导航系统

    耗时 xff1a 两个月 需求 xff1a 多从机协作 多地图系统 稠密建图 定位 导航 硬件 xff1a 二个D435 一台X86主机 xff08 CPU 13600kf 内存 32G xff09 X86主机环境 xff1a ubuntu
  • 平衡小车之家高配版全向轮小车部分源码分析(蓝牙控制端和运动控制端)

    提前说说 intel杯初选赛过了 xff0c 接下来就是区域决赛 准备时间有两个月 xff0c 时间还是比较紧张 xff0c 必须在这两个月内把所有的知识都消化掉 接下来的打算是想面试几家公司 xff0c 试试自己的水准 xff0c 打好比
  • 当我们在谈SWIFT时,到底在谈什么?

    胜利往往伴随着放弃不切实际的幻想 当地时间2月26日 xff0c 美国 英国 欧盟与加拿大发表共同声明 xff0c 宣布将俄罗斯主要银行从SWIFT体系中剔除 SWIFT凭借着其强大的制裁效果 xff0c 在民间一直有着金融核武器之称 xf
  • 使用Aruco二维码实现定位

    首先使用cv aruco estimatePoseSingleMarkers 函数后得到两个很重要的数据revc和tevc xff0c 分别是旋转向量和平移向量 通过这两个数据就可以得到相机在世界坐标系下的坐标 此处需要了解solvePnP
  • QGC关于SetMode运行流程解析

    QGC与飞控连接后初始化 xff0c 初始飞行模式为手动模式 模式切换在Vehicle中使用 base mode和 custom mode存储模式 xff0c 初始值均为0 当QGC与飞控连接后 xff0c 飞控通过心跳包 xff08 he
  • QGC UDP 建立通讯连接

    QGC关于通信连接建立部分的程序比较复杂 xff0c 但感觉写的很厉害 xff0c 通过读代码把自己的一点理解记录下来 收集接收 空地通信管理 空地通信的管理在 应用程序设置 gt 通讯连接 中进行通信连接创建 xff0c 连接和断开 通讯
  • Win10 Vscode 远程连接Linux 错误解决办法

    错误 xff1a 在网上查找一阵后发现都不能解决我的问题 xff0c 后来发现Vscode的设置里有个 Remote ssh里的Remote SSH Config file路径是空的 尝试把自己的config文件路径放进去 xff0c 发现
  • Ubuntu设置静态IP

    安装Ubuntu后有时候IP会变化导致远程连接不上 xff0c 网上很多都是命令行操作的或者改相应的文件 xff0c 如果能在界面上操作更简单了 右上角 Setting gt Network
  • Qt qml 输出行号 __LINE__ LINENO等信息

    使用 Qt Creator xff0c 按下面的路径可以设置 xff08 Ubuntu Window即可这样设置 xff09 xff1a QT MESSAGE PATTERN file line message 在windows下还可以通过
  • QT5.15.2 View3D 在Ubuntu上无法运行的解决办法

    QT 5 15 2 View3D 在Ubuntu20 04上运行的时候发现无法显示3D模型 xff0c 并报错 经反复折腾发现需要设置 MESA GL VERSION OVERRIDE 61 3 10 xff0c 具体为什么是3 10目前不
  • IMX6ULL + SPI LCD(驱动IC ILI9341)显示简单的QT界面

    1 硬件 xff1a 使用正点原子的IMX6ULL Linux开发板 开发板底板原理图版本 xff1a V2 1 核心板原理图版本 xff1a V1 6 LCD xff1a MSP2402 IC ILI9341 2 查找可用引脚 开发板上引