搜索
bottom↓
回复: 17

ST7920带字库液晶如何实现在任意一个位置点亮一个点的功能?

[复制链接]

出0入0汤圆

发表于 2009-2-24 17:39:38 | 显示全部楼层 |阅读模式
最近因为需要,所以要写一个描点的函数,但是带字库的夜晶,一次必须写入16个字节,我写个画点函数虽然可以实现任意位置的画点,但在画点的同时,有可能会把上一次画的点给清除掉。

我现在的想法,是能不能试着把液晶上一次写入的数据给读出来,然后通过取余或者是取或操作,保留上一次的数据,在把新的点给写进去。

我用的12864的串行驱动程序,我想问一下他读出来的数据是什么数据,为什么我每次所读出来的数据都是一样的呢。

用过带字库的液晶且成功编写出了画点函数的人,。。。请提示下我吧
这个问题已经捆饶我很久了,在这里先谢谢了。

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2009-2-24 17:47:17 | 显示全部楼层
串行控制数据只能写不能读!
可以在单片机内部建立一个1k显示缓存

出0入0汤圆

 楼主| 发表于 2009-2-24 19:07:37 | 显示全部楼层
串行数据不能读吗?
但是我看到很多串行驱动程序上面都有
都有读的子函数

出0入0汤圆

发表于 2009-2-24 19:11:33 | 显示全部楼层
搜索论坛,有方法。。。

出0入0汤圆

发表于 2009-2-24 22:02:28 | 显示全部楼层
你看下ST7920的数据手册哪里有说到串行读吗
事实上串行控制时SID不会输出数据的
你自己试试看,也许我还没找到读数据的方法
发送读命令应该是无效的,甚至连忙标志也是读不到的

出0入0汤圆

发表于 2009-2-24 23:49:01 | 显示全部楼层
最好建缓存,不至于太慢!

出0入0汤圆

发表于 2009-2-25 00:18:03 | 显示全部楼层
楼主,你也用7920啊!我也在探讨跟你一样的问题啊,不过我不是用串口的,正确读gdram的数据理论上要先预读一次,接下来连续读的两次就是正确的高8位和低8位了,我写了程序,单步运行的时候实现了,可是全速运行的时候就错了,读出来的都是一个样的,不知为何,望解答呢!

出0入0汤圆

发表于 2009-2-25 00:21:56 | 显示全部楼层
读原始数据部分:
read_data();  // 预读
datah=read_data();
datal=read_data();
原帖:
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=3217038&bbs_id=1000

出0入0汤圆

发表于 2009-2-25 08:32:54 | 显示全部楼层
这是我的程序,在论坛被攻击以前发过,
/********************************************************
名称:GUI_Point(打点)
说明:X:横坐标(代表列的位置,0~127)    Y:纵坐标(代表行的位置,0~63)
       根据Datesheet需先把数据写到GDRAM,读取当前位置的数据,经过或和移位后再把数据重新写入
           GDRAM每行有16个位元,共64行,每个位元有两个8位(高低8位)
           计算出在那个位元,在该位元的哪一位
易出现的问题:1、打点位置的定位
              2、读取当前显示的数据
                          3、或和移位,即重新写人的新数据
********************************************************/
void GUI_Point(uchar x,uchar y,uchar flag)
{      
   uchar x_Dyte,x_byte;                       //定义列地址的字节位,及在字节中的哪1位
   uchar y_Dyte,y_byte;                       //定义为上下两个屏(取值为0,1),行地址(取值为0~31)
   Write_command(0x36);                       //绘图模式命令
   /***X,Y坐标互换,即普通的X,Y坐标***/
   x_Dyte=x/16;                               //计算在16个字节中的哪一个
   x_byte=x&0x0f;                             //计算在该字节中的哪一位
   y_Dyte=y/32;                               //0为上半屏,1为下半屏
   y_byte=y&0x1f;                             //计算在0~31当中的哪一行
   
   Write_command(0x80+y_byte);                //设定行地址(y坐标)
   Write_command(0x80+x_Dyte+8*y_Dyte);       //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
                     
   Read_data();
   GDRAM_hbit=Read_data();                    //读取当前显示高8位数据
   GDRAM_lbit=Read_data();                    //读取当前显示低8位数据
   delay_us(5);
   
   if(flag==1)
   {
     Write_command(0x80+y_byte);                //设定行地址(y坐标)
     Write_command(0x80+x_Dyte+8*y_Dyte);       //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
     delay_us(5);
         if(x_byte<8)                                   //判断其在高8位,还是在低8位
     {
          Write_data(GDRAM_hbit|(0X01<<(7-x_byte)));   //显示GDRAM区高8位数据
      Write_data(GDRAM_lbit);                      //显示GDRAM区低8位数据
         }
         else
         {
          Write_data(GDRAM_hbit);
          Write_data(GDRAM_lbit|(0x01<<(15-x_byte)));
         }
   }
   else
   {
     Write_data(0x00);                           //清除GDRAM区高8位数据
     Write_data(0x00);                           //清除GDRAM区低8位数据
   }       
}

出0入0汤圆

发表于 2009-2-25 09:44:27 | 显示全部楼层
st7920是可以串行读的

出0入0汤圆

 楼主| 发表于 2009-2-25 18:13:10 | 显示全部楼层
我晕了~~~~

到底能不能串行读呢。。。。一回说可以读,一回说不可以读
有成功用串行读取数据的吗?
还有就是上面说到的 可以在单片机内部建立一个1k显示缓存,我不是很明白可以说的详细点吗

出0入0汤圆

发表于 2009-2-25 20:01:21 | 显示全部楼层
【6楼】 86csx:    注意时序Tas,Tpw,Tddr,Tah,Tc

