友达1.2寸圆形显示器,使用SPI或MIPI驱动.........啊!有好大个坑!

stm32驱动镁光emmc stm32怎么驱动mipi_引脚

1.2寸的AMOLED,看到这个OLED,好高大上,结果是MIPI+SPI驱动,第一反应是要两种协议同时用,MIPI在STM32上好难实现,就想用SPI,看完整个手册,也没有找到初始化demo或者说也没有驱动芯片手册,这个显示驱动芯片就是我认为的巨坑:AUO W0222 ASIC,找遍某娘,问遍某服,都没听过,找了大半年,总感觉浪费了我三块屏,150大洋啊。

stm32驱动镁光emmc stm32怎么驱动mipi_stm32驱动镁光emmc_02

stm32驱动镁光emmc stm32怎么驱动mipi_初始化_03

经过不懈努力,加上我能编会说(pian),最终在半年后的今天(2020年5月1号),发现了,这个显示器使用的驱动芯片型号“应该可能是”RM67162

所以必须要试一下!!!!!

根据手册上的SPI驱动方式,请看下图,写了一个驱动文件,还用了他给我的初始化demo"片段",结果没成功在使劲想不通,有不断修改SPI的驱动时,终于,我还是放弃了一下驱动成功,转而先确认我的资料是否有误。就是有坑好多坑。

stm32驱动镁光emmc stm32怎么驱动mipi_stm32驱动镁光emmc_04

第一个坑:我自己丢失了原本的资料,从屏幕上无法确认这个屏的真实型号,在网上搜罗了一堆型号,最相近的就是X20BLN01和X120BLN02以及一个H120BLN01。长得都差不多,驱动IC都是AUO W022 ASIC。

第二个坑:就是这个驱动时序了,STM32基本没有MIPI,所以在我使用SPI一下驱动不成功时,就搁置了大半年,然而如今却发现手册上的SPI不适合这个屏!!!

第三个坑:驱动IC:AUO W022???从上文就知道,现在大概确认驱动型号时RM67162了,所以终于可以找到驱动IC的手册了,注意这里找到的时驱动IC的手册,不是屏幕的手册,这个驱动手册里包含了寄存器等深层的资料。有他才真的找到了驱动时序。

下面来说一下如何正确从0开始,使用正确的资料,确定这些坑。

首先:要确定屏幕手册,浏览了多个手册,FPC排线都时24Pins,当然引脚名时不一样的,所以我就用火眼金睛(睁的比牛眼睛还大)仔细的看实际屏幕的引脚,对比手册上的可能排序,尤其时电源和GND,发现这个屏时X120BLN02的,这样才能确认如何接线。我使用如下硬件电路:还有一点这个屏FPC排线上自带电源处理器,所以无需担心AMOLED的驱动电源问题。

stm32驱动镁光emmc stm32怎么驱动mipi_stm32驱动镁光emmc_05

 硬件接线可以不看驱动IC,但要写软件,就离不开驱动IC的手册了。这个可是排坑最多的。一般而言,肯定是用屏幕手册上的时序,对应找驱动IC上的驱动时序,然后用这个时序驱动。但毕竟是排坑:这个屏幕手册上的时序不一定对。

软件上使用keil_v5加STM32F10x,我使用的是103VET6。如前面所说,直接驱动,屏幕没有反应,那就需要先确认硬件和时序,硬件确认了如何确认时序呢,不能使用直接驱动,结合以往经验,先读取驱动IC的ID,读出来就表示时序没有问题。

按照屏幕手册,读取了一个星期,一直是输出0xFF 0xFF 0xFF,使用逻辑器发现时序是有的。在不断修改硬件和软件时,发现驱动IC手册上还有好几种SPI时序,然后就一一测试,终于找到了正确的时序:

stm32驱动镁光emmc stm32怎么驱动mipi_引脚_06

