• S3C6410驱动I80接口LCD


    在嵌入式的主流 LCD屏中主要支持两大类的硬件接口,一种是常见的RGB接口,另外一种是MCU接口.后面因为最早是针对单片机的领域在使用,因此得名.后在中低端手机大量使用,其主要特点是价格便宜的.
    MCU-LCD接口的标准术语是Interface 80,因此在很多文档中用I80 来指MCU-LCD屏。
     
      MCU-LCD屏它与RGB-LCD屏主要区别在于显存的位置.RGB-LCD的显存是由系统内存充当的,因此其大小只受限于系统内存的大小,这样 RGB-LCD可以做出较大尺寸,象现在4.3"只能算入门级,而MID中7",10"的屏都开始大量使用.而MCU-LCD的设计之初只要考虑单片机的 内存较小,因此都是把显存内置在LCD模块内部.然后软件通过专门显示命令来更新显存,因此MCU屏往往不能做得很大.同时显示更新速度也比RGB- LCD慢.
     
       量示数据传输模式也有差别。
          RGB屏只需显存组织好数据。启动显示后。LCD-DMA会自动把显存通过RGB接口送到LCM。
         而MCU屏则需要发送画点的命令来修改MCU内部RAM。(即不能直接MCU屏RAM)

    所以RGB显示速度明显比MCU快,而且播放视频方面,MCU-LCD也比较慢.
     
     
     
     
     S3C6410 即支持RGB-LCD屏,也支持MCU-LCD屏.而对MCU-LCD屏的显示模块的显存显示,它除了支持传统的绘制命令,也支持一种特有的类似RGB- LCD屏的显示模式。即显示数据仍然在系统内存中组织,显示时通过DMA传输到显示器控制器,由硬件来产生绘制命令。相对纯软件绘制模式,这种方法速度更 快。
     
     
      MCU-LCD管脚分析
    ---------------------------------------------------------------------
         两种屏通过管脚直接就可以看出来的。RGB屏管脚主要分为两类
         控制脚是VSYNC/HSYNC/VDEN/VCLK S3C6410最高支持24个数据脚,数据脚是 VD[23-0];
     
        MCU接口标准名称是 I80 Interface.
    MCU管脚的控制脚有5个
    • CS 片选信号
    •  RS (置1为写数据,置0为写命令)
    • /WR (为0表示写数据)
    • /RD (为0表示读数据)
    • RESET 复位LCD( 用固定命令系列 0 1 0来复位)
    数据脚一般是18个,即DB[17:0],这样表示大部MCU最高支持18bpp
     

     
    S3C6410 I80管脚
     S3C6410采用非标准命令,因此有如下对应关系,控制脚
    • SYS_CSx 对应CS
    • SYS_OE 对应RD
    • SYS_WE对应WR
    • SYS_RS对应RS
    • 这里没有对应RESET,直接采用某一个IO口来代替。
       在mini6410中 这里采用VD[21]即GPJ5来充当RESET脚
    • 数据脚 输出VDOUT[17:0],与RGB管脚不一样的是,MCU-LCD还带有 VDIN[17:0],即显存中的数据可以通过命令读取出来。

     

    mini6410 LCM接口

       我们测试是采用学生公司的MCU LCM,爱诺信2.8"的mcu屏。因为接口不是完全兼容,因此只能用采用复杂连线板来匹配。开发板使用的是mini6410。

      

     注意这里RGB-LCD和I80接口是复用的。一块S3C6410同时支持两个LCD,mini6410用排线引出来LCD,这里我们把原来的4.3 "LCD的取下,然后再用自制排线接上。
     

    这个LCM按其管脚要求配置成 16bpp(565)。这是LCM一侧的跳线配置。

      相应的,在S3C6410一侧使用VD[0-15]

     

    因此在S3C6410 一侧,采用VD[0-15]来与其对接

     
     
     
    I80 硬件连线
      mini6410板上,我们这样进行连线。
    • RESET : 这里使用VD[21]来当RESET线,即 GPJ5的output脚.
    • CS0:    这里复用了HSYNC信号脚,即使用GPJ8
    • OE:    在引脚上悬空,即始终为高,这样不影响结果。
    • WE:    复用了VCLK信号脚,即采用 GPJ11脚
    • RS     复用了VDEN信号脚,即采用 GPJ10脚

     

    I80 硬件波形分析

    ---------------------------------------------------------

     启动波形

      根据I80的要求,每次如果需要RESET LCD屏,需要用软件发送 101序列。

      这是MCU-LCD IC里的RESET波形图

    这里我们实测LCD屏的启动波形

      MCU-LCD初始化屏幕,一般出现如下画面表示硬件连线正确,并且初始化成功.

    写入波形

      在MCU-LCD中,用RS脚来区别是向MCU屏发送命令还是数据。而且通常每一种MCU屏有一组初始化命令,它具体的序列取决了不同硬件,所以不同型号的MCU-LCD屏初始化命令序列是不一样的,这个要由生产厂家来提供。

    参考S3C6410提供的I80标准波形,在写入时,WE必须是低电平,RS取决于写入命令还数据。CS是片选有效,是低电平有效。

     
     
    以下是LCM模块提供写命令时序图,基本跟S3C6410的波形一致。
     
     
     
     
    以下波形是实测MCU-LCD波形,可以看到比较明显在,在MCU-LCD初始化时,CS脚被频繁的置低有效。这是在发送一系列的初始化命令,然后随后一直为高,表示在发送显示数据。

    这是放大后波形
     


    S3C6410 MCU-LCD编程
    -----------------------------------------------------------------------------

      MCU需要专门的绘点函数修改LCM内部RAM。。在S3C6410我们有两种方法来绘制MCU-LCD,一种是通用通用方法,在单片机以32位CPU都可以使用。另外一种是S3C6410的扩展,称为I80 RGB Trigger模式,它是先在系统内存组织好显存.然后通过DMA传输到LCM内部存储器上。这种模式的显示速度大大优于专门画点命令的函数,应该做较多优化。

     我们两种模式都实测了,前者是绘制的速度相当于之慢,无法实用(可能跟算法效率也有关系),因此我们有实用价值主要采用RGB 捕获模式的流程。
      
    我们后面主要是这个流程,这个在S3C6410算法最早由梁熠章实现验证。


       

      按照S3C6410的要求,MCU-LCD编程流程如下.这个算法里很多流程比如WINDOWS/OSD的操作可以直接重用RGB-LCD的代码。



    因此我们首先按MCU-LCD的屏的要求,
     1.首先是发送RESET信号,这个取决于硬件连续。在我们板上使用 GPJ5来充当RESET脚
       

    //MCU屏要求,每次Reset要求送一个 1,0,1的波形

    void LCD_MCU_Reset()
    {
    #ifdef LCD_TYPE_MCU_NOAIS28
        rGPJCON = (rGPJCON & ~(0x3<<10)) | (0x1<<10);
         rGPJDAT |= (0X1<<5);
         Delay(100);
          rGPJDAT &= ~(0X1<<5);
         Delay(100);
        rGPJDAT |= (0X1<<5);
        Delay(100);

    #endif
    }


     
    2.是配置LCD类型为 I80接口.
       这里有两步,一是配置 将rMIFPCON的SEL_BYPASS[3] 设为0 ,旁路掉Modem引脚.
          rMIFPCON &= ~(0x1 << 3);
       二是将接口配置为I80 的接口.
         rSPCON = (rSPCON & ~3) | (0x00 << 0);

    三.设置MCD-LCD硬件参数
      
       这里仍然采用RGB-LCD的经验值来进行调整,频率采用 HCLK的16分之一.bpp采用16.
        
      
       信号捕获模式完全等同于RGB模式,
         rVIDCON1 = IVCLK_RISE_EDGE | IHSYNC_NORMAL | IVSYNC_NORMAL | IVDEN_NORMAL ;
        
       2.8"分辨率分别是240x320。用VIDTCON2配置
         rVIDTCON2 = LINEVAL(pDevice->height -1 ) | HOZVAL(pDevice->width -1);
       
         另外I80有自己的专用时序参数,这里使用I80IFCONA0来配置,主要各段时序的时间长度,这由具体板的参数来读取。我们取一组经验值
       rI80IFCONA0 = (LCD_CS_SETUP << 16)| (LCD_WR_SETUP << 12) | (LCD_WR_ACT << 8)|(LCD_WR_HOLD  << 4)|(1<<2)|(1<<0);

       
          
       

    四.诺爱信2.8"的LCD 初始化命令
      这是产家规定一组序列参数
       
     
     

    LCD_MCU_Write_Register(0x00E3,0x3008);
         LCD_MCU_Write_Register(0x00E7,0x0012);
         LCD_MCU_Write_Register(0x00EF,0x1231);
         
         LCD_MCU_Write_Register(0x0001,0x0100);
         LCD_MCU_Write_Register(0x0002,0x0700);
         LCD_MCU_Write_Register(0x0003,0x1030); 
         
         LCD_MCU_Write_Register(0x0004,0x0000);
         LCD_MCU_Write_Register(0x0008,0x0207);
         LCD_MCU_Write_Register(0x0009,0x0000);
         LCD_MCU_Write_Register(0x000A,0x0000);
         LCD_MCU_Write_Register(0x000C,0x0000);
         LCD_MCU_Write_Register(0x000D,0x0000);
         LCD_MCU_Write_Register(0x000F,0x0000);
         
         LCD_MCU_Write_Register(0x0010,0x0000); 
            LCD_MCU_Write_Register(0x0011,0x0007);
            LCD_MCU_Write_Register(0x0012,0x0000);
              LCD_MCU_Write_Register(0x0013,0x0000);
              Delay(10);
               LCD_MCU_Write_Register(0x0010,0x1490); 
            LCD_MCU_Write_Register(0x0011,0x0227);
            Delay(10);
            LCD_MCU_Write_Register(0x0012,0x001A);
            Delay(10);
               LCD_MCU_Write_Register(0x0013,0x0700);//1000

               LCD_MCU_Write_Register(0x0029,0x0001);// 0015 

           
            LCD_MCU_Write_Register(0x002B,0x000C);
            Delay(10);
            LCD_MCU_Write_Register(0x0020,0x0000);
          LCD_MCU_Write_Register(0x0021,0x0000); 
          
         LCD_MCU_Write_Register(0x0030,0x0000);
         LCD_MCU_Write_Register(0x0031,0x0607);
         LCD_MCU_Write_Register(0x0032,0x0305);
         LCD_MCU_Write_Register(0x0035,0x0000);
         LCD_MCU_Write_Register(0x0036,0x1604);
         LCD_MCU_Write_Register(0x0037,0x0204);
         LCD_MCU_Write_Register(0x0038,0x0001);
         LCD_MCU_Write_Register(0x0039,0x0707);
         LCD_MCU_Write_Register(0x003C,0x0000);
         LCD_MCU_Write_Register(0x003D,0x000F);
         
          
         LCD_MCU_Write_Register(0x0050,0x0000);
         LCD_MCU_Write_Register(0x0051,0x00EF);
         LCD_MCU_Write_Register(0x0052,0x0000);
         LCD_MCU_Write_Register(0x0053,0x013F);
         
         LCD_MCU_Write_Register(0x0060,0xa700); 
         LCD_MCU_Write_Register(0x0061,0x0001);
         LCD_MCU_Write_Register(0x006A,0x0000);
         
         LCD_MCU_Write_Register(0x0080,0x0000);
         LCD_MCU_Write_Register(0x0081,0x0000);
         LCD_MCU_Write_Register(0x0082,0x0000);
         LCD_MCU_Write_Register(0x0083,0x0000);
         LCD_MCU_Write_Register(0x0084,0x0000);
         LCD_MCU_Write_Register(0x0085,0x0000);
         
         LCD_MCU_Write_Register(0x0090,0x0010); 
         LCD_MCU_Write_Register(0x0092,0x0600);          
         LCD_MCU_Write_Register(0x0093,0x0003);      
         LCD_MCU_Write_Register(0x0095,0x0110);
         LCD_MCU_Write_Register(0x0097,0x0000);
         LCD_MCU_Write_Register(0x0098,0x0000);
              
         
         LCD_MCU_Write_Register(0x0007,0x0133);


    五.S3C6410 I80命令的发送

    I80就是由命令和数据都是通过MCU接口发送到LCM进行解释。命令的含意取决于具体的LCM,不一定相同。S3C6410只是实现发送机制

      一个I80命令/数据由多个寄存器来设置,
        命令值本身,由LDI_CMDx来设定,x取值是 0 - 11(即一次性最多发送12个命令)
        命令的模式,即这一次发送中哪一个命令有效/以及采用哪一个模式,它由LDI_CMDCON0对应位来生效,命令发送有两种模式,一种单独手工发送,一种自动成批发送
        命令的类型,即每一个发送是命令还是数据,由LDI_CMDCON1来配置
       
      I80IFCONB0 /1来设置命令的总体配置,包括自动命令的帧数,或者普通命令的开始

    以下是由手工命令实现的写命令和数据函数
     

    #define LCD_MCU_START_WRITE() rI80IFCONB0 |=(1<<9)
     
     void LCD_MCU_Write_Cmd(unsigned short cmd)
    {
          rLDI_CMD0 = cmd;
          
          //等Normal command 变为0

          while(!( (rI80IFCONB0& (1<<9)) == 0));

        
        rLDI_CMDCON0 = (rLDI_CMDCON0 & (0x0)) |((0x01)<<0); //01 : Normal Command Enable

        rLDI_CMDCON1 = (rLDI_CMDCON1 & (0x0)) |((0x0)<<0);    //Command 0 RS control,送命令

        
        LCD_MCU_START_WRITE();

        
       Delay(10);
    }



    void LCD_MCU_Write_Data(unsigned short data)
    {
      rLDI_CMD0 = data;
          
          //等Normal command 变为0

          while(!( (rI80IFCONB0& (1<<9)) == 0));

        
        rLDI_CMDCON0 = (rLDI_CMDCON0 & (0x0)) |((0x01)<<0); //01 : Normal Command Enable

        rLDI_CMDCON1 = (rLDI_CMDCON1 & (0x0)) |((0x1)<<0);    //Command 0 RS control ,送数据

        
        LCD_MCU_START_WRITE();


        Delay(10);
    }


    七.显存数据组织

    采用16bpp(565)的形式在显存中组织.处理流程与RGB 16bpp几乎完全一样,采用short来发送点数据
    它会自动生成MCU命令来传输.
    组织好用TRIGCON来触发显示.
         rTRIGCON |= (1<<1)|(1 << 0);

    然后用VIDCON0中打开输出显示
       rVIDCON0 |= (1 << 1) | ( 1 << 0); //.Display On: ENVID & ENVID_F set to 1 
  • 相关阅读:
    HDU
    纯C++去雾算法
    拓扑排序
    SG 函数初步 HDU 1536 &amp;&amp; HDU 1944
    <html>
    XML制作RSS源
    ACM退役前2个月总结
    javascript 的 jasmine 的測试语句
    Vue.js父与子组件之间传参
    $.contents().find设置的data在iframe子页面无法获取值
  • 原文地址:https://www.cnblogs.com/LoongEmbedded/p/5298638.html
Copyright © 2020-2023  润新知