(原文件名:st7920并行读.JPG)

【9楼】 yaya001:    如何串行读,可否贴段程序看看,就这一个结论很难说服人,论据呢?
我的结论是串行不能读!
发送读寄存器命令(0xfc),然后将单片机IO置输入内部上拉,读出的数据就始终为0xff

(原文件名:st7920串行读.JPG)

出0入0汤圆

发表于 2009-2-26 03:17:55 | 显示全部楼层
不管如何,十分感谢【11楼】 lanlinhong 的回复,我会回去认真检查试验的。

出0入0汤圆

发表于 2009-2-26 04:24:51 | 显示全部楼层
哈哈,经过一个小时的探索,终于成功了,原来并不是因为时序Tas,Tpw,Tddr,Tah,Tc 的问题,而是我自己犯了一个严重的sb级的错误,我没有先在读数据函数里判忙,现在加上了判忙函数,结果正确,还是感谢【11楼】 lanlinhong ,你是第一个回复我的人,哈哈!感谢所有无私奉献的网友~!
如下:
//**********************************读数据**********************************//
uchar read_data(void)
{
uchar data;
busyloop();判忙
RS=1;
RW=1;
E=1;
SETIN;
data=DATAIN;
E=0;
return(data);
}
补充:(我刚写的画任意斜率直线函数和画圆函数,希望对需要的人有帮助)
//**********************************画任意点**********************************//
void lcd_draw_dot(uchar x, uchar y)//x。y为点坐标,按128*64来定义
{
uchar lcd_x,lcd_y,dot_datah,dot_datal,datah,datal;
uint dot_data=0x8000;
if(x>=0&&x<16)//初定x位置
   lcd_x=0x80;
else if(x>=16&&x<32)
   lcd_x=0x81;
else if(x>=32&&x<48)
   lcd_x=0x82;
else if(x>=48&&x<64)
   lcd_x=0x83;
else if(x>=64&&x<80)
   lcd_x=0x84;
else if(x>=80&&x<96)
   lcd_x=0x85;
else if(x>=96&&x<112)
   lcd_x=0x86;
else if(x>=112&&x<128)
   lcd_x=0x87;
else
{
   write_cmd(0x30);
   lcd_x=x;
   write_cmd(0x92);
   lcd_wz_display(wz2,sizeof(wz2)-1);
   while(1);
}
if(y>=0&&y<32)//进一步确定点所在的字的位置
   lcd_y=0x80+y;else
if(y>=32&&y<64)
  {
    lcd_y=0x80+y-32;
    lcd_x+=8;
  }
else
{
   write_cmd(0x30);
   write_cmd(0x92);
   lcd_wz_display(wz2,sizeof(wz2)-1);
   while(1);
}   
dot_data=dot_data>>(x%16);//确定写入点数据,最终确定点位置
dot_datal=dot_data&0x00ff;
dot_datah=dot_data>>8;
write_cmd(lcd_y);  //设置点的Y地址坐标
write_cmd(lcd_x);  //设置点的X地址坐标
read_data();
datah=read_data();
datal=read_data();
write_cmd(lcd_y);  //设置点的Y地址坐标
write_cmd(lcd_x);  //设置点的X地址坐标
write_data(dot_datah|datah);
write_data(dot_datal|datal);
}
//**********************************画任意直线********************************//
void lcd_draw_lin(uchar x1, uchar y1,uchar x2,uchar y2)//x。y为起始点坐标,按128*64来定义,x2>x1
{
signed char j,k;
j=x2-x1;
k=y2-y1;
if(j==0&&k==0)
   lcd_draw_dot(x1,y1);
else if(j==0&&k!=0)
   for(uchar i=0;i<=abs(k);i++)
     lcd_draw_dot(x1,k>0?y1++:y2++);
else if(j!=0&&k==0)
   for(uchar i=0;i<=abs(j);i++)
     lcd_draw_dot(j>0?x1++:x2++,y1);
else
for(uchar i=0;i<=(x2-x1);i++)
   k>0?lcd_draw_dot(i+x1,i*(y2-y1)/(x2-x1)+y1):lcd_draw_dot(i+x1,y1-i*(y1-y2)/(x2-x1));
}
//***********************************画圆***********************************//
void lcd_draw_circle(uchar x, uchar y,uchar r)//x、y为圆心坐标,r为半径
{
signed char k;
uchar x1,y1;
for(x1=x-r;x1<=x+r;x1++)
   {
     k=x1-x;
     y1=y+sqrt(r*r-k*k);
     lcd_draw_dot(x1,y1);   
   }
for(x1=x-r;x1<=x+r;x1++)
   {
     k=x1-x;
     y1=y-sqrt(r*r-k*k);
     lcd_draw_dot(x1,y1);   
   }
for(y1=y-r;y1<=y+r;y1++)
   {
     k=y1-y;
     x1=x+sqrt(r*r-k*k);
     lcd_draw_dot(x1,y1);   
   }
for(y1=y-r;y1<=y+r;y1++)
   {
     k=y1-y;
     x1=x-sqrt(r*r-k*k);
     lcd_draw_dot(x1,y1);   
   }
}

出0入0汤圆

发表于 2009-2-26 09:27:49 | 显示全部楼层
这个问题也困扰了我很长一段时间;我用的是51控制并行接口。

读出来的数据是错误的,后来也就不了了之了。

出0入0汤圆

发表于 2010-7-25 19:04:51 | 显示全部楼层
多谢啊!弄了几天了,都没弄出来!

出0入4汤圆

发表于 2010-7-25 23:32:14 | 显示全部楼层
试过了,串行不能读的

出0入0汤圆

发表于 2012-11-15 14:44:35 | 显示全部楼层
谢谢了,mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 07:13

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

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