ST7920带字库液晶如何实现在任意一个位置点亮一个点的功能?
最近因为需要,所以要写一个描点的函数,但是带字库的夜晶,一次必须写入16个字节,我写个画点函数虽然可以实现任意位置的画点,但在画点的同时,有可能会把上一次画的点给清除掉。我现在的想法,是能不能试着把液晶上一次写入的数据给读出来,然后通过取余或者是取或操作,保留上一次的数据,在把新的点给写进去。
我用的12864的串行驱动程序,我想问一下他读出来的数据是什么数据,为什么我每次所读出来的数据都是一样的呢。
用过带字库的液晶且成功编写出了画点函数的人,。。。请提示下我吧
这个问题已经捆饶我很久了,在这里先谢谢了。 串行控制数据只能写不能读!
可以在单片机内部建立一个1k显示缓存 串行数据不能读吗?
但是我看到很多串行驱动程序上面都有
都有读的子函数 搜索论坛,有方法。。。 你看下ST7920的数据手册哪里有说到串行读吗
事实上串行控制时SID不会输出数据的
你自己试试看,也许我还没找到读数据的方法
发送读命令应该是无效的,甚至连忙标志也是读不到的 最好建缓存,不至于太慢! 楼主,你也用7920啊!我也在探讨跟你一样的问题啊,不过我不是用串口的,正确读gdram的数据理论上要先预读一次,接下来连续读的两次就是正确的高8位和低8位了,我写了程序,单步运行的时候实现了,可是全速运行的时候就错了,读出来的都是一个样的,不知为何,望解答呢! 读原始数据部分:
read_data();// 预读
datah=read_data();
datal=read_data();
原帖:
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=3217038&bbs_id=1000 这是我的程序,在论坛被攻击以前发过,
/********************************************************
名称: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位数据
}
} st7920是可以串行读的 我晕了~~~~
到底能不能串行读呢。。。。一回说可以读,一回说不可以读
有成功用串行读取数据的吗?
还有就是上面说到的 可以在单片机内部建立一个1k显示缓存,我不是很明白可以说的详细点吗 【6楼】 86csx: 注意时序Tas,Tpw,Tddr,Tah,Tc
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422113.JPG
(原文件名:st7920并行读.JPG)
【9楼】 yaya001: 如何串行读,可否贴段程序看看,就这一个结论很难说服人,论据呢?
我的结论是串行不能读!
发送读寄存器命令(0xfc),然后将单片机IO置输入内部上拉,读出的数据就始终为0xff
http://cache.amobbs.com/bbs_upload782111/files_12/ourdev_422120.JPG
(原文件名:st7920串行读.JPG) 不管如何,十分感谢【11楼】 lanlinhong 的回复,我会回去认真检查试验的。 哈哈,经过一个小时的探索,终于成功了,原来并不是因为时序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);
}
} 这个问题也困扰了我很长一段时间;我用的是51控制并行接口。
读出来的数据是错误的,后来也就不了了之了。 多谢啊!弄了几天了,都没弄出来! 试过了,串行不能读的 谢谢了,mark
页:
[1]