注意看这个时序图,是四线SPI加命令数据线,,,而屏幕手册上命令数据线(DCX)根本没用。还有时序图在DCX上拉以后会多出一个空时钟,如果没有这个空时钟,ID会是:80 81 05,否则是01 02 A0。这里居然有一个坑:我也不知道这个ID哪个对,手册上两个都不是:看下面00 80 00,什么鬼

stm32驱动镁光emmc stm32怎么驱动mipi_初始化_07

 为了确认这个空时钟到底有没有用,我又找了一个多数据的寄存器去读,读出的结果:没有哪个空时钟时90 88 8B 8B 7F有了空时钟时21 11 17 16 FF ,从这个最后一个字节看,基本可以确认了,时必须要这个空时钟的。所以屏幕的ID是01 02 A0,但也不是手册上的00 80 00,是不是坑!!!

stm32驱动镁光emmc stm32怎么驱动mipi_stm32驱动镁光emmc_08

 现在确认了时序,可以读取ID了,就继续配置其他寄存器,但没有准确的初始化demo片段,所以也是举步维艰。

以下就是正确的软件了:SPI时序和普通的SPI没有太大区别,唯一就是时钟可以很快,快到200ns

uint8_t SPI_ReadWriteByte(uint8_t TxData)
 {
     uint8_t cnt;
     uint8_t RxData=0;    for(cnt=0; cnt <8; cnt++)
     {
         SPI_SCL_RESET();                            //时钟 - 低        RxData <<= 1;
         if(SPI_MISO_READ())                    //读取数据
         {
             RxData |= 0x01;
         }
         if(TxData & 0x80)                    //发送数据
         {
             SPI_MOSI_SET();
         }
         else
         {
             SPI_MOSI_RESET();
         }
         spi_delay_ns(1);
         SPI_SCL_SET();
         spi_delay_ns(1);
         TxData <<= 1;
     }
     return RxData;
 }

屏幕的驱动代码:(读取到正确的id)

//写命令
 void lcd_write_cmd(uint8_t cmd)
 {
     SPI_CS_RESET();
     delay_us(1);
   LCD_DCX_RESET();
     SPI_ReadWriteByte(cmd);//1st
     LCD_DCX_SET();
     delay_us(1);
     SPI_CS_SET();
 }//写数据
 void lcd_write_cmd_data(uint8_t cmd, uint8_t *data, uint8_t len)
 {
     uint8_t cnt;
     
     SPI_CS_RESET();
     delay_us(1);
   LCD_DCX_RESET();
     SPI_ReadWriteByte(cmd);//1st
     LCD_DCX_SET();
     for(cnt=0;cnt<len;cnt++)
         SPI_ReadWriteByte(data[cnt]);//2st
     delay_us(1);
     SPI_CS_SET();
 }//读数据
 void lcd_read_cmd_data(uint16_t cmd, uint8_t *data, uint8_t len)
 {    
     uint8_t cnt;
     
     SPI_CS_RESET();
     delay_us(1);
     LCD_DCX_RESET();
     SPI_ReadWriteByte(cmd);//1st
     LCD_DCX_SET();//2st
     if(len>1)
     {        
         SPI_SCL_RESET();
         SPI_SCL_SET();
         for(cnt=0;cnt<len;cnt++)
             data[cnt]=SPI_ReadWriteByte(0xFF);//2st
     }
     else
     {
         *data = SPI_ReadWriteByte(0xFF);//2st
     }
     delay_us(1);
     SPI_CS_SET();
 }void lcd_reset(void)
 {
     LCD_XRES_RESET();
     delay_ms(1);
     LCD_XRES_SET();
     delay_ms(10);
 }void lcd_Init(void)
 {
     uint8_t id[3];
     lcd_reset();
   lcd_read_cmd_data(0x04, id, 3);
     USART1_SendData(id, 3);
 }

OK,基本上有眉目了剩下的最后一个坑就是初始化demo片段了,下一个文章再见。