返回介绍

实验九 TMS320LF2407 与图形液晶显示模块接口及应用

发布于 2023-05-14 20:35:30 字数 38534 浏览 0 评论 0 收藏 0

一.实验说明

LCD 液晶显示具有低功耗、体积小、重量轻、超薄等诸多其它显示器无法比拟的优点,其应用领域特别广泛,从袖珍仪表到便携微型计算机,几乎随处可见。点阵图形式LCD不仅可以显示字符、数字,还可以显示各种图形、曲线及汉字,并且显示自由度大,可以实现屏幕上下左右滚动、动画功能、分区开窗口、反转、闪烁、文本特征显示等功能。

本实验选用的MG-12232液晶显示模块,其背面带有控制电路,上面有专门的IC来完成LCD的工作。实验时在设计的接口电路中,只要在硬件上满足LCD的接口要求,只要输入适当的命令代码和需要显示的数据,LCD便会将其信息显示出来,在程序控制上非常方便。

液晶显示SED1520F0A驱动器作为DSP与LCD之间的接口芯片。SED1520F0A是属行列驱动及控制合一的小规模液晶显示驱动芯片,装配在图形液晶显示模块上,以内藏式图形液晶模块的形式出现,内含振荡器,只需外接振荡电阻即可工作,它与DSP的接口信号为:

•DB0—DB7:数据总线。

•A0 :数据/指令选择信号。A0=1表示出现在数据总线上的是数据,A0=0表示出现在数据总线上的是指令或读出的状态。

:接口时序类型选择。=1为M6800时序,操作信号是E、R/W,=0为Intel8080时序,操作信号是

(E):在Intel8080时序时为读,低电平有效; 在M6800时序时为使能信号,该信号是个正脉冲,在下降沿处为写操作,在高电平时为读操作。

(R/W):在Intel8080时序时为写,低电平有效; 在M6800时序时为读、写选择信号,R/W=1为读,R/W=0为写。

SED1520F0A与2种总线的接口信号和时序的详细资料见液晶显示模块使用手册。

MG-12232为图形点阵式液晶显示屏,内藏控制器,数据转移为8位形式,采用扫描驱动方式,带背光源,双列显示,共有18个引脚,分别定义如表9.1所示:

表9.1 MG-12232模块的引脚定义

序号

符号

状态

功能说明

1

VCC

-

逻辑电源正

2

GND

-

逻辑电源地

3

V0

-

液晶显示驱动电源

4

RES(_______)

-

接口时序类型选择

5

E1

输入

主工作方式IC使能信号

6

E2

输入

从工作方式IC使能信号

7

R/W

输入

读/写选择信号

8

A0

输入

寄存器选择信号

9~16

DB0~DB7

三态

数据总线(低位)

17

SLA

-

18

SLK

-

背光灯负电源

二.实验目的

1. 理解TMS320LF2407与液晶显示MG-12232模块接口电路的链接。

2. 了解软件设计中指令的应用与编程特点、操作时序,以及LCD程序用模块化编程的移植性。

三.实验内容

1.理解图9.1实验硬件的布线。

2.编写并调试一个程序,其功能为依次循环显示自己的学号和姓名。

四.实验硬件电路

图9.1为TMS320LF2407与MG-12232模块的硬件接口电路, 其接口控制时序采用了M6800操作时序,这样 SED1520F0A引出的控制信号R/W、A0、E1和E2由TMS320LF2407的I/O端口的4个脚控制。电阻R2用来驱动液晶的背光灯,其中DSP侧的引脚都设为I/O端口方式。由于TMS320LF2407的位操作指令丰富,所以用软件不难模拟出M6800操作时序。

图9.1 TMS320LF2407与MG-12232模块的接口电路

五.实验参考程序清单

1.接口软件编程

•SED1520F0A的指令集

SED1520F0A液晶显示驱动器有13条指令,以与M6800系列MPU接口为例(RES=1)总结这些指令如表9.2所示。

•MG-12232模块的编程

以图9.1的接口电路为例, 给出了LCD的初始化及显示程序,程序用模块化编程,具有很强的移植性。

表9.2 SED1520F0A的指令集

指令名称

控制信号

控制代码

R/W A0

D7 D6 D5 D4 D3 D2 D1 D0

显示开/关指令

0 0

1 0 1 0 1 1 1 1/0

显示起始行设置

0 0

1 1 0 显示起始行(0—31)

设置页地址

0 0

1 0 1 1 1 0 页地址(0-31)

设置列地址

0 0

0 列地址(0—79)

读状态指令

1 0

BUSY ADC OFF/ON RESET 0 0 0 0

写数据

0 1

显示的数据

读数据

1 1

显示的数据

ADC选择指令

0 0

1 0 1 0 0 0 0 0/1

静态驱动开/关

0 0

1 0 1 0 0 1 0 0/1

占空比选择

0 0

1 0 1 0 1 0 0 0/1

改写开始指令

0 0

1 1 1 0 0 0 0 0

改写结束指令

0 0

1 1 1 0 1 1 1 0

复位

0 0

