自制RioTboard 7寸LCD驱动板

作者: xinxinyuan
上传时间为: 2014-08-14 09:40 PM

使用RioTboard开发板,通过自己设计LCD驱动电路,RioTboard配置LCD。本文主要介绍RioTboard开发板的LCD接口和修改驱动代码实现7寸LCD的显示。

使用硬件

RioTboard开发板,自己开发的7寸LCD驱动板,HDMI线。

使用软件

嵌入式linux开发环境+AD10 PCB设计软件。

首先介绍下RioTboard主处理器是freescale的imx6 Solo芯片,具有强大的数据处理和图像处理功能。

拿到板子后首先根据文档熟悉板子接口

从图中可以看到和LCD相关的就有LVDS接口和HDMI接口,如果我们自己做7寸屏幕的LCD驱动,就先用LVDS接口了

然后分析开发板LVDS接口的引脚定义,

看到原理图中的LVDS接口是四对,一对时钟,3对数据线,外加触摸屏的I2C接口和触摸中断,正好可以连接带触摸的LCD。于是开始着手弄LCD驱动+触摸小板,考虑到电容屏价格高,选择了电阻触摸,使用I2C接口的电阻触摸芯片。整个lcd驱动小板的主要规划如下:

1) LCD电源规划:

LCD需要电源有背光,VGH、VGL、DVDD、VCOM,其中

  • 上电时序:DVDD->VGL->VGH->Data->B/L
  • 掉电时序:B/L->Data->VGH->VGL->DVDD

Data包括RGB信号、U/D、L/R、DCLK、HS、VE、DE。

B/L是背光。

以上电源基本确定。

2) LVDS转RGB

由于demo板使用的是LVDS信号输出,LCD接收RGB信号,所以要完成LVDS信号转为RGB信号,为了操作简单,选择不需要编程的转换芯片。

3) 触摸屏

触摸使用的是电阻式触摸屏,由于LVDS接口信号中只有I2C和触摸中断,具体安排使用I2C接口的电阻式触摸屏芯片。

经过2天原理图绘制确认和PCB打板,期待已久的LCD驱动板终于出炉了,下面看看图片:

板子到了后就要研究代码看看如何修改支持我的LCD。

按照官方手册内容,LVDS输出是适合9.7寸LCD的,我们要更换LCD的话,就必须自己学会阅读驱动源码和配置参数。在看驱动之前我们首先应该了解LCD的显示原理:

这个说简单也简单,说麻烦一不是一两句就能说明白的,和我们主题不是那么相关,在这里就不阐述了,但是我们必须要看一下linux系统对LCD这个硬件做的抽象(详细参见:Documentationfbframebuffer.txt,源代码中Doucumentation下的文档都是很好的文档,能解决大家很多迷惑的问题,有时候大家一筹莫展的时候看看这个文件夹下的相关文档,也许大家就会豁然开朗。)

图中重要的参数有7个,下面我就看看这个抽象有关的数据结构参数和定义: RIOTboard板子的源代码中结构体如下:

struct fb_videomode {
         constchar *name;  /* optional */
         u32refresh;              /* optional */
         u32xres;
         u32yres;
         u32pixclock;
         u32left_margin;
         u32right_margin;
         u32upper_margin;
         u32lower_margin;
         u32hsync_len;
         u32vsync_len;
         u32sync;
         u32vmode;
         u32flag;
};

具体含义:

名称

意义

备注

const char *name

LCD名字,可以自己定义

u32 refresh

刷新频率,一般定义为60

u32 xres

行像素

u32 yres

列像素

u32 pixclock

像素时钟

u32 left_margin

在每行或每列的象素数据开始输出时要插入的象素时钟周期数

u32 right_margin

在每行或每列的象素结束到LCD 行时钟输出脉冲之间的象素时钟数

u32 upper_margin

在垂直同步周期之后帧开头时的无效行数

u32 lower_margin

本帧数据输出结束到下一帧垂直同步周期开始之前的无效行数

u32 hsync_len

行同步脉宽

u32 vsync_len

场同步脉宽

u32 sync

同步极性设置

可根据情况自行设置

u32 vmode

一般配置为隔行扫描

u32 flag

未使用

下面我们就看看根据我们实际的LCD规格书来填充这些参数,首先我们看LCD规格书中的timing时序:

以上就是关于LCD的主要参数列表。

下面看看根据我们自己LCD规格书配置参数。

  • Const char *name:这个是对应的LCD参数的名字,可以自己起名,但是要和后面给内核传递的参数名字一样。
  • Refresh:这个就是我们熟悉的刷新频率,我们不讨论LCD和CRT的刷新频率问题,这里选择默认60就好了。
  • Xres和Yres这两个是分辨率参数,即行和列的像素个数,我们的LCD是800*480的,直接就填写800和480就行了.
  • Pixclock:是像素时钟,在linux文档中给出了计算公式:  pixclock = 1000000 / DCF

下面看看后面6个参数的计算,首先看看LCD规格书里面的timing参数:

可以看到LCD时钟是33.3M,所以pixclock=1000000/33.3=30030

行同步脉冲宽度是一个时钟周期,所以,hsync_len=1

场同步脉冲的宽度是一个行周期,所以vsync_len = 1

然后看看一帧图像的时序图:

