搜索
bottom↓
回复: 4

浅谈液晶传输协议之MDDI标准

[复制链接]
(279188271)

出0入0汤圆

发表于 2012-12-18 00:21:43 | 显示全部楼层 |阅读模式
本帖最后由 john_patson 于 2012-12-18 11:59 编辑

闲着无聊也是无聊,在这里开帖谈谈关于液晶屏各种传输协议标准,首先说明本人能力有限,如有遗漏或错误之处请谅解。同样希望大家可以把它补全。
液晶屏的通讯协议目前有好几种,对于较流行的MIPI来说MDDI更具备所需的数据线少,MDDI最低只需要2组数据线即可,可分为Stb+/-和Data+/-这四根,其中Stb为基准线,其它的为数据线。VESA规范中是使用差分线进行数据传输,不过可以把它的负端直接接数据地,那么减少了一半,只剩两根,事实上通过两根数据线来传传输数据对于布线和资源端口少的单片机来说是极其具有优势的。MDDI的传输速率可达3.2Gbps,不过对于普通的液晶来说速率太大了。一般传输速率为10Mbps左右。它有四种传输模式,模式1下为两根据信号线分别为Stb和Data0,模式2下为三根信号线分别为Stb和Data0、Data1,模式3下为5根信号线分别为Stb和Data0、Data1、Data2、Data3,模式4和模式3一样有5根信号线,只不过模式4比模式3多增加了几根电源信号管理线。可由下图1来对比

比较有意思的是它的数据传输方式不像一般的采用时钟线的上升沿或下降沿来采样数据值或如串口传输那样规定传输速率来采样它的数据值。MDDI的数据传输是自带时钟的,即在传输数据的同时也把它的传输速率也包含进去了,就是因为这一点,很多人都很难理解MDDI的传输数据到底是怎么样进行的。这点一时半会很难说清楚它的格式到底是如何,不过简单点来说就是当数据线Data值与前一位值不相同时(即数据有变化),基准线Stb不变;数据线Data值与前一位值相同时(即数据没变化),基准线Stb则会翻转变化。如下图2所示。数据还是以采样它的数据线Data为准,Stb则是为了区别它每一位的值。
上图是1根数据线时的数据传输。
1根数据时传输一字节数据需要8个周期;2根数据线时传输一个字节数据只需要4个周期;4根数据线时传输一个字节数据只需要2个周期。如下图3所示为2根数据线时数据的传输。4根数据线时也是如此。

传输方向为LSB-->MSB。它的帧结构如下图4所示。

传输过程中以Sub-frame Header Packet为起始头。

接下来才是其它类型的封包数据传输。MDDIv1规范中规定了一共有40种类型的封包格式,每种封包都有独自的结构。每种封包的判定可从它的Packet Type值来确定属于哪种封包。这里就不一一列出,具体可查看MDDI的规范书,书中同时也说明了信号的延迟范围和硬件电路的结构。

同时封包中涉及到CRC校验,MDDI中的CRC校验采用的是CRC16的标准。其CRC16多项式为 X16+X15+X2+1,其对应校验二进制位列为1 1000 0000 0000 0101。说到CRC校验这里,不得不说一下CRC校验的实现方法。
方法如下:
CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1,然后把CRC寄存器与8-bit的数据进行异或(异或:二进制运算 相同为0,不同为1;0^0=0;0^1=1;1^0=1;1^1=0),   之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补零,而最低位(LSB,移位后已经被移出CRC寄存器)如果为1,则把寄存器与预定义的多项式码进行异或,否则如果LSB为零,则无需进行异或。重复上述的由高至低的移位8次,第一个8-bit数据处理完毕,用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。所有的字符处理完成后CRC寄存器内的值即为最终的CRC值。
1.设置CRC寄存器,并给其赋值FFFF(hex)。   
2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄存器。
3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。   
4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码相异或。   
5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。   
6.重复第2至第5步直到所有数据全部处理完成。   
7.最终CRC寄存器的内容即为CRC值。


参考网址:http://zhidao.baidu.com/question/242417637.html

用STM32官方库函实现它最底层每字节数据传输的代码,这里就写出模式1和模式2的实现方法。Stb为PA0、Data0为PA1、Data1为PA2。
#define Data                        GPIOA
#define Stb                        GPIOA
#define StbPin                        GPIO_Pin_0
#define DataPin                        GPIO_Pin_1
#define DataPin1                                GPIO_Pin_2