1 1 1 0 0 0 1 0

程序清单

C语言程序(完成)

//13.1 TMS320LF2407与图形液晶显示模块接口及应用

//源程序代码:

//(2)主程序

// 该程序利用C语言实现液晶的显示,字库以字的形式存储.该程序执行后,实验板上的液

// *晶片上显示两行相同的"DSP 实验板"字母和汉字字样液晶要求每次送一个字节的

// *(8位)数据,而为了节约存储空间,液晶的显示字库在DSP中以字(16位)的形式存储,但在

// *下面的程序中可以通过巧妙简单的方法解决这个问题,详细方法见程序

#include "register.h"

const int char1[8]={0x0fc04,0x004fc,0x0f80c,0x000f0,0x0f08,0x0080f,0x0070c,0x00003};// "D"

const int char2[8]={0x03c18,0x04464,0x09cc4,0x00018,0x00e06,0x00808,0x00f08,0x0007};// "S"

const int char3[8]={0x0fc04,0x044fc,0x07c44,0x00038,0x00f08,0x0080f,0x00000,0x00000};// "P"

const int char4[16]={0x00c10,0x04404,0x0948c,0x00635,0x004f4,0x00404,0x01404,0x0000c,

0x08202,0x04282,0x02342,0x00e12,0x00a03,0x02212,0x0c342,0x00002};// "实"

const int char5[16]={0x0fa02,0x00202,0x042ff,0x05020,0x0434c,0x0504c,0x06020,0x00020,

0x03110,0x04911,0x07f89,0x05c42,0x04f40,0x05860,0x06047,0x00040};// "验"

const int char6[16]={0x01010,0x0ffd0,0x01090,0x0fc00,0x0a424,0x02224,0x062a3,0x00000,

0x00304,0x0ff00,0x02140,0x04718,0x01320,0x0160c,0x06021,0x00020};// "板"

// 屏蔽中断子程序

void inline disable()

{

asm(" setc INTM");

}

// 系统初始化子程序

void initial()

{

asm(" setc SXM"); // 符号位扩展有效

asm(" clrc OVM"); // 累加器中结果正常溢出

asm(" clrc CNF"); // B0被配置为数据存储空间

*SCSR1=0x81FE; // CLKIN=6M,CLKOUT=4*CLKIN=24M

*WDCR=0x0E8; // 不使能看门狗,因为SCSR2中的WDOVERRIDE即

// 保护位的缺省值为1,故可以用软件禁止看门狗

*IMR=0X00; // 中断禁止

*IFR=0x0FFFF; // 清除全部中断标志,"写1清0"

*MCRC=*MCRC&0X0FBFF; // IOPF2口为通用的IO口

*PFDATDIR=(*PFDATDIR|0X0400)&0XFFFB; // 不使能74HC273芯片

*MCRA=*MCRA&0X000F; // 配置IOPA[4-7],IOPB[0-7]为一般I/O口功能

*PADATDIR=(*PADATDIR|0X0F000)&0X0FF0F;

// IOPA[4-7]为输出,且全部为0

disable() ; // 总中断禁止

}

// 读液晶显示器状态子程序,形参E代表处理的液晶的边(E1或E2边)

void LCDSTA1(E)

int E;

{

int E1FLAG;

*PBDATDIR=*PBDATDIR&0X00FF; // IOPB口为输入口

while(1)

{

if(E==1)

*PADATDIR=(*PADATDIR|0X00A0)&0X0FFAF;

// E1=1,E2=0,R/W=1,A0=0,以便读晶的状态

else *PADATDIR=(*PADATDIR|0X0060)&0X0FF6F;

// E1=0,E2=1,R/W=1,A0=0,以便液晶的状态

E1FLAG=*PBDATDIR&0X0080;

if(E1FLAG==0x0000) break; // 若液晶空闲,则停止等待

}

}

// 对液晶显示器发指令子程序,形参E代表处理的液晶的边(E1或E2边)

void TRANS1(TRANS,E) // 该函数采用形参和实参的方式传递数值,TRANS为 // 一个形参

int TRANS,E;

{

LCDSTA1(E); // 判断液晶是否为忙

*PBDATDIR=*PBDATDIR|0XFF00; // IOPB口为输出口

if(E==1) *PADATDIR=(*PADATDIR|0X0080)&0X0FF8F;

// E1=1,E2=0,R/W=0,A0=0,以便写入令字

else *PADATDIR=(*PADATDIR|0X0040)&0X0FF4F;

// E1=0,E2=1,R/W=0,A0=0,以便入命令字

*PBDATDIR=(*PBDATDIR&0X0FF00)|TRANS;

// 需要写入的命令字送入数据线

if(E==1) *PADATDIR=*PADATDIR&0X0FF7F; // E1=0,写入指令

else *PADATDIR=*PADATDIR&0X0FFBF; // E2=0,写入指令

}

// 对液晶显示器写数据子程序,注意在此子程序里面列地址没有加1,需要用户在外

// 对其进行操作,形参E代表处理的液晶的边(E1或E2边)

