//****************** bravey ************11.27
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit en=P2^7 //这些管乱蚂岁脚要看原理图的,或许我的单片机和你的不一样。
sbit rs=P2^6
sbit rw=P2^5
uchar code d1[]={填入你要现实的字的码值,用取模软件 };
uchar code d2[]={填入你要现实的字的码值,用取模软件 };
void delay(uint z)//延迟函数
{
uint x,y
for(x=zx>0x--)
for(y=0y<哗睁110y++)
}
void write_com(uchar com) //送地址函数定义
{
rs=0
rw=0
P0=com
delay(5)
en=1
delay(5)
en=0
}
void write_datt(uchar datt) //送数据
{
rs=1
rw=0
P0=datt
delay(5)
en=1
delay(5)
en=0
}
void lcd_init() //初始化
{
en=0
write_com(0x0c)//整体显示,无光标,不反白
write_com(0x07)//地址指针加一设置,且整体左移
write_com(0x01)//清屏
}
void main()
{
uchar i
lcd_init()
write_com(0x80)//地址指针初始化,第一行显示拼音名字
for(i=0i<13i++)
{
write_datt(d1[i])
delay(20)
}
write_com(0x90)
for(i=0i<9i++)
{
write_datt(d1[i])//物册高位
write_datt(d2[i])//低位
delay(20)
}
while(1)
}
这是一个简单的12864显示字的程序。LZ可以参考参考
我仿真过。proteus里AMPIRE 128x64器件。它是最基本的12864了亮猜银,基本控制指令就行。比实物要简单。网络上有个“大海橡树”的,他写了比较详细的关于它的教程。你可以找找。//************************************************************
#define P0Data P0 //宏定义所接的数据端口,方便移植
sbit RS=P2^0 //程序数据存储器选择:=0是程序存储器,=1是数据存储器
sbit RW=P2^1 //读写控制选择:=0是写,=1是读
sbit E=P2^2//使能,初端口初始化外,在写指令数据前都要检测busy标志。
sbit CS1=P2^3 //敬宴选中显示的芯片
sbit CS2=P2^4 //64x64一块,总共左右两片
#define AddressX 0xb8//定义第0行
#define AddressY 0x40//定义第0列
//************************************************************
static void Delay1ms(uchar x)
static void LcdWriteComOrData(uchar x,uchar content)//写指令或写数据
static void LcdReadComBusy(void)//读指令,读数据没有用到,所以只是读指令中的忙标志
static void ShowPicture(uchar (*p)[64])//显示图片
static void ShowChar(uchar p[][8][8]) //显示全屏字符
static void ShowCharPage(uchar page,uchar p[2][8][8]) //输出单行的一串字符
static void ShowChinaChar(uchar x,uchar page,uchar range,uchar p[2][16]) //输出一个汉字
static void ShowChinaSinger(uchar p[2][16])
static void ShowChina32(uchar p[4][8][2][16]) //满屏全32个汉字
//************************************************************
void _L12864Init(void) //用proteus仿真只用基本的7条指令
{
/* 这段不需要,因为仿真用基本兆中7条指令,而实际模块初始化要根据厂商提供的初始化规范做
uchar i
for(i=0i<5i++)
{
P0Data=0x30 //入口是8位接口,12864只能是8位的,不像L1602有四位的选择RE=0(右起第2位),选择基本指令集,扩充指令不用。
RS=0
RW=0
E=1//设置开始,至少450ns,执行指令时间差不多够了。
E=0 //设置结束
Delay1ms(3)//要求延时,这个延时比一般指令延时要长. 这里延时之前不要设置,防止中断打断设置
}
*/
LcdWriteComOrData(0,0x3f)//显示开
LcdWriteComOrData(0,0xc0)//定义起始行,这个指上下的64行从哪行开始,一般是0,有规律改变它,可以实现滚屏
ShowPicture(TabPicture0)
ShowChar(TabChar)
ShowCharPage(6,TabCharPageX)
ShowChinaChar(2,4,4,TabPicture0)
ShowChinaSinger(TabPicture0)
ShowChina32(TabChina32)
}
//************************************************************
//满屏输出4行*8个共32个汉字
static void ShowChina32(uchar p[4][8][2][16])//这里把入口指针直接写明需要32个汉字
{
uchar i,j,k
for(k=0k<4k++)//总共四行汉字
{
CS1=0CS2=1 //选中左半屏
for(i=0i<4i++)
{
LcdWriteComOrData(0,AddressX|(k<<1))
LcdWriteComOrData(0,AddressY|(i<<4))
for(j=0j<16j++)
LcdWriteComOrData(1, p[k][i][0][j] )
LcdWriteComOrData(0,AddressX|(k<<1)+1)
LcdWriteComOrData(0,AddressY|(i<<4))
for(j=0j<16j++)
LcdWriteComOrData(1, p[k][i][1][j] )
}
CS1=1CS2=0//选中右半屏
for(i=5i<9i++)
{
LcdWriteComOrData(0,AddressX|(k<<1))
LcdWriteComOrData(0,AddressY|((i-4)<<4))
for(j=0j<16j++)
LcdWriteComOrData(1, p[k][i][0][j] )
LcdWriteComOrData(0,AddressX|(k<<1)+1)
LcdWriteComOrData(0,AddressY|((i-4)<<4))
for(j=0j<16j++)
LcdWriteComOrData(1, p[k][i][1][j] )
}
}
}
//************************************************************
//在左上角显示一个汉字
static void ShowChinaSinger(uchar p[2][16])
{
uchar j
CS1=0CS2=1
LcdWriteComOrData(0,AddressX) //页决定,这里决定这个汉字是在那一页显示,这里移1位的意思是,让方块汉字开始显示在偶数页上。
LcdWriteComOrData(0,AddressY)
for(j=0j<16j++) //输出每个汉字组成的上16个字节,下面一半显示下一页
LcdWriteComOrData(1, p[0][j] )
LcdWriteComOrData(0,AddressX|1) //页决定,这里决定这个汉字是在那一页显示,这里移1位的意思是,让方块汉字开始显示在偶数页上。
LcdWriteComOrData(0,AddressY)
for(j=0j<16j++) //输出每个汉字组成的上16个字节,下面一半显示下一页
LcdWriteComOrData(1, p[1][j] )
}
//************************************************************
//在任意屏页列输出单个汉字。
static void ShowChinaChar(uchar x,uchar page,uchar range,uchar (*p)[16]) //输出一个汉字
{ //字符来自于一个二维数值,参数分别是屏选1~2,汉字行选1~4(总共能显示四行汉字),列选1~4,半屏一页能显示四个汉字
uchar j
x--,page--range--//把屏选、行、列习惯转为计算方式
switch(x) //x决定输出的汉字在左半屏还是右半屏,0表示左半屏,1表示右半屏
{
case 0: CS1=0CS2=1break
case 1: CS1=1CS2=0break
default:
}
LcdWriteComOrData(0,AddressX|(page<<1) ) //页决定,这里决定这个汉字是在那一页显示,这里移1位的意思是,让方块汉字开始显示在偶数页上。
LcdWriteComOrData(0,AddressY|(range<<4) )//列决定,这里决定这个汉字开始在那一列显示。每16列一个位置,所以左移动4位。
for(j=0j<16j++) //输出每个汉字组成的上16个字节,下面一半显示下一页
LcdWriteComOrData(1, p[0][j] )
LcdWriteComOrData(0,AddressX|(page<<1)+1)
LcdWriteComOrData(0,AddressY|(range<<4) )
for(j=0j<16j++) //输出每个汉字组成的上16个字节,下面一半显示下一页
LcdWriteComOrData(1, p[1][j] ) //注意这里如果写成指针形式*(p+1)[j]不等于p[1][j],通过*和[]的互换,得到*(*(p+1)+j)才是p[1][j]。
}
//************************************************************
//输出某一页(左半屏+右半屏)字符,字符来自于一个三维数值
static void ShowCharPage(uchar page,uchar p[2][8][8]) //以三维数组的形式输出所有的字符
{
uchar i,j
page--//把习惯改为计算方式
CS1=0CS2=1
LcdWriteComOrData(0,AddressX|page)
LcdWriteComOrData(0,AddressY) //列数值清零
for(i=0i<8i++)
for(j=0j<8j++) //输出每个字符组成的8个字节,横向的右半屏在下一组,所以这里k每次乘2
LcdWriteComOrData(1, p[0][i][j] )
CS1=1CS2=0 //输出右半屏8个字符
LcdWriteComOrData(0,AddressX|page) //这行指令不能省,X地址寄存器在片选后是另一个HD61202的x寄存器
LcdWriteComOrData(0,AddressY)
for(i=0i<8i++)
for(j=0j<8j++)
LcdWriteComOrData(1, p[1][i][j] )//这里重点说明下,取模工具取数是纵向到底的
}
//************************************************************
//逐页横向显示字符,修改后也试用于更大屏幕
static void ShowChar(uchar p[][8][8]) //以三维数组的形式输出所有的字符
{ //一维是8位字节,二维是8个8位字节组成一个字符,三维是8个字符组成的半屏的一页。
uchar i,j,k //显示128x64屏幕就是有16块这样的8个一组的字符串,
for(k=0k<8k++) //而192x64的屏幕有24个这样的8个一组的字符串
{ //这里k<8,不能写成k<16,k是页值,用页值来访问不同的三维数组的,下面k<<1就是这个意思
CS1=0CS2=1 //输出左半屏8个字符
LcdWriteComOrData(0,AddressX|k)//行的改写不能太远,因为下次读写数据才修改页地址.
LcdWriteComOrData(0,AddressY) //列数值清零
for(i=0i<8i++)
for(j=0j<8j++) //输出每个字符组成的8个字节,横向的右半屏在下一组,所以这里k每次乘2
LcdWriteComOrData(1, p[k<<1][i][j] )
CS1=1CS2=0 //输出右半屏8个字符
LcdWriteComOrData(0,AddressX|k)
LcdWriteComOrData(0,AddressY)
for(i=0i<8i++)
for(j=0j<8j++)
LcdWriteComOrData(1, p[(k<<1)+1][i][j] )//这里重点说明下,取模工具取数是纵向到底的
} //因此这里上一块8个字符完了,就是右半屏的一块字符,因此这里三维k值加1
}
//************************************************************
//左右半屏方式,显示图像
static void ShowPicture(uchar (*p)[64])//显示一张图片,因为图片是没有字符那样的局部空间,一个整体
{ //显示一页就是64列,这里64是二维数组的第二维是64
uchar i,j
CS1=0CS2=1//显示左半屏
for(i=0i<8i++)
{
LcdWriteComOrData(0,AddressX|i) //确定要显示的页
LcdWriteComOrData(0,AddressY) //确定要显示的初始列,不能丢,很重要
for(j=0j<64j++)
LcdWriteComOrData(1, p[i<<1][j] )//把i*2变成i<<1,乘法变成移位
}
CS1=1CS2=0 //换右半屏显示
for(i=0i<8i++)
{
LcdWriteComOrData(0,AddressX|i) //page还从第0行开始
LcdWriteComOrData(0,AddressY)
for(j=0j<64j++)
LcdWriteComOrData(1, p[(i<<1)+1][j])
}
}
//***********************************************************
static void LcdWriteComOrData(uchar x,uchar content)
{
LcdReadComBusy()//检测忙标志
P0Data=content
E=0 //按照HD44780/KS0066控制器的脉冲时序走
if(x==0){RS=0RW=0} //如果是0,选址程序寄存器写;这种程序结构来自于金鹏LCD
else{RS=1RW=0} //如果是1,选择数据寄存器写
E=1
Delay1ms(1) //写程寄存器需要一段延时,执行也有延时。因为控制字写入之后,查书发现,执行至少需要40us,如果在E=1和0之间没有延时,程序不执行
E=0 //这行和上一行Delay1ms(1)交换后,发现检测不到了,原因就是以上的延时问题。
}
//************************************************************
static void LcdReadComBusy(void) //这种程序结构来自于网友大海橡树的程序
{
P0Data=0 //准备读忙标志,用的是P0口,所以可以直接放低就可以了,如果用其他口,Px不能直接写0,必须先写1才能读入外部信息
RS=0//选择程序寄存器
RW=1//读
E=1//使能打开
while( P0Data &0x80 )//如果是忙P0data与0x80就不等于0,所以while语句总是执行。
E=0//使能关闭
}
//***********************************************************
//功能:12MHz下延时1ms标准程序,延时时间为 1ms*x,
//输入:x 最大为255,即最大范围255ms
static void Delay1ms(uchar x)
{
uchar i,j
for(i=0i<xi++)
for(j=0j<=161j++)
}
//***********************************************************
上面是我写的驱动,你可以直接用。很久以前写的,现在再看了我自己写得太繁杂了,太啰嗦了。没必要,你可以在看懂的基础优化一下。采用的模块化编程,因此您建一个*.h文件再使用它比较好。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)