- 前言
- 实验须知
- 概述
- 实验一 TMS320LF2407 DSP 实验开发系统及CC软件应用
- 实验二 常用指令操作实验
- 实验三 追灯式电路控制
- 实验四 按键计数器
- 实验五 键盘和 LED 发光二极管显示电路
- 实验六 模/数转换器 ADC 应用
- 实验七 串行外围接口 SPI 的应用
- 实验八 串行通信接口模块(SCI)
- 实验九 TMS320LF2407 与图形液晶显示模块接口及应用
- 实验十 I2C 串行日历时钟与 TMS320LF2407 的接口应用
- 附录一 DSP 器件仿真开发技术基础
- 附录二 TMS320LF2407 DSP 实验开发系统
- 附录三 TMS320LF2407 DSP 器件简介
- 附录四 XDS510 仿真开发系统的基本操作技术
- 附录五 程序开发平台 Code Composer
- 参考文献
实验九 TMS320LF2407 与图形液晶显示模块接口及应用
一.实验说明
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论