void WRITE1(WRITE,CLMADD,E)

// WRITE代表需要写入的数据,CLMADD代表要的列地址

int WRITE,CLMADD,E;

{

TRANS1(CLMADD,E); // 设置列地址

LCDSTA1(E); // 查询液晶是否为空闲

*PBDATDIR=*PBDATDIR|0XFF00; // IOPB口为输出口

if(E==1) *PADATDIR=(*PADATDIR|0X0090)&0X0FF9F;

// E1=1,E2=0,R/W=0,A0=1,以便写入要显示的数据

else *PADATDIR=(*PADATDIR|0X0050)&0X0FF5F;

// E1=0,E2=1,R/W=0,A0=1,以便要显示的数据

*PBDATDIR=(*PBDATDIR&0X0FF00)|WRITE;

// 需要写入的数据送入数据线

if(E==1) *PADATDIR=*PADATDIR&0X0FF7F; // E1=0,写入数据

else *PADATDIR=*PADATDIR&0X0FFBF; // E2=0,写入数据

}

// 开E1显示子程序,形参E代表处理的液晶的边(E1或E2边)

void DISP1(E)

int E;

{

int E1FLAG;

while(1)

{

TRANS1(0X0AF,E); // 送出控制命令

LCDSTA1(E); // 判断液晶是否为空闲

*PBDATDIR=*PBDATDIR&0X00FF; // IOPB口为输入口

if(E==1) *PADATDIR=(*PADATDIR|0X00A0)&0X0FFAF;

// E1=1,E2=0,R/W=1,A0=0,以便读晶的状态

else *PADATDIR=(*PADATDIR|0X0060)&0X0FF6F;

// E1=0,E2=1,R/W=1,A0=0,以便液晶的状态

E1FLAG=*PBDATDIR&0X0020;

if(E1FLAG==0) break; // 如果液晶没被打开,则继续打开

}

}

// E1边清屏子程序,形参E代表处理的液晶的边(E1或E2边)

void CLEAR1( int E)

{

int PAGEADD,PAGENUM,CLMADD,CLMSUM;// 定义所需要的局部变量

for(PAGENUM=0X04,PAGEADD=0x0B8;PAGENUM>0;PAGENUM--,PAGEADD++)

{

TRANS1(PAGEADD,E); // 设置相应的页地址

for(CLMSUM=0X00;CLMSUM<0X3E;CLMSUM++)

{

LCDSTA1(E); // 判断液晶是否为空闲

WRITE1(0X00,CLMSUM,E); // 向相应的列送0以清屏

}

}

}

// 关 E1显示子程序,形参E代表处理的液晶的边(E1或E2边)

void DISOFF1(int E)

{

int E1FLAG;

while(1)

{

TRANS1(0X0AE,E); // 发出控制命令

LCDSTA1(E); // 判断液晶是否为空闲

*PBDATDIR=*PBDATDIR&0X00FF; // IOPB口为输入口

if(E==1) *PADATDIR=(*PADATDIR|0X00A0)&0X0FFAF;

// E1=1,E2=0,R/W=1,A0=0,以便读晶的状态

else *PADATDIR=(*PADATDIR|0X0060)&0X0FF6F; // E1=0,E2=1,R/W=1,A0=0,以便

// 液晶的状态

E1FLAG=*PBDATDIR&0X0020;

if(E1FLAG==0x0020)

break; // 如果液晶没有被关闭,则继续关

}

}

// LCD的E1边初始化子程序,形参E代表处理的液晶的边(E1或E2边)

void LCD1INIT(int E)

{

DISOFF1(E); // 关显示E1

TRANS1(0X0A4,E); // 静态显示驱动

TRANS1(0X0A9,E); // 占空比为1/32

TRANS1(0X0E2,E); // 复位

TRANS1(0X0A0,E); // ADC选择正常输出

CLEAR1(E); // 清屏

LCDSTA1(E); // 判断液晶是否为空闲

DISP1(E); // 开显示

}

// 汉字显示子程序,入口为存储汉字库的数组的首地址,页地址和起始列地址

// 和选中的E1或E2的边数

DISPLAY1(ARRAY,E,PAGADD,CLMADD)

int *ARRAY,PAGADD,CLMADD,E; // 定义所需要的局部变量

{

int K,TEMP;

TRANS1(0X0C0,E); // 从第0行开始显示

TRANS1(PAGADD,E); // 送需要显示的页地址

for(K=0;K<8;K++,CLMADD++,ARRAY++)

{

TEMP=*ARRAY&0X00FF;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

CLMADD++;

TEMP=(*ARRAY&0X0FF00)>>8;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

}

CLMADD=CLMADD-16; // 恢复列地址

PAGADD=PAGADD+1; // 页地址加1

TRANS1(PAGADD,E);

for(;K<16;K++,CLMADD++,ARRAY++)

{

TEMP=*ARRAY&0X00FF;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

CLMADD++;

TEMP=(*ARRAY&0X0FF00)>>8;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

}

}

// 数字和字母显示子程序,入口为存储字母或数字库的数组的首地址,页地址和

