博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
S3C6410驱动I80接口LCD
阅读量:5301 次
发布时间:2019-06-14

本文共 7084 字,大约阅读时间需要 23 分钟。

在嵌入式的主流 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 

转载于:https://www.cnblogs.com/LoongEmbedded/archive/2013/05/22/5298638.html

你可能感兴趣的文章
BZOJ_1018_[SHOI2008]_交通堵塞traffic_(线段树)
查看>>
PyCharm Change Font Size
查看>>
理解Python中的__init__和__new__
查看>>
None.js 第六步 Stream(流)
查看>>
ajax:error:function (XMLHttpRequest, textStatus, errorThrown) 中status、readyState和textStatus状态意义...
查看>>
Day4 数据类型
查看>>
【转】Nicescroll滚动条插件的用法
查看>>
Redis复制与可扩展集群搭建(转)
查看>>
软件工程概论第六章--面向对象基础
查看>>
网络传输方式的分类
查看>>
思1-基本三观
查看>>
angularJS--apply() 和digest()方法
查看>>
Alpha 冲刺 (5/10)
查看>>
PHP函数之$_SERVER
查看>>
利用安装光盘创建本地yum源补装 RPM 软件包-通过命令行模式
查看>>
XML通過XSD產生CLASS
查看>>
跨线程调用窗体控件
查看>>
linq to sql 扩展方法
查看>>
241. Different Ways to Add Parentheses
查看>>
实验10 编写子程序 1.显示字符串
查看>>