数据的读写主要是通过SDI和SDO来实现的,其中SDI如果配置为SDA,那么它既可以写入也可以读出数据,而SDO只能是读取数据,之前采用的一些显示屏没有SDO这个引脚,估计增加SDO是为了可以实现同时读写,SDI和SDO引脚说明如下:
图1
1. 选择读取ID的方式
SDI和SDO由page 1的08h寄存器来配置,下面见此寄存器:
图2
(1) SDI读取数据
如果要用SDI读取数据,需要设置SEPT_SDIO=0,SDO_STATUS=1,也就是SPI接口从SDI(SDA)传输数据(读和写共用此引脚)。
(2) SDO读取数据
如果要用SDO读取数据,需要设置SEPT_SDIO=1,SDO_STATUS=0,也就是SPI接口从SDI往显示屏写输入数据,SDO把数据从显示屏传送给显示控制器。
根据图2的描述,根据上电后默认值为08h可知,默认是需要用SDI和SDO结合来传输数据的。但我们采用SDI来读取,所以,需要设置为10h。
2. 从哪些寄存器读取ID
选择了读取ID的方式后,我们来看是从哪些寄存器读取,如下图:
图3
由图3可知,page 1的寄存器00到02h对应了Device Code,这个值就是我们用来判断不同驱动IC的依据。
寄存器
3. 如何读取ID
先来看page 0的寄存器FEh,如下图:
图4
先来看FEh寄存器的意义:
(1) ext_spi_read_en
用于选择SPI模式,读或是写,默认是写(0),所以如果要读,就要把这一位设置为1。
(2) ext_spi_cnt[6:0]
描述我们要度或是写的寄存器的第几个参数,为了更好的理解,下面给出有些寄存器有几个参数的情况:
图5
这里就有5个参数,但好像除了这个寄存器,此驱动IC就没有多参数的了。
根据图4的描述,总结读取ID的流程如下:
(1) 进入page1或者page 2/3/4/5
因为我们要读取的寄存器实在page 1中,所以FFh命令的第5个参数值为1(选择page 1)。
(2) 配置SPI接口为读模式和设置要读取对应的第几个参数。
因为我们要读取的是page 1的00到02寄存器值,而这3个寄存器都只有一个参数(见图3),所以这里读取第1个参数。
(3) 设置寄存器命令和读取对应寄存器的第几个参数。
比如我们读取page 1的00h寄存器的第1个参数。
(4) 读取结束,需要关闭SPI读模式
为什么要关闭呢?因为我们读ID的目的是为了判断采用的是哪个驱动IC的显示屏(),然后才能调用对应的驱动IC初始化代码(写数据),所以需要读取结束后关闭SPI读模式,也就是使能写模式,否则后面就算调用了对应的初始化代码也无效。当然不关闭也可以,可以再复位一次显示屏,然后再调用初始化代码就可以了。
4. 读写的时序
(1) 数据包格式
图6
D/C是数据和命令选择为,D/C=0后面的字节数据,被当做一个命令字节;D/C=1,传输的字节作为一个参数数据保存到命令寄存器中。
(2) 写时序
写书序图如下:
图7
(3) 读时序
读时序图如下:
图8
由图8可知,读的操作包括了写的动作,需要先写命令(比如告诉显示屏我要读取哪个寄存器的值),然后才是读数据(读取我刚刚告诉显示屏要读取的寄存器的第几个参数)。
根据图8可知是在下降沿的时候读取数据的,但是我改为上升沿读取也可以,不知道为什么。
5. 读取时序的代码
下面给出读取ID的相关代码
(1) 写命令
void spi_write_comm(int i) { intn,j; j=i+0x0000; for(n=0;n<9; n++) { LCD_SCL_LOW; if(j&0x0100) { LCD_SDA_HIG; } else { LCD_SDA_LOW; } j<<=1; LCD_SCL_HIG; } } void SPI_WriteComm(int i) { LCD_CS_HIG; LCD_CS_LOW; spi_write_comm(i); LCD_CS_HIG; }
(2) 写数据
void SPI_WriteData(int i) { intn,j; LCD_CS_HIG; LCD_CS_LOW; j=i+0x0100; for(n=0;n<9; n++) { LCD_SCL_LOW; if(j&0x0100) { LCD_SDA_HIG; } else { LCD_SDA_LOW; } j<<=1; LCD_SCL_HIG; } LCD_CS_HIG; }
(3) 读一个字节
unsigned char Lcd_Read_Byte(BOOL RisingEdge) { unsignedchar i,data=0; LCD_SDA_IN; for(i=0;i<8;i++) { data<<=1; if(RisingEdge) { LCD_SCL_LOW; LCD_SCL_HIG; } else { LCD_SCL_HIG; LCD_SCL_LOW; } if(LCD_SDA_GET) { data++; } } LCD_SDA_OUT; LCD_SDA_HIG; returndata; }
(4) 读取寄存器的数据
unsigned char SPI_read_reg(unsigned charaddr) { unsignedchar data=0; LCD_CS_HIG; LCD_CS_LOW; DelayLoop_1us(1); spi_write_comm(addr); data= Lcd_Read_Byte(FALSE); LCD_CS_HIG; returndata; }
(5) 读取此驱动IC的函数
DWORD ILI9806E_read_id(void) { DWORDDeviceCode=0; unsignedchar id= 0x00; SPI_WriteComm(0xFF); SPI_WriteData(0xFF); SPI_WriteData(0x98); SPI_WriteData(0x06); SPI_WriteData(0x04); SPI_WriteData(0x01); DelayLoop_1ms(10); SPI_WriteComm(0x08); SPI_WriteData(0x10);//or 08h SPI_WriteComm(0xfe); SPI_WriteData(0x81);//; id= SPI_read_reg(0x00); DeviceCode= id<<16; id= SPI_read_reg(0x01); DeviceCode= (DeviceCode |id<<8); id= SPI_read_reg(0x02); DeviceCode= (DeviceCode |id); RETAILMSG(1,(TEXT("ILI9806E_read_id() DeviceCode=0x%x\r\n"),DeviceCode)); SPI_WriteComm(0xfe); SPI_WriteData(0x00); returnDeviceCode; }