// 始列地址和选中的E1或E2的边数

DISPLAY2(ARRAY,E,PAGADD,CLMADD)

int *ARRAY,PAGADD,CLMADD,E; // 定义所需要的局部变量

{

int K,TEMP;

TRANS1(0X0C0,E); // 从第0行开始显示

TRANS1(PAGADD,E); // 送需要显示的页地址

for(K=0;K<4;K++,CLMADD++,ARRAY++)

{

TEMP=*ARRAY&0X00FF;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

CLMADD++;

TEMP=(*ARRAY&0X0FF00)>>8;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

}

CLMADD=CLMADD-8; // 恢复列地址

PAGADD=PAGADD+1; // 页地址加1

TRANS1(PAGADD,E);

for(;K<8;K++,CLMADD++,ARRAY++)

{

TEMP=*ARRAY&0X00FF;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

CLMADD++;

TEMP=(*ARRAY&0X0FF00)>>8;

WRITE1(TEMP,CLMADD,E); // 送需要显示的数据字节

}

}

// 主程序

main()

{

initial(); // 系统初始化

// 显示第一行"DSP 实验板"

LCD1INIT(1); // LCD的E1边初始化

LCD1INIT(2); // LCD的E2边初始化

DISPLAY2(char1,1,0x0BA,00); // 调用字母和数字显示子程序

DISPLAY2(char2,1,0x0BA,8); // 调用字母和数字显示子程序

DISPLAY2(char3,1,0x0BA,17); // 调用字母和数字显示子程序

DISPLAY1(char4,2,0x0BA,0); // 调用汉字显示子程序

DISPLAY1(char5,2,0x0BA,15); // 调用汉字显示子程序

DISPLAY1(char6,2,0x0BA,30); // 调用汉字显示子程序

// 显示第行行"DSP 实验板"

DISPLAY2(char1,1,0x0B8,00); // 调用字母和数字显示子程序

DISPLAY2(char2,1,0x0B8,8); // 调用字母和数字显示子程序

DISPLAY2(char3,1,0x0B8,17); // 调用字母和数字显示子程序

DISPLAY1(char4,2,0x0B8,0); // 调用汉字显示子程序

DISPLAY1(char5,2,0x0B8,15); // 调用汉字显示子程序

DISPLAY1(char6,2,0x0B8,30); // 调用汉字显示子程序

}

// 如若因干扰引起中断的误执行,则执行此中断服务程序

void interrupt nothing()

{

return;

}

汇编程序

;C2xx Core Registers

;~~~~~~~~~~~~~~~~~~~

IMR .set 0004h ; Int Mask

GREG .set 0005h ; Global memory allocation

IFR .set 0006h ; Int Flag

ABRPT .set 01fh ; Analysis BreakPoint

WSGR .set 0FFFFh ; Wait State Control (IO space mapped)

;系统模块寄存器

;~~~~~~~~~~~~~~~~~~~~~~

PIRQR0 .set 7010h ; Peripheral Interrupt Request Reg0

PIRQR1 .set 7011h ; Peripheral Interrupt Request Reg1

PIRQR2 .set 7012h ; Peripheral Interrupt Request Reg2

PIACKR0 .set 7014h ; Peripheral Interrupt Acknowledge Reg0

PIACKR1 .set 7015h ; Peripheral Interrupt Acknowledge Reg1

PIACKR2 .set 7016h ; Peripheral Interrupt Acknowledge Reg2

SCSR1 .set 7018h ; System contr & stat 1

SCSR2 .set 7019h ; System contr & stat 2

DIN .set 701Ch ; Device Identification register

PIVR .set 701Eh ; Peripheral Interrupt Vector Register

;Watch-Dog(WD) / Real Time Int(RTI) / Phase Lock Loop(PLL) Registers

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

WDCNTR .set 7023h ; WD Counter reg

WDKEY .set 7025h ; WD Key reg

WDCR .set 7029h ; WD Control reg

;对系统和LCD显示程序中用到的寄存器定义:

LCD_FLAG .usect ".data0",1 ;LDP=5

LCD_FLAG1 .usect ".data0",1 ;LCD的两个标志寄存器

LCDCMD .usect ".data0",1 ;LCD 列地址寄存器

LCDZKTAB .usect ".data0",1 ;查表地址临时寄存器

LCDDATA .usect ".data0",1 ;LCD 显示的数据

SHIJIAN .usect ".data0",1

DP_USER .set 5H

DP_USER1 .set 12H

DP_PF2 .set 0E1H

PADATDIR .set 7098H

PBDATDIR .set 709AH

MCRA .set 7090H

;LCD 宏定义:

E1_H .set 00080H ;E1=IOPA7=1, 选中E1块,即LCD模块左边

E1_L .set 0FF7FH ;E1=0

E2_H .set 00040H ;E2=IOPA6=1, 选中E2块,即LCD模块右边

E2_L .set 0FFBFH ;E2=0

RW_H .set 00020H ;R/W=IOPA5=1, 读LCD显示的内容

