钻石会员
主题
回帖0
积分21684
阅读权限50
注册时间2010-3-13
最后登录1970-1-1
在线时间 小时
|
楼主 |
发表于 2012-6-21 22:11
|
显示全部楼层
本周事情比较多,晚上回家就不想写东西了,今晚就说说读取LCD2004/1602接口数据的思路。
其实很简单,2004、1602屏一般都只用到写操作,读操作基本上不用,而是用延时代替。Gandf老大的M8电源也只有写操作,因此,根据2004/1602的写操作时序就可以很方便使用外部中断的方式读取接口数据。
对于M8V7电源,由于是4线接口,因此需要读取两次,第一次是高四位,第二次是低四位,指令和数据我使用了两个变量作为高字节标识。
使用80字节的数组作为接收缓存,以存放接收到的数据。
下面是部分代码,写得非常直白,一看就懂。
uchar sBuffer[80]; //20x4显示缓存
uchar sCommand=0x00; //接收到的指令
uchar nAddress=0x00; //当前Buff地址,自动+1
//uchar bNewData=0; //数据是否更新标志
uchar bCmdFirst=1; //指令高字节标志
uchar bDataFirst=1; //数据高字节标志
uchar bAddValid=0; //地址有效标志,1-有效,0-无效
uchar nFlashAdd=0x00; //闪烁地址
uchar bFlashFlag=0; //闪烁标志
uchar bDisBanFlag=0; //光标显示标志
uchar bDisOK=0; //进入正常状态标志,区分起始logo与正常显示(正常显示包括正常输出和调试)
uchar nCommdNum[8]={0,0,0,0,0,0,0,0}; //指令的数量,供调测用
//INT0中断
SIGNAL(SIG_INTERRUPT0)
{
//读取E、R/W、RS的电平,以确定要进行的操作
uchar datad=PIND;
//经测试,没有读操作,因此代码不再写
//此外,中断方式也可以改为下降沿触发,不用再判断电平变化了
if(datad&0x01) //RS高电平,写数据
{
if(bAddValid)
{
//已知为4位接口,因此固定判断
if(bDataFirst) //首次接收,高4位
{
sBuffer[nAddress]=datad&0xf0;
bDataFirst=0;
}
else
{
sBuffer[nAddress]|=(datad>>4)&0x0f;
bDataFirst=1;
nAddress++; //地址自动+1
if(nAddress>=0x50)
{
nAddress=0;
bAddValid=0;
}
}
}
else //写数据,但是地址并未准备好,因此可以判断第一次接收到的是数据
{
bCmdFirst=1;
bDataFirst=1;
}
}
else //RS低电平,写指令
{
//已知为4位接口,因此固定判断
if(bCmdFirst) //首次接收,高4位
{
sCommand=datad&0xf0;
bCmdFirst=0;
}
else
{
sCommand|=(datad>>4)&0x0f;
bCmdFirst=1;
}
//解析指令,主要是提取DDRAM地址,以便放置数据到sBuffer中
if(sCommand>=0x80) //DDRAM地址设置
{
nAddress=sCommand&0x7F;
//判断地址有效性
bAddValid=1;
bDataFirst=1;
if((nAddress>0x27 && nAddress<0x40) || nAddress>0x67)
bAddValid=0;
//将设置地址与sBuffer序号对应起来
if(nAddress>=0x40)
nAddress-=0x18;
nCommdNum[7]++;
}
else if(sCommand>=0x40) //CGRAM地址设置(用到)
{
nCommdNum[6]++;
}
else if(sCommand>=0x20) //功能设置(用到)
{
nCommdNum[5]++;
}
else if(sCommand>=0x10) //移位(用到)
{
nCommdNum[4]++;
}
else if(sCommand>=0x08) //显示开关(用到)
{
//显示开关用来显示光标闪烁
bDisOK=1;
if(sCommand&0x01) //仅判断闪烁标志
{
bFlashFlag=1;
nFlashAdd=nAddress;
}
else
bFlashFlag=0;
nCommdNum[3]++;
}
else if(sCommand>=0x04) //设置输入方式(没用到)
{
nCommdNum[2]++;
}
else if(sCommand>=0x02) //光标返回,此处也清屏(用到1次)
{
uchar i;
for(i=0;i<80;i++)
sBuffer[i]=0x20;
nAddress=0;
nCommdNum[1]++;
}
else if(sCommand==0x01) //清屏(没用到)
{
//Clr_Scr();
uchar i;
for(i=0;i<80;i++)
sBuffer[i]=0x20;
nAddress=0;
nCommdNum[0]++;
}
}
//固定赋值
if(bDisOK)
{
sBuffer[9]='+';
sBuffer[29]='|';
sBuffer[49]='|';
sBuffer[69]='|';
}
// }
//}
} |
|