调试OTM4001A液晶驱动的一点心得 .
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
这几天调试一块以OTM4001A作驱动芯片的LCM模组,调试完毕后,终于有结果OK了。之前对这块一直用的不太透彻,恰好趁这次摸清楚了。需要注意的几点记录如下:
(1)关于信号类型的片选。在很多LCD芯片规格书上都有关于信号片选的描述,如
M2/M1/M0,典型如下:
如上图,上面的三个M接口脚是有连接线直接连到主板接口上的,至于是高还是低,可以由主板硬件限定死,另一方面也可以由LCM模组自身做工来限制。具体到我的工作内容上,主板上IM0是不接的,IM2接地,基本上就由IM1来决定是16位是18位,用一个电阻来控制。目前我是用的18位接口,多属于DBI B类型。
关于DBI接口,18位数据线连接和16位连接线要作下说明,针对16位寄存器(8位寄存器不存在这个问题)。
A,18位
可以看出:18位的数据线传输16位的寄存器参数和命令时,DB0和DB9是跳过去的。这就决定了在写寄存器控制命令时要注意移位(假设32位系统上,怎么样将16位寄存器数
据分离,然后放到18位数据线上发送出去),这个在后面会有程序说明。18位的数据传输就是RGB666了,此处不作说明。
B,16位
可以看出:16位的数据线,硬件上是直接对应上的,所以写控制命令和参数时,不存在上述移位的问题。16位的数据就是RGB565,这个也不做说明。
从上可以看出,不管是16位还是18位,传输命令的总是那几根线。在硬件接线上注意具体要求。
(2)关于写寄存器的说明。
主芯片自带的读写语句分别是:写寄存器地址SendCtrlComnd(),写寄存器参数SendDataComnd()。两者的形参后来我验证了,应该是32位。硬件采用18位,传输18位数据。那么需要对数据线对应的位进行适当的处理,以在写寄存器命令时跳过DB0和DB9:
#define
SendCtrlComndWrapped(value) SendCtrlComnd(((value<<1)&0x1fe)|(((value<<2)& 0x3fc00)))
#define
SendDataComndWrapped(value) SendDataComnd(((value<<1)&0x1fe)|(((value<<2) &0x3fc00)))
说明:((value<<1)&0x1fe)保证跳过DB0后传输采用的DB8到DB1,恰好在位置上对应。((value<<2)&0x3fc00)保证跳过DB0跟DB9两个位,取得DB17到DB10的数据,从这里可以看出,该寄存器参数类型是32位的,否则无法跟0x3fc00相与。
另外,跳过DB0和DB9还有另一种写法:
#define SendCtrlComndWrapped(value) SendCtrlComnd(((value&0xFF00)<<2) | ((value&0x00FF)<<1) )
#define SendDataComndWrapped(value) SendDataComnd(((value&0xFF00)<<2) | ((value&0x00FF)<<1) )
另补充:以上写控制命令和命令参数都是16位的,所以在18位数据线和16位数据线上要考虑时序。如果控制命令和参数都是8位的,则不需考虑这个过程,也即直接用:
#define SendCtrlComndWrapped(value) SendCtrlComnd(value&0xff)
#define SendDataComndWrapped(value) SendDataComnd(value&0xff)
(3)关于配新屏的过程。
大部分的LCM模组只需要处理好四个函数就可以了。初始化,进入睡眠,唤醒睡眠,写GRAM。都是通过一系列寄存器语句来实现的,比如对于OTM4001A,典型的语句是:
SendCtrlComndWrapped(0x0200);SendDataComndWrapped(0x0000);
其它典型的要补充的是:初始化时要在写GRAM前设置RAM ADDR参数、起始终结的水平垂直位置、Display ON、Write Start;唤醒和睡眠都是有特定的sleep寄存器来控制的,唤醒后可以再把初始化执行一次就可以了。
(4)关于RGB565向RGB666转化
写GRAM的本质就是向不同地址写入对应的点阵颜色的数据,而每个颜色点的格式可能有16位或者18位。如果是单点16位的点阵格式,采用在地址自加的同时,执行WriteHwDataAddrWrapped( color );如果是18位的格式,除了在配置时要改成18位和RGB666格式外,在循环写入颜色数据时需要一个转换:
UINT16 color; //16位颜色值存储单元
UINT32 rgb666; //18位颜色值存储单元
UINT32 panelX, panelY;
UINT16 x0, y0, x1, y1;
x0 = (UINT16)rc.left;
y0 = (UINT16)rc.top;
x1 = (UINT16)rc.right-1;
y1 = (UINT16)rc.bottom-1; //起始终结坐标
for (panelY = y0; panelY <= y1; panelY++)
{
for (panelX = x0; panelX <= x1; panelX++)
{
color = pFB[pixelIndex++];
rColor = ((color & 0xF800) >> 10);
gColor = ((color & 0x07E0) >> 5);
bColor = ((color & 0x001F) << 1);
rgb666 = ((rColor << 12) | (gColor << 6) | (bColor)); //RGB565转成RGB666
WriteHwDataAddrWrapped( rgb666 );
}
}
(5)关于图像倾斜。如果一个图像出现一个对角线,整体倾斜,那么可以考虑是多写了数据或是少些了数据。我的改动方法是一定要注意矩形窗口坐标是0到WIDTH-1,和0到HEIGHT-1。如果没有减去1,则会出现此问题。
(6)关于读芯片的ID号
很多芯片的ID都是0X0000寄存器的值,不需要发读出命令。所以只要在读数据前把寄存器的地址0X0000写进去,就可以读到正确的ID。6516提供的命令如下:
VOID LCDReadDataCommand(void )
{
UIN T32 data;
LCD_OUTREG32(PARALLEL[s_pLCDParams->m_ifIndex].CON TROL, 0x0000);//写索引地址0X0000 data = LCD_INREG32(PARALLEL[s_pLCDPar ams->m_ifIndex].DATA);
SHIPMSG(2,(L"Read lcd id is : 0x%x /r /n",data));
}
直接把该函数放到初始化开始就可以了。
实际调试R61509V的代码时,读得的ID号是0x2d412。而芯片规格书上的0XB509,不一致。后来想了一下,由于是18位的接口,对于命令来说,读和写都要跳过第零位和第九位。所以把0x2d412处理一下后就是0XB509。
(7)关于TE(tearing effect)现象