RW_L .set 0FFDFH ;R/W=0, 写LCD显示的内容

A0_H .set 00010H ;A0=IOPA4=1, 选择数据操作

A0_L .set 0FFEFH ;A0=0, 选择指令操作

;主程序:显示一屏,主要用于测试LCD底层程序

.def _c_int0,nothing

.text

_c_int0

CALL SYSINIT

CALL LCDINIT

LAR AR1,#SHIJIAN ;送显示时间03年09月23日

MAR *,AR1 ;16:08:14

LACL #03H

SACL *+

LACL #0923H

SACL *+

LACL #16H

SACL *+

LACL #0814H

SACL *

CALL LCDP0 ;显示一屏信息

WAIT: NOP

NOP

B WAIT

;系统初始化程序

SYSINIT:

SETC INTM

CLRC SXM

CLRC OVM

CLRC CNF ;B0 被配置为数据存储空间

LDP #0E0H

SPLK #81FEH,SCSR1 ;CLKIN=6M,CLKOUT=24M

SPLK #0E8H,WDCR ;关闭WDT

LDP #0

SPLK #0000H,IMR ;不使能中断

SPLK #0FFFFH,IFR ;清全部中断标志

RET

;LCD初始化及底层程序

;****************************************

; 描述:LCD初始化程序

; 被修改的寄存器:ACC, LCDCMD

; 调用到的子程序:COMWE, CLEAR

;****************************************

LCDINIT:

LDP #DP_PF2 ;DP-->7080H-70FFH

LACL MCRA

AND #000FH ;配置IOPA[4-7],IOPB[0-7] 为一般I/O口功能

SACL MCRA

LACL PADATDIR

OR #0F000H ;IOPA4-IOPA7 为输出方式

AND #0FF0FH ;IOPA[4-7]=0

SACL PADATDIR

LDP #DP_USER

SPLK #0AEH,LCDCMD ;关显示 10101110B

CALL COMWE

SPLK #00E2H,LCDCMD ;复位 11100010B

CALL COMWE

SPLK #0A4H,LCDCMD ;正常显示驱动 10100101B

CALL COMWE

SPLK #0A9H,LCDCMD ;占空比为1/32,10101001B

CALL COMWE

SPLK #0A0H,LCDCMD ;ADC选择,正常输出 10100000B

CALL COMWE

SPLK #0C0H,LCDCMD ;显示起始行

CALL COMWE

CALL CLEAR ;清屏

SPLK #0AFH,LCDCMD ;开显示 10101111B

CALL COMWE

RET

;****************************************

; 描述:对E1和E2写控制命令子程序,此程序只用在LCD初始化程序中

; 被修改的寄存器:ACC, LCD_FLAG

; 调用到的子程序:CWE

;****************************************

COMWE:

LACL LCD_FLAG

AND #0FFFEH ;LCD_FLAG.0=0选中E1

SACL LCD_FLAG

CALL CWE

LACL LCD_FLAG

OR #0001H ;LCD_FLAG.0=1选中E2

SACL LCD_FLAG

CALL CWE

LDP #DP_USER

RET

;****************************************

; 描述:写控制命令子程序,向LCD写一个控制字

; 入口:LCD_FLAG, LCDCMD

; 被修改的寄存器:ACC

;****************************************

CWE:

LDP #DP_USER ;@@@ 原为0

BIT LCD_FLAG,15 ;判是E1还是E2? LCD_FLAG.0=0,则选中E1

BCND CWE1,TC ;TC=1 则选中E2

LDP #DP_PF2

LACL PADATDIR

AND #E2_L ;E2=0

AND RW_L ;R/W=0

OR #E1_H ;E1=1

SACL PADATDIR

B CWE2

CWE1: LDP #DP_PF2 ;LCD_FLAG=01,则选中E2

LACL PADATDIR

AND #E1_L ;E1=0

AND #RW_L ;R/W=0

OR #E2_H ;E2=1

SACL PADATDIR

CWE2: LACL PADATDIR

AND #A0_L ;A0=0

SACL PADATDIR

LACL PBDATDIR

OR #0FF00H ;IOPB[0-7]设置为输出

AND #0FF00H ;IOPB[0-7]=0

LDP #DP_USER

OR LCDCMD ;IOPB[0-7]=LCDCMD

LDP #DP_PF2

SACL PBDATDIR ;送列地址

LACL PADATDIR

AND #E1_L ;E1=0

AND #E2_L ;E2=0

SACL PADATDIR

LDP #DP_USER

RET

;****************************************

; 描述:写数据子程序,向LCD写一个数据

; 人口:LCD_FLAG,AR7, LCDDATA

; 被修改的寄存器:ACC,LCDCMD

; 调用到的子程序:CWE

;****************************************

DWE:

LDP #DP_USER

SAR AR7,LCDCMD ;AR7存放列地址

CALL CWE

BIT LCD_FLAG,15 ;判是 E1 或E2模块?

LDP #DP_PF2

BCND DWE1,TC ;LCD_FLAG=01H, 则为E2模块

LACL PADATDIR

AND #E2_L ;E2=0

