微机原理第二次实验报告
一、实验目的
1. 了解ARM汇编语言和C语言交互编程和调用的方法和机制。
2. 掌握汇编和C语言变量和函数调用时的规则和注意事项。
3. 掌握多个源文件构成工程项目的软件开发模式。
二、实验设备
PC计算机,Windows XP操作系统和Keil for ARM(MDK4.14)开发环境。
三、实验内容
1、汇编程序访问C程序变量
2、汇编程序调用C程序
3、C程序内嵌汇编指令
4、C程序调用汇编程序
四、实验步骤
1.汇编程序访问C程序变量
实验步骤:
(1)建立一个新的项目,一个汇编源文件 hello.s 和一个 C 语言文件 str.c,将这两个文件加入项目中。
(2)根据指导书中的参考代码和书中的相关例题输入代码。其中,hello.s文件要在参考代码的基础上添加引用其他文件中定义的变量的声明“IMPORT globvar”,并进行修改,删除“MOV PC,LR”一句。str.c文件中定义了全局变量globvar。
(3)项目属性设置:Debug选项卡去掉“Run to main()”,Linker选项卡勾选“Use Memory Layout from Target Dialog”。
(4)单步运行调试,将全局变量globvar加入观察窗口 1,并打开符号窗口查看 globvar的地址等信息。
调试结果:
程序段ARMCODE每运行一次,寄存器R0中的值从3开始增加2,观察窗口中globvar的值也增加2。
2.汇编程序调用C程序
实验步骤:
(1)建立一个新的项目,一个汇编源文件ARM_add.s和一个 C 语言文件C_add.c,将这两个文件加入项目中。
(2)根据参考代码编写程序。C_add.c中定义的函数g()实现5个整数的相加功能,汇编程序中则要设置5个参数的值并调用此段c代码完成5个整数的加法的功能。参数利用堆栈传递,根据ATPCS规则,使用R0,R1,R2和R3存放第1-4个参数,第5个参数则需利用数据栈传送。由于利用数据栈传递参数,在程序调用结束后要调整数据栈的指针。
在运行参考代码时出现了较大问题,不能得到想要的结果,因此对参考代码进行了修改,将汇编程序的两段合成一段,修改后的代码如下:
AERA RESET,CODE,READONLY
EXPORT RESET
IMPORT g
ENTRY
PRESERVE8
MOV SP,#0x20000000
STR LR,[SP,#0]!
?(以下同参考代码)
END
(3)同上设置项目属性,单步运行调试,观察结果。
调试结果:
修改后程序实现了把寄存器R0-R3中的值以及堆栈中的值共5个数相加,结果存入R0,5个数分别为1、2、3、4、5,故最终R0的值为0x0000000F。
3.C程序内嵌汇编指令
实验步骤:
(1)建立一个新的项目,选择CPU的型号为STR710FZ1,选择需要拷贝启动代码。项目的其他设置与前面相同。
(2)新建一个C程序文件EmbedASM.c,并加入项目中。
(3)编写程序,单步运行调试。注意在跳转目标指令处加断点,否则程序不能正常跳转。
调试结果:
由于printf函数无法使用,通过Memory窗口查看内存中的值,知可以实现字符串的复制。
4.C程序调用汇编程序
实验步骤:
(1)建立一个新的项目,选择CPU的型号为STR710FZ1,选择需要拷贝启动代码。项目的其他设置与前面相同。
(2)新建一个C程序文件strest.c和scopy.s,并加入项目中。
(3)编写程序,汇编程序 strcopy函数实现字符串的复制功能,C程序调用该函数完成字符串复制工作。对参考代码进行修改,删除strcpy.s中的MOV PC,LR。单步运行调试。注意在跳转目标指令处加断点,否则程序不能正常跳转。
调试结果:
由于printf函数无法使用,通过Memory窗口查看内存中的值,知可以实现字符串的复制。
五、实验总结
这次实验中进行了C语言和汇编语言的相互调用及共同编程,这样的编程方式可以综合汇编语言和高级语言的优点,在今后的项目开发中是非常有用的。但是在实验的过程中我感觉自己对这部分知识掌握还不够牢固,有很多东西不太理解,因此还需要巩固和复习基本知识。
第二篇:北航微机原理实验(源程序)-教师手册
目录
第一章:汇编基础与硬件基础... 2
实验二 TPC2300A集成开发环境... 2
内容1.2.2 分段存储结构和数据变量的定义... 2
内容1.2.3 汇编程序设计---数据串操作... 3
内容1.2.4 汇编程序设计--循环和分支程序... 3
内容1.2.5 汇编程序设计---子程序及其调用... 4
内容1.2.6 汇编程序设计--DOS中断调用... 5
实验三 TPC-2003A接口箱系统硬件及逻辑电路... 6
内容1.3.2 I/O译码电路... 6
第二章 基础实验... 7
实验一 8253接口芯片基础... 7
内容2.1.1 8253用于手动脉冲计... 7
内容2.1.2 8253用于分频... 8
实验二 8255接口芯片基础... 9
内容2.2.1 8255作为基本输入输出... 9
内容2.2.2 8255方式0的应用-红绿灯控制... 9
内容2.2.3 8255对8253GATE的控制... 11
内容2.2.4: 手动脉冲计数输出显示... 13
第三章 综合实验... 14
实验一 AD/DA接口芯片基础... 14
内容3.1.1:ADC0809的数据采集功能... 14
内容3.1.2:DAC0832的波形输出功能... 15
实验一 8253/8255综合实验... 16
内容3.2.1: 继电器控制... 16
内容3.2.2: 自动计数输出显示... 18
内容3.2.3 直流电机转速显示与计算... 19
实验三 8253/8255/DAC0832综合实验... 23
内容3.3.1:直流电机转速控制... 23
内容3.3.2:直流电机测速... 25
实验四 8255综合实验... 28
内容3.4.1:步进电机控制... 28
第一章:汇编基础与硬件基础
;* *;
实验二 TPC2300A集成开发环境
;* *;
内容1.2.2 分段存储结构和数据变量的定义
;******************************************;
;* *;
;* 编写程序统计字符串str的字符个数, *;
;*存于counts单元。字符串以“$”为结束符, *;
;* 长度小于255个字符。 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 1-2-2.asm *;
;******************************************;
mydata segment
str db 'assemble language$'
counts db ?
mydata ends
mycode segment
assumecs:code,ds:data
start: mov ax,data
mov ds, ax
mov cl,0
mov bx, offset str
next: cmp [bx] '$'
jz exit
inc cl
inc bx
jmp next
exit: mov counts,cl ;存储字符的个数
mov ah,4ch
int21h
mycode ends
end start
;******end of program 1-2-2.asm**************
内容1.2.3 汇编程序设计---数据串操作
;************************************************;
;;* *;
;* 将buffa开始的连续字节单元数 *;
;* 传送到buffb开始的连续字操作数单元 *;
;* (不考虑数据块的 重叠) *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 1-2-3.asm *;
;************************************************;
data segment
bufa dw 0234h,2345h,987fh
dw 0c234h,0012h,1234h,7890h
bufb dw 7dup(?)
data ends
code segment
assume cs:code,ds:data
mov ax,data
mov ds, ax
mov si,offset bufa
mov di,offset bufb
mov cx,14
next: mov ax,[si]
mov [di],ax
inc si
inc di
loop next ;循环传送,直到传送完
mov ah,4ch
int 21h
code ends
end start
;**********end of progme 1-2-3.asm***************;
内容1.2.4 汇编程序设计--循环和分支程序
;************************************************;
;* 在字节存储单元d1、d2和d3中存有三个 *;
;*不相等无符号数,由大到小排列后存于d1、d2、d2,*;
;* 注意使用无符号数比较时的转移指令。 *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 1-2-4.asm *;
;************************************************;
data segment
d1 db 30h
d2 db 0e2h
d3 db 80h
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov al,d1
mov bl,d2
mov cl,d3
cmp al,bl
ja lpl
xchg al,bl
lpl: cmp al,cl
ja lp2
xchg al,cl
lp2: cmp bl,cl
ja lp3
xchg bl,cl
lp3: mov d1,al
mov d2,bl
mov d3,cl
mov ah,4ch
int 21h
code ends
end start
;**********end of program 1-2-4.asm*************;
内容1.2.5 汇编程序设计---子程序及其调用
;* *************************************************;
;* 计算3个带符号数的绝对值之和,三个数长度为 *;
;* 字类型,要求用子程序计算绝对值,用主程序实现 *;
;* 累加;整理实验结果。 *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 1-2-5.asm *;
;************************************************;
mydata segment
data dw -20h, 34h, 21h,23a5h,1200h
absm dw 0
mydata ends
mycode segment
assume cs:mycode, ds:mydata
start: mov ax,mydata
mov ds,ax
mov si, offset data
mov cx, 5
xor bx,bx
rept: mov ax,[si]
call subabs
add bx,ax
inc si
inc si
loop rept
mov absm,bx ;绝对值之和
mov ah,4ch
int 21h
subabs proc near
and al, al
jns bck
neg al
bck: ret
subabs endp
mycode ends
end start
;**********end of program 1-2-5.asm**************;
内容1.2.6 汇编程序设计--DOS中断调用
;************************************************;
;* 利用DOS中断6号功能调用,在屏幕上显示字符A~Z *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 1-2-6.asm *;
;************************************************;
code segment
assume cs:code
start: mov dl,'A'
mov cx,26
next: mov ah,06h ;DOS调用,功能好06,dl中为在屏幕上显示的字符
int 21h
inc dl ;下一个字符ASCII
loop next ;显示下一个字符
mov ah,4ch
int 21h
code ends
end start
;**********end of program 1-2-6.asm*************;
实验三 TPC-2003A接口箱系统硬件及逻辑电路
内容1.3.2 I/O译码电路
;************************************************;
;;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 1-3-2.asm *;
;************************************************;
ioport equ 0ec00h-0280h; 0ec00h替换为本机基地址
outport1 equ ioport+2a0h
outport2 equ ioport+2a8h
code segment
assume cs:code
start: mov dx,outport1
out dx,al
call delay ;调延时子程序
mov dx,outport2
out dx,al
call delay ;调延时子程序
mov ah,1 ;bios中断调用,判断有无键入字符,
int 16h
je start ;zf=1无键入,转start继续,zf=0有键入,结束
mov ah,4ch
int 21h
delay proc near ;延时子程序
mov bx,2000 ;修改计数值可改变LED亮灭频率
lll: mov cx,0
ll: loop ll
dec bx
jne lll
ret
delay endp
code ends
end start
;**********end of program 1-3-2.asm*************;
第二章 基础实验
实验一 8253接口芯片基础
内容2.1.1 8253用于手动脉冲计
; ;************************************************;
*; Create Data: 26/06/2009 YHB *;
;* Prog ID: 2-1-1.asm *;
;************************************************;
ioport equ 0d400h-0280h ; 0ec00h替换为本机基地址
io53ctl equ ioport+283h
io53_0 equ ioport+280h
code segment
assume cs:code
start: mov al,14h ;设置8253通道0为工作方式2,二进制计数
mov dx,io53ctl ;8253 控制口端口
out dx,al ;送控制字
mov dx,io53_0 ;计数器0端口
mov al,0fh ;设计数初值0FH (0aQ)
out dx,al ;送计数初值
lll: in al,dx ;读计数初值
call disp ;调显示子程序
push dx ;保护端口值,防止中断调用破坏
mov ah,06h ;6号中断,
mov dl,0ffh ;表示该功能调用是输入,如果dl不是0ffh,表示把dl中的asciia码输出
int 21h
pop dx
jz lll ;循环显示
mov ah,4ch ;退出
int 21h
disp proc near ;显示子程序
push dx ;dx为端口地址,先保存起来,防止后面调用中断功能时使用dl寄存器时破坏dx值
and al,0fh ;首先取低四位,al值是读取的计数器的当前计数值
mov dl,al
cmp dl,9 ;判断当前计数值是否<=9
jle num ;若为'0'-'9',其ASCII码值为计数值加30H,0+30h=30h
add dl,7 ;否为'A'-'F',其ASCII码值为计数值加37H, A+37h=41h
num: add dl,30h
mov ah,02h ;中断功能号02,显示ASCII值为dl的字符
int 21h
mov dl,0dh ;显示回车符
int 21h
mov dl,0ah ;显示换行符
int 21h
pop dx
ret ;子程序返回
disp endp
code ends
end start
;**********end of program 2-1-1.asm*************;
内容2.1.2 8253用于分频
; ;**************************************************;
;* 用1MHz的频率源,输出1Hz的频率, *;
;* 用示波器或者逻辑笔观察 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 2-1-2.asm *;
;************************************************;
ioport equ 0ec00h-0280h ;0ec00h替换为本机基地址
io8253a equ ioport+280h
io8253b equ ioport+281h
io8253d equ ioport+283h
code segment
assume cs:code
start: mov dx,io8253d ;向8253写控制字
mov al,36h ;使0通道为工作方式3
out dx,al ;写入控制字
mov ax,1000 ;写入循环计数初值1000
mov dx,io8253a
out dx,al ;先写入低字节
mov al,ah
out dx,al ;后写入高字节
mov dx,io8253d
mov al,76h ;设8253通道1工作方式2
out dx,al ;写入控制字
mov ax,1000 ;写入循环计数初值1000
mov dx,io8253b
out dx,al ;先写低字节
mov al,ah
out dx,al ;后写高字节
mov ah,4ch ;程序退出
int 21h
code ends
end start
;;**********end of program 2-1-2.asm*************;
实验二 8255接口芯片基础
内容2.2.1 8255作为基本输入输出
;************************************************;
;* *;
;* 端口设置: C口输入,A口输出 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 2-2-1.asm *;
;************************************************;
ioport equ 0d400h-0280h ;0d400h替换为本机基地址
io55a equ ioport+288h
io55ctl equ ioport+28bh
io55c equ ioport+28ah
code segment
assume cs:code
start: mov dx,io55ctl ;设8255为C口输入,A口输出
mov al,8bh
out dx,al ;送入控制字
inout: mov dx,io55c ;从C口输入一数据
in al,dx
mov dx,io55a ;从A口输出刚才自C口
out dx,al ;所输入的数据
mov dl,0ffh ;判断是否有按键,dos中断功能06h
mov ah,06h
int 21h
jz inout ;若无,则继续自C口输入,A口输出;zf=1表示无键按下
mov ah,4ch ;否则返回DOS
int 21h
code ends
end start
;;**********end of program 2-2-1.asm*************;
内容2.2.2 8255方式0的应用-红绿灯控制
;************************************************;
;*;* *;
;* 十字路口红绿灯模拟 *;
;* 端口各灯的设置: *;
;* L7红 L6黄 L5绿 0 0 L2红 L1黄 L0绿 *;
;* L7L6L5 模拟南北向,L2L1L0模拟东西向 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 2-2-2.asm *;
;************************************************;
data segment
ioport equ 0ec00h-0280h ;0ec00h替换为本机基地址
io55a equ ioport+288h
io55b equ ioport+289h
io55c equ ioport+28ah
io55ctl equ ioport+28bh
traffctl db 24h,44h,81h,82h
msg db 0dh,0ah, 'check L7 L6 L5 and L2 L1 L0 ', 0dh,0ah,'press any ken to stop program',0ah,0dh,'$'
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,offset msg ;屏幕上显示提示信息
mov ah,09h ;中断功能号09h
int 21h
ctn: mov dx,io55ctl
mov al,90h
out dx,al ;设置8255为C口输出
mov dx,io55c
mov al,traffctl
out dx,al ;南北绿灯,东西红灯,L7~L0 =24h
call delay
mov al,traffctl+1 ;南北黄灯,东西红灯,L7~L0 =44h
out dx,al
call delay
mov al,traffctl+2 ;南北红灯,东西绿灯,L7~L0 =81h
out dx,al
call delay
mov al,traffctl+3 ;南北红灯,东西黄灯,L7~L0 =82h
out dx,al
call delay
push dx
mov ah,06h
mov dl,0ffh
int 21h
pop dx
jz ctn ;没有键按下,继续循环
exit: mov ah,4ch
int 21h
delay proc near ;延时子程序,采用寄存器自减实现
mov cx,0ffffh
cxdown: mov si,0ffffh
sidown: dec si
jnz sidown
loop cxdown
ret
delay endp
code ends
end start
;;**********end of program 2-2-2.asm*************;
内容2.2.3 8255对8253GATE的控制
;********************************************************;
;* 8255对8253计数器门控 *;
; create 06/07/2009 by YHB *;
; program ID: 2-2-3.asm *;
;*********************************************************;
ioport equ 0ec00h-0280h
io55ctl equ ioport+28bh ;8255控制口
io55a equ ioport+288h ;8255 A口
io55c equ ioport+28ah ;8255C
io53ctl equ ioport+283h ;8253控制
io53_2 equ ioport+282h ;8253计数器2
io53_1 equ ioport+281h ;8253计数器1
io53_0 equ ioport+280h ;8253计数器0
data segment
mess db 'Press any key to exit the program',0aH,0dH,'$'
led db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,77h,7ch,39h,5eh,79h,71h
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,offset mess ;在屏幕上显示提示信息
mov ah,09h
int 21h ;显示提示信息
mov dx,io55ctl ;8255,方式0,A口输出,C口高四位输入,C口低四位输出
mov al,88h
out dx,al
mov dx,io53ctl
mov al,36h ;计数器0,方式3,先读写低8位,再读写高8位
out dx,al ;送控制端口
mov dx,io53_0
mov ax,10000 ;输入时钟1MHZ,计数初值50000,输出时钟周期50ms
out dx,al
nop
nop
mov al,ah
out dx,al
mov dx,io53ctl
mov al,54h ;计数器1,方式2,只读写低8位
out dx,al ;送控制端口
mov dx,io53_1
mov al,100 ;输入CLK1接OUT0,计数初值100
out dx,al ;送初值
mov dx,io53ctl
mov al,94h ;计数器2,方式2,只读写低8位
out dx,al
mov dx,io53_2
mov al,0fh ;计数初值
out dx,al
ctn: mov dx,io53_2;读当前计数值并显示
call leddisp
mov ah,01h ;判断有无键按下
int 16h
jnz stp ;zf=0,有键按下,返回,zf=1,无键按下,继续程序
mov dx,io55c
in al,dx ;读C口状态
and al,80h ;判断PC7是否为1
jnz seth ; 如为1,转seth,
mov dx,io55c
mov al,0h ;否者,设置PC0为低电平
out dx,al
jmp ctn
seth: mov dx,io55c ;设置PC0为高电平
mov al,0ffh
out dx,al
jmp ctn
stp: mov ah,4ch ;退出程序,返回DOS
int 21h
leddisp proc near
push dx
in al,dx ;读当前计数值
mov bx,offset led ;bx为数码表的起始地址
xlat ;求出相应的段码代表的LED数字,存于al
mov dx,io55a ;从8255的A口输出
out dx,al
pop dx
ret
leddisp endp
code ends
end start
;****************end of program 2-2-3.asm******************************;
内容2.2.4: 手动脉冲计数输出显示
************************************************;
;* *;
;* 输入为脉冲发生器,在LED上输出F~0的计数值 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 2-2-3.asm *;
;************************************************;
data segment
ioport equ 0ec00h-0280h ;0ec00h由本机接口卡实际基地址代替
io55a equ ioport+288h
io55b equ ioport+289h
io55c equ ioport+28ah
io55ctl equ ioport+28bh
io53_0 equ ioport+280h
io53_1 equ ioport+281h
io53_2 equ ioport+282h
io53ctl equ ioport+283h
led db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,77h,7ch,39h,5eh,79h,71h
mesg db 0dh,0ah,'check led for timing value, press any key to stop program',0dh,0ah,'$'
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,io55ctl ;使8255的A口为输出方式
mov ax,80h
out dx,al
mov dx,io55a ;LED清屏
mov al,0
out dx,al
mov dx,offset mesg ;屏幕上显示提示
mov ah,09h
int 21h
mov dx,io53ctl ;向8253写控制字
mov al,14h ;使0通道为工作方式2,二进制计数
out dx,al
mov al,0fh ;计数初值
mov dx,io53_0
out dx,al
ctn: call leddisp ;调LED显示子程序
push dx ;保存8253-2通道端口地址
mov ah,06h
mov dl,0ffh
int 21h
pop dx
jz ctn ;没有键按下时,继续循环
mov ah,4ch ;有键按下,退出
int 21h
leddisp proc near
push dx
in al,dx ;读当前计数值
mov bx,offset led ;bx为数码表的起始地址
xlat ;求出相应的段码代表的LED数字,存于al
mov dx,io55a ;从8255的A口输出
out dx,al
pop dx
ret
leddisp endp
code ends
end start
;;**********end of program 2-2-3.asm*************;
第三章 综合实验
实验一 AD/DA接口芯片基础
内容3.1.1:ADC0809的数据采集功能
;************************************************;
;* *;
;* ADC0809的数据采集功能 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 3-1-1.asm *;
;************************************************;
ioport equ 0ec00h-0280h ;0ec00h替换为本机基地址
io0809a equ ioport+298h
code segment
assume cs:code
start: mov dx,io0809a ;启动A/D转换器
out dx,al
mov cx,0ffh ;延时
delay: mov si,0ffh ;选择显示刷新速率
delay1: dec si
jnz delay1
loop delay
in al,dx ;从A/D转换器输入数据
mov bl,al ;将AL保存到BL
mov cl,4
shr al,cl ;将AL右移四位
;bios 中断调用
mov dh,05 ;光标移动到第5行第5列显示
mov dl,05
mov ah,02
int 10h
call disp ;调显示子程序显示其高四位
mov al,bl
and al,0fh ;高四位清零
;bios 中断调用
mov dh,05 ;光标移动到第5行第8列显示
mov dl,08h
mov ah,02
int 10h
call disp ;调显示子程序显示其低四位
mov ah,02 ;dos中断功能02h,
mov dl,20h ;加回车符,将dl中的ascii码输出到屏幕
int 21h
mov dl,20h
int 21h
push dx
mov ah,06h ;判断是否有键按下,dos中断功能06h
mov dl,0ffh ;表示该功能调用时输入,如果dl不是0ffh,表示把dl中的asciia码输出
int 21h
pop dx
je start ;若没有转START,zf=1表示无键按下,zf=0有键按下,则结束
mov ah,4ch ;退出
int 21h
disp proc near ;显示子程序
mov dl,al
cmp dl,9 ;比较DL是否>9
jle ddd ;若不大于则为'0'-'9',加30h为其ASCII码
add dl,7 ;否则为'A'-'F',再加7
ddd: add dl,30h ;显示
mov ah,02
int 21h
ret
disp endp
code ends
end start
;;**********end of program 3-1-1.asm*************;
内容3.1.2:DAC0832的波形输出功能
;************************************************;
;* *;
;* DAC0832的波形输出功能 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 3-1-2.asm *;
;************************************************;
ioport equ 0ec00h-0280h ;0ec00h替换为本机基地址
io0832a equ ioport+290h
code segment
assume cs:code
start: mov cl,0
mov dx,io0832a
lll: mov al,cl
out dx,al
inc cl ;cl加1
inc cl
inc cl
inc cl
inc cl
inc cl
inc cl
push dx
mov ah,06h ;中断06功能
mov dl,0ffh ;dl=0ffh,表示输入,判断是否有键按下
int 21h
pop dx
jz lll ;若无则转LLL,zf=1无键按下,zf=0有键按下则结束
mov ah,4ch ;返回DOS
int 21h
code ends
end start
;;**********end of program 3-1-2.asm*************;
实验一 8253/8255综合实验
内容3.2.1: 继电器控制
;************************************************;
;*
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 3-2-1.asm *;
;************************************************;
ioport equ 0ec00h-0280h ;0ec00h由本机接口卡实际基地址代替
io53_0 equ ioport+280h
io53_1 equ ioport+281h
io53ctl equ ioport+283h
io55a equ ioport+288h
io55ctl equ ioport+28bh
code segment
assume cs:code
start: mov dx,io55ctl ;设8255为A口输入,C口输出,控制口
mov al,90h ;控制字
lll: out dx,al
mov al,01 ;将PC0置位
out dx,al ;送控制字到控制口
call delay ;延时5s
mov al,0 ;将PC0复位
out dx,al
call delay ;延时5s
jmp lll ;转lll
delay proc near ;延时子程序
push dx
mov dx,io53ctl ;设8253计数器为方式3,控制口
mov al,36h ;控制字
out dx,al
mov dx,io53_0 ;8253计数器0
mov ax,1000 ;写入计数器初值1000
out dx,al
mov al,ah
out dx,al
mov dx,io53ctl ;8253控制口
mov al,70h ;设计数器1为工作方式0
out dx,al
mov dx,io53_1 ;8253计数器1
mov ax,1000 ;写入计数器初值500
out dx,al
mov al,ah
out dx,al
ll2: mov ah,06 ;中断06号调用
mov dl,0ffh ;dl=0ffh,表示输入,是否有键按下
int 21h
jne exit ;zf=0,有键按下,若有则转exit,zf=1无键按下
mov dx,io55a ;8255A口
in al,dx ;查询8255的PA0是否为高电平
and al,01
jz ll2 ;若不是则继续,若是,则结束
pop dx ;释放调用子程序前的端口地址值
ret ;定时时间到,子程序返回
exit: mov ah,4ch
int 21h
delay endp
code ends
end start
;;**********end of program 3-2-1.asm*************;
内容3.2.2: 自动计数输出显示
;***** *******************************************;
;* *;
;* *;
;* 输入为1MHz的频率,在LED上输出F~0的计数值 *;
;* *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 3-2-2.asm *;
;************************************************;
data segment
ioport equ 0ec00h-0280h ;0ec00h由本机接口卡实际基地址代替
io55a equ ioport+288h
io55b equ ioport+289h
io55c equ ioport+28ah
io55ctl equ ioport+28bh
io53_0 equ ioport+280h
io53_1 equ ioport+281h
io53_2 equ ioport+282h
io53ctl equ ioport+283h
led db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,77h,7ch,39h,5eh,79h,71h
mesg db 0dh,0ah,'check led for timing value',0dh,0ah,' press any key to stop program',0dh,0ah,'$'
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,io55ctl ;使8255的A口为输出方式
mov ax,80h
out dx,al
mov dx, offset mesg ;在屏幕上显示提示信息
mov ah,09h
int 21h
mov dx,io53ctl ;向8253写控制字
mov al,36h ;使0通道为工作方式3
out dx,al
mov ax,1000 ;写入循环计数初值1000
mov dx,io53_0
out dx,al ;先写入低字节
mov al,ah
out dx,al ;后写入高字节
mov dx,io53ctl
mov al,76h ;设8253通道1工作方式2
out dx,al
mov ax,1000 ;写入循环计数初值1000
mov dx,io53_1
out dx,al ;先写低字节
mov al,ah
out dx,al ;后写高字节
mov dx,io53ctl
mov al,94h ;计数器2工作方式2
out dx,al
mov al,0fh
mov dx,io53_2
out dx,al
ctn: call leddisp ;调LED显示子程序
push dx ;保存8253-2通道端口地址
mov ah,06h
mov dl,0ffh
int 21h
pop dx
jz ctn ;没有键按下时,继续循环
mov ah,4ch ;有键按下,退出
int 21h
leddisp proc near
push dx
in al,dx ;读当前计数值
mov bx,offset led ;bx为数码表的起始地址
xlat ;求出相应的段码代表的LED数字,存于al
mov dx,io55a ;从8255的A口输出
out dx,al
pop dx
ret
leddisp endp
code ends
end start
;;**********end of program 3-2-2.asm*************;
内容3.2.3 直流电机转速显示与计算
;***** *******************************************;
;* 在屏幕上显示编码器脉冲数 *;
;* 及计数器时间,手工计算出直流电机转速 *;
;* Create Data: 26/06/2009 YHB *;
;* Prog ID: 3-2-3.asm *;
;************************************************;
ioport equ 0ec00h-0280h ;0ec00h由本机的接口卡基地址代替
io55ctl equ ioport+28bh ;8255控制口
io55a equ ioport+288h ;8255 A口
io55c equ ioport+28ah ;8255C
io53ctl equ ioport+283h ;8253控制
io53_2 equ ioport+282h ;8253计数器2
io53_1 equ ioport+281h ;8253计数器1
io53_0 equ ioport+280h ;8253计数器0
data segment
mess db 'Press any key to exit the program',0aH,0dH,'$'
mesg1 db 'No.Rad','$'
mesg2 db 'n(T=n*Tout2)','$'
led db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh,77h,7ch,39h,5eh,79h,71h
count4 db 0
count3 db 0
count2 db 0
count1 db 0
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,offset mess ;在屏幕上显示提示信息
mov ah,09h
int 21h ;显示提示信息
mov dx,io55ctl ;8255,方式0,A口输出,C口高四位输入,C口低四位输出
mov al,88h
out dx,al
mov dx,io53ctl
mov al,36h ;计数器0,方式3,先读写低8位,再读写高8位
out dx,al ;送控制端口
mov dx,io53_0
mov ax,50000 ;输入时钟1MHZ,计数初值50000,输出时钟周期50ms
out dx,al
nop
nop
mov al,ah
out dx,al
mov dx,io53ctl
mov al,54h ;计数器1,方式2,只读写低8位
out dx,al ;送控制端口
mov dx,io53_1
mov al,0 ;输入CLK1接OUT0,计数初值100
out dx,al ;送初值
mov dx,io53ctl
mov al,0b4h ;计数器2,方式2,先读写低8位,再读写高8位
out dx,al ;CLK2接直流电机计数器
mov dx,io53_2
mov al,0ffh ;计数初值
out dx,al
nop
nop
out dx,al
ctn: mov dh,04
mov dl,03
mov ah,02
int 10h
mov dx,offset mesg1 ;在屏幕上显示提示信息
mov ah,09h
int 21h ;显示提示信息
mov dh,05 ;第5行第5列显示脉冲数
mov dl,05
mov ah,02
int 10h
mov dx,io53_2 ;读当前光电脉冲计数值并显示
in al,dx; 低8位
sub al,0ffh
neg al
mov count1, al
ror al,1
ror al,1
ror al,1
ror al,1
mov count2,al
in al,dx ;高8位
sub al,0ffh
neg al
mov count3,al
ror al,1
ror al,1
ror al,1
ror al,1
call disp
mov al,count3
call disp
mov al,count2
call disp
mov al,count1
call disp
mov dh,04
mov dl,10
mov ah,02
int 10h
mov dx,offset mesg2 ;在屏幕上显示提示信息
mov ah,09h
int 21h ;显示提示信息
mov dh,05 ;第5行第15列显示计数器1计数
mov dl,15
mov ah,02
int 10h
mov dx,io53_1; 读取计数器1的当前计数值并显示,只有低8位
in al,dx; lsb read
sub al,0ffh
neg al
mov count1, al
ror al,1
ror al,1
ror al,1
ror al,1
call disp
mov al,count1
call disp
mov ah,01h ;判断有无键按下
int 16h
jnz stp ;zf=0,有键按下,返回,zf=1,无键按下,继续程序
mov dx,io55c
in al,dx
and al,80h
jnz seth
mov dx,io55c
mov al,0h
out dx,al
jmp ctn
seth: mov dx,io55c
mov al,0ffh
out dx,al
jmp ctn
stp: mov ah,4ch ;退出程序,返回DOS
int 21h
disp proc near ;显示低四位ASCII码子程序,入口参数为al
push dx ;dx为端口地址,先保存起来,防止后面调用中断功能时使用dl寄存器时破坏dx值
push ax
and al,0fh ;首先取低四位,al值是读取的计数器的当前计数值
mov dl,al
cmp dl,9 ;判断当前计数值是否<=9
jle numl ;若为'0'-'9',其ASCII码值为计数值加30H,0+30h=30h
add dl,7 ;否为'A'-'F',其ASCII码值为计数值加37H, A+37h=41h
numl: add dl,30h
mov ah,02h ;中断功能号02,显示ASCII值为dl的字符
int 21h
pop ax
pop dx
ret ;子程序返回
disp endp
code ends
end start
实验三 8253/8255/DAC0832综合实验
内容3.3.1:直流电机转速控制
;************************************************;
;* Create Data: 26/06/2009 by YHB *;
;* Prog ID: 3-3-1.asm *;
;************************************************;
ioport equ 0ec00h-0280h ;0ec00h由本机接口卡实际基地址代替
io55a equ ioport+0288h
io55c equ ioport+028Ah
io55ctl equ ioport+028bh
dac0832 equ ioport+0290h
mydata segment
mesg db 0dh,0ah,'K1~K4 drive DC MOTOR, K0-STOP, press any keY to stop program',0dh,0ah,'$'
mydata ends
assume cs:mycode,ds:mydata
mycode segment
start: mov ax,mydata
mov ds,ax
mov dx,offset mesg ;屏幕上要显示的字符首地址DS:DX
mov ah,09h ;中断功能9
int 21h ;中断调用,显示字符串
mov dx, io55ctl
mov al,90h ;8255的A口输入状态
out dx,al
mov dx,dac0832 ;DA设置
lll: mov al,80h ;给直流电机加电压0V,即数字量为80h负,81h~ffh为正,且速度逐渐增加
out dx,al
push dx ;调用中断功能号06,先保存断口地址入堆栈
mov ah,06h
mov dl,0ffh
int 21h
pop dx
je chk_pota ;没有键按下zf=1,转chk_pota,有键按下,zf=0, 则退出
mov ah,4ch
int 21h
chk_pota: mov dx,io55a
in al,dx
test al,01h ;测试是否K0为1
jnz k0 ;K0为1,转k0,否则测k1
test al,02h ;测试是否K1为1
jnz k1 ;K1为1,转k1,否则测k2
test al,04h ;测试是否K2为1
jnz k2 ;K2为1,转k2,否则测k3
test al,08h ;测试是否K3为1
jnz k3 ;K3为1,转k3,否则测k4
test al,10h ;测试是否K4为1
jnz k4 ;K4为1,转k4否则转lll
jmp lll
k0: mov dx,dac0832 ;K0为停止
mov al, 080h ;送0V电压,电机停止
out dx,al
call subdelay
jmp chk_pota
k1: mov dx,dac0832 ;最低速
mov al, 0a5h
out dx,al ;驱动电压a5h,约(a5h-80h)*0ah/ffh=1.45v
call subdelay
jmp chk_pota
k2: mov dx,dac0832
mov al, 0aah ;0aah,约1.65v
out dx,al
call subdelay
jmp chk_pota
k3: mov dx,dac0832
mov al, 0b5h ;0b5h,约2.1v
out dx,al
call subdelay
jmp chk_pota
k4: mov dx,dac0832 ;最高速
mov al, 0ffh ;0ffh,约4.99v
out dx,al
call subdelay
jmp chk_pota
subdelay proc near
mov cx,0003h
outdelay: mov si,0002h
delay: dec si
jnz delay
dec cx
jnz outdelay
ret
subdelay endp
mycode ends
end start
;**********end of program 3-3-1.asm*************;
内容3.3.2:直流电机自动测速
;***********************;
;* 直流电机自动测速 *;
; create 03/07/2009 *;
; program ID: 3-3-2.asm
;***********************;
ioport equ 0ec00h-0280h ;0ec00h由本机的实际接口卡基地址代替
io55ctl equ ioport+28bh ;8255控制口
io55a equ ioport+288h ;8255 A口
io53ctl equ ioport+283h ;8253控制
io53_2 equ ioport+282h ;8253计数器2
io53_1 equ ioport+281h ;8253计数器1
io53_0 equ ioport+280h ;8253计数器0
data segment
mess db 'press any to stop program!',0aH,0aH,'$'
cou db 0
cou1 db 0
count1 db 0
count2 db 0
count3 db 0
count4 db 0
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,offset mess
mov ah,09h
int 21h ;显示提示信息
mov dx,io53ctl
mov al,36h ;计数器0,方式3,先读写低8位,再读写高8位
out dx,al ;输入时钟,1MHZ
mov dx,io53_0
mov ax,50000 ;初值50000,输出时钟周期50ms
out dx,al
nop
nop
mov al,ah
out dx,al
mov dx,io55ctl ;8255,A通道输入,C0输出
mov al,90h
out dx,al
mov al,00 ;C口的复位控制字
out dx,al ;C0(GATE1)低电平,定时器1禁止计数
ll: mov ah,01h ;功能号,判断有无按键输入
int 16h ;BIOS中断调用16h
jnz quit1 ;如果有按键,转quit1,退出程序
mov dx,io53ctl
mov al,70h ;计数器1,方式0,先读写低8位,再读写高8位。
out dx,al
mov dx,io53_1 ;输入时钟为光电开关输出。
mov ax,0ffffh
out dx,al
mov al, ah
nop
out dx,al
mov dx,io53ctl
mov al,90h ; ;计数器2,方式0,只读写低8位
out dx,al
mov dx,io53_2
mov al,100
out dx,al ;初值100,检测5秒
mov dx,io55ctl
mov al,01h
out dx,al ;PC0输出1,定时器1开始计数
jmp a0
quit1: jmp quit
a0: mov dx,io55a
a1: in al,dx
and al,01h
jz a1 ;8255 PA0是否为0
mov dx,io55ctl
mov al,00h
out dx,al ;定时器1停止计数
mov dx,io53_1
in al,dx
mov bl,al
in al,dx
mov bh,al ;16位计数值送bx
mov ax,0ffffh
sub ax,bx ;计算脉冲个数
call disp ;显示
mov dl,0dh
mov ah,02
int 21h
mov dl,0ah
mov ah,02
int 21h
jmp ll ;无键,测量
;------------------------------------------------------------
disp proc near ;BCD转换并显示子程序
mov dx,0000h
mov cx,03e8h ;除1000
div cx
mov count1,al ;千位
mov ax,dx
mov cl,64h
div cl ;除100
mov count2,al ;百位
mov al,ah
mov ah,00h
mov cl,10
div cl ;除10
mov count3,al ;10位
mov count4,ah ;个位
mov al,count1
call disp1
mov al,count2
call disp1
mov al,count3
call disp1
mov al,count4
call disp1
ret
disp endp
;--------------------------------------------------------------------
disp1 proc near ;将数字位的每个数值位字符以ASCII的形式在屏幕上显示
and al,0fh
cmp al,09h
jle num
add al,07h
num: add al,30h
mov dl,al
mov ah,02
int 21h
ret
disp1 endp
;-------------------------------------------------------------
quit: mov ah,4ch ;返回DOS
int 21h
code ends
end start
;************* end of program 3.4.1*****************
实验四 8255综合实验
内容3.4.1:步进电机控制
;************************************************;
;;* *;
;* Check Data: 26/06/2009 by YHB *;
;* Prog ID: 3-4-1.asm *;
;************************************************;
DATA SEGMENT
Ioport EQU 0ec00h-0280h ; 0ec00h由本机接口卡实际基地址代替
P55A EQU ioport+288H ;8255 A PORT OUTPUT
P55C EQU ioport+28AH ;8255 C PORT INPUT
P55CTL EQU ioport+28BH ;8255 COUTRL PORT
BUF DB 0
MES DB 'K0-K6 ARE SPEED CONTYOL',0AH,0DH
DB 'K6 IS THE LOWEST SPEED ',0AH,0DH
DB 'K0 IS THE HIGHEST SPEED',0AH,0DH
DB 'K7 IS THE DIRECTION CONTROL',0AH,0DH,'$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,CS
MOV DS,AX
MOV AX,DATA
MOV DS,AX
MOV DX,OFFSET MES
MOV AH,09 ;中断调用功能9,在屏幕上显示一串字符,字符串首地址由DS:DX确定
INT 21H
MOV DX,P55CTL ;8255控制口
MOV AL,8BH ;控制字
OUT DX,AL ;8255 C 输入, A 输出
MOV BUF,33H
OUT1: MOV AL,BUF
MOV DX,P55A ;8255A 口
OUT DX,AL ;8255A 口输出
push dx
MOV AH,06h
mov dl,0ffh
INT 21H ;判断有键按下否
pop dx
JE IN1 ;zf=1,表示无键按下,转IN1, zf=0,表示有键按下,则结束
MOV AH,4CH
INT 21H
IN1: MOV DX,P55C ;8255c口
IN AL,DX ;用8255c口读入开关状态
TEST AL,01H
JNZ K0
TEST AL,02H
JNZ K1
TEST AL,04H
JNZ K2
TEST AL,08H
JNZ K3
TEST AL,10H
JNZ K4
TEST AL,20H
JNZ K5
TEST AL,40H
JNZ K6
STOP: MOV DX,P55A
MOV AL,0FFH
JMP OUT1
K0: MOV BL,10H ;置延时时间
SAM: TEST AL,80H ;k7是否为1,判定正反转
JZ ZX0 ;k7=1,转zx0
JMP NX0 ;k7=0, 转nx0
K1: MOV BL,18H
JMP SAM
K2: MOV BL,20H
JMP SAM
K3: MOV BL,40H
JMP SAM
K4: MOV BL,80H
JMP SAM
K5: MOV BL,0C0H
JMP SAM
K6: MOV BL,0FFH
JMP SAM
ZX0: CALL DELAY ;延时,正转
MOV AL,BUF
ROR AL,1
MOV BUF,AL
JMP OUT1
NX0: CALL DELAY ;延时,反转
MOV AL,BUF
ROL AL,1
MOV BUF,AL
JMP OUT1
DELAY PROC NEAR
DELAY1: MOV CX,05A4H
DELAY2: LOOP DELAY2
DEC BL
JNZ DELAY1
RET
DELAY ENDP
CODE ENDS
END START
;**********end of program 3-4-1.asm*************;