2012-09-29 17:12:02| 分类: windows CE 驱动 | 标签: |举报 |字号大中小 订阅
备注:GRAM:Graphics RAM,即图像寄存器,用于存储要显示的图像信息。
由于项目的需要,在支持采用HX8347D驱动IC的显示屏基础上,需要增加采用HX8347-H驱动IC的显示屏,这样就需要软件上的兼容,也就说要通过软件来自动判断产品当前采用的显示屏,大众的做法就是根据显示屏的ID来做区分,下面就总结兼容过程中遇到的问题和需要重点注意的地方。
1. 显示屏的ID
HX8347D驱动IC中关于显示屏ID的寄存器是R00h,如下图:
图1
由图1可知,采用HX8347D驱动IC中的显示屏ID是0x47,其值保存在寄存器R00h中,那么采用HX8347-H驱动IC的显示屏ID是多少呢?见下图:
图2
由图2可知其ID值是0x79,也是保存在R00h寄存器中。这样我们就只需要在eboot中初始化显示控制器之前通过显示屏ID来识别不同的显示屏。
2. 显示屏接口
采用上面两种驱动IC的显示屏是引脚兼容的,下面简要描述主要的引脚:
2.1 系统接口选择
图3
结合下图
图4
结合图3和图4可知,我们的设计中显示屏是作为3线串行接口的方式和显示控制器交互的,这里注意了,IM0对应ID,这里ID是什么?做什么用呢?见后面的描述。
2.2 时序控制接口
图5
这里重点注意RESET引脚,这个引脚是低电平可以复位显示屏的驱动IC,在我们设备上电的时候需要复位,控制代码如下:
s2450IOP->GPDCON&=~(0x3<<0);
s2450IOP->GPDCON|=(0x01<<0);
//拉低CS
LCD_CS_LOW;//要有效控制和访问显示屏的IC,先输出低电平
DelayX1ms(15);
//RESET
s2450IOP->GPDDAT&=~(0x1<<0);
DelayX1ms(30); //实际4.5ms
s2450IOP->GPDDAT|=(0x1<<0);
DelayX1ms(40);
LCD_CS_HIG;//不需要访问显示屏IC后,就要输出高电平,也起到误操作引起隐患 的作用。
2.3 通讯接口
图6
图6中FMARK没有使用,根据图4的配置决定了WR/SCL引脚是作为SCL来使用的,我们的实际中用普通的GPIO口GPK0和GPK1分别来模拟I2C总线和SDA与SCL通讯。
2.4
3. 读写时序
HX8347D驱动IC和HX8347-H驱动IC的读写时序很接近,这里就以HX8347-H驱动IC的时序来说明。
HX8347-H01通过外部引脚IM3、IM2、IM1来支持两种3线和4线串行总线接口模式,这里介绍我们用到的3线串行总线接口模式,3线是指片选引脚NCS、串行数据线SDA和串行时钟线SCL。
3.1 3线串行接口数据通讯说明
当片选信号NCS为低,首先要发送开始字节,开始字节是由6位总线设备标识码、寄存器选择(RS)位和读/写(R/W)操作位组成,其中6位总线设备标识码的高5位必须被设置为01110,并且标识码的最小位必须被设置为何IM0引脚的电平状态一样,这位就是ID位,见图7可更好理解。
开始字节的第7位是RS位,此位决定是对内部索引寄存器,或是寄存器,还是GRAM的访问。当写数据到索引寄存器或是读取索引寄存器的状态时,必须设置RS=0;当写/读一个命令或是GRAM数据时,必须设置RS=1。开始字节的第8位是RW位,此位决定了读/写操作,当向显示屏写数据时必须设置R/W=0,从显示屏读取数据时必须设置R/W=1,下图是RS和RW这两位组合对应的功能表:
图7
这个表格很重要,在读写的时候如果搞错了,就导致读写出错的。HX8347-H01中有一个索引寄存器(index register,IR),它保存有内部控制寄存器和GRAM的索引数据。
3.2 写时序
图8
从图8的时序可知,在SCL的16个时钟脉冲之内,依次发送的是开始字节和IR/控制寄存器的值,假如我们要向列地址结束寄存器(Column address end register)低字节寄存器0x05写入数据0xEF(239),我们在软件上写操作流程如下:
图9
源代码的实现如下所示:
lcd_write_reg(0x05,0xEF); //Column End
void lcd_write_reg(unsigned char addr,unsigned char data)
{
LCD_CS_LOW;
DelayX1us(1);
lcd_write_byte(0x70);
lcd_write_byte(addr);
LCD_CS_HIG;
DelayX1us(1);
LCD_CS_LOW;
DelayX1us(1);
lcd_write_byte(0x72);
lcd_write_byte(data);
LCD_CS_HIG;
DelayX1us(1);
}
这里解释一下为什么第一个写周期需要首先写入的值是0x70呢?因为我们先指定要写入的寄存器地址到IR中,结合图7可知,对应的RS=0,R/W=0,再结合控制字节的格式(见图8),这样就可以确定我们如果要设置IR,就要先发送0x70;而第二个写周期的目的是要把数据写入指定的寄存器中,结合图7可以,对应的RS=1,R/W0,所以可以确定是0x72,接下来看lcd_write_byte函数是如何发送一个字节的数据的:
图10
这里需要重点注意数据的发送是在SCL的上升沿还是下降沿有效的,根据图8可知是在SCL的上升沿的时候,处理器应该向SDA端发送当前数据位的,所以就有了图10的控制方式,假如我把SCL上升沿的时间提前,比如:
图11
这时候就设备启动的时候显示屏是白屏,这是因为我们要发送的数据没有在正确的时序发送过去而导致的,从而可以看出要密切结合时序来控制的重要性。
3.3 读时序
图12
图12可知读操作的一个周期也是16个时钟脉冲,前8个时钟脉冲同步开始字且是向驱动IC写入,后8个时钟脉冲同步寄存器值的输出。那么假如我们要读取Himax ID register(地址为0x00)的值,该如何实现呢?首先要告诉(写)驱动IC,处理器要读取地址为0x00寄存器的值,那么肯定要把0x00的值写入到IR(索引寄存器);然后从保存在IR中的值0x00对应的寄存器中读取数据,操作流程如下:
图13
这里解释一下为什么第二个周期发送的开始字节是0x73,因为第一个周期发送的开始字节0x70是告诉驱动IC要对地址为0x00的寄存器进行操作(读还是写就有第二个周期发送的开始字节的内容决定),因为我们要从地址为0x00的寄存器中读取数据(要获取ID),结合图7可知,需要设置RS=1,R/W=1才能读取对应的寄存器的值,所以就有了0x73,对应的控制代码如下:
unsigned char lcd_read_reg(unsigned char addr)
{
unsigned char data=0;
LCD_CS_LOW;
DelayX1us(1);
lcd_write_byte(0x70);
lcd_write_byte(addr);
LCD_CS_HIG;
DelayX1us(1);
LCD_CS_LOW;
DelayX1us(1);
lcd_write_byte(0x73);
data = Lcd_Read_Byte();
LCD_CS_HIG;
DelayX1us(1);
return data;
}
根据图2可知,此驱动IC的ID code是0x79,可是为什么我读取到的值却是0x78呢?后来我继续读取最低位为1的寄存器的值,读取出来的却是0,而不是1,为什么呢?从这个现象上来看,应该是在读取的时候丢掉了最低位D0了,先来看Lcd_Read_Byte的实现部分:
图14
评论