AND #RW_L ;R/W=0

OR #E1_H ;E1=1

SACL PADATDIR

B DWE2

DWE1: LACL PADATDIR

AND #E1_L ;E1=0

AND RW_L ;R/W=0

OR #E2_H ;E2=1

SACL PADATDIR

DWE2: LACL PADATDIR

OR #A0_H ;A0=1

SACL PADATDIR

LACL PBDATDIR

OR #0FF00H ;IOPB[0-7]设置为输出

AND #0FF00H ;IOPB[0-7]=0

LDP #DP_USER

OR LCDDATA ;IOPB[0-7]=LCDDATA

LDP #DP_PF2

SACL PBDATDIR ;送显示的数据

LACL PADATDIR

AND E1_L ;E1=0

AND #E2_L ;E2=0

SACL PADATDIR

MAR *,AR7

ADRK #1 ;向列地址增1,以便向下一列写数

LDP #DP_USER

RET

;****************************************

; 描述:清屏子程序,LCD清屏

; 被修改的寄存器:ACC, AR0, AR6, AR7, LCD_FLAG, LCDCMD, LCDDATA

; 调用到的子程序:CWE, DWE

;*******************************************************

CLEAR:

LDP #DP_USER

LAR AR6,#0B8H ;设置页地址代码指令 10111000B

;AR6存放的是页地址

SPLK #00H,LCDDATA ;将00写入

CLR1:

SAR AR6,LCDCMD

LACL LCD_FLAG

AND #0FFFEH ;LCD_FLAG.0=0

SACL LCD_FLAG

CALL CWE ;设置页号

LACL LCD_FLAG

OR #0001H ;LCD_FLAG.0=1

SACL LCD_FLAG

CALL CWE

LAR AR7,#00H ;从00列开始清0, AR7存放的是列地址

LAR AR0,#80 ;比较值( 可以61列)

CLR2:

LACL LCD_FLAG

AND #0FFEH ;LCD_FLAG.0=0

SACL LCD_FLAG

CALL DWE ;向E1写入00

MAR *,AR7 ;AR7兼为循环计数器

CMPR 01 ;(AR7<AR0)?

BCND CLR2,TC

LAR AR7,#00H ;从00列开始清0

CLR3:

LACL LCD_FLAG

OR #0001H ;LCD_FLAG.0=1

SACL LCD_FLAG

CALL DWE ;向E2写入00

MAR *,AR7

CMPR 01

BCND CLR3,TC

LAR AR0,#0BCH ;比较值(10111100B)

MAR *,AR6

ADRK #1 ;将页号增1,以便向下一页写数

CMPR 01 ;(AR6)<(AR0)?

BCND CLR1,TC

LDP #DP_USER

RET

;****************************************

;描述: 汉字显示子程序,LCD显示汉字程序

;人口: LCD_FLAG, AR6--页号,AR7--列地址

;LCD_FLAG的高8位--字号,LCD_FLAG的低8位为标志位

;LCD_FLAG.0=0选中E1,LCD_FLAG.0=1选中E2

;被修改的寄存器:ACC, AR0, AR5, AR6, AR7, LCD_FLAG, LCDCMD, LCDDATA, LCDZKTAB

;调用到的子程序:CWE, DWE

;****************************************

LCDHZ:

LDP #DP_USER

LACL LCD_FLAG

MAR *,AR7

LAR AR0,#59

CMPR 2 ;(AR7)>60?

BCND HZ0,TC

AND #0FFFEH ;在E1 块显示

B HZ00

HZ0: OR #0001H ;在E2 块显示

SBRK #59 ;(AR7)-60

HZ00: SACL LCD_FLAG ;根据AR7的值设置LCD_FLAG.0

LACL LCD_FLAG

AND 0FF00H

RPT #7

SFR

SUB #1

LDP #DP_USER

SACL LCDZKTAB ;得字号

LT LCDZKTAB

MPY #10H

SPM #0H ;P寄存器无输出移位

PAC ;ACC=PREG

ADD #LCDHZK ;&&&&&&&&&&&&&&&

SACL LCDZKTAB

LAR AR0,#0H

MAR *,AR6

CMPR #2H ;AR6>AR0 则显示在B8位置

BCND HZPSET0,TC

LAR AR6,#0BAH

B HZPSET1

HZPSET0: LAR AR6,#0B8H

HZPSET1: SAR AR6,LCDCMD ;设置页号

CALL CWE

MAR *,AR6

ADRK #1 ;页号加1,以准备显示汉字的下半部分

LAR AR0,#9

LAR AR5,#1 ;计数器

HZ1: LACC LCDZKTAB

TBLR LCDDATA ;表读

LACC #00FFH

AND LCDDATA

SACL LCDDATA

CALL DWE

LACC LCDZKTAB

TBLR LCDDATA

ADD #1

SACL LCDZKTAB

LACC #0FF00H

AND LCDDATA

RPT #7

SFR

SACL LCDDATA

CALL DWE

MAR *,AR5

ADRK #1 ;计数器加1

