12864绘图时,图像周围有杂点,是不是绘图有特殊的设置?
本帖最后由 paradisespace 于 2012-5-29 10:03 编辑只显示字符很正常,添加绘图后就出现很多杂点。用的是st7820控制器的液晶显示。
模拟指针时钟也是这样,指针式时钟跑的时间越长周围的杂点就越多。
程序是用模块写的 就直接上传文件了吧,贴出来太长了。
代码:
我把相关代码贴上来。大神帮我看看吧。什么时候需要清GDRAM,12864的绘图让人纠结。。。void main()
{
/********************DS1302初始值设置************************/
DS1302_Init();
DS1302_Set_RTC(); //设置时钟初值
/*************************定时器*****************************/
Init_Timer0(); //Timer0初始化
/***********************液晶初始化***************************/
Display_Init();
Display_Clear(); //清除屏幕
// interface_clock();
while(1)
{
if(Read_RTC_Flag==1) //1S定时到
{
Read_RTC_Flag=0; //清空1S定时到标志
// interface_two(); //使用界面2时需打开interface_clock
interface_three();
}
}
}
void interface_clock()
{
Display_Clear();
/***********************绘制模拟时钟*************************/
Clean_12864_GDRAM(); //填充GDRAM
GUI_Circle(96,32,31,1); //画圆
GUI_Point(96,32,1); //画圆心
//画刻度
// GUI_RLine(96,1,4,1); //画垂直线
GUI_Line(112,5,110,8,1);
GUI_Line(123,17,120,18,1);
// GUI_HLine(123,127,32,1); //画水平线
GUI_Line(123,48,120,46,1);
GUI_Line(111,59,110,56,1);
// GUI_RLine(96,59,63,1); //画垂直线
GUI_Line(80,59,82,56,1);
GUI_Line(69,47,72,46,1);
// GUI_HLine(65,69,32,1); //画水平线
GUI_Line(69,16,72,18,1);
GUI_Line(81,5,82,8,1);
//显示刻度3,6,9,12
GUI_Put_Area(94,3,(unsigned char *)NUM5x5_12,5,5,0);//显示12
GUI_Put_Area(95,55,(unsigned char *)NUM3x5_6,3,5,0);//显示6
GUI_Put_Area(68,30,(unsigned char *)NUM3x5_9,3,5,0);//显示9
GUI_Put_Area(122,30,(unsigned char *)NUM3x5_3,3,5,0);//显示3
}
/*需要绘图显示的:时、分、秒--------------------------------------------------*/
void displaytime(void)
{
/*往液晶屏填写 小时 数据-----------------------------------------*/
// hour = read_clock(0x85); //读取DS1302的 时
Write1632GDRAM(1,2,num1632);
Write1632GDRAM(2,2,num1632);
Write1632GDRAM(3,2,num1632); //时钟分隔符“:”
/*往液晶屏填写 分钟 数据-----------------------------------------*/
// min = read_clock(0x83); //读取DS1302的 分
Write1632GDRAM(4,2,num1632);
Write1632GDRAM(5,2,num1632);
Write1632GDRAM(6,2,num1632); //时钟分隔符“:”
/*往液晶屏填写 秒钟 数据-----------------------------------------*/
// sec= read_clock(0x81); //读取DS1302的 秒
Write1632GDRAM(7,2,num1632);
Write1632GDRAM(8,2,num1632);
}
/**************************************************************************************
//函数功能:显示16X32图形,适用于st7920型液晶
//形式参数:uchar x,uchar y,uchar *bmp
//行参说明:横坐标X列,纵坐标Y行,要显示的图形BMP
//************************************************************************************/
void Write1632GDRAM(unsigned char x,unsigned char y,unsigned char *bmp)
{
unsigned char i,j,basex,basey;
switch(y) //由y纵坐标定是上半屏还是下半屏
{
case 1: basex=0x80; break;//上半屏
case 2: basex=0x80; break;//先上半屏,下面再下半屏。
case 3: basex=0x88; break;//下半屏
default: return; //别的则返回
}
basey=basex+x-1;
LcdWcom(0x36);
if(y==1||y==3) //如为第一第三行,则直接是在同一半屏,直接绘完32行点阵数据。
{
for(i=0;i<32;i++) //写入32行点阵
{
LcdWcom(0x80+i);//先写入垂直位址,选上下32行的哪一行,不管上下半屏,首行都为0X80
LcdWcom(basey); //再写入水平位址(选上下半屏)
for(j=0;j<2;j++) //2个8位元的数据,即16BIT宽度
LcdWdata(*bmp++);
}
}
if(y==2)//从第二行开始则画图将上下半屏都有,所以先画完上半屏16行,再画下半屏16行。
{
for(i=0;i<16;i++) //写入上半屏16行点阵
{
LcdWcom(0x90+i);//先写入垂直位址,选上下32行的哪一行,不管上下半屏,首行都为0X80,第二行为0X90。
LcdWcom(basey); //(选上半屏)再写入水平位址
for(j=0;j<2;j++) //2个8位元的数据,即16BIT宽度
LcdWdata(*bmp++);
}
for(i=0;i<16;i++) //写入下半屏16行点阵
{
LcdWcom(0x80+i);//先写入垂直位址,选上下32行的哪一行,不管上下半屏,首行都为0X80
LcdWcom(basey+8); //(选下半屏)再写入水平位址
for(j=0;j<2;j++) //2个8位元的数据,即16BIT宽度
LcdWdata(*bmp++);
}
}
LcdWcom(0x36);//写完数据,开图片显示
}
/**************************************************************************************
//函数名称:Clean_12864_GDRAM(void)
//函数功能:清屏函数
//使用说明:GDRAM填满0
//************************************************************************************/
void Clean_12864_GDRAM(void)
{
unsigned char x,y;
LcdWcom(0x36);
init_12864_GDRAM(); //设置扩展指令集,按手册说明,仅设置了绘图位,
LcdWcom(0x36); //需要两次,本次设置扩展指令集。
for (y=0;y<32;y++)
{
LcdWcom(0x80+y);//设置y=1000+00xx,y+1则往下一行
LcdWcom(0x80); //设置x=1000 0000
for (x=0;x<16;x++)
{
LcdWdata(0x00); //高字节数据
LcdWdata(0x00); //低字节数据
}
}
}
写新的数据前没有清屏? LcdWcom、LcdWdata和LcdRdata
函数内部实现中每次E的跳变都要加延时,而且延时值要足够长
另外考虑是否加入忙判断,我对这个控制芯片不熟,但是ks107/ks108是要的 液晶屏必须增加判断忙信号,要详细的阅读液晶驱动的时序控制电路。
清屏幕的话可以解决问题,但是会出现刷屏的现象,显示不够流畅。
lvyunzeng 发表于 2012-5-28 15:29 static/image/common/back.gif
液晶屏必须增加判断忙信号,要详细的阅读液晶驱动的时序控制电路。
清屏幕的话可以解决问题,但是会出现刷 ...
是在写数据,读数据,写命令,这三个函数里加个忙判断就可以了吗? 本帖最后由 paradisespace 于 2012-5-29 02:41 编辑
都半夜了。。。还是没有调出来,睡会儿吧,明天继续。纠结的不是问题,而是不知道问题出在哪里。请高人指点啊。。。 这种情况大都不是程序问题。 一个看总线电平是不是够,还有一个降低速度 BDXing6 发表于 2012-5-29 09:22 static/image/common/back.gif
这种情况大都不是程序问题。
那可能是什么问题? 还望指点。一直在线期待解答。 你的MCU与12864是如何连接的? chenerbox2 发表于 2012-5-29 09:29 static/image/common/back.gif
一个看总线电平是不是够,还有一个降低速度
你指的是在使能端的电平跳变时加足够的延时吗? 是用的排针,排线,还是一般的单根线? 有可能是干扰,有时候接线接得不好就会这样。
但看你这个情况那么久都是这样。应该是程序问题。
你的是ST7920控制器吧?
用的是串口还是并口? BDXing6 发表于 2012-5-29 09:32 static/image/common/back.gif
你的MCU与12864是如何连接的?
RS——P3^5 WR——P3^6LCDEN——P3^4 RD——P3^7 数据总线接的是P0口 joing2000 发表于 2012-5-29 09:34 static/image/common/back.gif
有可能是干扰,有时候接线接得不好就会这样。
但看你这个情况那么久都是这样。应该是程序问题。
你的是ST79 ...
是ST7920,并口 BDXing6 发表于 2012-5-29 09:33 static/image/common/back.gif
是用的排针,排线,还是一般的单根线?
是开发板上的排针接口 我不是要你的电路图。这样说吧,如果你是用连接线连接起来的,这些线又比较长的话,试着把线缩短些,一般不要超过5cm,另外,最好不要用排线连,如果是把它们撕开来,这种显示屏,读写时序没有问题,一般不用另加延时,但一定要有忙判断语句。 void wr_lcd (uchar dat_comm,uchar content)
{
chk_busy ();
if(dat_comm)
{
rs=1; //data
rw=0; //write
}
else
{
rs=0; //command
rw=0; //write
}
P1=content; //output data or comm
e=1;
;
e=0;
}
e=1;
;
e=0;
这个中间的空语句,加个延时试试吧。
是写数据命令的子程序,你对着你的程序改就行了。
对了,换屏之前要加清屏命令。 BDXing6 发表于 2012-5-29 09:43 static/image/common/back.gif
我不是要你的电路图。这样说吧,如果你是用连接线连接起来的,这些线又比较长的话,试着把线缩短些,一般不 ...
没加忙判断,线长上没有问题,液晶是直接插在板子上的排针接口上的。昨天加过忙判断,花屏更严重,感谢你们这么耐心的为我解答!! joing2000 发表于 2012-5-29 09:44 static/image/common/back.gif
void wr_lcd (uchar dat_comm,uchar content)
{
chk_busy ();
我没加忙检测。昨天加了忙检测效果更乱,我今天再试试。若是你现在有时间的话,帮我把程序看看吧。辛苦了! paradisespace 发表于 2012-5-29 09:49 static/image/common/back.gif
我没加忙检测。昨天加了忙检测效果更乱,我今天再试试。若是你现在有时间的话,帮我把程序看看吧。辛苦了 ...
我看了。关键不在你发的那部分程序上面呀。我发我的例程给你看看。
#include <reg52.h>
#define uintunsigned int
#define uchar unsigned char
#define x 0x80
#define y 0x80
#define comm0
#define dat 1
sbit rs = P3^0; //H=data; L=command;
sbit rw = P3^1; //H=read; L=write;
sbite = P3^2; //input enable;
sbit psb= P3^3; //H=并口; L=串口;
sbit rst= P3^4; //Reset Signal 低电平有效
sbit busy=P1^7; //lcd busy bit
void wr_lcd (uchar dat_comm,uchar content);
void chk_busy (void);
void delay (uint us);
uchar code tab1[]={
"锐显科技有限公司"
"NS:www.rxlcd.com"
};
uchar code tab5[]={
/*------------------------------------------------------------------------------
;若数据乱码,请检查字模格式设置,注意选择正确的取模方向和字节位顺序。
;源文件 / 文字 : C:\Documents and Settings\Administrator\桌面\新建文件夹\图片\16032(1).bmp字模
;宽×高(像素): 128×32
;字模格式/大小 : 单色点阵液晶字模,横向取模,字节正序/512字节
;数据转换日期: 2011-4-25 9:28:51
------------------------------------------------------------------------------*/
0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x03,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x1F,0xF8,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x3E,0xFC,0x0C,0x00,0x70,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x7C,0x7E,0x1E,0x00,0xF0,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xF8,0x3F,0x3F,0x00,0x70,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0xF0,0x1F,0xFF,0x80,0x79,0xEF,0x0F,0x9E,0xF7,0x80,0x00,0x00,0x00,0x00,0x00,
0x03,0xE0,0x0F,0xFB,0xC0,0x79,0xEF,0x1F,0xDE,0xF7,0x80,0x00,0x00,0x00,0x00,0x00,
0x07,0xC0,0x07,0xF1,0xE0,0x39,0xC7,0x39,0xDE,0xF7,0x80,0x00,0x00,0x00,0x00,0x00,
0x0F,0x80,0x03,0xE0,0xF0,0x39,0xC7,0x3F,0xCF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
0x1F,0x00,0x07,0xC0,0x78,0x19,0x87,0x3F,0xCF,0x9F,0x00,0x38,0x00,0x00,0x00,0x00,
0x3E,0x00,0x0F,0x80,0x3C,0x1F,0x87,0x38,0x0F,0x9F,0x3F,0x38,0x00,0x00,0x00,0x00,
0x7C,0x00,0x1F,0x00,0x1E,0x0F,0x07,0x3C,0xC7,0x9E,0x7F,0xB8,0x00,0x00,0x00,0x00,
0xFC,0x00,0x3E,0x00,0x0F,0x0F,0x07,0x1F,0xC7,0x9E,0x7B,0xB8,0x00,0x00,0x00,0x00,
0x7E,0x00,0x3E,0x00,0x0F,0x0F,0x07,0x1F,0x87,0x9E,0x70,0x3F,0x87,0xC6,0x6F,0xF0,
0x3F,0x00,0x1F,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x70,0x3F,0xC7,0xE7,0xEF,0xF8,
0x1F,0x80,0x0F,0x80,0x3C,0x00,0x00,0x00,0x00,0x00,0x7E,0x3D,0xE0,0xF7,0x8F,0x78,
0x0F,0xC0,0x07,0xC0,0x78,0x00,0x00,0x00,0x00,0x00,0x3F,0x38,0xE7,0xF7,0x0E,0x38,
0x07,0xE0,0x0F,0xE0,0xF0,0x00,0x00,0x00,0x00,0x00,0x0F,0xB8,0xE7,0xF7,0x0E,0x38,
0x03,0xF0,0x1F,0xF1,0xE0,0x00,0x00,0x00,0x00,0x00,0x03,0xB8,0xEE,0x77,0x0E,0x38,
0x01,0xF8,0x3F,0xFB,0xC0,0x00,0x00,0x00,0x00,0x00,0x7F,0xB8,0xEE,0x77,0x0F,0x78,
0x00,0xFC,0x7E,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x7F,0xB8,0xEF,0xF7,0x0F,0xF8,
0x00,0x7E,0xFC,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x38,0xE7,0xFF,0x0E,0xF0,
0x00,0x3F,0xF8,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,
0x00,0x1F,0xF0,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,
0x00,0x0F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,
0x00,0x07,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x03,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
/*------------------初始化-----------------*/
void init_lcd (void)
{
rst=1;
psb=1;
wr_lcd (comm,0x30);/*30---基本指令动作*/
wr_lcd (comm,0x01);/*清屏,地址指针指向00H*/
wr_lcd (comm,0x06);/*光标的移动方向*/
wr_lcd (comm,0x0c);/*开显示,关游标*/
}
/*---------------显示汉字或字符----------------*/
void chn_disp (uchar code *chn)
{
uchar i,j;
wr_lcd (comm,0x30);
wr_lcd (comm,0x80);
j=0;
for (i=0;i<16;i++)
wr_lcd (dat,chn);
wr_lcd (comm,0x90);
j=1;
for (i=0;i<16;i++)
wr_lcd (dat,chn);
}
/*----------------显示图形-----------------*/
void img_disp (uchar code *img)
{
uchar i,j;
for(j=0;j<32;j++)
{
for(i=0;i<8;i++)
{
wr_lcd (comm,0x34);
wr_lcd (comm,y+j);
wr_lcd (comm,x+i);
wr_lcd (comm,0x30);
wr_lcd (dat,img);
wr_lcd (dat,img);
}
}
wr_lcd (comm,0x36);
}
/*--------------显示点阵----------------*/
void lat_disp (uchar data1,uchar data2)
{
uchar i,j;
for(j=0;j<16;j++)
{
for(i=0;i<8;i++)
{
wr_lcd (comm,0x34);
wr_lcd (comm,y+j*2);
wr_lcd (comm,x+i);
wr_lcd (comm,0x30);
wr_lcd (dat,data1);
wr_lcd (dat,data1);
}
for(i=0;i<8;i++)
{
wr_lcd (comm,0x34);
wr_lcd (comm,y+j*2+1);
wr_lcd (comm,x+i);
wr_lcd (comm,0x30);
wr_lcd (dat,data2);
wr_lcd (dat,data2);
}
}
wr_lcd (comm,0x36);
}
/*-----------------------------------------------*/
//当data1=0xff,data2=0xff时,在x0,y0处反白显示16xl*yl.
void con_disp (uchar data1,uchar data2,uchar x0,uchar y0,uchar xl,uchar yl)
{
uchar i,j;
for(j=0;j<yl;j++)
{
for(i=0;i<xl;i++)
{
wr_lcd (comm,0x34);
wr_lcd (comm,y0+j);
wr_lcd (comm,x0+i);
wr_lcd (comm,0x30);
wr_lcd (dat,data1);
wr_lcd (dat,data2);
}
}
wr_lcd (comm,0x36);
}
/*--------------清DDRAM------------------*/
void clrram (void)
{
wr_lcd (comm,0x30);
wr_lcd (comm,0x01);
}
/*---------------------------------------*/
void wr_lcd (uchar dat_comm,uchar content)
{
chk_busy ();
if(dat_comm)
{
rs=1; //data
rw=0; //write
}
else
{
rs=0; //command
rw=0; //write
}
P1=content; //output data or comm
e=1;
;
e=0;
}
void chk_busy (void)
{
P1=0xff;
rs=0;
rw=1;
e =1;
while(busy==1);
e =0;
}
/*---------------------------------------*/
void delay (uint us) //delay time
{
while(us--);
}
void delay1 (uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<15;j++)
delay(1);
}
/*------------------主程序--------------------*/
void main ()
{
SP=0x5f;
init_lcd ();
while (1)
{
lat_disp (0x00,0x00);
chn_disp (tab1);
con_disp (0xff,0xff,0x80,0x90,1,16);
delay1 (5000);
clrram();
lat_disp (0xcc,0xcc);
delay1 (5000);
clrram();
lat_disp (0xff,0x00);
delay1 (5000);
img_disp (tab5);
delay1 (5000);
}
}
我没看代码。
楼主有没有写一个for loop,尝试不断刷新该图片? 没有忙判断是肯定不行的 brahen 发表于 2012-5-29 09:51 static/image/common/back.gif
我没看代码。
楼主有没有写一个for loop,尝试不断刷新该图片?
我试过把绘图的所有函数都放在一个while里死循环,但是还是有杂点,唯一区别就是屏幕一直刷新,显示的也不流畅 joing2000 发表于 2012-5-29 09:51 static/image/common/back.gif
我看了。关键不在你发的那部分程序上面呀。我发我的例程给你看看。
#include
整个工程文件我上传了,我对着你的代码看看。你也帮我看看我的代码吧。 我感觉判断是不是读写速度的问题,可以把单片机时钟降下来,比如原来12M,现在换4M 1M的 看看是不是一样效果
电平你要单片机5v 屏也5v 估计不存在问题 chenerbox2 发表于 2012-5-29 10:56 static/image/common/back.gif
我感觉判断是不是读写速度的问题,可以把单片机时钟降下来,比如原来12M,现在换4M 1M的 看看是不是一样效果
...
应该不是单片机速度的问题,开始也考虑到这个了,所以在读写的时候都加了足够的延时,但是只是刷新频率变慢了 也来mark一下 标记一下,以后会用到的资料,呵呵 我把每一个绘图函数都在main的外面显示了一次,函数都没问题。绘制静态的图像也没问题。只要是画动态的就出现问题了。现在觉得是GDRAM的清除导致的。我是这样理解的:画每一副图像前都要清除一次GDRAM,但是把他放在while循环中,清除的太快了,还没来得及显示完全就清除了。一点点的发现,我相信能成功的。别人用一天做到的我用两天!期待各路高人的指点 问题已经解决,软件没有问题。12864液晶也可以不用忙检测,用适当的延时函数。硬件问题,DS1302和液晶公用了一个IO口,实在是疏忽啊,白白浪费了这么多天去反复的检查软件。由于用的是开发板疏忽了这个问题了。就当是个经验教训吧。累死了。。。。 拜读了,最近也在处理这个问题,不过我的问题是产品在做干扰测试的时候出现的,不知道有人遇到这个问题没有,如何解决的? 本帖最后由 paradisespace 于 2012-6-19 13:20 编辑
chliken 发表于 2012-6-18 09:00 static/image/common/back.gif
拜读了,最近也在处理这个问题,不过我的问题是产品在做干扰测试的时候出现的,不知道有人遇到这个问题没有 ...
我的问题解决了。出现这样的问题可能有几种可能:1、液晶的控制端口与其他的端口的复用。2、液晶的数据口的抗干扰能力不是很好,建议与数据端口的线尽可能短或采取某些防干扰措施。3、处理器的速度也有一定的影响。4、清屏处理。
你的是在产品干扰测试的时候出现的这样的情况。我觉得还最可能是数据口的干扰。
——————————恕我愚钝,乃小生之鄙见。有不得道之处还望多多交流。 最好判断读忙和清屏,但经常清屏可能会引起刷新速度不够快,出现闪屏现像。 panguoxian 发表于 2012-6-19 16:41 static/image/common/back.gif
最好判断读忙和清屏,但经常清屏可能会引起刷新速度不够快,出现闪屏现像。 ...
这款液晶也可以不用忙判断。直接加个短暂的延时也可以。刚开始也做过忙判断,也试着直接用延时,都可以。但是按照严格的程序还是应该加忙判断的。
其次,清屏也是很关键的问题,这个问题说实话我总不能彻底的运用。。。。清除GDRAM总把握不好。只能再程序中试效果。 恭喜楼主把问题给解决了,没帮上忙却很无耻的下了个你的代码,{:lol:}
页:
[1]