根据up_margin定义:在垂直同步周期之后帧开头时的无效行数,也就是图中的tvb-tvpw即23-1=22。

根据lower_margin定义:本帧数据输出结束到下一帧垂直同步周期开始之前的无效行数

Lower_margin=tv-tvd-up_margin,就是525-480-22=23.

然后再看看一行的时序图:

这个图有点模糊了,根据left_margin          定义:在每行或每列的象素数据开始输出时要插入的象素时钟周期数,left_margin=thb,即46

根据u32 right_margin定义:在每行或每列的象素结束到LCD 行时钟输出脉冲之间的象素时钟数.right_margin=th-thd-thb,即1056-800-46=210.

这样相对于LCD的主要参数我们就设置完毕了。

根据上述的内容来修改RIoTboard的LCD配置文件,来使LCD的分辨率等参数适合我们的7寸LCD。

首先我们看看使用LVDS0通道输出的配置步骤:

1.     打开ldb.c文件找到static struct fb_videomode ldb_modedb[]这个结构体定义:

结构体定义中将LCD配置参数修改为适合我们LCD的配置参数,具体配置方式上文给出了分析,请自行查阅,其中红色字体是我们根据上述计算内容修改好的:

staticstruct fb_videomode ldb_modedb[] = {
{
  "LDB-WXGA", 60, 1280, 800, 14065,
  40, 40,
  10, 3,
  80, 10,
  0,
  FB_VMODE_NONINTERLACED,
  FB_MODE_IS_DETAILED,},
  {
  "LDB-XGA", 60, 800, 480, 30030,
  210, 46,
  22, 23,
  1, 1,
        0,
       FB_VMODE_NONINTERLACED,
        FB_MODE_IS_DETAILED,},
  {
  "LDB-1080P60", 60, 1920, 1080, 7692,
  100, 40,
  30, 3,
  10, 2,
  0,
  FB_VMODE_NONINTERLACED,
  FB_MODE_IS_DETAILED,},
};

2.      调整BSP文件,找到board-mx6q-riot.c文件,找到static struct fsl_mxc_ldb_platform_data ldb_data结构体定义:

staticstruct fsl_mxc_ldb_platform_data ldb_data = {
.ipu_id = 0,
.disp_id = 0,
.ext_ref = 1,
.mode = LDB_SEP0,//这个地方设置LVDS输出通道,LDB_SEP0为LVDS0通道输出。
.sec_ipu_id = 0,
.sec_disp_id = 1,
};

这个LVDS输出通道,RIoTboard上默认也是使用LVDS0,所以我们就不用修改了。

现在主要修改这两个参数,然后重新编译kernel,下载运行,就可以看到我们的ubuntu在7寸屏上的完美显示了。接下来就是触摸的I2C驱动了,

本来以为I2C是比较简单的linux驱动,但是看了linux下的I2C驱动程序框架确实不是一般的麻烦,在这里简单的描述下使用RIoTboard上的I2C接口的I2C通信问题。

首先实验环境,是使用RIoTboard的I2C3接口,即miniHDMI上的I2C接口,连接7寸LCD的触摸屏芯片TSC2007(I2C接口).

通信调试简单步骤:

  • 1.配置menuconfig选项,选在tsc2007驱动,现在想想当时触摸屏芯片选择TSC2007芯片真是幸运,源代码中就用这个芯片的驱动文件,这样就少了很多工作。
  • 2.驱动文件有了,就是tsc2007.c,现在就是配置RIoTboard的I2C通信接口的问题了。

我们在源代码中做如下修改:

添加I2C platform_data:

struct tsc2007_platform_data  tsc2007_data = {
.model = 2007,
.x_plate_ohms = 180,
.fuzzx = 0,
.fuzzy = 0,
.fuzzz = 0,
.init_platform_hw = tsc2007_init_hw,
.exit_platform_hw = tsc2007_exit_hw,
.get_pendown_state = tsc2007_state_hw,
.irq_pin = RIOT_Touch_Int,};

添加I2C board_info:

static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
{   I2C_BOARD_INFO("tsc2007", (0x90>>1)),
.platform_data = &tsc2007_data, }, }; //tsc2007 i2c client

tsc2007的I2C地址配置为0x90。

接下来就实现tsc2007的三个硬件函数

  • .init_platform_hw = tsc2007_init_hw,
  • .exit_platform_hw = tsc2007_exit_hw,
  • .get_pendown_state = tsc2007_state_hw,

具体实现大家可以根据自己需要,来具体实现。

在tsc2007.c文件中添加读取触摸坐标的打印信息:

/* Prepare for next touch reading - power down ADC, enable PENIRQ */

tsc2007_xfer(tsc, PWRDOWN);

printk("zfm read the x is %d,y is %d z1 is %d z2 is %d /n",tc->x,tc->y,tc->z1,tc->z2);

这样我们编译uImage,下载,查看串口终端:

由此可见我们的I2C和tsc2007的通信已经建立并能读取数据。后面就是将触摸屏的坐标数据传给操作系统,但是我们用的是ubuntu,还没有研究透彻如何使用触摸,就先到这儿了,其余的等慢慢在做,有时间出一系列教程。多谢大家支持。

下面看看现实效果,手机拍照像素不高,大家勉强看看,实际现实还是挺好的:

先看看整体连接:

再看看细节:

全部评论 ()

创建讨论帖子

登录 后参与评论
系统提示