Upload
evelia
View
107
Download
0
Embed Size (px)
DESCRIPTION
单片机原理及其嵌入式应用 实 验. 基本实验 综合实例.
Citation preview
2
基本实验
• 程序框架• (开关量输入输出 IO)实验• 串行通信及AD转换实验• 键盘编程实验• 液晶显示实验
• 数码管显示实验• FLASH编程实验• 定时器溢出中断实验• 定时器输入中断捕捉
实验
<<<
6
硬件接线 :
VCC
PTC3
PTA7
PTA6
PTA5
PTA4
PTA3
PTA2
PTA1
PTA0PTC0
PTC1
PTC2
MO
TO
RO
LA
GP
32 MC
U PTC4
PTB7
PTB6
PTB5
PTB4
PTB3
PTB2
PTB1
PTB0
9
*--------- 文件说明 ------------------------------------
* 文件名 :PrgFrame.ASM
* 硬件连接 :PTA.1 接指示灯
* 程序描述 : 指示灯 PTA.1 闪烁
* 目的 : 第一个 Motorola MCU 程序框架
* 说明 : 提供 Motorola MCU 的编程框架,供教学入门使用
*-----------------------------------------------------
11
RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可以更改)
FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可以更改)
* 数据区定义(变量名定义)——————————————————
org RAMstartAddr ;RAM 的起始地址
N1 rmb 1 ; 变量 N1, 缓冲使用
12
* 主程序—————————————————————————————— org FlashStartAddr ; 程序起始地址MainInit: ; 复位后程序从此开始执行 ; 系统初始化 SEI ; 禁止所有中断 LDHX #$023F ; 堆栈初始化,放入 GP32的 RAM 最高端 TXS JSR Init0 ; 调系统初始化子程序 Init0 ,初始学习时跳过此处 ;I/O 初始化 BSET 1,DDRA ; 设置 PTA.1 为输出 BSET 1,PTA ; 初始时, PTA.1 指示灯 " 暗 "MainLoop: ; 程序总循环入口 BCLR 1,PTA ;PTA.1 指示灯“亮” MOV #$2,N1 ; 延时子程序 DelaySub 的时间长度入口 JSR DelaySub ; 调用延时子程序 BSET 1,PTA ; 初始时, PTA.1 指示灯 " 暗 " MOV #$4,N1 ; 延时子程序 DelaySub 的时间长度入口 JSR DelaySub ; 调用延时子程序 ;------------------------------------------------------- JMP MainLoop ; 转总循环入口处
13
Init0: ; 系统初始化 Init0 子程序 LDA #%00000001 ; 初始化 CONFIG2
STA $001E
LDA #%00111101 ; 初始化 CONFIG1
STA $001F
CLR $0036 ; 初始化 PTCL
MOV #$01,$0036
MOV #$01,$0038
MOV #$2C,$0039
MOV #$80,$003A
BSET 5,$0036
BSET 7,$0037
BSET 4,$0036
RTS
*---- 中断矢量 --------------------------------- ORG $FFFE ; 复位矢量 DW MainInit
14
延时子程序DelaySub: ; 延时 0.1 秒 PSHH ; 保据寄存器 HX PSHX DelaySub1: LDHX #$FFFF DelaySub2: PSHA ; 保护寄存器 A LDA #$FFDelaySub3: DBNZA DelaySub3 PULA DBNZX DelaySub2 DBNZA DelaySub1 PULX PULH RTS
1818
vcc
vcc
PTC0
PTA7PTA6PTA5PTA4PTA3PTA2
PTA1
PTA0
vcc
PTB1
PTC1
PTB0
MO
TO
RO
LA
GP
32 MC
U
黄线为学生接线黄线为学生接线
硬件接线硬件接线 ::
19
程序功能 :• 开关 PTA7-4 分别控制着指示灯 PTA3-0
亮暗• 开关 PTB0\PTC0 其中之一闭合 , 指示灯
PTB7-1与 PTC1 交替暗亮 ;
若两个均未闭合 , 则指示灯 PTB1与 PTC1
均不亮 ;
若两个均闭合 , 则两个指示灯均亮 .
21
*------ 程序说明 --------------------------------** 文件名 :IOEXMA.ASM
* 硬件连接 :PTA7-4 接开关 ,PTA3-0 接指示灯 *PTB1 接指示灯 ,PTB0 接开关 *PTC1 接指示灯 ,PTC0 接开关 * 程序描述 :① 开关 PTA7-4 分别控制着指示灯 PTA3-
0 暗* ② 开关 PTB0、 PCT0 其中之一闭合指示 PTB7-1
* 与 PTC1 交替暗亮,若两个均未闭合则指示灯 * PTB1与 PTC1 均不亮,若两个均闭合则两排 * 指示灯均亮。* 目的 :I/O 口的基本使用方法 * 说明 : 仅作为基本教学例程 *----------------------------------------------*
22
*----- 口地址定义————————————————— DDRA equ $0004 ;A 口数据方向寄存器 PTA equ $0000 ;A 口数据寄存器 PTAPUE equ $000D ;A 口上拉电阻允许寄存器 DDRB equ $0005 ;B 口数据方向寄存器 PTB equ $0001 ;B 口数据寄存器 DDRC equ $0006 ;C 口数据方向寄存器 PTC equ $0002 ;C 口数据寄存器RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同
可以更改)FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可
以更改)
*----- 数据区定义(变量名定义)——————————
org RAMstartAddr
TmpVar rmb 1 ; 变量 TmpVar ,缓冲使用 Light_BC rmb 1 ;BC 口灯的状态
23
*------ 主程序———————————————— org FlashStartAddr ; 程序起始地址
MainInit:
NOP ; 初始化—————— SEI ; 禁止所有中断
LDHX #$023F ; 堆栈初始化,
;放GP32的 RAM 最高端
TXS
JSR Init0 ; 调系统初始化子程序 Init0,
; 初始学习时跳过此处
24
LDA #%00001111 ; 定义 A 口 7-4 为输入, 3-0为输出
STA DDRA
LDA #%11110000 ; 定义 A 口 7-4 有上拉电阻
STA PTAPUE
LDA #%11111110 ; 定义 B 口 7-1 为输出, 0为输入
STA DDRB
STA DDRC ; 定义 C 口 7-1 为输出, 0 为输入
MOV #$FF,Light_BC ;BC 口灯的状态赋初值
25
Start: ; 程序总循环入口——
NOP
LDA PTA ; 读取 A 口状态
NSA ;A 口 7-4 输入控制 A 口 3-0 输出
; 刚好为 A.7-4->A.3-0
COMA
STA PTA
LDA PTB ; 取开关 PTB0 状态 ,0- 闭合
AND #%00000001 ; 剩下 PTB0 位
STA TmpVar ; 放入变量 TmpVar
26
NOP
LDA PTC ; 取开关 PTC0 状态 ,0- 闭合
AND #%00000001 ; 剩下 PTC0 位
NOP
ADD TmpVar ; 经过此运算 若 A=0, 两个均闭合
; 若 =1, 有一个闭合 ;=2, 均未闭合
CBEQA #$0,Light0 ; 比较 , 相等转移 ,A=0 转向Light0
27
NOP
CBEQA #$1,Light1 ;A=1转 Light1
NOP ;A=2, 两排均不亮
LDA #$FF ; 两排灯均不亮 1- 不亮
STA PTB
STA PTC
BRA IO_End ; 转 IO_END, 延时
28
Light0:
LDA #$00 ; 两排灯均亮 0- 亮 STA PTB
STA PTC
BRA IO_End ; 无条件转 IO_END
Light1:
LDA Light_BC ; 两排灯之一亮 0- 亮 STA PTB ; 驱动 B 口灯 NEGA ; 求补命令 STA PTC ; 驱动 B 口灯 STA Light_BC ; 保存状态
29
IO_End:
LDA #$FE ; 延时Delay1:
LDX #$FC
Delay2:
NOP
NOP
NOP
DBNZX Delay2
DBNZA Delay1
BRA Start ; 无条件转开始处*-------------------------------------------
30
*------ 子程序 --------------------------*Init0: ; 系统初始化 Init0 子程序 LDA #%00000001 ; 初始化 CONFIG2
STA $001E LDA #%00111101 ; 初始化 CONFIG1
STA $001F CLR $0036 ; 初始化 PTCL
MOV #$01,$0036
MOV #$01,$0038
MOV #$2C,$0039
MOV #$80,$003A
31
BSET 5,$0036 BSET 7,$0037 BSET 4,$0036 RTS*-------- 复位矢量 ---------------------------- ORG $FFFE ; 复位矢量 DW MainInit
36
硬件接线 :
VCC
PTC3
PTA7
PTA6
PTA5
PTA4
PTA3
PTA2
PTA1
PTA0PTC0
PTC1
PTC2
MO
TO
RO
LA
GP
32 MC
U
PTC4
PTB7
PTB6
PTB5
PTB4
PTB3
PTB2
PTB1
PTB0
VCC
38
软件功能 :•由 PORTB 口的模拟量输入,通过单片
机的 A/D 转换器采集 8 路数据,并放在ADBUF 开始的地址中。
• 再在 INBUF 中放开关量。• 发 86给 PC 机作为握手信号,进行通信
测试, PC 机判断后确认,发 86 作为确认信号,单片机收到 86 后,把模拟量0-7和开关量送 PC 机显示。
39
程序清单:• 文件说明• 口地址定义• SCI寄存器• A/D寄存器• 数据区定义• 主程序• A/D转换• 串行通信输出
• 串行通信输入• 从PC
机接收数据,并存储后送PTA输出
• 把在INBUF和ADBUFF的数据送PC
机输出• 中断矢量
40
*--------- 文件说明 -------------------------------------------** 文件名: sci.as
* 硬件连接: PORTA 口输出它的 PTA7-0接OUT 的 7-0 号* 指示灯( A0 作为运行指示不受其它数据控制) PORTB 作为 AD 输入连接,*PORTB 口为模拟量输入口 ,PORTC的C0-4接 IN 的 5个拨位开关 0-4 作为
开关* 输入串行口与微机串行口相接( 9600,N, 8, 1)
* 程序描述: 1.由PORTB 口的模拟量输入,通过单片机的 A/D 转换器采集 8* 路数据,并放在 ADBUF 开始的地址中* 2.再在 INBUF 中放开关量* 3.发 86给PC 机作为握手信号,进行通信测试 ,PC 机判断后确* 认 , 发 86 作为确认信号,单片机收到 86 后 ,把模拟量 0-7和* 开关量送PC 机显示* 目的: A/D 转换,单片机异步串行通信 *------------------------------------------------------------*
41
*---- 口地址定义 ----------------------------PTA EQU $0000 ;A 口数据寄存器
PTB EQU $0001 ;B 口数据寄存器
PTC EQU $0002 ;C 口数据寄存器
PTD EQU $0003 ;D 口数据寄存器
DDRA EQU $0004 ;A 口数据方向寄存器
DDRB EQU $0005 ;B 口数据方向寄存器
DDRC EQU $0006 ;C 口数据方向寄存器
DDRD EQU $0007 ;D 口数据方向寄存器
DDRE EQU $0008 ;E 口数据寄存器
42
*----SCI 寄存器 -----------------------------SCS1 EQU $0016 ;SCI 状态寄存器 1B-SCTE EQU 7 ; 发送缓冲区空标志位B-TC EQU 6 ; 发送完成标志位B-SCRF EQU 5 ; 接收器满标志位SCDR EQU $0018 ;SCI 数据寄存器*---A/D 寄存器 -----------------------------ADSCR EQU $003C ;A/D 转换状态和控制寄存器B-COCO EQU 7 ; 转换完成标志位ADR EQU $003D ;A/D 转换数据寄存器ADCLK EQU $003E ;A/D 转换输入时钟寄存器RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可
以更改)FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可以
更改)
43
*---- 数据区定义(变量定义) -------------- ORG RAMstartAddr ;RAM 的起始地址
INBUF RMB 1 ;1字节存放 5位开关量
ADBUF RMB 8 ;8字节存放 8路 A/D 转换结果
ONOFF RMB 1 ;1字节存放从 PC 的数据
TMPVAR RMB 1 ; 暂存使用
44
*---- 主程序 --------------------------------- ORG FlashStartAddr ; 程序起始地址MainInit:: NOP LDA #$3E ;A/D 初始化 2 分频、使用内部总线时钟 STA ADCLK LDA #$FF ; 定义 PORTA 输出 STA DDRA LDA #$00 STA PTA STA ONOFF ;ONOFF=0
LDA #$00 ; 定义 PORTB, PORTC 作为输入 STA DDRB STA DDRC
45
*-------A/D 转换 ------------------------------Main: NOP ; 循环获得 8路 AD 值 LDHX #$0 ;H: X=0
GA-REPEAT: TXA ;X 寄存器送到累加器 STA ADSCR ; 选定一路 A/D ,启动转换 BRCLR 7,ADSCR,* ; 等待 A/D 转换完成 LDA ADR ;A/D 转换结果给 A
STA ADBUF,X ;A给 {ADBUF+X} ,储存数据
AIX #1 ; 下一存储单元 CPX #$08 ; 判断 8 路转换是否完成 BNE GA-REPEAT ; 循环 8次转换 8 个通道模拟
量
46
*---- 串行通信输出 -------------------------------GET-IN:
LDA PTC ;5 位开关量采集 STA INBUF ; 暂放 INBUF
NOP
LDA #$56 ; 把 86 ( 16 进制数 56 )为握 ; 手信号送出到 PC 中 BRCLR 7,SCS1,* ; 等待以前数据全部发出, ;SCTE 置 1 ,发送缓冲区空 STA SCDR ; 发送缓冲区空时, ; 可向 SCI 数据寄存器送数
47
*---- 串行通信输入 ----------------------------- NOP LDHX #0WS-REPE1: BRSET 5,SCS1,WS-RECE1 ; 测试 SCRF 位, ; 判断接收缓冲器是否满 NOP NOP AIX #1 ; 延时等待 CPHX #$FFFF BNE WS-REPE1 BRA DISP1 ; 超时退出WS-RECE1: LDA SCDR ; 读取收到的数据
48
CMP #$56 ; 判断是否为确认信号 86
BNE DISP1 ; 不是退出,是就开始通信 NOP
LDHX #0
WS-REPE2: BRSET 5,SCS1,WS-RECE2 ; 测试 SCRF 位, ; 判断接收缓冲器是否满 NOP
NOP AIX #1 ; 延时等待 CPHX #$6688 BNE WS-REPE2 ; 超时退出 BRA DISP1
49
*----从 PC 机接收数据,并储存后送 PTA 输出 ----------*----( A.0 不受影响) ----------------------------WS-RECE2
LDA SCDR
NOP AND #$FE ;A0=0
STA TMPVAR ; 暂时缓存 LDA ONOFF AND #$1 ; 留下 A.0
ORA TMPVAR ; 处理接收的数据,放在 A 中 STA ONOFF ; 储存接收数据在 ONOFF 中
NOP ; 送 A/D 值
50
*----把在 INBUF和 ADBUFF 的数据送 PC 机输出 --------
LDHX #$0
SA-REPEAT:
LDA INBUF,X
BRCLR 7,SCS1,* ;SCTE 置 1 ,
; 发送缓冲区空
STA SCDR ;A给 SCDR ,发送出去
AIX #1
CPX #$09 ;9 个数据输出
BNE SA-REPEAT
51
DISP1:
NOP
LDA ONOFF
EOR #$1 ; 把原 A.0 取反,使灯闪烁 STA ONOFF
STA PTA
BRA MAIN
**********************************************
*---- 中断矢量 --------------------------------- ORG $FFFE ; 复位矢量 DW MainInit:
56
硬件接线 :
红线为学生接线
PTC3
PTA7PTA6PTA5PTA4PTA3PTA2PTA1PTA0PTC0PTC1PTC2
MO
TO
RO
LA
GP
32 MC
UPTC4
内置电阻
VCC
58
软件功能 :• 开始运行时,指示灯 7 亮,等待键盘按键。• 按下“ D”键进入运行状态,指示灯 7 闪烁。• 在指示灯 7 闪烁状态,按“ 0-9”任意一键,指示灯 3-0 显示对应的二进制值( 0为灯亮, 1 为灯暗,如 1 的二进制为 0001 ,显示应为“亮亮亮暗”),按“ A-F”任意一键,指示灯 3-0全暗。
60
*--------- 程序说明 ----------------------------------------** 文件名: key.asm* 使用 4*4键盘实现输入控制* 硬件连接:* PTA7-4 接 4根键盘列线( X4-1), PTA3-0 接 4根键盘行
线* ( Y4-1)* PTC4 接指示灯 7(OUT7), PTC3-0 分别接指示灯 3-0(OUT3-0)
* 程序描述: 1.开始运行时,指示灯 7 亮,等待键盘按键* 2. 按下“ D”键进入运行状态,指示灯 7 闪烁* 3.在指示灯 7 闪烁状态,按“ 0-9”任意一键,指示灯 3-0* 显示对应的二进制值( 0 为灯亮, 1 为灯暗,如 1 的二进制为 0001* 显示应为“亮亮亮暗”),按“ A-F”任意一键,指示灯 3-0全暗。* 目的:键盘查询,键盘中断,键值识别,键盘编码*---------------------------------------------------------*
61
*---- 口地址定义 -------------------------------------------------
DDRA EQU $0004 ;A 口数据方向寄存器PTA EQU $0000 ;A 口数据寄存器PTAPUE EQU $000D ;A 口上拉电阻允许寄存器
DDRC EQU $0006 ;C 口数据方向寄存器PTC EQU $0002 ;C 口数据寄存器
INTKBSCR EQU $001A ; 键盘状态和控制寄存器INTKBIER EQU $001B ; 键盘中断允许寄存器
62
*----- 数据区定义(变量定义) ----------------- ORG $0090
TMPVAR1 RMB 1 ; 变量 TMPVAR1 ,缓冲使用
TMPVAR2 RMB 1 ; 变量 TMPVAR2 ,缓冲使用
KBVALUE RMB 1 ; 存放键盘按键值
PTCSTATE RMB 1 ;PTC 口状态变量
RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可以更改)FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可以更改)
*********************************************
63
ORG FlashStartAddr ; 程序起始地址*---- 主程序 ----------------------------------------MainInit:
NOP
LDA #$00 ; 定义 C 口之前复位 PTC
STA PTC
LDA #%00011111 ; 定义 C 口 4-0 为输出 STA DDRC ;C 口接指示灯 STA PTC ; 初始时指示灯熄灭 BCLR 4,PTC ;PTC4 为 0 ,指示灯 7点亮 ;表示进入开始状态
64
;--------A 口接键盘,查询等待按键 ----------- LDA #$00 ; 定义 A 口前复位 PTA
STA PTA
LDA #%00001111
STA DDRA
LDA #%11110000
STA PTAPUE
65
MainIni1:
JSR KBA ; 取得键值在 A 中 STA KBVALUE ; 键值放在 KBVALUE 中 ; 作为 KBdef 的入口 JSR KBdef ; 具体值在 A 中 cmp #$46 ;ASCII “( F” )是否为 $46 BNE MainIni1 ; 不是等待“ F”键;------- 设置键盘中断 ----------------------------JSR KBInit ; 已按“ F”键,进入运行状态, ; 执行键盘中断初始化子程序 BCLR 1,INTKBSCR ; 开放键盘中断 CLI
66
;---- 开始总循环处理键盘 ------------------Start:
NOP
;---- 使灯闪烁 ----------------------------- BCLR 4,PTC ;PTA4=0 ,电亮指示灯 7
LDA #$08
JSR Delaysub
BSET 4,PTC ;PTA4=1 ,熄灭指示灯 7
LDA #$08
JSR Delaysub
67
JSR Kbde ; 执行键盘转化为具体值子程序, ; 转成键定义值 CMP #$39 ; 测试是否是 0-9 BHI Start1 ; 大于 ASCII “( 9” )到 Start1
SUB #$30 ; 数字实际值 =ASCII 值 -$30 STA PTC ; 送 PTC 口 ,由指示灯 3-0 显示 BRA Start
Start1:
LDA #$FF ; 大于 ASCII “( 9”) ,消灭指示灯 STA PTC
JMP Start ; 继续循环处理
68
*-键盘中断初始化子程序(从 KBInit 开始) ---------------* 功能:对被定义为键盘中断的引脚初始化,但未开放键盘中断*占用 CPU内寄存器: A*---------------------------------------------------KBInit: LDA #$00 ; 定义 A 口之前复位 PTA STA PTA LDA #%00001111 ; 定义 A 口 7-4 输入作为列, ;3-0 输出作为行 STA DDRA LDA #%11110000 ; 定义 A 口 7-4 有上拉电阻 STA PTAPUE BSET 1,INTKBSCR ; 屏蔽键盘中断 LDA #%11110000 ; 允许 KBIE7-4PIN 中断进入 STA INTKBIER BSET 2,INTKBSCR ; 清除键盘中断 RTS
69
*----扫描读键值子程序(从 KBA 开始) ----------------* 功能 :扫描一次接在 PTA 口的 4*4键盘( PTA7-4 接 4根键盘*(X4-1), PTA3-0 接 4根键盘行线( Y4-1 )上的按键(使* 用行扫描法),键值放在 A 中 , 若无按键, A 中值 $FF*占用内存: TMPVAR1 (缓冲使用)* 出口: A=键值*-------------------------------------------------KBA: MOV #%11111110,TMPVAR1 ; 第一根行线为 0 LDX #$04 ;扫描 4根行线KB1: LDA PTA ;取 PTA给A ORA #%00001111 ;PTA7-4 保留原态, PTA3-0为 1 AND TMPVAR1 ;令
PTAn=0, n=0, 1, 2, 3 STA PTA ; 处理后给 PTA 以便查询
70
NOP NOP LDA PTA ; 查第 n 列上是否有键按下 AND #%11110000 ; 保留 PTA7-4列值,令低
PTA3-0=0 CBEQA #$F0,KB2 ;A 等于 $F0 ,本行线没键按下 ;A 不等于 $F0, 本行有键按下 LDA PTA ;A 放键值 BRA KB3 ; 转到 KB3结束中断KB2: SEC ; 令 C=1 ROL TMPVAR1 ; 使下一个行线为 0 ,查下一行 DBNZX KB1 ; 对行线循环 LDA #$FF ; 没有键被按下为 $FFKB3:RTS
71
*---键盘中断子程序(从 KBint 开始) ----------------* 功能:键盘中断程序,键值放入内存 KBVALUE 中* 调用子程序:扫描法读键值子程序( KBA),* 键盘中断初始化子程序( KBInit)* 出口:第 0页内存单元 KBVALUE 中为键值*------------------------------------------------Bint:
PSHH ; 保护H SEI
BSET 1,INTKBSCR ; 禁止键盘中断;---- 以下为中断程序任务 -------------------------- JSR KBA ; 调子程序 KBA ,键值放在 A 中 STA KBVALUE ; 放入内存 KBVALUE;---- 以上为中断程序任务 --------------------------
72
PULH ;H 出栈 JSR KBInit ; 调用键盘中断初始化子程序 BCLR 1,INTKBSCR ; 开放键盘中断 CLI RTI
****************************************************
*----键盘转化为具体值子程序(从 KBdef 开始) ----------* 功能:键值转为键盘表面具体的字符或符号代表值* 入口:内存第 0页中 KBVALUE 为键值,使用键值编号表*占用 CPU 寄存器: X (存放相对地址)* 出口: A=键定义值
*---------------------------------------------------KBdef: LDHX #$0000
73
KBkey1:
LDA KBTABLE,X
BEQ KBkey3 ;=0 ,表示表中未定义此键值 CMP KBVALUE ; 与 KBVALUE 入口键值相比
较 BNE KBkey2 ; 不等,未找到转 KBkey2
INCX ; 找到地址加 1 LDA KBTABLE,X ; 取键定义值给 A
BRA KBkeyr
KBkey2:
INCX
INCX
BRA KBkey1
74
KBkey3:
LDA #$FF ; 未定义键用 FF标志
KBkeyr: RTS
KBTABLE FCB $EE,"1",$DE,"2",$BE,"3",$7E,"4"
FCB $ED,"5",$DD,"6",$BD,"7",$7D,"8"
FCB $EB,"9",$DB,"0",$BB,"A",$7B,"B"
FCB $E7,"C",$D7,"D",$B7,"E",$77,"F"
FCB $00
***********************************************
75
*----- 程序延时程序子程序( Delaysub) -----------
* 功能 : 程序方法延时,延时长短由入口 A 中的数值决定
* 入口: A= 延时长度*占用内存 : 无*占用寄存器 :A
*----------------------------------------------
Delaysub:
PSHH
PSHX
Delay1:
LDHX #$5588
76
Delay2: NOP AIX #-1 CPHX #$0000 BNE Delay2 DBNZA Delay1 PULX PULH RTS*********************************************------ 中断矢量 ------------------------------- ORG $FFE0 ; 键盘中断矢量 DW KBint ORG $FFFE ; 复位矢量 DW MainInit
80
硬件接线 :
16151413121110090807060504030201
LC
D(H
D4478
0)
PTA7PTA6PTA5PTA4PTA3PTA2PTA1PTA0PTC2PTC1PTC0
MC
68H
C908G
P3
2
VCC
84
*------ 程序说明 -------------------------------------** 文件名: LCD.ASM
* 硬件连接 :1.LCD的DB0-7与单片机的 PORTA的 PTA0-7 连接作为
* 输出* 2.LCD的RS,R/W,E与单片机的 PTC0,PTC1,PTC2 连接* 程序描述 :1.开始运行时 ,LCD 显示“ Wait Receiving..”
* 2. 等待接收字符,当收到 16 个字符时显示之,重复* 此功能* 实验目的:不使用单片机串行外设接口 (SPI) 进行点阵字符* 型液晶显示 (LCD) 编程*--------------------------------------------------*
85
*------ 口地址定义 --------------------------------PTA EQU $0000 ;A 口数据寄存器
DDRA EQU $0004 ;A 口数据方向寄存器
PTC EQU $0002 ;C 口数据寄存器
DDRC EQU $0006 ;C 口数据方向寄存器
LCD-RS EQU 0 ;LCD 寄存器选择信号接 PTC0
LCD-RW EQU 1 ; 读写信号接 PTC1
LCD-E EQU 2 ;LCD 使能信号接 PTC2
86
*----SCI 串行通信口地址 -----------------------------SCC1 EQU $0013 ;SCI 控制寄存器 1SCC2 EQU $0014 ;SCI 控制寄存器 2SCS1 EQU $0016 ; 串行通信接口状态寄存器地址SCDR EQU $0018 ; 串行通信接口数据寄存器地址SCBR EQU $0019 ;SCI波特率寄存器FULL EQU 5 ; 用于 SCI 接收缓冲器是否满标志位RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可
以更改)FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可以
更改)*----- 变量定义 ---------------------------------------- ORG RAMstartAddr ;RAM 的起始地址LCD-BUFFER RMB 16 ; 存放 16字节
87
*************************************************
*----- 主程序 -------------------------------------
ORG FlashStartAddr ; 程序起始地址MAININIT:
NOP
LDA #%11111111 ;A 口为输出
STA DDRA
LDA #%00010111 ;C 口的 PTC0-2 为输出
STA DDRC
88
*---- 串行口初始化 ------------------------------- LDA #%01000000 ;D6(ENSCI)=1, 允许 SCI,
; 其它位为 0,正常码输出
;8 位数据 , 无检验
STA SCC1
LDA #%00001100 ; 允许发送器 , 允许接收器 ,
; 不允许发送与接收中断
STA SCC2
LDA #%00000010 ; 波特率为 9600
STA SCBR
89
LDHX #$00
DISPLAY1: ; 把要显示的 16 个初始字符 ; 放入 LCD-BUFFER 中 LDA DISPLAYBYTES,X
STA LCD-BUFFER,X
AIX #1
CPHX #$10
BNE DISPLAY1 ; 循环 16次 BRA START
DISPLAYBYTES FCB "WAIT RECEIVING.."
START:
JSR INIT-LCD ;LCD 初始化 JSR SHOW-LCD-BUFFER ; 把 LCD-BUFFER 中的 16
个字符 ;送 LCD 显示
90
LDHX #$00
DISPLAY2: ; 从 PC 机接收 16 个字符放入 ;LCD-BUFFER 开始的内存中 BRCLR FULL,SCS1,* ; 与 PC 机串行通信 , ; 判断接收器是否满 LDA SCDR ; 读 SCI 数据寄存器 STA LCD-BUFFER,X
AIX #1
CPHX #$10
BNE DISPLAY2
JMP START
*************************************************
91
*---INIT-LCD(LCD 初始化子程序 )-------------------
* 入口 : 无
* 功能 : 初始化 LCD(HD44780)
* 调用子程序 :LCDCOMMAND(LCD 命令执行子程序 )
*占用 CPU内部寄存器 :A,X
*------------------------------------------------
INIT-LCD:
BCLR LCD-RS,PTC ;令 LCD的RS=0,R/W=0, 进行LCD 初始化
BCLR LCD-RW,PTC
LDA #%00111000 ; 功能设置 :8 位数据接口 ,
;2 行显示 ,5*7点阵模式
92
JSR LCDCOMMAND
LDA #%00001000 ; 显示开关控制 : 关显示,
; 关光标显示 , 不闪烁
JSR LCDCOMMAND
LDHX #$0020 ; 等待 40us
DBNZX *
BCLR LCD-RS,PTC ;RS,RW 清零开始清屏
BCLR LCD-RW,PTC
LDA #%00000001 ; 清屏指令
JSR LCDCOMMAND
LDHX #$2DF ; 等待清屏完毕 , 时间 >1.6ms
93
CLR-LCD-2-MS: ; 延时 AIX #-1
CPHX #0
LDA #%00000110 ; 输入方式设置 : 数据读写操作后 ,
;AC自动增 1, 显示不动 ,光标左 JSR LCDCOMMAND
LDA #%00010100 ; 光标移位设置 :光标右移一个 ;字符位 ,AC自动加 1 JSR LCDCOMMAND
LDA #%00001100 ; 显示开关设置 : 开显示 , ; 关光标显示 , 不闪烁 JSR LCDCOMMAND
RTS
94
*----LCDCOMMAND(LCD 命令执行子程序 )-----------------
* 入口 :A
* 功能 : 对 A 中指令使用 PORTA 作为输出口 ,* 到 LCD 进行命令执行或字符显示*占用 CPU内部寄存器 :A
*--------------------------------------------------
LCDCOMMAND:
PSHH ; 保护现场 PSHX
LDHX #$0020 ; 等待 40us
DBNZX *
STA PTA ; 把指令码送到 A 口
95
NOP
NOP
BSET LCD-E,PTC ;LCD 开始接受数据 , 置使能位为 1 NOP
NOP
BCLR LCD-E,PTC ;LCD结束接受数据 , 置使能位为 0 LDHX #$0020 ; 等待 40us
DBNZX *
PULX ; 恢复现场 PULH
RTS
****************************************************
96
*----SHOW-LCD-BUFFEER(LCD 显示子程序 )-----------------* 入口 :内存 LCD-BUFFER 开始的 16 个地址中存放要显示的字符
* 编码* 功能 : 显示内存 LCD-BUFFER 开始的 16字节数据* 调用 :LCDCOMMAND 子程序*占用 CPU内部寄存器 :A,HX
*----------------------------------------------------
SHOW-LCD-BUFFER: ; 进行显示数据寄存器 (DD RAM) 地址设置
BCLR LCD-RS,PTC
BCLR LCD-RW,PTC ; 设置前 8 个字符首DD RAM 地址 LDA #%10000000
JSR LCDCOMMAND
LDHX #$0 ; 显示前 8 个字符
97
SHOW-FIRST-8BYTE:
BSET LCD-RS,PTC ; 令 LCD的 RS=1,R/W=0,写入数
; 据到 DD RAM 中
BCLR LCD-RW,PTC
LDA LCD-BUFFER,X ; 将 {LCD-BUFFER+X} 的数据 ; 放入 A 作为入口
JSR LCDCOMMAND
AIX #1
CPHX #$8
BNE SHOW-FIRST-8BYTE
98
LDA #%11000000 ; 设置后 8 个字符首DD RAM地址
BCLR LCD-RS,PTC
BCLR LCD-RW,PTC
JSR LCDCOMMAND
LDHX #$08 ; 显示后 8 个字符
SHOW-NEXT-8BYTE:
BSET LCD-RS,PTC ; 令 LCD的 RS=1,R/W=0,
; 写入数据到 DD RAM 中
BCLR LCD-RW,PTC
99
LDA LCD-BUFFER,X ; 将 {LCD-BUFFER+X}的数据
; 放入 A 作为入口
JSR LCDCOMMAND
AIX #1
CPHX #$10
BNE SHOW-NEXT-8BYTE
RTS
*--- 中断矢量 --------------------------------------* ORG $FFFE ; 复位向量
DW MAININIT
100
系统初始化Init0: ; 系统初始化 Init0 子程序 LDA #%00000001 ; 初始化 CONFIG2 STA $001E LDA #%00111101 ; 初始化 CONFIG1 STA $001F CLR $0036 ; 初始化 PTCL MOV #$01,$0036 MOV #$01,$0038 MOV #$2C,$0039 MOV #$80,$003A BSET 5,$0036 BSET 7,$0037 BSET 4,$0036 RTS
105
硬件接线 :PTB0
PTB1
PTB2
PTB3
PTB4
PTB5
PTB6
PTB7
PTC0
PTC1
PTC2
PTC3
MC
68H
C908G
P3
2
LA
LB
LC
LD
LE
LF
LG
LDP
L11
L12
L13
L14
LE
D
109
*-------- 程序说明 ---------------------------------------------------
* 文件名 :LED.ASM
* 使用数码管对数字 (整数或小数 ) 进行显示* 硬件连接 :PTB0,1,2,3,4,5,6,7 分别接 * LA,LB,LC,LD,LE,LF,LG,LDP
* PTC0,1,2,3 分别接 L11,L12,L13,L14
* 功能描述 :从 PC 机收到数字 (整数或小数 ), 使 4 个数字并排
* 在一个数码管上显示 ,由 PC 机的 VB 界面显示控制* 目的 : 数码管的显示*------------------------------------------------------------------------
110
*---- 口地址定义 ----------------------------------------------
PTB EQU $0001 ;B 口数据寄存器
DDRB EQU $0005 ;B 口数据方向寄存器
PTC EQU $0002 ;C 口数据寄存器
DDRC EQU $0006 ;C 口数据方向寄存器
PTD EQU $0003 ;D 口数据寄存器
DDRD EQU $0007 ;D 口数据方向寄存器
111
*---- 串行口地址定义 -------------------------------------
SCS1 EQU $0016 ;SCI 状态寄存器 1
SCDR EQU $0018 ;SCI 数据寄存器SCC1 EQU $0013 ;SCI 控制寄存器 1
SCC2 EQU $0014 ;SCI 控制寄存器 2
SCBR EQU $0019 ;SCI波特率寄存器RAMstartAddr equ $0040
;RAM 的起始地址(因芯片不同可以更改)FlashStartAddr equ $8000
; 程序开始地址(因芯片不同可以更改)*---内存变量定义 ------------------------------------------
ORG RAMstartAddr
PC_Buffer RMB 4 ; 存放从 PC 接收的数据 Show_Buffer RMB 4 ; 存放待显示的数据Cs RMB 1 ; 位选信号
112
*------ 主程序 -------------------------------------------------
ORG FlashStartAddr ; 初始化
Main:
LDA #$FF ; 定义 B 口为输出
STA DDRB
LDA #$FF ; 定义 C 口为输出
STA DDRC
LDA #$FF ; 定义 D 口为输出
STA DDRD
113
*---- 串行口初始化 -------------------------------------------
LDA #%01000000 ;D6(ENSCI)=1, 允许 SCI,
; 其它位为 0,正常码输出 ,
;8 位数据 , 无检验
STA SCC1
LDA #%00001100 ; 允许发送器 , 允许接收器 ,
; 不允许发送与接收中断
STA SCC2
LDA #%00000010 ;波特率为 9600
STA SCBR
114
Display_Init: ; 起始数据赋值
MOV #$1,PC_Buffer
MOV #$2,{PC_Buffer+$1}
MOV #$3,{PC_Buffer+$2}
MOV #$4,{PC_Buffer+$3}
Start:
JSR Translate_Num ; 起始数据转码 JSR Show_Num ; 显示起始数据
BRSET 5,SCS1,Rece_Num ; 等待接受数据 , 有
;就跳向 Rece_Num
BRA Start
115
Rece_Num: LDHX #$0000 ; 清空缓冲区Rece_Num1: BRCLR 5,SCS1,* ; 等待数据 , 无就转向自己 ,
; 有就往下执行 LDA SCDR ; 取数据寄存器中内容放入 A
STA PC_Buffer,X ;将 PC_Buffer 中的数据 ;依次存入 A
INCX CPX #!4 ; 接收满 4 个数就开始显示 BLO Rece_Num1
BRA Start
116
*----- 显示子程序(Show_Num)-------------------------------------
* 入口 :以 Show_Buffer首地址的内存区 ,共 4 个字节* 出口 : 无*占用寄存器 :HX,A
*占用内存 :CS
* 调用子程序 :Delay_ns
* 描述 : 显示 Show_Buffer 中的四个字符*--------------------------------------------------------------------------
Show_Num: PSHH ; 进栈 , 保存 HX,A 中内容 PSHX
PSHA LDHX #$00 ; 清空缓冲区 LDA #$01 ;先取第一位 STA CS
117
Show_Num_Loop: LDA Show_Buffer,X ; 取出 Show_Buffer 中 ; 第一个字符放入 A
STA PTB ; 再将 A 中内容存入 B 输出 LDA CS STA PTC ;将 A 中内容存入 C 中输出 LDA #!100 ; 延时 100毫秒 JSR Delay_ns ASL CS ; 算术左移 ,修改位选信号 INCX CPX #!4 ; 判断是否已经扫描完毕 BLO Show_Num_LOOP ;小于则循环
118
PULA ; 出栈 PULX
PULH
RTS
*----------- 转码子程序 (Translate_Num)-----------------------
* 子程序名 :Translate_Num
* 入口 :以 PC_Buffer 为首地址的内存区四个字节* 出口 :以 Show_Buffe 为首地址的内存区四个字节*占用寄存器 :HX,A
*占用内存 :Show_Buffer
* 调用子程序 : 无* 描述 :将 PC_Buffer 中字符转换为相应的字型码* 放入 Show_Buffer 中*------------------------------------------------------------------------
119
Translate_Num: PSHH ; 进栈 , 保存 HX,A 中内容
PSHX
PSHA LDHX #$0000 ; 清空缓冲区
Translate_Num1: LDA PC_Buffer,X ;取 PC_Buffer 中一个数 ; 放入 A
PSHH ; 进栈 , 保存 HX内容
PSHX
120
TAX ;将 A 中内容放入 X 中 LDA Table,X ; 取出对应的字形码
PULX
PULH STA Show_Buffer,X ;将 Show_Buffer 中字符 ;依次放入 A 中
INCX
CPX #$4 BLO Translate_Num1 ;小于四个字符则循环
121
PULA ; 出栈
PULX
PULH
RTS
Table FCB $C0,$CF,$A4,$B0,$99,$92,$82,$F8,$80, $90
; 显示码表 0 1 2 3 4 5 6 7 8 9
;0 1 2 3 4 5 6 7 8 9
FCB $40 ,$4F ,$24,$30,$19,$12,$02,$78,$00 ,$10
; 显示码表 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
; 10 11 12 13 14 15 16 17 18 19
122
*------------ 延时子程序( Delay_ms )---------------------------
* 入口 :HX(表示要延时的毫秒数 ) HX=1 延时 1毫秒*占用内部寄存器: A
*占用内存:无*-------------------------------------------------------------------------
Delay_ms: LDA #!248 ;0.5ms
JSR Delay_ns LDA #!248 ;0.5ms
JSR Delay_ns
AIX #-!1
CPHX #!0 BNE Delay_ms ;4Cycles
RTS ;4Cycles
123
*----------- 延时子程序( Delay_ns )------------------------
* 入口: A
*占用内部寄存器:无*占用内存:无* 使用方法:设延时 10μs, A=(T-4)/2=3
* LDA #!3 ; 延时 10μs
* BSR Delay_nus
*--------------------------------------------------------------------
Delay_ns: NOP ;1Cycles
NOP ;1Cycles
DBNZA Delay_ns ;3Cycles
RTS ;4Cycles
124
************************************************
*--- 中断矢量 -------------------------------------------------------
ORG $FFFE
DW MAIN
130
软件功能 :① 系统初始化: CONFIG2、 1、 PTCL、串行口、堆
栈 ② 进行通信握手,即与 PC 机进行通信测试,发出 86 ,
收到 56 ,则表明握手成功 ③ 等待接收 PC送来N1+1 个数,其中 N1 为要写入
Data8000 开始 Flash 区的数据 ④ 擦除以 Data8000 为首地址的 Flash 区的一页,将
N1 个数据写入 ⑤ 从以 Data8000 为首地址的 Flash 区读取 N1 个数据,由串行口发送到 PC 机
⑥ PTA1 为通信指示灯 , 通信握手时闪动,表明正在与PC 机握手 <<<
132
口地址定义• DDRA equ $0004 ;A 口数据方向寄存器• PTA equ $0000 ;A 口数据寄存器• FLCR EQU $FE08 ;Flash 控制寄存器• FLBPR EQU $FF7E ;Flash 块保护寄存器• SCC1 EQU $0013 ;SCI 控制寄存器 1• SCC2 EQU $0014 ;SCI 控制寄存器 2• SCBR EQU $0019 ;SCI 波特率寄存器• SCS1 EQU $0016 ;SCI 状态寄存器 1• SCDR EQU $0018 ;SCI 数据寄存器• RAMstartAddr equ $0040 • ;RAM 的起始地址(因芯片不同可以更
改)• FlashStartAddr equ $8000 • ; 程序开始地址(因芯片不同可以更改)<<<
133
内存变量定义• org RAMstartAddr• Address1 RMB 2 ; 地址缓冲单元• N1 RMB 1 ; 写入数据的个数• I1 RMB 1 ; 计数变量• FlashAddress RMB 2 ;Flash 页的首地址• DATA1 RMB !64 ; 数据区• P_AddressInRAM RMB !90 ;FLASH 中程序移入 RAM 后的首地址• *---------Flash 数据区 ( 一页 128 字节 )-------------------------------------------• ORG FlashStartAddr• ; 设写入区为 $8000 ~ $807F 一页• Data8000: FCB !11,!12,!13,!14,!15,!16,!17,!18,!66 ; 几个初始值,仅为实
验对比• *--------- 程序区 -------------------------------------------------------------• ORG $9000• * 包含子程序 =============================================
=====================• $INCLUDE "Writesub.asm"• $INCLUDE "EraseSub.asm" <<<
134
程序初始化• ;---------- 主程序开始 ------------------------------------------------• MainInit:• : ; 复位后程序从此开始执行 • ; 系统初始化• SEI ; 禁止所有中断• LDHX #$023F ; 堆栈初始化,放入 GP32的 RAM 最高端• TXS• JSR Init0 ; 调系统初始化子程序 Init0 ,初始学习时跳过此处• BSET 1,DDRA ; 定义 PTA.1 为输出(通信指示灯)• ;------ 串行口初始化 --------------------------------------------------• LDA #%01000000 ;D6( ENSCI) =1 ,允许 SCI 。其它位为 0 ,• STA SCC1 ; 即正常码输出、 8 位数据、无校验等• LDA #%00001100 ;D3( TE) =1 ,允许发送器; D2(RE)=1, 允
许接收器。• STA SCC2 ; 其它位为 0, 查询方式收发• LDA #%00000010 ; 例如: fBUS= 2.4576MHz ,取 PD=1 (即
SCP1、 SCP0=00)、• STA SCBR ;BD=2(即 SCR2、 SCR1、 SCR0=010),• ; 则波特率 =2457600 /(64*1*4) = 9600• ;-------------------- 初始化结束 -------------------------------------
<<<
135
主循环• MainLoop: • BRCLR 1,PTA,PTA1SET ; 指示灯状态变换• BCLR 1,PTA• BRA PTA1CLR• PTA1SET:• BSET 1,PTA• PTA1CLR:• JSR CommunicateTest ; 调用“通信握手子程序”• BCC MainLoop ;C= 0 表明握手未成功,继续握手• ;-------- 接收要写入的字符个数 (N1<=128) 及字符 ----------------------• BRCLR 5,SCS1,* ; 测试位 5, 直到为 1 (等待接收一个数据)• LDA SCDR ; 取收到的数据 ->A• STA N1 ; 放入内存 N1 中• LDHX #$0000• ReceiveData:• BRCLR 5,SCS1,* ; 测试位 5, 直到为 1 (等待接收一个数据) • LDA SCDR ; 取收到的数据 ->A• STA DATA1,X ; 放入内存 {DATA1+X} 中• AIX #$1• CPX N1 <<<
136
主循环续• BLO ReceiveData ; 是否收到 N1 个数据,若没收到,则继续收• ;------- 擦除要写入的 Flash 区 (1 页 ,GP32:128Bytes))--------------------• LDHX #Data8000 ; 擦除程序的入口参数 FlashAddress• STHX FlashAddress ; 要擦除 Flash 区首地址• JSR EraseSub ; 执行擦除子程序• ;------------------------------------------------------------------ • LDHX #DATA1 ; 写入程序的入口参数① • STHX Address1 ; 内存数据首地址放入 Address1~ Address1+1 中• ; 写入程序的入口参数② :N1 为写入的数据个数,已放入• LDHX #Data8000 ; 写入程序的入口参数③ :Flash 的首地址• STHX FlashAddress • JSR WriteSub ; 执行写入程序• ;------------------------------------------------------------------• ;向 PC 机发送写入 Flash 区的数据 N1 个,共 PC 机接收并比较• LDHX #Data8000• SendData:• LDA ,X ; 取内存数据 ->A• BRCLR 7,SCS1,* ; 测试第 7 位直到为 1, 即发送出去• STA SCDR ;A->SCDR• AIX #$1 ;HX=HX+1• DBNZ N1,SendData ;N1-1 不等于 0, 则再继续发送写入的数• MainError1:• MainExit:• JMP MainLoop ; 转总循环 <<<
137
握手子程序CommunicateTest: LDA #!86 ; 发送握手信号:数字 86 BRCLR 7,SCS1,* ; 测试第 7 位直到为 1, 即发送出去 STA SCDR ;A→SCDR, 发送出去 LDHX #$0000 ;0→H:XReceive56: BRSET 5,SCS1,Receive561 ; 测试位 5, 看它是否为 1 ,即收到数据转 AIX #1 ; 未收到数据, HX+1 计数 CPHX #$AABB ; 延时等待时间常数 BNE Receive56 ; 等待时间未到,继续监测 JMP Test_Fail ; 等待时间到,转通信息检测失败Receive561: ; 收到数据情况 LDA SCDR ; 读取收到的数据 CMP #!56 ; 与约定数 "56" 进行比较 BNE Test_Fail ; 不等,转通信息检测失败 JMP Test_Success ; 相等,转 Test_Success Test_Fail: CLC ; 通信息检测失败 C= 0 JMP Test_Exit ; 跳转至总退出处Test_Success: SEC ; 通信息检测成功 C= 1Test_Exit: RTS
<<<
138
系统初始化子程序Init0: ; 系统初始化 Init0 子程序 LDA #%00000001 ; 初始化 CONFIG2 STA $001E LDA #%00111101 ; 初始化 CONFIG1 STA $001F CLR $0036 ; 初始化 PTCL MOV #$01,$0036 MOV #$01,$0038 MOV #$2C,$0039 MOV #$80,$003A BSET 5,$0036 BSET 7,$0037 BSET 4,$0036 RTS
<<<
146
*----------------- 程序说明 -----------------------------------------*
* 文件名称 : Timer_5s.asm( 定时器接口模块编程实验)* 硬件连接 : PTA1 接指示灯 D1
* 程序描述 : ① 系统初始化: CONFIG2、 1、* PTCL、堆栈 * ② 以定时中断方式 ,每 5秒取反指示灯
PTA1 ,* 使其闪动 * 实验目的 : 熟悉定时器接口模块的使用 *----------------------------------------------------------------------*
147
*---------- 寄存器地址 -----------------------------------------------
DDRA equ $0004 ;A 口数据方向寄存器PTA equ $0000 ;A 口数据寄存器*T1SC EQU $0020 ; 定时器 1 状态和控制寄存器T1CNTHEQU $0021 ; 定时器 1计数寄存器 ( 高位 )
T1CNTL EQU $0022 ; 定时器 1计数寄存器 (低位 )
T1MODH EQU $0023 ; 定时器 1 模数寄存器 ( 高位 )
T1MODL EQU $0024 ; 定时器 1 模数寄存器 (低位 )
RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可以更
改)RAMstartAddr equ $8000 ; 程序开始地址(因芯片不同可以更改)
148
*---------内存变量 ---------------------------------------------
org RAMstartAddrFiv RMB 1
org RAMstartAddr ;---------- 主程序开始 ----------------------------------
MainInit: SEI ; 禁止所有中断 LDHX #$023F ; 堆栈初始化, ; 放入 GP32的 RAM 最高端 TXS
149
;---------- 系统初始化 ----------------------------------------------
MOV #%00000001,$001E ; 初始 CONFIG2
MOV #%00111101,$001F ; 初始化 CONFIG1
MOV #%00110001,$0036 ; 初始化 PTCL
BSET 7,$0037 ;PBWC 第 7 位为 1
MOV #$01,$0038 ;PMSH
MOV #$2C,$0039 ;PMSL
MOV #$80,$003A ;PMDS
BSET 1,DDRA ; 定义 PTA.1 为输出(指示灯)
BSET 1,PTA
; 定时器 1 初始化
150
LDA #%01100110 ; 允许溢出中断、不启动计数、 ; 分频因子 =64
STA T1SC LDHX #$0000 ;计数寄存器初值 =$0000
STHX T1CNTH LDHX #$9600 ; 设 1秒产生 1次溢出中断 STHX T1MODH ; 模数寄存器设定值 ;=1×(2457600/64)=$9600
BCLR 5,T1SC ; 允许定时器 1计数寄存器计数 MOV #!0,Fiv CLI ; 开放中断 ;-------------------- 初始化结束 -----------------------------
152
*---------- 定时器 1溢出中断子程序 -------------------------
Timer1overflow:
INC Fiv
LDA #!5
CMP Fiv
BHI PTA1CLR
MOV #!0,Fiv
BRCLR 1,PTA,PTA1SET ; 指示灯状态变换 BCLR 1,PTA
BRA PTA1CLR
154
*---------- 向量区 ----------------------------------------ORG $FFF2 ; 定时器 1溢出中断向量
DW Timer1overflow
ORG $FFFE ; 复位向量 DW MainInit
159
硬件接线:
• 使用实验板固定接线( PTB0,1,2,3,4,5,6,7 分别接
LA,LB,LC,LD,LE,LF,LG,LDP
PTC0,1,2,3 分别接L11,L12,L13,L14)
163
口地址定义PTA EQU $0000 ;A 口数据寄存器DDRA EQU $0004 ;A 口数据方向寄存器PTB EQU $0001 ;B 口数据寄存器DDRB EQU $0005 ;B 口数据方向寄存器PTC EQU $0002 ;C 口数据寄存器DDRC EQU $0006 ;C 口数据方向寄存器PTD EQU $0003 ;D 口数据寄存器DDRD EQU $0007 ;D 口数据方向寄存器
PTDPUE EQU $000F
164
寄存器地址T1SC EQU $0020 ; 定时器 1 状态和控制寄存器T1CNTH EQU $0021 ; 定时器 1 计数寄存器 ( 高位 )T1CNTL EQU $0022 ; 定时器 1 计数寄存器 ( 低位 )T1MODH EQU $0023 ; 定时器 1 模数寄存器 ( 高位 )T1MODL EQU $0024 ; 定时器 1 模数寄存器 ( 低位 )RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可以更改)FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可以更改)
165
内存变量定义
ORG RAMstartAddr
Show_Buffer RMB 8 ; 存放待显示的数据Cs RMB 1 ; 位选信号Sec RMB 1
Min RMB 1
Hou RMB 1
I1 RMB 1
166
主程序*------ 主程序 --------------------------------------- ORG FlashStartAddr ; 初始化 NOP ; 初始化——————————— SEI ; 禁止所有中断 LDHX #$023F ; 堆栈初始化,放入 GP32的 RAM 最高端 TXS ; 系统初始化 MOV #%00000001,$001E ; 初始化 CONFIG2, 内部总线时钟用作 SCI 的时钟 MOV #%00111101,$001F ; 初始化 CONFIG1, 允许 LVI 复位信号 , ; 禁止 LIV 模块的电源 ,LIV 工作在 5V, ;经过 32 个周期退出 STOP 模式 , 禁止 COP 模块 CLR $0036 ; 清零 , 初始化 PCTL, MOV #$01,$0036 MOV #$01,$0038 MOV #$2C,$0039 MOV #$80,$003A BSET 5,$0036 BSET 7,$0037 ;自动方式 BSET 4,$0036 ; 选择 PLL 为系统时钟源
167
主程序续 LDA #$FF ; 定义 A 口为输出 STA DDRA LDA #$FF ; 定义 B 口为输出 STA DDRB LDA #$FF ; 定义 C 口为输出 STA DDRC LDA #$00 ; 定义 A 口之前复位 PTA STA PTD ;D 口 STA DDRD ; 输入 LDA #$FF ; 定义 D 口有上拉电阻 STA PTDPUE ;STA PTD ; 定时器 1 初始化 LDA #%01100110 ; 允许溢出中断、不启动计数、分频因子 =64 STA T1SC LDHX #$0000 ; 计数寄存器初值 =$0000 STHX T1CNTH LDHX #$9600 ; 设 1 秒产生 1次溢出中断 STHX T1MODH ; 模数寄存器设定值 =1×(2457600/64)=$9600 ; 设置初始时间 MOV #$7F,{Show_Buffer+2} MOV #$7F,{Show_Buffer+5} MOV #$00,Sec
168
主程序续 MOV #$00,Min MOV #$00,Hou ;--------- 设置当前时间 -------------SetUp: JSR Scan SetSec: BRSET 0,PTD,SetMin INC Sec LDA Sec CMP #!59 BNE SetMin MOV #!0,SecSetMin: BRSET 1,PTD,SetHou INC Min LDA Min CMP #!59 BNE SetHou MOV #!0,Min
169
主程序续SetHou: BRSET 2,PTD,SetExit INC Hou LDA Hou CMP #!23 BNE SetExit MOV #!0,Hou SetExit: BRCLR 3,PTD,SetExit2 Mov #$FF,I1ScanDlay: JSR SCAN DBNZ I1,ScanDlay JMP SetUpSetExit2: BCLR 5,T1SC ; 允许定时器 1 计数寄存器计数 CLI
170
扫描子程序Scan:
LDA Hou
LDHX #Show_Buffer
JSR Trans1
LDA Min
LDHX #{Show_Buffer+3}
JSR Trans1
LDA Sec
LDHX #{Show_Buffer+6}
JSR Trans1
JSR Show_Num ; 显示起始数据 RTS
171
转码子程序Trans1: PSHA PSHH PSHX LDHX #$000A DIV LDHX #$0000 TAX LDA Table,X PULX PULH STA ,X AIX #$1 PULA
172
转码子程序续 PSHH PSHX LDHX #$000A DIV PSHH PULA LDHX #$0000 TAX LDA Table,X PULX PULH STA ,X RTS Table FCB $C0,$F9,$A4,$B0,$99,$92,$82,$F8,$80,$90,$40,$4F,
$24,$30,$19,$12,$02,$78,$00,$10,$7f ; 显示码表 0 1 2 3 4 5 6 7 8 9 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. . ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
173
显示子程序Show_Num:
PSHH ; 进栈 , 保存 HX,A 中内容 PSHX
PSHA
LDHX #$0000 ; 清空缓冲区 MOV #$01,CS ;先取第一个数Show_Num_Loop:
LDA Show_Buffer,X ; 取出 Show_Buffer 中一个字符放入 A
STA PTB
PSHX
PSHH
AIX #$4
LDA Show_Buffer,X ; 取出 Show_Buffer 中一个字符放入 A
STA PTA
174
显示子程序续LDA CS ;将 A 中第一个数存入 C 中输出 STA PTC
LDA #!100 ; 延时 100毫秒 JSR Delay_ns
ASL CS ;算术左移 ,修改位选信号 PULH
PULX
AIX #!1
CPX #!4 ;判断扫描是否完毕 BLO Show_Num_Loop ;小于 4 则循环 ;-----------------
PULA ; 出栈 PULX
PULH
RTS
175
延时子程序 1
Delay_ms: LDA #!248 ;0.5ms JSR Delay_ns LDA #!248 ;0.5ms JSR Delay_ns AIX #-!1 CPHX #!0 BNE Delay_ms ;4Cycles RTS ;4Cycles
177
定时器 1 溢出中断子程序Timer1OvF: INC Sec LDA Sec CMP #!60 BLO Tim1OvF_Exit CLR Sec INC Min ; 一分到 LDA Min CMP #!60 BLO Tim1OvF_Exit CLR Min INC Hou ; 一小时到 LDA Hou CMP #!24 BLO Tim1OvF_Exit CLR Sec CLR Min CLR HouTim1OvF_Exit: LDA T1SC ; 清除定时器溢出标志位 BCLR 7,T1SC RTI
182
硬件接线: 使用实验板 LCD固定接线 (1. 单片机的 PTB0-PTB7 作为输出与 LCD的 D0-D7 连接 ;
2. 单片机的 PTC0,PTC1,PTC2 分别接LCD的 RS R/W E;
3. 单片机的 PTA7-4 接 4根键盘列线( X4-1),
PTA3-0 接 4根键盘行线( Y4-1) )
183
软件功能:
• 开始时 ,LCD 显示两行“ Current Time is:
00:00:00 SUDA ”
“*”键为设置键 ,按下后可设置时 , 分 ,秒 , 随后
按“ #” 时钟开始运行 。
184
程序清单:• 口地址定义• 定时器的寄存器地址
定义• 变量定义• 系统初始化• 总循环• 扫描读键值子程序• 键盘中断子程序• 定时器溢出子程序
• 键盘中断初始化子程序
• 键盘转化为具体值子程序
• LCD初始化子程序• LCD命令执行子程序• LCD显示子程序• 转码子程序• 中断矢量
186
口地址定义• * 单片机的 PTA7-4 接 4根键盘列线( X4-1), PTA3-0 接 4根键盘
行线( Y4-1)• DDRA EQU $0004 ;A 口数据方向寄存器• PTA EQU $0000 ;A 口数据寄存器• PTAPUE EQU $000D ;A 口上拉电阻允许寄存器• * 单片机的 PTB0-PTB7 作为输出与 LCD的 D0-D7连接• DDRB equ $0005 ;B 口数据方向寄存器 • PTB equ $0001 ;B 口数据寄存器• * 单片机的 PTC0,PTC1,PTC2分别接 LCD的 RS R/W E• PTC EQU $0002 ;C 口数据寄存器• DDRC EQU $0006 ;C 口数据方向寄存器• LCD-RS EQU 0 ;LCD 寄存器选择信号接 PTC0• LCD-RW EQU 1 ; 读写信号接 PTC1• LCD_E EQU 2 ;LCD使能信号接 PTC2• INTKBSCR EQU $001A ; 键盘状态和控制寄存器• INTKBIER EQU $001B ; 键盘中断允许寄存器 <<<
187
定时器的寄存器地址定义
• T1SC EQU $0020 ; 定时器 1 状态和控制寄存器• T1CNTH EQU $0021 ; 定时器 1 计数寄存器 (高
位 )• T1CNTL EQU $0022 ; 定时器 1 计数寄存器 (低
位 )• T1MODH EQU $0023 ; 定时器 1 模数寄存器 (高
位 )• T1MODL EQU $0024 ; 定时器 1 模数寄存器 (低
位 ) <<<
188
变量定义• RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可以更
改)• FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可以更改)
• ORG RAMstartAddr• LCD_Buffer1 RMB 16 ; 存放 16 字节显示缓冲数据(第一行)• LCD_Buffer2 RMB 16 ; 存放 16 字节显示缓冲数据(第二行)• Sec RMB 1 ; 时钟的秒 • Min RMB 1 ; 时钟的分• Hou RMB 1 ; 时钟的小时• BeginRun RMB 1 ; • SetByte RMB 1 ;• KBValue RMB 1 ; 执行键盘中断程序后,存放键值的内存
KbValue• Tmpvar1 RMB 1 ; 变量 Tmpvar1 ,缓冲使用• Tmpvar2 RMB 1 ; 变量 Tmpvar2 ,缓冲使用• Tmpvar3 RMB 1 ; 变量 Tmpvar3• Tmpvar4 RMB 1 ; 变量 Tmpvar4
<<<
190
系统初始化
NOP ; 初始化开始 SEI ; 禁止所有中断 LDHX #$023F ; 堆栈初始化,放入 GP32的 RAM 最高端 TXS MOV #%00000001,$001E ; 初始化 CONFIG2, 内部总线
时钟用作 SCI 的时钟 MOV #%00111101,$001F ; 初始化 CONFIG1, 允许 LVI
复位信号 , ;禁止 LIV 模块的电源 ,LIV 工作在 5V, ; 经过 32个周期退出 STOP 模式 ,禁止 COP
模块
<<<
191
PLL 初始化
; 外接晶阵32.768KHz, 初始化成总线频率为 2.4576MHz CLR $0036 ; 清零 ,初始化 PCTL, MOV #$01,$0036 MOV #$01,$0038 MOV #$2C,$0039 MOV #$80,$003A BSET 5,$0036 BSET 7,$0037 ;自动方式 BSET 4,$0036 ; 选择 PLL 为系统时钟源
<<<
192
端口初始化
LDA #%11110000 STA PTAPUE LDA #%11111111 ;B 口为输出 STA DDRB LDA #%00000111 ;C 口的 PTC0-2 为输出 STA DDRC
<<<
193
定时器 1 初始化
LDA #%01100110 ; 允许溢出中断、不启动计数、分频因子 =64
STA T1SC LDHX #$0000 ; 计数寄存器初值 =$0000
STHX T1CNTH LDHX #$9600 ; 设 1 秒产生 1次溢出中
断 STHX T1MODH ; 模数寄存器设定值 =1×(2457600/64)=$9600
<<<
194
设定初始时间 LDHX #$0000Display1: ;把要显示的 16 个初始字符放入
LCD_Buffer1—2 中 LDA DisplayBytes1,X STA LCD_Buffer1,X LDA DisplayBytes2,X STA LCD_Buffer2,X AIX #1 CPHX #$10 BNE Display1 ; 循环 16次 JSR Init_LCD ;LCD 初始化 JSR Show_LCD ;将内存 LCD_Buffer1—2 的 32字节
ASCII 字符送 LCD 显示 MOV #$00,SEC MOV #$00,MIN MOV #$00,HOU
<<<
196
总循环
;允许定时器 1 计数寄存器计数, ;开放定时中断 ,开放键盘中断 BCLR 1,INTKBSCR ; 开放键盘中断 BCLR 5,T1SC ; 允许定时器 1 计数寄存器计数 CLI ; 开放中断 ;总循环Start_1: ; 总循环开始处 NOP ; 仅为实验例程,主循环无实际工作 BRA Start_1
<<<
197
扫描读键值子程序(从 KBA 开始)
功能:扫描一次接在 PTA 口的 4*4 键盘 ( PTA7-4 接 4根键盘列线( X4-1), PTA3-0 接 4根键盘行线( Y4-1 )上的按键(使用行扫描法), 键值放在A 中若无按键 , A 中值 $FF
占用内存: Tmpvar1 (缓冲使用) 出口: A= 键值 -------------------------------------------------------------------
<<<
198
扫描读键值子程序
KBA: MOV #%11111110,Tmpvar1 ; 第一根行线为 0 LDX #$04 ; 扫描 4根行线KB1: LDA PTA ;取 PTA给 A ORA #%00001111 ;PTA7-4 保留原态, PTA3-0 为 1 AND Tmpvar1 ;令 PTAn=0, n=0, 1, 2, 3 STA PTA ; 处理后给 PTA 以便查询 NOP NOP LDA PTA ; 查第 n 列上是否有键按下 AND #%11110000 ; 保留 PTA7-4列值,令低 PTA3-0=0 CBEQA #$F0,KB2 ;A 等于 $F0 ,本行线没键按下,转到 KB2 ;A 不等于 $F0, 本行有键按下 LDA PTA ;A 放键值 BRA KB3 ; 转到 KB3 结束中断KB2: SEC ;令 C=1 ROL Tmpvar1 ;使下一个行线为 0,查下一行 DBNZX KB1 ; 对行线循环 LDA #$FF ; 没有键被按下为 $FFKB3:RTS
<<<
200
键盘中断初始化子程序
KBInit: LDA #$00 ; 定义 A 口之前复位 PTA STA PTA LDA #%00001111 ; 定义 A 口 7-4 输入(作为列), 3-0 输出(作为
行) STA DDRA LDA #%11110000 ; 定义 A 口 7-4 有上拉电阻 STA PTAPUE BSET 1,INTKBSCR ;屏蔽键盘中断 LDA #%11110000 ; 允许 KBIE7-4PIN 中断进入 STA INTKBIER BSET 2,INTKBSCR ; 清除键盘中断 RTS <<<
201
键盘中断子程序(从 KBint 开始)
--- 键盘中断子程序(从 KBint 开始) --------------
功能:键盘中断程序,键值放入内存 KbValue 中
调用子程序:扫描法读键值子程序( KBA),键盘中断初始化子程序( KBInit )
出口:第 0 页内存单元 KbValue 中为键值 -------------------------------------------------------------- <<<
202
键盘中断子程序 1KBint: PSHH ; 保护 H SEI ; 禁止中断 BSET 1,INTKBSCR ; 禁止键盘中断 JSR KBA ; 调子程序 KBA ,键值放在 A 中 STA KbValue ; 放入内存 KbValue JSR KBdef ; 执行键盘转化为具体值子程序,转成键定义值 ; 是否为 "*"? , 不是退出 KBint_Exit CMP #!42 ;ASCI "*" 键 BEQ SetUpBegin JMP KBint_Exit ; 不是 , 等待 "*" 键SetUpBegin: ; 是 "*",xx:xx:xx BSET 2,INTKBSCR ; 清除键盘中断 MOV #$0,SetByte ;赋初值 0SetUpStore: ; 保存原来每位显示的数据 LDHX #$00 LDX SetByte LDA LCD_Buffer2,X STA Tmpvar4 SetUp: LDHX #$00 LDX SetByte LDA #!32 ;" "
<<<
203
键盘中断子程序 2
STA LCD_Buffer2,X
JSR Show_LCD ;将内存 LCD_Buffer1—2 的 32 字节 ASCII 字符送 LCD 显示 LDHX #!90 ; 延时 90毫秒 JSR Delay_ms
LDHX #$00
LDX SetByte
LDA Tmpvar4 ;原来的值 STA LCD_Buffer2,X
JSR Show_LCD ;将内存 LCD_Buffer1—2 的 32 字节 ASCII 字符送 LCD 显示 LDHX #!90
JSR Delay_ms
JSR KBA ; 调子程序 KBA ,键值放在 A 中 STA KbValue ; 放入内存 KbValue
JSR KBdef ; 执行键盘转化为具体值子程序,转成键定义值放入 A 中 CMP #$23 ; 是 "#"
BEQ KBint_Exit0
CMP #$39
BHI SetUp ;>$39( 数值 >9)转 SetUp
CMP #$30
BLO SetUp ;<$30( 数值 <0)转 SetUp
<<<
204
键盘中断子程序 3 PSHA ; 保护 A(ASCII 值 ) ;判断当前位的输入是否有效 ; 第 0 位只能是 0~2 ,第 0 位和第 1 位合在一起小于 24 ; 第 3 、 6 位小于 6 LDA SetByte CMP #!0 BEQ SetUp0 CMP #!1 BEQ SetUp1 CMP #!3 BEQ SetUp2 CMP #!6 BEQ SetUp2 PULA BRA SetUp3 SetUp0: ; 第 0 位只能是 0~2(ASCII 值小于等于 32 ) PULA CMP #$32 BHI SetUp ;>$32( 数值 2) 无效 转 SetUp BRA SetUp3 <<<
205
键盘中断子程序 4SetUp1: ; 第 0 位和第 1 位合在一起小于 24 LDA LCD_Buffer2 SUB #$30 ;ASCII 值 ---> 数值 LDX #!10 MUL ;(A)*(X)-->A STA TmpVar3 ;A---->临时单元 TmpVar3 PULA PSHA SUB #$30 ;ASCII 值 ---> 数值 ADD TmpVar3 CMP #!23 PULA BHI SetUp ;>23 无效 转 SetUp BRA SetUp3 ; 有效 转 SetUp3SetUp2: ; 第 3 、 6 位小于 6(ASCII 值小于 36 ) PULA CMP #$36 BHS SetUp ;>=36( 数值 >=6) 无效 转 SetUp SetUp3: ; 是有效的数,则置于相应位置 LDHX #$00 LDX SetByte STA LCD_Buffer2,X <<<
206
键盘中断子程序 5
INC SetByte ; 设置下一位
;判断下一位是不是第 2 、 5 (:)、 8 位 LDA SetByte
CMP #!2
BEQ SetUp4
CMP #!5
BEQ SetUp4
CMP #!8 ; 是第 8 位,退出设置 BHS KBint_Exit0
BRA SetUp5
SetUp4: ; 是第 2 、 5 位(:) , 跳过该位的设置 INC SetByte
SetUp5:
JMP SetUpStore
KBint_Exit0:
;将当前的设置值放到变量 Hou、Min、 Sec 中 LDA LCD_Buffer2
SUB #$30 ;ASCII 值 ---> 数值 LDX #!10
MUL
LDHX #!1
ADD LCD_Buffer2,X <<<
207
键盘中断子程序 6 SUB #$30
STA Hou
LDHX #!3
LDA LCD_Buffer2,X
SUB #$30 ;ASCII 值 ---> 数值 LDX #!10
MUL
LDHX #!4
ADD LCD_Buffer2,X
SUB #$30
STA Min
LDHX #!6
LDA LCD_Buffer2,X
SUB #$30 ;ASCII 值 ---> 数值 LDX #!10
MUL
LDHX #!7
ADD LCD_Buffer2,X
SUB #$30
STA Sec
JSR Show_LCD ;将内存 LCD_Buffer1—2 的 32 字节 ASCII 字符送 LCD 显示<<<
208
键盘中断子程序 7
BCLR 7,T1SC ; 清除定时器溢出标志位
KBint_Exit:
PULH ;H 出栈 BSET 1,INTKBSCR ; 禁止键盘中断 BSET 2,INTKBSCR ; 清除键盘中断 JSR KBInit ; 调用键盘中断初始化子程序 BCLR 1,INTKBSCR ; 开放键盘中断 CLI
RTI<<<
209
键盘转化为具体值子程序(从 KBdef 开始)
功能:键值转为键盘表面具体的字符或符号代表值
入口:内存第 0页中 KBValue 为键值, 使用键值编号表 占用 CPU 寄存器: X (存放相对地址)
出口: A= 键定义值
<<<
210
键盘转化为具体值子程序KBdef: LDHX #$0000 KBkey1: LDA KBTABLE,X BEQ KBkey3 ;=0 ,表示表中未定义此键值 CMP KBValue ;与 KBValue 入口键值相比较 BNE KBkey2 ; 不等,未找到转 KBkey2 INCX ;找到地址加 1 LDA KBTABLE,X ; 取键定义值给 A BRA KBkeyrKBkey2: INCX INCX BRA KBkey1KBkey3: LDA #$FF ; 未定义键用 FF标志KBkeyr:RTSKBTABLE FCB $EE,"1",$DE,"2",$BE,"3",$7E,"A" FCB $ED,"4",$DD,"5",$BD,"6",$7D,"B" FCB $EB,"7",$DB,"8",$BB,"9",$7B,"C" FCB $E7,"*",$D7,"0",$B7,"#",$77,"D" FCB $00
<<<
211
Init_LCD(LCD 初始化子程序 )• 入口 : 无 • 功能 : 初始化 LCD(HD44780)
• 调用子程序 :LCD_Command(LCD 命
令执行子程序 ) •占用 CPU 内部寄存器 :A,X
<<<
212
Init_LCDInit_LCD: BCLR LCD-RS,PTC ;令 LCD的 RS=0,R/W=0, 进行 LCD 初始化 BCLR LCD-RW,PTC LDA #%00111000 ; 功能设置 :8位数据接口 ,2行显示 ,5*7 点阵模式 JSR LCD_Command LDA #%00001000 ; 显示开关控制 :关显示,关光标显示 ,不闪烁 JSR LCD_Command LDHX #$0020 ; 等待 40us DBNZX * BCLR LCD-RS,PTC ;RS,RW 清零开始清屏 BCLR LCD-RW,PTC LDA #%00000001 ; 清屏指令 JSR LCD_Command LDHX #$2DF ; 等待清屏完毕 ,时间 >1.6msCLR-LCD-2-MS: ; 延时 AIX #-1 CPHX #0 BNE CLR-LCD-2-MS LDA #%00000110 ; 输入方式设置 : 数据读写操作后 ,AC自动增 1 ;显示不动 ,光标左移 JSR LCD_Command LDA #%00010100 ;光标移位设置 :光标右移一个字符位 ,AC自动加 1 JSR LCD_Command LDA #%00001100 ; 显示开关设置 : 开显示 , 关光标显示 ,不闪烁 JSR LCD_Command RTS
<<<
213
LCD_Command(LCD 命令执行子程序 )
• 入口 :A
• 功能 :对 A中指令使用 PORTA 作为输出口 ,• 到 LCD 进行命令执行或字符显示 •占用 CPU 内部寄存器 :A
<<<
214
LCD_CommandLCD_Command: PSHH ; 保护现场 PSHX LDHX #$0020 ; 等待 40us DBNZX * STA PTB ;把指令码送到 A 口 NOP NOP BSET LCD_E,PTC ;LCD 开始接受数据 , 置使能位为 1 NOP NOP BCLR LCD_E,PTC ;LCD 结束接受数据 , 置使能位为 0 LDHX #$0020 ; 等待 40us DBNZX * PULX ;恢复现场 PULH RTS
<<<
216
Show_LCD
; 第一行Show_LCD: ; 进行显示数据寄存器 (DD RAM) 地址设置 BCLR LCD-RS,PTC
BCLR LCD-RW,PTC ; 设置前 8 个字符首 DD RAM 地址 LDA #%10000000
JSR LCD_Command
LDHX #$00 ; 显示前 8 个字符Show-First-8Byte:
BSET LCD-RS,PTC ;令 LCD的 RS=1,R/W=0, 写入数据到 DD RAM 中 BCLR LCD-RW,PTC
LDA LCD_Buffer1,X ;将 {LCD_Buffer+X} 的数据放入 A 作为入口 JSR LCD_Command
AIX #1
CPHX #$8
BNE Show-First-8Byte
LDA #%10001000 ; 设置后 8 个字符首 DD RAM 地址 BCLR LCD-RS,PTC
BCLR LCD-RW,PTC
JSR LCD_Command
LDHX #$08 ; 显示后 8 个字符 <<<
217
Show_LCD1Show-Next-8Byte:
BSET LCD-RS,PTC ;令 LCD的 RS=1,R/W=0, 写入数据到 DD RAM 中 BCLR LCD-RW,PTC
LDA LCD_Buffer1,X ;将 {LCD_Buffer+X} 的数据放入 A 作为入口 JSR LCD_Command
AIX #1
CPHX #$10
BNE Show-Next-8Byte
; 第二行 , 进行 DD RAM 地址设置 BCLR LCD-RS,PTC ;令 LCD的 RS= 0、 R/W=0
BCLR LCD-RW,PTC
LDA #%11000000 ; 设置 DD RAM 地址为 #%1000000 (即 40H)
JSR Lcd_Command ; 执行设置光标在 DDRAM 位置 LDHX #$0 ; 显示前 8 个字符 Show_F_8b2:
BSET LCD-RS,PTC ;令 LCD的 RS=1,R/W=0 :写数据 BCLR LCD-RW,PTC
LDA LCD_Buffer2,x ;将 LCD_Buffer 开始的中第 x 位数据存放入 A 中 JSR Lcd_Command ; 执行命令 AIX #1
CPHX #$8
BNE Show_F_8b2 ;完成前 8 个字符的显示<<<
218
Show_LCD2
; 进行 DD RAM 地址设置
LDA #%11001000 ; 设置 DDRAM 地址为 #%1000000 (即 48H)
BCLR LCD-RS,PTC ;令 LCD的 RS= 0、 R/W=0
BCLR LCD-RW,PTC
JSR Lcd_Command ; 执行命令
LDHX #$08 ; 显示后 8 个字符
Show_N_8b2:
BSET LCD-RS,PTC ;令 LCD的 RS=1,R/W=0 :写数据
BCLR LCD-RW,PTC
LDA LCD_Buffer2,x ;将 LCD_Buffer 开始的中第 x 位数据存放入 A 中
JSR Lcd_Command ; 执行命令
AIX #1
CPHX #$10
BNE Show_N_8b2 ;完成后 8 个字符的显示
RTS <<<
219
转码子程序TimeCH: PSHA ; 进栈 , 保存 A,H,X 中的内容 PSHH PSHX LDHX #$000A ; 取 10 DIV ; 除以 10,A 中放商 ,H 中放余数 ADD #$30 ; 实际数值加上 $30(!48)变 ASCII 码 PULX ;X 出栈 PULH ;H 出栈 STA ,X ;把 A 的内容存储到以 (X) 为地址的单元中 AIX #$1 ;立即数 1加到变址寄存器 , 转下一字符 PULA PSHH PSHX LDHX #$000A DIV PSHH PULA ADD #$30 PULX PULH STA ,X RTS
<<<
220
定时器溢出中断子程序Timer1OvF: INC Sec LDA Sec CMP #!60 BLO Tim1OvF_Exit CLR Sec INC Min ; 一分到 LDA Min CMP #!60 BLO Tim1OvF_Exit CLR Min INC Hou ; 一小时到
LDA Hou CMP #!24 BLO Tim1OvF_Exit CLR Sec CLR Min CLR Hou
<<<
221
定时器溢出中断子程序 1
Tim1OvF_Exit: LDA T1SC ; 清除定时器溢出标志位 BCLR 7,T1SC SendToDisp: LDA Hou ;将小时转为两字节 ACSII 码字符放入显示缓冲区 LCD_Buffer2: LDHX #LCD_Buffer2 JSR TimeCH LDA min ;将小时转为两字节 ACSII 码字符放入显示缓冲区 LCD_Buffer2: LDHX #{LCD_Buffer2+!3} JSR TimeCH LDA SEC ;将小时转为两字节 ACSII 码字符放入显示缓冲区 LCD_Buffer2: LDHX #{LCD_Buffer2+!6} JSR TimeCH JSR Show_LCD ; 显示起始数据 RTI
<<<
222
延时子程序Delay_ms: LDA #!248 ;0.5ms JSR Delay_ns LDA #!248 ;0.5ms JSR Delay_ns AIX #-!1 CPHX #!0 BNE Delay_ms ;4Cycles RTS ;4Cycles
<<<
224
中断矢量 ORG $FFE0 ; 键盘中断矢量 DW KBint ORG $FFF2 ; 时钟中断矢量 DW Timer1OvF ORG $FFFE ; 复位向量 DW MainInit
<<<
228
硬件接线 :
VCC
16151413121110090807060504030201
LC
D(H
D4478
0)
Q7Q6Q5Q4Q3Q2Q1Q0
B
A
CP
CR
VCC
74H
C164
MOS1
SPSCK
PTC3
PTC2PTC1PTC0
SSVCC
MC
68H
C908G
P3
2
230
程序清单: 程序说明 口地址定义 SPI地址定义 SCI串行通信口定义 变量定义 系统初始化
主程序 LCD初始化子程序 LCD命令执行子程序 74HC164初始化 LCD显示子程序 中断矢量
231
*-------------- 程序说明 --------------------------** 文件名 LCD.ASM* 硬件连接: 74HC164的Q0-Q7 分别接 LCD的DB0-
DB7;* 74HC164的MR,CLK 接分别 MCU的
PTC3,SCK;* 74HC164的 B接MCU的VCC(+5V);* 74HC164的 A 接MCU的MOSI;* LCD的 E,R/W,RS 分别接的
PTC2,PTC1,PTC0。* 程序描述: 1.开始运行时 ,LCD 显示“ Wait Receiving..”* 2. 等待接收字符,当收到 16 个字符时显示之,* 重复此功能。* 目的:掌握点阵字符型液晶显示 (LCD) 编程方法*备注说明:从 PC 机输入被显示的 16 个字符,以串行通信方* 式发送到单片机,在液晶屏上显出这些字符。*-------------------------------------------------*
232
*----- 口地址定义 -------------------------------PTC EQU $0002 ;C 口数据寄存器LCD-RS EQU 0 ;LCD 寄存器选择信号接 PTC0
LCD-RW EQU 1 ; 读写信号接 PTC1
LCD-E EQU 2 ;LCD 使能信号接 PTC2
HC164-CR EQU 3 ;74HC164 (移位寄存器) ; 清除端接 PTC3
DDRC EQU $0006 ;C 口数据方向寄存器*----SPI( 串行外设接口 )地址定义 -------------------SPCR EQU $0010 ;SPI 控制寄存器SPSCR EQU $0011 ;SPI 状态和控制寄存器BIT-SPTE EQU 3 ;SPI 发送器空标志位SPDR EQU $0012 ;SPI 数据寄存器
233
*----SCI 串行通信口地址 ------------------------SCS1 EQU $0016 ; 串行通信接口状态寄存器地址
SCDR EQU $0018 ; 串行通信接口数据寄存器地址
*---- 变量定义 ---------------------------------ORG $0090
BYTEDISPLY RMB 1 ; 临时存放一个字符
LCD-BUFFER RMB 16 ; 存放 16字节
FlashStartAddr equ $8000
; 程序开始地址(因芯片不同可以更改)
**********************************************
234
*--------- 主程序 -------------------------------- ORG FlashStartAddr
MainInit: ; 复位后程序从此开始执行 ; 系统初始化 SEI ; 禁止所有中断 LDHX #$023F ; 堆栈初始化,放入 GP32的 RAM 最高端
TXS JSR Init0 ; 调系统初始化子程序 Init0 ,初始学习时跳过此处
;I/O 初始化 NOP ; 初始化 LDA #%00111010 ;SPI 初始化设置 : 禁止中断 , ; 主机方式 , 时钟低电平有 SPSCK启动移位、 ;脉冲 ,普通推拉模式 , 允许 SPI
STA SPCR LDA #%00000000 ; 禁止中断 , 禁止错误检测 , ; 时钟分频系数为 2 STA SPSCR
235
LDA DDRC ; 初始化 E, RW, RS 控制信号
ORA #%00001111 ;PTC3-0 为输出 STA DDRC
LDHX #$00DISPLAY1: ; 把要显示的 16 个初始字符 ; 放入 LCD-BUFFER 中 LDA DISPLAYBYTES,X
STA LCD-BUFFER,X
AIX #1
CPHX #$10 BNE DISPLAY1 ; 循环 16次 BRA START
236
DISPLAYBYTES FCB "WAIT RECEIVING.."
START:
JSR INIT-74HC164 ; 初始化 74HC164
;( 移位寄存器 )
JSR INIT-LCD ;LCD 初始化
JSR SHOW-LCD-BUFFER ; 把 LCD-BUFFER 中的
;16 个字符送 LCD 显示
237
LDHX #$00 DISPLAY2: ; 从 PC 机接收 16 个字符放入 LCD-
;BUFFER 开始的内存中 BRCLR 5,SCS1,* ; 与 PC 机串行通信 , 判断接收器 ;是否满 LDA SCDR ; 读 SCI 数据寄存器 STA LCD-BUFFER,X
AIX #1
CPHX #$10
BNE DISPLAY2
JMP START
***************************************************
238
*---INIT-LCD(LCD 初始化子程序 )------------------* 入口 : 无* 功能 : 初始化 LCD(HD44780)
* 调用子程序 :LCDCOMMAND(LCD 命令执行子程序 )*占用 CPU内部寄存器 :A,X
*----------------------------------------------
INIT-LCD: BCLR LCD-RS,PTC ;令 LCD的 RS=0,R/W=0,
; 进行 LCD 初始化 BCLR LCD-RW,PTC LDA #%00111000 ; 功能设置 :8 位数据接口 , ;2 行显示 ,5*10点阵模式 JSR LCDCOMMAND
239
LDA #%00001000 ; 显示开关控制 : 开显示, ; 关光标显示 , 不闪烁 JSR LCDCOMMAND JSR INIT-74HC164 ;74HC164( 移位寄存器 ) ; 初始化 BCLR LCD-RS,PTC ;RS,RW 清零开始清屏 BCLR LCD-RW,PTC BRCLR BIT-SPTE,SPSCR,* ; 判断发送数据寄存器 ;是否为空 LDA #%00000001 ; 清屏指令 JSR LCDCOMMAND LDHX #$2DF ; 等待清屏完毕 , 时间 >1.6ms
240
CLR-LCD-2-MS: ; 延时 AIX #-1 CPHX #0 BNE CLR-LCD-2-MS LDA #%00000110 ; 输入方式设置 : 数据读写
;操作后 ,AC自动增 1 显示不动 , ;光标左移 JSR LCDCOMMAND LDA #%00010100 ; 光标移位设置 :光标右 ; 移一个字符位 ,AC自动加 1 JSR LCDCOMMAND LDA #%00001100 ; 显示开关设置 : 开显示 , ; 关光标显示 , 不闪烁 JSR LCDCOMMAND RTS
241
*----LCDCOMMAND(LCD 命令执行子程序 )----------
* 入口 :A
* 功能 :对 A 中指令送 LCD(HD44780), 进行命令执行或
*字符显示*占用 CPU内部寄存器 :A
*-------------------------------------------
LCDCOMMAND:
PSHH ; 保护现场
PSHX
PSHA ; 保护入口指令码
BRCLR BIT-SPTE,SPSCR,* ; 测试状态 , 发送数据 ; 寄存器是否为空
242
JSR INIT-74HC164 ; 初始化 74HC164 芯片
PULA ; 弹出入口指令码
STA SPDR ; 把指令码发送出去
BRCLR BIT-SPTE,SPSCR,* ; 测试发送完毕
NOP
NOP
BSET LCD-E,PTC ;LCD 开始接受数据 , ; 置使能位为 1
243
NOP
NOP BCLR LCD-E,PTC ;LCD结束接受数据 , 置 ; 使能位为 0 LDHX #$0020 ; 等待 40us
DBNZX * PULX ; 恢复现场
PULH
RTS
********************************************
244
*---INIT-74HC164(74HC164 初始化 )--------------* 入口 : 无* 功能 : 清空 74HC164
*占用 CPU内部寄存器 :HX
*-------------------------------------------
INIT-74HC164:
BCLR HC164-CR,PTC ;CR 为 0 清除 74HC164 中的数据
BSET HC164-CR,DDRC LDHX #$0020 ; 等待 40us
DBNZX * BSET HC164-CR,PTC ; 清除完毕 ,74HC64的 CR
; 转为高电平 RTS
245
*----SHOW-LCD-BUFFEER(LCD 显示子程序 )-------*
* 入口 :内存 LCD-BUFFER 开始的 16 个地址中存放要显
* 示的字符编码* 功能 : 显示内存 LCD-BUFFER 开始的 16字节数据* 调用 :LCDCOMMAND 子程序*占用 CPU内部寄存器 :A,HX
*------------------------------------------*SHOW-LCD-BUFFER: ; 进行显示数据寄
存器 ;(DD RAM) 地址设置 BCLR LCD-RS,PTC BCLR LCD-RW,PTC ; 设置前 8 个字符 ;首DDRAM 地址
246
LDA #%10000000
JSR LCDCOMMAND LDHX #$0 ; 显示前 8 个字符
SHOW-FIRST-8BYTE: BSET LCD-RS,PTC ; 令 LCDRS=1,R/W=0,
; 写入数据到 DD RAM 中
BCLR LCD-RW,PTC LDA LCD-BUFFER,X ; 将 {LCD-
BUFFER+X}
; 的数据放入 A 作为入口
JSR LCDCOMMAND
247
AIX #1
CPHX #$8
BNE SHOW-FIRST-8BYTE LDA #%11000000 ; 设置后 8 个字符首DD
RAM 地址
BCLR LCD-RS,PTC
BCLR LCD-RW,PTC
JSR LCDCOMMAND LDHX #$08 ; 显示后 8 个字符
SHOW-NEXT-8BYTE: BSET LCD-RS,PTC ; 令 LCD的 RS=1,R/W=0,写入
; 数据到 DD RAM 中
248
BCLR LCD-RW,PTC LDA LCD-BUFFER,X ; 将 {LCD-
BUFFER+X} 的数据 ; 放入 A 作为入口 JSR LCDCOMMAND
AIX #1
CPHX #$10
BNE SHOW-NEXT-8BYTE
RTS
********************************************
-- 中断矢量 --------------------------------* ORG $FFFE ; 复位向量 DW MAININIT
249
系统初始化• Init0: ; 系统初始化 Init0 子程序• LDA #%00000001 ; 初始化 CONFIG2• STA $001E• LDA #%00111101 ; 初始化 CONFIG1• STA $001F• CLR $0036 ; 初始化 PTCL• MOV #$01,$0036• MOV #$01,$0038• MOV #$2C,$0039• MOV #$80,$003A• BSET 5,$0036• BSET 7,$0037• BSET 4,$0036• RTS
254
软件功能:1、 LCD 上下两层每 0.5秒滚动显示以下内容
"0123456789ABCDEF""abcdefgh…xyz"
每滚动一次,都将 PTC.3 取反
2、当键盘任一键按下时, LCD 下层清屏显示该字 符, 0.5秒后,恢复“ abcdefgh…xyz”滚动 显示
3、串行口向 PC 机发送 189作为握手信号,接着发一开关信号, PC 机接收到握手信号189和开关信号回送一个握手信号 并发送一个 0 到 63 之间的数,并将发送数据在界面上用指示灯模拟显示 , 串行口接收后,送入 PTD, 并用指示灯高 6 位显示
256
程序清单:• 口地址定义• 变量定义• 系统初始化• 总循环• 扫描读键值子程序• 键盘中断子程序键盘• 中断初始化子程序
• 键盘转化为具体值子程序• LCD初始化子程序• LCD命令执行子程序• LCD显示子程序• 延时子程序• 系统初始化子程序• 中断矢量
257
口地址定义
PTA equ $0000 ;A 口寄存器
PTB equ $0001 ;B 口寄存器
PTC equ $0002 ;C 口寄存器
PTD equ $0003 ;D 口寄存器
DDRA equ $0004 ;A 口方向寄存器
DDRB equ $0005 ;B 口方向寄存器
DDRC equ $0006 ;C 口方向寄存器
DDRD equ $0007 ;D 口方向寄存器
PTAPUE equ $000D ;A 口上拉电阻允许寄存器
PTE equ $0008 ;E 数据寄存器<<<
258
寄存器及相关变量定义SCC1 EQU $0013 ;SCI 控制寄存器 1
SCC2 EQU $0014 ;SCI 控制寄存器 2
SCSR EQU $0016 ; 串行通信接口状态寄存器地址SCDR EQU $0018 ; 串行通信接口数据寄存器地址SCBR EQU $0019 ;SCI 波特率寄存器INTKBSCR EQU $001A ; 键盘状态和控制寄存器INTKBIER EQU $001B ; 键盘中断允许寄存器LCD-RS EQU 0 ;LCD 寄存器选择信号接 PTC0
LCD-RW EQU 1 ; 读写信号接 PTC1
LCD-E EQU 2 ;LCD使能信号接 PTC2
b_TDRF EQU 7 ; 发送缓冲区空标志位B_TC EQU 6 ; 发送完成标志位b_RDRF EQU 5 ; 接收器满标志位 <<<
259
内存变量定义
RAMstartAddr equ $0040 ;RAM 的起始地址(因芯片不同可以更改)
FlashStartAddr equ $8000 ; 程序开始地址(因芯片不同可以更改)
org RAMstartAddr ;RAM 的起始地址Lcd-Buffer RMB 16 ;LCD上层值Lcd-Buffer1 RMB 26 ;LCD下层值Lcd-Buffer2 RMB 16 ;LCD 键盘值TmpVar1 rmb 1 ; 变量 TmpVar1, 缓冲使用TmpVar2 rmb 1 ; 变量 TmpVar2, 缓冲使用KB_Value rmb 1 ; 键盘按键值LCD_Loop RMB 1 ;LCD 循环变量
<<<
260
主程序 org FlashStartAddr ; 程序起始地址MainInit: ; 复位后程序从此开始执行 ; 系统初始化 SEI ; 禁止所有中断 LDHX #$023F ; 堆栈初始化,放入 GP32的 RAM 最高端 TXS JSR Init0 ; 调系统初始化子程序 Init0 ,初始学习时跳过此处 ;I/O 初始化 LDA #%11111111 ;A 口为输出 STA DDRA STA DDRD STA PTD STA DDRB LDA #%00001111 ;PTC0-PTA3 为输出 ,PTC4 为输入 STA DDRC STA PTC
<<<
261
串行口初始化和键盘中断
;---- 串行口初始化 ------------------------------------------------- LDA #%01000000 ;D6(ENSCI)=1, 允许 SCI, 其它位为 0, ;正常码输出 ,8位数据 ,无检验 STA SCC1 LDA #%00001100 ;允许发送器 ,允许接收器 ,不允许发送与接收中断 STA SCC2 LDA #%00000010 ; 波特率为 9600 STA SCBR ;RAM 区 ;---- 设置键盘中断,开放键盘中断 JSR KB_Init ; 执行键盘初始化程序 BCLR 1,INTKBSCR ; 开放键盘中断 (IMASKK=0) CLI
262
主循环开始处START: JSR INIT-LCD ;LCD 初始化 JSR Display MOV #$00,LCD_loopBEGIN: LDA LCD_Loop AND #$00000001 ; 取出最后一位,判断是否为 0 CMP #$0 BNE CON BSET 3,PTC ;PTDC.3=1.PTC.4=0 BCLR 4,PTC JMP CON1 CON: BCLR 3,PTC ;PTDC.3=1.PTC.4=0 BSET 4,PTC
<<<
263
主循环 1CON1: LDA LCD_Loop ; 取出循环变量值 CMP #$10 ;判断是否大于 16 BLO LcdBuffEnd ; 若大于取模( A-16-->A) SUB #$10LcdBuffEnd: JSR Show-Lcd-Buffer1 ; 显示 LCD上层 16 字符 LDA LCD_Loop JSR Show-Lcd-Buffer2 ; 显示 LCD下层 26 字符循环 LDA #!86 ; 发送握手信号:数字 86 BRCLR 7,SCS1,* ; 测试第 7位直到为 1,即发送出 STA SCDR ;A→SCDR, 发送出去 ;取 C 口开关量 BRCLR 4,PTC,PTC4_0 ;判断 PTC4 值 LDA #!1 ;PTC4=1, 允许发送 BRA PTC4_EXITPTC4_0: LDA #!0 ;PTC4=0, 不允许发送PTC4_EXIT: ; 发送数据 BRCLR 7,SCS1,* ; 测试第 7位直到为 1,即发送出去 STA SCDR ;A→SCDR, 发送出去 LDHX #$FFFF ; 延时
<<<
264
主循环 2CommTest1: BRCLR 5,SCS1,CommTest2 ; 接收回送数据 LDA SCDR ; CMP #!86 ;判断是否为 86 BNE CommTest2 ; 不是跳出 LDA LCD_Loop ;回送本次循环值 BRCLR 7,SCS1,* ; 测试第 7位直到为 1,即发送出去 STA SCDR ;A→SCDR, 发送出去 BRCLR 5,SCS1,* ; 接收 PC 机发送用于 PTD 显示的数据 LDA SCDR ; 取数 STA PTD ; 放入 PTD 口,并送灯显示 JSR DelaySubCommTest2: AIX #-1 ;HX-1 CPHX #$0000 BNE CommTest1 ;判断延时是否结束 INC LCD_Loop ; 循环变量加 1 LDA LCD_Loop ;将循环变量送入 A CMP #!26 ;判断是否循环 26次 BNE BEGIN JMP START
<<<
265
系统初始化
Init0: ; 系统初始化 Init0 子程序 LDA #%00000001 ; 初始化 CONFIG2 STA $001E LDA #%00111101 ; 初始化 CONFIG1 STA $001F CLR $0036 ; 初始化 PTCL MOV #$01,$0036 MOV #$01,$0038 MOV #$2C,$0039 MOV #$80,$003A BSET 5,$0036 BSET 7,$0037 BSET 4,$0036 RTS
<<<
266
键盘中断初始化子程序 (KB_Init)功能:度被定义为键盘中断的引脚进行初始化,但未开放键盘中断占用 CPU 内寄存器: A *KB_Init: LDA #%00 ; 定义 A 口之前复位 PTA STA PTA LDA #%00001111 ; 定义 A 口 6-4 为输入, 3-0 为输出 STA DDRA LDA #%11110000 ; 定义 A 口 7-4 有上拉电阻 STA PTAPUE BSET 1,INTKBSCR ;屏蔽键盘中断 (IMASK=1) LDA #%11110000 ; 允许 KBIE7-4pin 中断进入 STA INTKBIER BSET 2,INTKBSCR ; 清除键盘中断请求 (ACKK=1) RTS
<<<
267
扫描读取键值 (KB_A)KB_A: MOV #%11111110,TmpVar1 ;使第一根行线为 0( 低电平 ) LDX #$04 ;将扫描 4根行线KB_A1: LDA PTA ;取 PTA->A ORA #%00001111 ;PTA7-4 保留原态, PTA3-0 令为 1 AND TmpVar1 ;令 PTAn=0,n=0、 1、 2、 3 STA PTALDA PTA ; 看第 n列是否有键按下 AND #%11110000 ;PTA7-4 保留原态,令低 4 为 =0 CBEQA #$F0,KB_A2 ;A 等于 $F0, 说明本列线上没有键家按下,在转 KB_A2
;A 不等于 $F0,找到了被按下得键取键值 -〉 A LDA PTA BRA KB_A3KB_A2: SEC ;令 C=1 ROL TmpVar1 ;使下一个列线为 0 DBNZX KB_A1 ; 对列线循环 LDA #$FF ; 没有键被按下为 $FFKB_A3: RTS
<<<
268
键值转为定义值子程序 (KB_def)KB_def: LDHX #$0000KB_def1: LDA KB_Table,X ; BEQ KB_def3 ;=0, 表示表中未定义此键值 CMP KB_Value ; 与入口键值相比较 BNE KB_def2 ; 不等,未找到转 KB_key2 INCX ;找到 LDA KB_Table,X ; 取键定义值 -〉 A BRA KB_defR KB_def2: INCX INCX BRA KB_def1KB_def3: LDA #$FF ; 未定义键用 FF标志KB_defR: RTSKB_Table FCB $EE,"1",$DE,"2",$BE,"3",$7E,"A" FCB $ED,"4",$DD,"5",$BD,"6",$7D,"B" FCB $EB,"7",$DB,"8",$BB,"9",$7B,"C" FCB $E7,"*",$D7,"0",$B7,"#",$77,"D" FCB $00
<<<
269
键盘中断子程序 (KB_Int)KB_Int: PSHH ; 保护 H( 其他 CPU 寄存器已自动保护 ) SEI BSET 1,INTKBSCR ; 禁止键盘中断 JSR KB_A ; 调子程序 KB_A 取得键值 -〉 A STA KB_Value ; 放内存 KB_Value 中 JSR KB_def STA Lcd-Buffer2 LDA #$0 JSR Show-Lcd-Buffer3 JSR DelaySub PULH ;H 出栈 ( 其他 CPU 寄存器已自动保存 ) JSR KB_Init ; 执行键盘初始化程序 BCLR 1,INTKBSCR ; 开放键盘中断 (IMASKK=0) CLI RTI
<<<
270
INIT-LCD(LCD 初始化子程序 )INIT-LCD: BCLR LCD-RS,PTC ;令 LCD的 RS=0,R/W=0, 进行 LCD 初始化 BCLR LCD-RW,PTC LDA #%00111000 ; 功能设置 :8 位数据接口 ,2 行显示 ,5*7点阵模式 JSR LcdCommand LDA #%00001000 ; 显示开关控制 :关显示,关光标显示 , 不闪烁 JSR LcdCommand LDHX #$0020 ; 等待 40us DBNZX * BCLR LCD-RS,PTC ;RS,RW 清零开始清屏 BCLR LCD-RW,PTC LDA #%00000001 ; 清屏指令 JSR LcdCommand LDHX #$2DF ; 等待清屏完毕 , 时间 >1.6msCLR-LCD-2-MS: ; 延时 AIX #-1 CPHX #0 BNE CLR-LCD-2-MS LDA #%00000110 ; 输入方式设置 : 数据读写操作后 ,AC自动增 1
JSR LcdCommand LDA #%00010100 ;光标移位设置 :光标右移一个字符位 ,AC自动加 1 JSR LcdCommand LDA #%00001100 ; 显示开关设置 : 开显示 ,关光标显示 , 不闪烁 JSR LcdCommand RTS
<<<
271
LcdCommand(LCD 命令执行子程序 )LcdCommand: PSHH ; 保护现场 PSHX LDHX #$0020 ; 等待 40us DBNZX * STA PTB ;把指令码送到 B 口 NOP NOP BSET LCD-E,PTC ;LCD 开始接受数据 ,置使能位为 1 NOP NOP BCLR LCD-E,PTC ;LCD 结束接受数据 ,置使能位为 0 LDHX #$0020 ; 等待 40us DBNZX * PULX ;恢复现场 PULH RTS <<<
272
Show-Lcd-Buffer1(LCD 显示上层子程序 )
Show-Lcd-Buffer1: ; 进行显示数据寄存器 (DD RAM) 地址设置 PSHA
BCLR LCD-RS,PTC
BCLR LCD-RW,PTC ; 设置上层 16 个字符首 DD RAM 地址 LDA #%10000000
JSR LcdCommand
LDHX #$0 ; 显示上层 16 个字符 PULA
PSHA
SHOW-FIRST-16BYTE:
PSHX
PSHA
BSET LCD-RS,PTC ;令 LCD的 RS=1,R/W=0, 写入数据到 DD RAM 中BCLR LCD-RW,PTC
TAX
<<<
274
程序延时子程序 (DelaySub)DelaySub: PSHH PSHX PSHA LDA #$14DelaySub1: LDHX #$03E8DelaySub2: PSHH PSHX LDHX #$0050 ; 延时 0.1 秒 DBNZX * PULX PULH DBNZX DelaySub2 DBNZA DelaySub1 PULA PULX PULH RTS <<<
275
Show-Lcd-Buffer1(LCD 显示上层子程序 )1
LDA Lcd-Buffer,X ;将 {Lcd-Buffer+X} 的数据放入 A 作为入口 JSR LcdCommand
PULA
INCA
CMP #10
BNE SKIP1
LDA #0
SKIP1:
PULX
AIX #1
CPHX #$10
BNE SHOW-FIRST-16BYTE
PULA
RTS
<<<
283
*----------------- 程序说明 -----------------------------------------*
* 文件名: Tim1Ch0I.ASM-- 定时器接口模块编程实验 2- 输入捕捉
* 功能: • ① 系统初始化: CONFIG2、 1 、 PTCL、堆栈 • ② 以输入捕捉中断方式 , 取反指示灯 PTA1 ,使其闪动
说明 : 本例是将定时器 1 通道 0(21脚 ) 设为“跳变沿捕捉” ( 即电平发生变化时产生中断 ),
* 验证方法是将 21脚不断接高电平、低电平,此时指示灯PTA1 状态跟随改变 *
284
*------------- 寄存器地址 ------------------------------DDRA EQU $0004 ;A 口数据方向寄存器PTA EQU $0000 ;A 口数据寄存器T1SC EQU $0020 ; 定时器 1 状态和控制寄存器T1CNTH EQU $0021 ; 定时器 1 计数寄存器 ( 高位 )T1CNTL EQU $0022 ; 定时器 1 计数寄存器 ( 低位 )T1MODH EQU $0023 ; 定时器 1 模数寄存器 ( 高位 )T1MODL EQU $0024 ; 定时器 1 模数寄存器 ( 低位 )T1SC0 EQU $0025 ; 定时器 1 通道 0 状态和控制寄存器T1CH0H EQU $0026 ; 定时器 1 通道 0 的通道寄存器 ( 高位 )T1CH0L EQU $0027 ; 定时器 1 通道 0 的通道寄存器 ( 低位 )RAMstartAddr EQU $0040 ;RAM 的起始地址(因芯片不同可以更
改)FlashStartAddr EQU $8000 ; 程序开始地址(因芯片不同可以更
改)
285
*---------内存变量 ----------------------------------------- org FlashStartAddr
MainStart: SEI ; 禁止所有中断 LDHX #$023F ; 堆栈初始化, ; 放入 GP32的 RAM 最高端 TXS
286
;------- 系统初始化 ----------------------------- MOV #%00000001,$001E ; 初始化 CONFIG2 MOV #%00111101,$001F ; 初始化 CONFIG1
MOV #%00110001,$0036 ; 初始化 PTCL BSET 7,$0037 MOV #$01,$0038 MOV #$2C,$0039 MOV #$80,$003A BSET 1,DDRA 定义 PTA.1 为输出(指示灯) BSET 1,PTA
287
; 定时器 1 通道 0 初始化 LDA #%00110000 ; 不允许溢出中断、不启动计数、 ; 分频因子 =1 STA T1SC ; 定时器 1 状态和控制寄存器 LDA #%01001100 ; 设为输入捕捉模式,允许输入捕捉中断 ,
; 跳变沿捕捉 ( 即电平发生变化时产生中断 ) STA T1SC0 ; 定时器 1 通道 0 状态和控制寄存器 BCLR 5,T1SC ; 允许定时器 1 计数寄存器计数 CLI ; 开放中断 -------------------- 初始化结束 -------------------
289
*---------- 定时器 1 通道 0 输入捕捉中断子程序 --------Timer1CH0In: PSHH ; 保护 h 寄存器 ; ; 至此 , 可读取计数器的值,可在此处添加用户的程序 ; 本程序仅为实验例程,用指示等状态改变,说明发生了中断 BRCLR 1,PTA,PTA1SET ; 指示灯状态变换 BCLR 1,PTA BRA PTA1CLRPTA1SET: BSET 1,PTAPTA1CLR: ; LDA T1SC0 ; 清除定时器 1 通道 0 输入捕捉中断标志位 BCLR 7,T1SC0 ; PULH ;释放 h 寄存器 RTI