CMPR 01 ;比较,是否该汉字在本页的显示完成

BCND HZ1,TC

SAR AR6,LCDCMD

CALL CWE ;设置汉字下半部分显示的页

MAR *,AR7

SBRK #16

LAR AR0,#17 ;新比较值

MAR *,AR5

CMPR 01 ;比较,是否该汉字显示完成

BCND HZ1,TC

LDP #DP_USER

MAR *,AR7 ;准备下一个汉字显示

BIT LCD_FLAG,15

BCND HZ2,NTC

ADRK #59 ;E2 块 (AR7)+60

HZ2: ADRK #16

LAR AR0,#0BBH

MAR *,AR6

CMPR 00

BCND HZ3,NTC

LAR AR6,#0

B HZRET

HZ3: LAR AR6,#1

HZRET: SPLK #00,LCD_FLAG

LDP #DP_USER

RET

;****************************************

;描述: 数字、字母显示子程序,LCD显示数字或字母程序

;人口: LCD_FLAG, AR6--页号,AR7--列地址

;LCD_FLAG的高8位--字号,LCD_FLAG的低8位为标志位

;LCD_FLAG.0=0选中E1,LCD_FLAG.0=1选中E2

;被修改的寄存器:ACC, AR0, AR5, AR6, AR7, LCD_FLAG, LCDCMD, LCDDATA, LCDZKTAB

;调用到的子程序:CWE, DWE

;****************************************

LCDSZ:

LDP #DP_USER

LACL LCD_FLAG

MAR *,AR7

LAR AR0,#59

CMPR 2 ; (AR7)>60?

AND #0FFFEH ; E1 块

BCND SZ0,TC ; 原在上面

B SZ00

SZ0: OR #0001H ;E2 块

SBRK #59 ;(AR7)-60

SZ00: SACL LCD_FLAG ;根据AR7的值设置LCD_FLAG.0

LACL LCD_FLAG

AND #0FF00H

RPT #7

SFR

LDP #DP_USER

SACL LCDZKTAB

LT LCDZKTAB

MPY #08H

SPM #0H

PAC

ADD #LCDSZK

SACL LCDZKTAB

LAR AR0,#0

MAR *,AR6

CMPR #2H

BCND SZPSET0,TC

LAR AR6,#0BAH

B SZPSET1

SZPSET0: LAR AR6,#0B8H

SZPSET1: SAR AR6,LCDCMD ;设置页号

CALL CWE

MAR *,AR6

ADRK #1 ;页号加1,以准备显示字符的下半部分

LAR AR0,#5

LAR AR5,#1 ;计数器

SZ1: LACC LCDZKTAB

TBLR LCDDATA ;表读

LACC #00FFH

AND LCDDATA

SACL LCDDATA

CALL DWE

LACC LCDZKTAB

TBLR LCDDATA

ADD #1

SACL LCDZKTAB

LACC #0FF00H

AND LCDDATA

RPT #7

SFR

SACL LCDDATA

CALL DWE

MAR *,AR5

ADRK #1 ;计数器加1

CMPR #01 ;比较,是否该数字在本页的显示完成

BCND SZ1,TC

SAR AR6,LCDCMD

CALL CWE

MAR *,AR7

SBRK #8

LAR AR0,#9 ;新比较值

MAR *,AR5

CMPR #01 ;比较,是否该数字显示完成

BCND SZ1,TC

LDP #DP_USER

MAR *,AR7 ;准备下一个字符显示

BIT LCD_FLAG,0

BCND SZ2,NTC

ADRK #59 ;E2 块 (AR7)+60

SZ2:

ADRK #0AH

LAR AR0,#0BBH

MAR *,AR6

CMPR 00

BCND SZ3,NTC

LAR AR6,#0

B SZRET

SZ3: LAR AR6,#1

SZRET: SPLK #00,LCD_FLAG

LDP #DP_USER

RET

;显示主屏程序

;****************************************

; 描述:液晶显示液晶主屏程序,显示日期 XX年XX月XX日,显示时间 XX:XX:XX

; 人口:为要显示内容寄存器

; 被修改的寄存器:ACC, AR1, AR6, AR7, LCD_FLAG

; 调用到的子程序:CLEAR, LCDSZ, LCDHZ

;****************************************

LCDP0:

CALL CLEAR

LAR AR6,#0 ;页地址为BAH

LAR AR7,#2H ;列地址为02H

LAR AR1,#SHIJIAN ;(年,月,日,时,分秒)

MAR *,AR1

LACL *

AND #0F0H ;取"年"的十位

RPT #3

SFL ;左移4位得到字号

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"年"的十位

LAR AR7,#0CH

MAR *,AR1

LACL *+

AND #0FH ;取"年"的个位

RPT #7

SFL ;左移8位得到字号

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"年"的个位

LAR AR7,#18H

SPLK #01FFH,LCD_FLAG ;显示"年"这个字

CALL LCDHZ

LAR AR7,#2AH

MAR *,AR1

LACL *

AND #0F000H ;取"月"的十位

RPT #3

SFR

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"月"的十位

