//TITLE:
// 漫谈LCD调试(一)
//AUTHOR:
// norains
//DATE:
// Friday 23-July-2008
//Environment:
// NONE
//========================================================================
对于嵌入式设备来说,在主芯片的输出格式固定的前提之下,调LCD也就是剩下初始化寄存器而已。而寄存器的初始化数值或代码,在相应的datasheet中已经写得非常详细,只要按部就班即可。也许有朋友可能觉得奇怪,既然LCD的初始化代码都是固定不变的,为何在出厂的时候不直接固化到LCD中呢?其实我们可以从另一个角度来看,初始化寄存器的数值充其量也就十几B,远远达不到1KB。如果仅仅为这几十B的数据而添加一个存储设备,无形中增加了成本。所以很多LCD在使用之前都需要初始化其寄存器。
在WINCE环境之下,初始化LCD其实很简单。无非是三步走:
1.找到合适添加初始化代码的地方。
2.将PIN作为GPIO。
3.写入寄存器数值。
也许这三步中的最大难点可能就是如何写寄存器。在进行这一步之前,我们必须要知道写寄存器的时序。
我们以Innolux PT035TN01 V.6为例,该LCD的写寄存器时序为(如图1):
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><shapetype id="_x0000_t75" path=" m@4@5 l@4@11@9@11@9@5 xe" stroked="f" filled="f" o:spt="75" o:preferrelative="t" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0 "></f><f eqn="sum @0 1 0 "></f><f eqn="sum 0 0 @1 "></f><f eqn="prod @2 1 2 "></f><f eqn="prod @3 21600 pixelWidth "></f><f eqn="prod @3 21600 pixelHeight "></f><f eqn="sum @0 0 1 "></f><f eqn="prod @6 1 2 "></f><f eqn="prod @7 21600 pixelWidth "></f><f eqn="sum @8 21600 0 "></f><f eqn="prod @7 21600 pixelHeight "></f><f eqn="sum @10 21600 0 "></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 414.75pt; HEIGHT: 110.25pt" coordsize="21600,21600" type="#_x0000_t75"><imagedata src="%E6%BC%AB%E8%B0%88LCD%E8%B0%83%E8%AF%95.files/image001.png" o:title=""></imagedata></shape>
首先说明的是,图中的SPENB,SPDA,SPCK分别是LCD的其中三个PIN。从图中我们可以看出,当SPENB为low时,数据开始有效;当SPCK为上升沿时,对SPDA开始进行采样。
对LCD的寄存器进行写操作,并不需要太复杂的协议。以本文所举的例子而言,只需要和SPENB,SPDA,SPCK连接的这三个CPU PIN能做为GPIO即可。剩下的,仅仅是代码如何组织而已。
对应时序图,代码的流程可以这样组织:
1.SPENB,SPDA,SPCK作为GPIO。
2.SPENB输出LOW
3.SPCK输出LOW
4.SPDA输出D15
5.SPCK输出HIGH
6.重复3~5,直到address输出完毕
7.SPCK输出LOW
8.SPDA输出HIGH,代表是要写入数据。
9.SPCK输出HIGH
10.SPCK输出LOW
11.SPDA输出任意数据,作为HI-Z
12.SPCK输出HIGH
13.SPCK输出LOW
14.SPDA输出D7
15.SPCK输出HIGH
16.重复13~15,直到DATA数据全部输出
17.SPENB输出HIGH
18.延迟
19.如果还要继续写LCD寄存器数值,重复1~18即可
对于这18个步骤,可以具现到该伪代码:
WriteRegister(unsigned char reg,unsigned short value)
{
//Enable the CS
GPIO_OUTPUT_LOW(LCDIF_SPCK);
GPIO_OUTPUT_LOW(LCDIF_SPDA);
GPIO_OUTPUT_LOW(LCDIF_SPENB);
DWORD dwMask = 0;
//Register Address
for(dwMask = 0x20; dwMask != 0; dwMask >>= 1)
{
GPIO_OUTPUT_LOW(LCDIF_SPCK);
if (reg & dwMask)
{
GPIO_OUTPUT_HIGH(LCDIF_SPDA);
}
else
{
GPIO_OUTPUT_LOW(LCDIF_SPDA);
}
GPIO_OUTPUT_HIGH(LCDIF_SPCK);
}
// W/R control bit
GPIO_OUTPUT_LOW(LCDIF_SPCK);
GPIO_OUTPUT_HIGH(LCDIF_SPDA);
GPIO_OUTPUT_HIGH(LCDIF_SPCK);
//Hi-Z bit
GPIO_OUTPUT_LOW(LCDIF_SPCK);
GPIO_OUTPUT_LOW(LCDIF_SPDA);
GPIO_OUTPUT_HIGH(LCDIF_SPCK);
//Data for the W/R operation to the address indicate by Address phase
for(dwMask = 0x80; dwMask != 0; dwMask >>= 1)
{
GPIO_OUTPUT_LOW(LCDIF_SPCK);
if (value & dwMask)
{
GPIO_OUTPUT_HIGH(LCDIF_SPDA);
}
else
{
GPIO_OUTPUT_LOW(LCDIF_SPDA);
}
GPIO_OUTPUT_HIGH(LCDIF_SPCK);
}
//Disable the CS
GPIO_OUTPUT_LOW(LCDIF_SPCK);
GPIO_OUTPUT_HIGH(LCDIF_SPENB);
//Delay
Sleep(10);
}