求一个12864的测试程序。单片机是89C52RC型号的,显示屏是FM-12864M-12L型号的。

求一个12864的测试程序。单片机是89C52RC型号的,显示屏是FM-12864M-12L型号的。,第1张

//*****1062液晶双行显示

//****************** 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文件再使用它比较好。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12447527.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存