void ByteOperating1(unsigned int Sum)
{
        static unsigned char DataFlag=1;
        unsigned char i;
        for(i=0;i<8;i++)
        {
                if((Sum&(0x01<<i))==0)
                {                       
                        GPIO_ResetBits(Data, DataPin);  //置0
                        if(DataFlag)
                        {                               
                                if(GPIO_ReadOutputDataBit(Stb, StbPin))
                                GPIO_ResetBits(Stb, StbPin);  //置0
                                else
                                GPIO_SetBits(Stb, StbPin);          //置1
                        }               
                        DataFlag=1;
                        delay_us(2);
                }       
                else
                {                       
                        GPIO_SetBits(Data, DataPin);          //置1
                        if(DataFlag==0)
                        {                               
                                if(GPIO_ReadOutputDataBit(Stb, StbPin))
                                GPIO_ResetBits(Stb, StbPin);  //置0
                                else
                                GPIO_SetBits(Stb, StbPin);          //置1
                        }
                        DataFlag=0;
                        delay_us(2);
                }

        }


}




void ByteOperating2(unsigned int Sum)
{
        static unsigned char DataFlag=0;
        unsigned char i,MDDIData=0;
        for(i=0;i<4;i++)
        {
                if((Sum&(0x01<<(i*2)))==0)                                       
                        //GPIO_ResetBits(Data, DataPin);  //置0
                        {
                        MDDIData&=0xFD;
                        if(GPIO_ReadOutputDataBit(Data, DataPin))
                        DataFlag|=0x02;        //置位Data0位数据有变化标志
                        else
                        DataFlag&=0xFD;        //清除Data0位数据有变化标志
                        }
                else
                        //GPIO_SetBits(Data, DataPin);          //置1
                        {
                        MDDIData|=0x02;
                        if(GPIO_ReadOutputDataBit(Data, DataPin)==0)
                        DataFlag|=0x02;        //置位Data0位数据有变化标志
                        else
                        DataFlag&=0xFD;        //清除Data0位数据有变化标志
                        }

                if((Sum&(0x01<<(i*2+1)))==0)
                           //GPIO_ResetBits(Data, DataPin1);          //置0
                        {
                           MDDIData&=0xFB;
                        if(GPIO_ReadOutputDataBit(Data, DataPin1))
                        DataFlag|=0x04;        //置位Data1位数据有变化标志
                        else
                        DataFlag&=0xFB;        //清除Data1位数据有变化标志
                        }
                else
                        //GPIO_SetBits(Data, DataPin1);          //置1       
                        {
                        MDDIData|=0x04;
                        if(GPIO_ReadOutputDataBit(Data, DataPin1)==0)
                        DataFlag|=0x04;         //置位Data1位数据有变化标志
                        else
                        DataFlag&=0xFB;         //清除Data1位数据有变化标志
                        }
                switch(DataFlag)
                        {       
                                case 0x00:
                                                        if(GPIO_ReadOutputDataBit(Stb, StbPin))
                                                        //GPIO_ResetBits(Stb, StbPin);  //置0
                                                        MDDIData&=0xFE;
                                                        else
                                                        //GPIO_SetBits(Stb, StbPin);          //置1
                                                        MDDIData|=0x01;       
                                                        break;               
                                default:        break;
                        }
                        GPIO_Write(Data,MDDIData);                       
                        delay_us(2);

        }


}

目前关于MDDI标准就说到这里了。接下来有时间再说一说MIPI标准。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
(279156065)

出0入66汤圆

发表于 2012-12-18 09:18:29 | 显示全部楼层
看懂了,两线异或就是时钟,数据是从LSB到MSB。
(279017906)

出0入0汤圆

 楼主| 发表于 2012-12-19 23:41:08 | 显示全部楼层
wye11083 发表于 2012-12-18 09:18
看懂了,两线异或就是时钟,数据是从LSB到MSB。

是的,不过两信号异或后得出的信号的时钟周期需乘以2才是它真正的传输速率或时钟周期了。
(269718255)

出0入0汤圆

发表于 2013-4-6 14:55:19 | 显示全部楼层
非常不错,感谢分享.
(209602710)

出0入0汤圆

发表于 2015-3-3 09:41:04 | 显示全部楼层
不错,收藏了。MIPI可以用MCU的GPIO来模拟不?对于小分辨率的屏。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安交互式论坛备案:44190002001997 粤ICP备09047143号 )

GMT+8, 2021-10-23 08:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表