发一个ST7920控制器LCD12864源代码,有画点、画线功能
最近做个项目,要用到一块12864的液晶CM12864-12,使用ST7920控制器,这款控制器内置了汉字库显示字符汉字方便,但是汉字库是16*16点阵的,我要显示点别的怎么??可以用图形RAM画图。我想显示12*12的汉子,这样就能显示五行了!我的实现思路是实现画点函数,画点函数需要对GDRAM读,不然显示一团糟!这里用7920的并行模式,串行模式虽然节省IO口,但是不能读出数据!那就开始吧!在网上找了7、8个版本的7920驱动,发现几乎都只用了基本的显示字符汉字功能,即使使用的画图,也没有画点!!
自己写!看着液晶手册写,但是显示乱七八糟,怎么改都不行,以前也过KS0108的画点函数不难啊??怎么这个就不行了!一点点着,发现读GDRAM数据有问题,读出的数据不正确!液晶手册不是很详细,还是看7920的手册!
终于找到问题所在:原来7920读出数据时,需要DUMMY READ,就是要读两次!!液晶手册很害人,就说个大概!看来以后要注意啊,要从跟上看!!!
简单一改,就OK了!!
现在把照片,电路(非常简单),源码都亮出来!!希望阿莫给个COOL!(7920的实现画点的代码网上可能没有啊,反正我没找到!嘿嘿)
电路
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_456694.JPG
(原文件名:12864.JPG)
显示效果
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_456647.JPG
(原文件名:IMG_3244.JPG)
实验板
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_456648.JPG
(原文件名:IMG_3245.JPG)
源码
点击此处下载 ourdev_456695.rar(文件大小:424K) (原文件名:OM_test.rar) cool! cool 这么长时间了,我抢了靠前的位置,哈哈,板凳学习 源码。。。。。。。 昨晚忘传代码了,不好意思,现在已经补上了!!! 好! dddddddddddd 程序的基本操作,是从51中移植过来的,感谢原作者!
程序还不是特别完善,请大家多提建议!
目前程序支持8bit并行和串行操作(串行不能读)
下一步看看手中的模块是否支持4bit并行,争取弄出来,继续公布源码! 无语,我发过两次ST7920芯片的程序,
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=3349967&bbs_page_no=1&search_mode=3&search_text=liudeee&bbs_id=9999
上面这个事第一发,有几处有问题。
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=3411711&bbs_page_no=1&search_mode=3&search_text=liudeee&bbs_id=9999
这个是后来修改又发的,
画线,画点,画圆,用绘图方法写任意大小的字体,函数都有,LZ怎么说没找到。无语,绝对方便在AVR上移植
同样是并行
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_456715.jpg
画图方法写任意大小字体 (原文件名:ourdev_445191.jpg) 真的没找到啊!在这个坛子就找了5、6个版本呢!呵呵,用搜索找的,大海捞针呢,不一定就捞得到想要的啊! 能否放出GUI里面的画点程序阿,为什么网上找的东西都是不完全的呢?
不过楼主的程序真漂亮,呵呵,我觉得用漂亮来形容比较合适.我现在写的东西还是很乱那,不过以后争取写得规范些. //**********************************************************
// 名称:GUI_Point(unsigned char y,unsigned char x,unsigned colour)
// 功能:在指定位置上画点。
// 入口参数:x 指定点所在行的位置
// y 指定点所在列的位置
// color 显示颜色(对于黑白色LCD12864,为0时灭,为1时显示)
// 出口参数:无
//**********************************************************
void GUI_Point(unsigned char y,unsigned char x,unsigned colour)
{
unsigned char GDRAM_hbit,GDRAM_lbit;
unsigned char x_Dyte,x_byte; //定义列地址的字节位,及在字节中的哪1位
unsigned char y_Dyte,y_byte;
x--;y--; //定义为上下两个屏(取值为0,1),行地址(取值为0~31)
/***X,Y坐标互换,即普通的X,Y坐标***/
x_Dyte=y/16; //计算在16个字节中的哪一个
x_byte=y&0x0f; //计算在该字节中的哪一位
y_Dyte=x/32; //0为上半屏,1为下半屏
y_byte=x&0x1f; //计算在0~31当中的哪一行
LCD12864_Write(COMMAND,0x80+y_byte); //设定行地址(y坐标)
LCD12864_Write(COMMAND,0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
LCD12864_Read();
GDRAM_hbit=LCD12864_Read(); //读取当前显示高8位数据
GDRAM_lbit=LCD12864_Read(); //读取当前显示低8位数据
Delay_nus(1);
if(colour==1)
{
LCD12864_Write(COMMAND,0x80+y_byte); //设定行地址(y坐标)
LCD12864_Write(COMMAND,0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
Delay_nus(1);
if(x_byte<8) //判断其在高8位,还是在低8位
{
LCD12864_Write(DATA,GDRAM_hbit|(0X01<<(7-x_byte))); //显示GDRAM区高8位数据
LCD12864_Write(DATA,GDRAM_lbit); //显示GDRAM区低8位数据
}
else
{
LCD12864_Write(DATA,GDRAM_hbit);
LCD12864_Write(DATA,GDRAM_lbit|(0x01<<(15-x_byte)));
}
}
else
{
LCD12864_Write(COMMAND,0x80+y_byte); //设定行地址(y坐标)
LCD12864_Write(COMMAND,0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
Delay_nus(1);
if(x_byte<8) //判断其在高8位,还是在低8位
{
LCD12864_Write(DATA,GDRAM_hbit & ~(0X01<<(7-x_byte))); //显示GDRAM区高8位数据
LCD12864_Write(DATA,GDRAM_lbit); //显示GDRAM区低8位数据
}
else
{
LCD12864_Write(DATA,GDRAM_hbit);
LCD12864_Write(DATA,GDRAM_lbit & ~(0x01<<(15-x_byte)));
}
}
}
/***********************************************************
* 名称:GUI_Line(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char colour)
* 功能:在指定位置上画线。
* 入口参数:x0 指定线起点所在行的位置
* y0 指定线起点所在列的位置
* x1 指定线终点所在行的位置
* y1 指定线终点所在列的位置
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
/**********************************************************/
void GUI_Line(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char colour)
{
int temp;
int dx,dy; //定义起点到终点的横、纵坐标增加值
int s1,s2,status,i;
int Dx,Dy,sub;
dx = x1 - x0;
if(dx >= 0) //X的方向是增加的
s1 = 1;
else //X的方向是降低的
s1 = -1;
dy = y1 - y0; //判断Y的方向是增加还是降到的
if(dy >= 0)
s2 = 1;
else
s2 =- 1;
Dx = abs(x1-x0); //计算横、纵标志增加值的绝对值
Dy = abs(y1-y0);
if(Dy > Dx)
{ //以45度角为分界线,靠进Y轴是status=1,靠近X轴是status=0
temp = Dx;
Dx = Dy;
Dy = temp;
status = 1;
}
else
status = 0;
/*********Bresenham算法画任意两点间的直线********/
sub = Dy + Dy - Dx; //第1次判断下个点的位置
for(i = 0;i < Dx;i ++)
{
GUI_Point(x0,y0,colour); //画点
if(sub >= 0)
{
if(status == 1) //在靠近Y轴区,x值加1
x0 += s1;
else //在靠近X轴区,y值加1
y0 += s2;
sub -= (Dx + Dx); //判断下下个点的位置
}
if(status == 1)
y0 += s2;
else
x0 += s1;
sub += Dy + Dy;
}
}
/****************************************************************************
* 名称:plotC(int x,int y,int xc,int yc,unsigned char colour)
* 功能:八分点画圆函数
* 入口参数:x 指定线起点所在行的位置
* y 指定线起点所在列的位置
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
****************************************************************************/
void plotC(int x,int y,int xc,int yc,unsigned char colour)
{
GUI_Point(xc+x,yc+y,colour);
GUI_Point(xc+x,yc-y,colour);
GUI_Point(xc-x,yc+y,colour);
GUI_Point(xc-x,yc-y,colour);
GUI_Point(xc+y,yc+x,colour);
GUI_Point(xc+y,yc-x,colour);
GUI_Point(xc-y,yc+x,colour);
GUI_Point(xc-y,yc-x,colour);
}
/****************************************************************************
* 名称:GUI_Circle(int xc,int yc,int r,unsigned char colour)
* 功能:画圆
* 入口参数:xc 圆心的行坐标
* yc 圆心的列坐标
* r 半径
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
****************************************************************************/
void GUI_Circle(int xc,int yc,int r,unsigned char colour)
{
int x,y,d;
y = r;
d = 3 - (r + r);
x = 0;
while(x <= y)
{
plotC(x,y,xc,yc,colour);
if(d < 0)
d += (x + x + x + x) + 6;
else
{
d+=((x - y) + (x - y) + (x - y) + (x - y)) + 10;
y = y - 1;
}
x = x + 1;
}
}
/****************************************************************************
* 名称:GUI_Full(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char colour)
* 功能:用绘图的方法填充一个矩形
* 入口参数:x0 起始点横坐标
* y0 起始点纵坐标
* x1 终止点横坐标
* y1 终止点纵坐标
* color 显示颜色(对于黑白色LCM,为0时灭,为1时显示)
* 出口参数:无
****************************************************************************/
void GUI_Full(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char colour)
{
unsigned char i,j;
for(j = y0;j <= y1;j ++)
for(i = x0;i <= x1;i ++)
GUI_Point(i,j,colour);
} //******************************************************************************
//*函数名称:void LCD_Point(unsigned char x,unsigned char y,unsigned char color)*
//*函数功能:使用绘图的方法,在(x,y)处画一个16*16点阵的图案,也可以是字符 *
//*形式参数:unsigned char x,unsigned char y,unsigned char color *
//* x取值范围:0~127 *
//* y取值范围:0~63 (针对CM12864-12型液晶) *
//*形参说明:坐标水平位置,坐标垂直位置 *
//*液晶屏坐标说明: *
//* ________________128个像素______________________ *
//* |(0,0) (7,0)| *
//* | | *
//* 64 | | *
//* 个 |(0,31) (7,31)| *
//* 像 |(8,0) (15,0)| *
//* 素 | | *
//* | | *
//* |(8,31) (15,31)| *
//* |______________________________________________| *
//* *
//*返回参数:无 *
//*使用说明:此函数适用于CM12864-12型液晶 *
//******************************************************************************
void LCD_Point(unsigned char x,unsigned char y,unsigned char color)
{
unsigned char i,AddrX,AddrY; //寄存器地址
unsigned char BitTemp; //该点在16bit的位置
unsigned char DataH,DataL;
AddrX = x>>4; // x/16
AddrY = y&0x3F; // y%64
if(y > 31)
{
AddrX += 8;
AddrY -= 32;
}
BitTemp = x&0x0F; // x%16
LCD_GraphModeSet(0x00); //先关闭图形显示功能
//LCD_Write(LCD_COMMAND,LCD_EXTEND_FUNCTION);
for(i=0;i<4;i++)
{
LCD_GDRAM_AddressSet(0x80+AddrY);
LCD_GDRAM_AddressSet(0x80+AddrX);
//LCD_Write(LCD_COMMAND,LCD_BASIC_FUNCTION); //基本指令集
DataH = LCD_ReadData();
DataH = LCD_ReadData();
DataL = LCD_ReadData();
//DataH = LCD_ReadData();
//DataL = LCD_ReadData();
}
if(color == LCD_COLOR_BLACK)
{
if(BitTemp > 7)
{
DataL |= (0x80>>(BitTemp-8));
}
else
{
DataH |= (0x80>>(BitTemp));
}
}
else
{
}
LCD_GDRAM_AddressSet(0x80+AddrY);
LCD_GDRAM_AddressSet(0x80+AddrX);
LCD_Write(LCD_DATA,DataH);
LCD_Write(LCD_DATA,DataL);
LCD_GraphModeSet(0x01); //最后打开图形显示功能
} 【11楼】 zhseedling
谬赞了!我写的一般,比起高手差很多啊!不过一直在学习呢! 我用楼主的程序写的,呵呵,研究了好多天呢,终于会用了。
我想用12864作为屏幕做魏坤示波器(本论坛里的开源项目)的屏,楼主有没有好建议啊
只是图片,没有实质的东西
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457519.jpg
(原文件名:1.jpg)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457520.jpg
(原文件名:2.jpg)
http://cache.amobbs.com/bbs_upload782111/files_16/ourdev_457521.jpg
(原文件名:3.jpg) 【15楼】 zhseedling
刚刚才用7920的LCD,是从一个一起上拆下的,呵呵!明天就要给人家装上了,要拿走!
所以就玩了这几天!
我的感觉如果显示图形,特别是需要频繁刷新图形(示波器恰恰如此),7920并不适合,因为他需要频繁的关闭显示,这样感觉闪烁,不如KS0108方便!7920更适合显示字符!
以上愚见,请高手指正! 为了这个示波器,12864已经是我买的第二个屏了,之前买了一个320240的tft,hx8347主控的,也研究了好些天,首先是没资料,后来东凑西凑的终于找到一些资料,可始终点不亮那个屏,没办法,才买了12864,后来才发现,12864画图可真够费劲的了 如果做示波器还是320240比较好,分辨率高,27元那个液晶就不错,有驱动和示例代码,好像没有资料!现在好像35元了!
在 淘宝超值推荐论坛有他的连接,你可以看看! 能留下联系方式么?
hfd2k@qq.com
根据你的程序改写后,画长的斜线是一节一节的。
垂线和水平线就没问题 很好!
标记! 哇。。。。帅气。。。。。。。。。。。 楼主 我怎么把你的程序复制到我的界面下 怎么好多错误的呀我用的CVAVR 可以把你的源程序 给我看看嘛?我的QQ 619089960 谢了
zhseedling你是怎么移植的呀?你用的什么编译软件? 【19楼】 hfd999
估计是读数据有问题!
我的EMAIL:jackielau1980@sohu.com
欢迎交流,最近在外地!
【22楼】 wuyuwuqi
当然了我用的GCC,呵呵看看什么错误,改改就好了
我不懂CVAVR啊 头文件看了一下,好像原有的设计应该是并行、串行都可以用的,不知为什么串行的没用出来,那我就花点功夫看看并行的吧。 好东西,留名 mark一个,回头继续看 【24楼】 haozi_1989
本来打算把串行的弄出来,但是手上LCD拿走了,再加上最近出差没空,也就一直没写!!
这个控制器有个缺点,就是串行不能读操作,这样花点画线就很难实现,(除非在RAM中开辟一块1024B的缓存,我用的M16,好像只有1KRAM,所以比较难实现了),所以就尽头不大了!! 通用24CXXX读写程序(GCC),兼容24C系列存储器(24C01到24C1024),支持跨器件跨页读写,支持连续读写32K字节
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3444492&bbs_page_no=1&search_mode=3&search_text=jackielau&bbs_id=9999
也是我也写的,呵呵,欢迎提出意见 同文件兼顾了串行和并行两种方式,但是发的好像有问题,头文件里的函数和测试程序里的好像不匹配,不知是何原因 【29楼】 haozi_1989
呵呵,找到问题了,你看的是main。c,测试程序不是这个文件!!是OM_test.c.c
重新上传!!!
点击此处下载 ourdev_462016.rar(文件大小:421K) (原文件名:ourdev_456695.rar) 受教了! jihao 字符汉字显示用7920很方便,但是画图还是KS0108的感觉好一些 我的7920屏有个问题:一进入图形模式就花屏(黑白点乱乱的),害得我每次都要全屏写零一次。不知道是啥原因?
请高手帮忙找找原因。 mark! 【35楼】 vipxuliang
应该是屏RAM数据没有全部变零。你的是不是有大电容或者掉电时间很多才出啊?关机很长时间也出这个问题吗?
另外,我觉得开机对屏RAM清零是必要的! 记号 我用楼主的程序,怎么画一条竖线时会同时出现三条竖线呢?环境:M16,studio 4.16,(GCC)WinAVR-20080610,金鹏OCMJ4X8C型12864液晶,一直没搞明白哪地方错了,希望楼主能帮忙看一下...本人在校生...QQ:897772871,同时欢迎各位朋友加友交流,注明avr论坛...
程序自己稍稍改了一下,如下:
#include<avr/io.h>
#include<delay.h>
#include<math.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define CTRL_PORTPORTA
#define CTRL_DDRDDRA
#define CTRL_PINPINA
#define RS 5 //CS 第四引脚
#define RW 6 //SIO第五引脚
#define E7 //SCK第六引脚
#define DATA_DDR DDRD
#define DATA_PIN PIND
#define DATA_PORT PORTD
#define CTRL_OUT() CTRL_DDR |= (1<<(RS))|(1<<(RW))|(1<<(E))
#defineCLR_RS() CTRL_PORT &= ~(1<<RS)
#defineSET_RS() CTRL_PORT |= (1<<RS)
#define CLR_RW() CTRL_PORT &= ~(1<<RW)
#define SET_RW() CTRL_PORT |= (1<<RW)
#define CLR_E()CTRL_PORT &= ~(1<<E)
#define SET_E() CTRL_PORT |= (1<<E)
#define DATA_IN() DATA_DDR &= ~0xFF
#define DATA_OUT() DATA_DDR |= 0xFF
#define DATA_GET() DATA_PIN
//液晶基本参数
#define X_MAX 127
#define Y_MAX 63
//每行的首地址
#define ONE 0x80
#define TWO 0x90
#define THREE 0x88
#define FOUR0x98
//基本指令集预定义
#define DATA 1 //数据位
#define COMMAND 0 //命令位
#define CLEAR_SCREEN 0x01 //清屏
#define ADDRESS_RESET 0x02 //地址归零
#define BASIC_FUNCTION 0x30 //基本指令集
#define EXTEND_FUNCTION 0x34 //扩充指令集
//扩展指令集预定义
#define AWAIT_MODE 0x01 //待命模式
#define ROLLADDRESS_ON 0x03 //允许输入垂直卷动地址
#define IRAMADDRESS_ON 0x02 //允许输入IRAM地址
#define SLEEP_MODE 0x08 //进入睡眠模式
#define NO_SLEEP_MODE 0x0c //脱离睡眠模式
#define GRAPH_ON 0x36 //打开绘图模式
#define GRAPH_OFF 0x34 //关闭绘图模式
#ifndef COLOR
#define BLACK 1
#define WHITE 0
#endif
void SendByte(unsigned char a)
{
unsigned char i,d;
SET_RS();
CLR_RW();
for(i=0;i<8;i++)
{
CLR_E(); //clrbit(LCD_CTRL,E);
d = a&0x80;
if(d)
SET_RW(); //setbit(LCD_CTRL,RW);
else
CLR_RW(); //clrbit(LCD_CTRL,RW);
a<<=1;
SET_E(); //setbit(LCD_CTRL,E); //上升弦发送
}
CLR_RS();
}
void CheckBusy(void)
{
unsigned char temp;
DATA_IN();
CLR_RS(); //RS = 0;指令
SET_RW(); //RW = 1;读模式
delay3us(); //延时
delay3us(); //延时
SET_E(); //E= 1,使能
do
{
temp = DATA_GET(); //temp = BUSY;
}
while( 0x80==(temp&0x80) ); //等待不忙,temp=0x00时不忙
CLR_E(); //E= 0;
}
void Write( unsigned char Data_Command , unsigned char uc_Content )
{
CheckBusy();
DATA_OUT();
if(Data_Command==COMMAND)
{
CLR_RS(); //RS = 0;指令
}
else
{
SET_RS(); //RS = 1; 数据
}
CLR_RW(); //RW = 0; //写模式
DATA_PORT = uc_Content;
SET_E(); //E = 1;
delay3us(); //延时
CLR_E(); //E = 0;
}
unsigned char ReadData(void)
{
unsigned char uc_Content;
CheckBusy();
DATA_PORT = 0xff ;
DATA_IN(); //P1 = 0xff;//输入前置1
SET_RS(); //RS = 1; //数据
SET_RW(); //RW = 1; //读模式
SET_E(); //E = 1; //使能
delay3us(); //延时很重要
uc_Content = DATA_GET(); //uc_Content = P1; //P1口的内容放到变量中
CLR_E(); //E = 0;
delay3us(); //延时很重要
return uc_Content;
}
void DDRAM_AddressSet(unsigned char ucDDramAdd)
{
Write(COMMAND,BASIC_FUNCTION); //基本指令集
Write(COMMAND,ucDDramAdd); //设定DDRAM地址到地址计数器AC
}
void CGRAM_AddressSet(unsigned char ucCGramAdd)
{
Write(COMMAND,BASIC_FUNCTION); //基本指令集
Write(COMMAND,ucCGramAdd); //设定CGRAM地址到地址计数器AC
}
void GDRAM_AddressSet(unsigned char ucGDramAdd)
{
Write(COMMAND,EXTEND_FUNCTION); //扩展指令集
Write(COMMAND,ucGDramAdd);
}
void Init(void)
{
CTRL_OUT();
Write(COMMAND,BASIC_FUNCTION); //基本指令动作
delay50us();
Write(COMMAND,CLEAR_SCREEN); //清屏,地址指针指向00H
delay50us();
Write(COMMAND,0x06); //光标的移动方向
delay50us();
Write(COMMAND,0x0C); //开显示,关游标
}
void ClearRam(void)
{
Write(COMMAND,BASIC_FUNCTION); //基本指令集
Write(COMMAND,CLEAR_SCREEN); //清屏
}
void GraphModeSet(unsigned char Select)
{
Write(COMMAND,EXTEND_FUNCTION); //扩展指令集
if(Select==1)
{
Write(COMMAND,GRAPH_ON); //打开绘图模式
}
else
{
Write(COMMAND,GRAPH_OFF); //关闭绘图模式
}
}
void DisplayCLR()
{
unsigned char i,j;
GraphModeSet(0); //先关闭图形显示功能
for(j=0;j<32;j++)
{
for(i=0;i<8;i++)
{
Write(COMMAND,0x80+j); //设定垂直坐标
Write(COMMAND,0x80+i); //设定水平坐标
Write(DATA,0x00); //放入数据高字节
Write(DATA,0x00); //放入数据低字节
}
}
for(j=32;j<64;j++)
{
for(i=0;i<8;i++)
{
Write(COMMAND,0x80+j-32);
Write(COMMAND,0x88+i);
Write(DATA,0x00);
Write(DATA,0x00);
}
}
GraphModeSet(1);//最后打开图形显示功能
}
void LCD_Point(unsigned char x,unsigned char y,unsigned char color)
{
unsigned char i,AddrX,AddrY; //寄存器地址
unsigned char BitTemp; //该点在16bit的位置
unsigned char DataH,DataL;
AddrX = x>>4; // x/16
AddrY = y&0x3F; // y%64
if(y > 31)
{
AddrX += 8;
AddrY -= 32;
}
BitTemp = x&0x0F; // x%16
GraphModeSet(0x00); //先关闭图形显示功能
for(i=0;i<4;i++)
{
GDRAM_AddressSet(0x80+AddrY);
GDRAM_AddressSet(0x80+AddrX);
DataH = ReadData();
DataH = ReadData();
DataL = ReadData();
}
if(color == BLACK)
{
if(BitTemp > 7)
{
DataL |= (0x80>>(BitTemp-8));
}
else
{
DataH |= (0x80>>(BitTemp));
}
}
else
{
}
GDRAM_AddressSet(0x80+AddrY);
GDRAM_AddressSet(0x80+AddrX);
Write(DATA,DataH);
Write(DATA,DataL);
GraphModeSet(0x01); //最后打开图形显示功能
}
int main()
{
uchar i;
Init(); //液晶屏初始化
ClearRam(); //清除显示存储区内的内容
DisplayCLR();
for(i=0;i<50;i++)
{
LCD_Point(0,i,1);
}
} 先做个记号,,,,, 【39楼】 coolc : ReadData 有错哦~
unsigned char ReadData(void)
{
unsigned char uc_Content;
CheckBusy();
/*!!*/
DATA_PORT = 0xff ; /*!!*/
/*!!*/
DATA_IN(); //P1 = 0xff;//输入前置1
SET_RS(); //RS = 1; //数据
SET_RW(); //RW = 1; //读模式
SET_E(); //E = 1; //使能
delay3us(); //延时很重要
uc_Content = DATA_GET(); //uc_Content = P1; //P1口的内容放到变量中
CLR_E(); //E = 0;
delay3us(); //延时很重要
return uc_Content;
}
应改为
unsigned char ReadData(void)
{
unsigned char uc_Content;
CheckBusy();
DATA_IN(); //P1设置为输入
DATA_IN();
SET_RS(); //RS = 1; //数据
SET_RW(); //RW = 1; //读模式
SET_E(); //E = 1; //使能
delay3us(); //延时很重要
uc_Content = DATA_GET(); //uc_Content = P1; //P1口的内容放到变量中
CLR_E(); //E = 0;
delay3us(); //延时很重要
DATA_OUT(); //P1设置为输出
return uc_Content;
} 谢了!!楼上的,这个地方确实有点问题,但是我改过了,还是在(0,0)写一点在其后又出现两点,画一条竖线出现三条竖线的情况啊!!附上12864连接图,PSB接的是高电平,不会是连接的问题或是液晶屏的问题吧....
还有楼主的程序:这里为什么要循环读四次呢?
for(i=0;i<4;i++)
{
GDRAM_AddressSet(0x80+AddrY);
GDRAM_AddressSet(0x80+AddrX);
DataH = ReadData();
DataH = ReadData();
DataL = ReadData();
}
http://cache.amobbs.com/bbs_upload782111/files_17/ourdev_466339.jpg
(原文件名:12864.jpg) mark 【42楼】 coolc
那个实在最初试验时加的,当时没有明白“假读”,用多循环几次解决问题!现在说应该是没用的
“在(0,0)写一点在其后又出现两点,画一条竖线出现三条竖线的情况”
估计是读数据出的问题,画点需要读数据,如果有足够的RAM,建议不用他,在RAM建立镜像BUF ..嗯 不错 学习了 谢谢啊 【42楼】 coolc
那个实在最初试验时加的,当时没有明白“假读”,用多循环几次解决问题!现在说应该是没用的
“在(0,0)写一点在其后又出现两点,画一条竖线出现三条竖线的情况”
估计是读数据出的问题,画点需要读数据,如果有足够的RAM,建议不用他,在RAM建立镜像BUF
我也出现类似的问题,读数据出现什么问题了,能否具体说明!!!!!!!! //读数据
unsigned char Lcd_Readdata()
{
idata uchar dudata ;
wait();
RS=1;
RW=1;
E=0;
delay_us(1);
dudata=LcdData;
E=1;
delay_us(1);
E=0;
return dudata;
}
void GUI_Point(uchar x,uchar y)
{
uchar x_Dyte,x_byte; //定义列地址的字节位,及在字节中的哪1位
uchar y_Dyte,y_byte;//定义为上下两个屏(取值为0,1),行地址(取值为0~31)
uchar GDRAM_hbit,GDRAM_lbit;
/***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当中的哪一行
Lcd_WriteCmd(0x36); //绘图模式命令
Lcd_WriteCmd(0x80+y_byte);//设定行地址(y坐标)
Lcd_WriteCmd(0x80+x_Dyte+8*y_Dyte);//设定列地址(x坐标),并通过8*y_Dyte选定上下屏
Lcd_Readdata();
GDRAM_hbit=Lcd_Readdata();
GDRAM_lbit=Lcd_Readdata();
Lcd_WriteCmd(0x80+y_byte);//设定行地址(y坐标)
Lcd_WriteCmd(0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏
if(x_byte<8)//判断其在高8位,还是在低8位
{
Lcd_Writedata(GDRAM_hbit|(0X01<<(7-x_byte))); //显示GDRAM区高8位数据
Lcd_Writedata(GDRAM_lbit); //显示GDRAM区低8位数据
}
else
{
Lcd_Writedata(GDRAM_hbit);
Lcd_Writedata(GDRAM_lbit|(0x01<<(15-x_byte)));
}
Lcd_WriteCmd(0x30);
}
这是我的画点函数,用的是12楼的程序,不知哪里有错啊!!!!!知道的兄弟请指点!!!!! 【49楼】 jiang0603
读函数错了,首先读时序就错了,
应该是置位E再读延时后E清零
还有如果是AVR等真正双向I/O口(51是伪双向的)LcdData的方向要改为输入 我试过这种写法,用的是STC的51单片机
//读数据
unsigned char Lcd_Readdata()
{
idata uchar dudata ;
wait();//判忙
RS=1;
RW=1;
E=1;
delay_us(1);
dudata=LcdData;
delay_us(1);
E=0;
return dudata;
}
但问题还是没有解决啊!!!!!! 好东西 ,谢谢 【51楼】 jiang0603
你问题是什么啊??现象呢 现象是:不能写直线,写直线时二个字节只能写一个点,写斜线和竖线没问题,所以我觉得问题应该是没有把上一次的数据给读会来!!
不知道各位高手有没其它意见啊!!!!! ps:
也就是这里:
Lcd_Readdata();
GDRAM_hbit=Lcd_Readdata();
GDRAM_lbit=Lcd_Readdata(); 用过 顶个 好东西,留名 【54楼】 jiang0603
从现象上看,应该是读数据有问题!
你可以具体试一试,比如向某一位置写入数据(例如0x55),然后读出看看还是不是这个值啊?!
你说的问题,没出现,试了多次!可能器件不同有点差别! jiang0603,我的也是这样,“写直线时二个字节只能写一个点,写斜线和竖线没问题”
不知道你的问题解决了没有哇? 为什么水平画线就会出现 一个字只能显示一个点?而竖直画线也只能在特定的列画出来。有没有高手指点下? 十五楼你好。请问你现在示波器做怎么样了?我也在也做。遇到点问题。可以交流下吗? jiang0603,我的也是这样,“写直线时二个字节只能写一个点,写斜线和竖线没问题”
不知道你的问题解决了没有哇?
问题已经发现了,确实出现在读数据上面啊!!!!把我的对数据函数贴出来你看看:
//读数据
unsigned char Lcd_Readdata()
{
idata uchar dudata ;
wait();
LcdData=0xff;//关键!!!!! 就是要加这一句就ok了!!!!!!!!!!
RS=1;
RW=1;
E=1;
delay_us(1) ;
dudata=LcdData;
E=0;
return dudata;
} 【62楼】 jiang0603
你用的不是AVR?是51吗?? 用的不是avr单片机,用的是51(stc) 【64楼】 jiang0603
知道了,51的IO口做输入时,必须输出高,它没有IO方向控制!呵呵,我一直以为用的AVR呢! 标个记 很好 很强大 先标记一个!以后肯定用的着! 鱼和熊掌不能兼得,我用串行弄了半天却发现串行不能读数据。得买个可位操作的液晶。 【69楼】 hxjsini 似泥
呵呵,这也是我为什么不在更新程序了!!
7920这个片子不咋地,所以写着没劲了! 真棒 我正需要 谢谢楼主 共享 好贴啊.这几天正在做12864相关的实验....
谢谢LZ共享 MARK mark mark mark~ mark~ mark mark mark。 thanks 。 mark mark 回复【12楼】liudeee 小菜
-----------------------------------------------------------------------
我想请教下:Dx = abs(x1-x0); //计算横、纵标志增加值的绝对值 次句中abs是什么意思?????
新手来着!!! mark mark 一年了。很有用,适合于金鹏的12864OCMJ4X8C,套用楼主程序,文字,图片都可以,就是画点是出现花屏,点已经画上去了就是花屏,不知什么原因。 我以前写过12864的驱动,觉得很奇怪,如果显示一小块图形的时候,其它的地方就是花的,害我一次就得刷整块屏,
楼主有没有写过TFT的,最近写一块2.6"的TFT,几天过去了,还没初始化, 回复【88楼】AAVVRR
一年了。很有用,适合于金鹏的12864ocmj4x8c,套用楼主程序,文字,图片都可以,就是画点是出现花屏,点已经画上去了就是花屏,不知什么原因。
-----------------------------------------------------------------------
估计是读屏幕数据时有问题 好像mark过 mark 多谢 多谢!! 谢谢 我很汗用了串行方式 难怪测试了这么多次 就是读不出来,还准备加上周立功的gui了,看来 要改改了 mark,谢谢了 收藏了,正想画圆呢。 很好 学习了... mark MARK mark 请问楼主 怎么会出现这样的提示信息
Build started 17.11.2010 at 22:21:57
0 sh.exe" 3264 fork_copy: user/cygwin data pass 0 failed, 0x46F000..0x474434, done 1776, windows pid 2400, Win32 error 5
"D:/Program Files/WinAVR-20090313/utils/bin/sh.exe": fork: Resource temporarily unavailable
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex OM_test.elf OM_test.eep || exit 0
0 sh.exe" 1824 fork_copy: user/cygwin data pass 0 failed, 0x46F000..0x474434, done 1784, windows pid 3816, Win32 error 5
"D:/Program Files/WinAVR-20090313/utils/bin/sh.exe": fork: Resource temporarily unavailable
make: Error 128 (ignored)
avr-objdump -h -S OM_test.elf > OM_test.lss
0 sh.exe" 1252 fork_copy: user/cygwin data pass 0 failed, 0x46F000..0x474434, done 1784, windows pid 1364, Win32 error 5
"D:/Program Files/WinAVR-20090313/utils/bin/sh.exe": fork: Resource temporarily unavailable
make: *** Error 128
Build failed with 1 errors and 0 warnings...
页:
[1]
2