LAR AR7,#34H

MAR *,AR1

LACL *

AND #0F00H ;取"月"的个位

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"月"的个位

LAR AR7,#3EH

SPLK #02FFH,LCD_FLAG;显示"月"这个字

CALL LCDHZ

LAR AR7,#50H

MAR *,AR1

LACL *

AND #0F0H ;取"日"的十位

RPT #3

SFL

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"日"的十位

LAR AR7,#5AH

MAR *,AR1

LACL *+

AND #0FH ;取"日"的个位

RPT #7

SFL

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"日"的个位

LAR AR7,#64H

SPLK #03FFH,LCD_FLAG;显示"日"这个字

CALL LCDHZ

LAR AR6,#1 ;页地址为B8H

LAR AR7,#10H

MAR *,AR1

LACL *

AND #0F0H ;取"小时"的十位

RPT #3

SFL

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"小时"的十位

LAR AR7,#1CH

MAR *,AR1

LACL *+

AND #0FH ;取"小时"的个位

RPT #7

SFL

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"小时"的个位

LAR AR7,#28H

SPLK #0AFFH,LCD_FLAG;显示 " :"

CALL LCDSZ

LAR AR7,#34H

MAR *,AR1

LACL *

AND #0F000H ;取"分"的十位

RPT #3

SFR

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"分"的十位

LAR AR7,#40H

MAR *,AR1

LACL *

AND #0F00H ;取"分"的个位

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"分"的个位

LAR AR7,#4CH

SPLK #0AFFH,LCD_FLAG ;显示 " :"

CALL LCDSZ

LAR AR7,#58H

MAR *,AR1

LACL *

AND #0F0H ;取"秒"的十位

RPT #3

SFL

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"秒"的十位

LAR AR7,#64H

MAR *,AR1

LACL *

AND #0FH ;取"秒"的个位

RPT #7

SFL

OR LCD_FLAG

SACL LCD_FLAG

CALL LCDSZ ;显示"秒"的个位

LDP #DP_USER

RET

nothing:

KICK_DOG

RET

;字库列表

LCDHZK ;汉字库,16*16点阵

.word 02000H ;年 (1),其中1表示是汉字库中第1个汉字

.word 0cc10H

.word 4447H

.word 0fc44H

.word 4444H

.word 6444H

.word 0446H

.word 0000H

.word 0404H

.word 0704H

.word 0404H

.word 0ff04H

.word 0404H

.word 0404H

.word 0604H

.word 0004H

.word 0000H ;月 (2)

.word 0000H

.word 22feH

.word 2222H

.word 2222H

.word 0ff22H

.word 0002H

.word 0000H

.word 0080H

.word 3040H

.word 020fH

.word 0202H

.word 4202H

.word 7f82H

.word 0000H

.word 0000H

.word 0000H ;日 (3)

.word 0fe00H

.word 8282H

.word 8282H

.word 8282H

.word 0ff82H

.word 0002H

.word 0000H

.word 0000H

.word 07f00H

.word 2020H

.word 2020H

.word 2020H

.word 7f20H

.word 0000H

.word 0000H

LCDSZK ;数字、字母8*16点阵表

.word 0f8f0H ;"0"(0)

.word 0c40cH

.word 0f80cH

.word 00f0H

.word 0703H

.word 080cH

.word 070cH

.word 0003H

.word 1000H ;"1"(1)

.word 0fc18H

.word 00fcH

.word 0000H

.word 0800H

.word 0f08H

.word 080fH

.word 0008H

.word 0c08H ;"2"(2)

.word 0c484H

.word 3c64H

.word 0018H

.word 0f0eH

.word 0809H

.word 0c08H

.word 000cH

.word 0c08H ;"3"(3?

.word 4444H

.word 0fc44H

.word 00b8H

.word 0c04H

.word 0808H

.word 0f08H

.word 0007H

.word 0e0c0H ;"4"(4)

.word 98b0H

.word 0fcfcH

.word 0080H

.word 0000H

.word 0800H

.word 0f0fH

.word 0008H

.word 7c7cH ;"5"(5)

.word 4444H

.word 0c444H

.word 0084H

.word 0c04H

.word 0808H

.word 0f08H

.word 0007H

.word 0f8f0H ;"6"(6)

.word 444cH

.word 0c044H

.word 0080H

.word 0f07H

.word 0808H

.word 0f08H

.word 0007H

.word 0c0cH ;"7"(7)

.word 8404H

.word 7cc4H

.word 003cH

.word 0000H

.word 0f0fH

.word 0000H

.word 0000H

.word 0fcb8H ;"8"(8)

.word 4444H

.word 0fc44H

.word 00b8H

.word 0f07H

.word 0808H

.word 0f08H

.word 0007H

.word 7c38H ;"9"(9)

.word 4444H

.word 0fc44H

.word 00f8H

.word 0800H

.word 0808H

.word 070cH

.word 0003H

.word 0000H ;":"(a)

.word 3000H

.word 0030H

.word 0000H

.word 0000H

.word 0600H

.word 0006H

.word 0000H

END

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文