实验目的:
验证一些实验的正确性,通过验证性试验掌握这些芯片,并加深对这些芯片的理解。
实验要求:
验证下列实验:
1.8255控制交通灯实验;
2.8253方波实验;
3.8259A中断控制器实验;
4.8237 DMA传输实验;
5.ADC0809并行AD实验(数字电压表实验),并行DA实验DAC0832;
6.8251可编程通信实验(与微机)。
实验描述:
1.8255控制交通灯实验:
使用8255的PA0..2、PA4..6控制LED指示灯,实现交通灯功,并能连接线路验证8255的功能,熟悉它的使用方法。通过A口来控制交通灯的亮灭。我认为这个试验中最重要的就是初始化代码如下:
MOV |
AX,@DATA |
|
MOV |
DS,AX |
|
NOP |
|
|
MOV |
DX,COM_ADD |
|
MOV |
AL,80H |
;PA、PB、PC为基本输出模式 |
OUT |
DX,AL |
|
MOV |
DX,PA_ADD |
;灯全熄灭 |
MOV |
AL,0FFH |
|
OUT |
DX,AL |
|
这些代码的作用就是初始化8255,设置8255的控制字,让A、B、C口作为输出模式并工作在方式0下。
然后再令灯全灭,之后就可以进行之后是红绿灯闪烁的操作。
比较重要的还有延时程序如下:
DL500ms |
PROC |
NEAR |
|
PUSH |
CX |
|
MOV |
CX,60000 |
DL500ms1: |
LOOP |
DL500ms1 |
|
POP |
CX |
|
RET |
|
DL500ms |
ENDP |
|
DL3S |
PROC |
NEAR |
|
PUSH |
CX |
|
MOV |
CX,6 |
DL3S1: |
CALL |
DL500ms |
|
LOOP |
DL3S1 |
|
POP |
CX |
|
RET |
|
|
ENDP |
|
DL5S |
PROC |
NEAR |
|
PUSH |
CX |
|
MOV |
CX,10 |
DL5S1: |
CALL |
DL500ms |
|
LOOP |
DL5S1 |
|
POP |
CX |
|
RET |
|
|
ENDP |
|
这些代码的作用就是延时,当想让灯闪烁的时候使用CALL调用这些子程序。
这个实验让我进一步掌握了8255的设计、编程方法。掌握了矩阵键盘的扫描方法。掌握了动态扫描数码块的方法。
2.8253方波实验;
用8253的计数器0和计数器1实现对输入时钟频率的两级分频,得到一个周期为1秒的方波,用此方波控制蜂鸣器,发出报警信号,也可以将输入脚接到逻辑笔上来检验程序是否正确。
连接线路,验证8253的功能,熟悉它的使用方法。
测试实验结果:蜂鸣器发出时有时无的声音;用逻辑笔测试蜂鸣器的输入端口,红绿灯交替点亮。
我认为主要的核心代码如下:
MOV |
DX,COM_ADDR |
|
MOV |
AL,35H |
|
OUT |
DX,AL |
;计数器T0设置在模式2状态,BCD码计数 |
MOV |
DX,T0_ADDR |
|
MOV |
AL,00H |
|
OUT |
DX,AL |
|
MOV |
AL,10H |
|
OUT |
DX,AL |
;CLK0/1000 |
MOV |
DX,COM_ADDR |
|
MOV |
AL,77H |
|
OUT |
DX,AL |
;计数器T1为模式3状态,输出方波,BCD码计数 |
MOV |
DX,T1_ADDR |
|
MOV |
AL,00H |
|
OUT |
DX,AL |
|
MOV |
AL,10H |
|
OUT |
DX,AL |
;CLK1/1000 |
JMP |
$ |
;OUT1输出1S的方波 |
|
|
|
这些代码的作用就是初始化8253,并且使计数器T1为模式3状态,输出方波,BCD码计数。因为输出方波频率到蜂鸣器,所以蜂鸣器发出时有时无的声音;用逻辑笔测试蜂鸣器的输入端口,红绿灯交替点亮。
这也让我了解了8253的内部结构、工作原理;了解了8253与8086的接口逻辑;熟悉了8253的控制寄存器和初始化编程方法,熟悉了8253的6种工作模式。
3.8259A中断控制器实验;
拨动单脉冲开关,“”送给8259A的IR0,触发中断,8086计数中断次数,显示于F5区的数码管上。
运行程序后,上下拨动单脉冲开关,拨动二次,产生一个“”,观察结果,数码管上显示的次数与拨动开关次数是否对应。
我认为核心代码如下:
MOV |
AX,@DATA |
|
MOV |
DS,AX |
|
MOV |
ES,AX |
|
NOP |
|
|
CALL |
InitKeyDisplay |
;对键盘、数码管控制器8255初始化 |
CALL |
Init8259 |
|
CALL |
WriIntver |
|
MOV |
Counter,0 |
;中断次数 |
MOV |
ReDisplayFlag,1 |
;需要显示 |
STI |
;开中断 |
|
这些代码的主要作用是通过调用子程序对键盘、数码管控制器8255初始化、以及调用8259的初始化子程序。
8259初始化如下:
Init8259 |
PROC |
NEAR |
|
|
MOV |
DX,IO8259_0 |
|
|
MOV |
AL,13H |
|
|
OUT |
DX,AL |
|
|
MOV |
DX,IO8259_1 |
|
|
MOV |
AL,08H |
|
|
OUT |
DX,AL |
|
|
MOV |
AL,09H |
|
|
OUT |
DX,AL |
|
|
MOV |
AL,0FEH |
|
|
OUT |
DX,AL |
|
|
RET |
|
|
Init8259 |
ENDP |
|
|
这个子程序主要是初始化8259。
这个实验让我了解了8259A的内部结构、工作原理;了解了8259A与8086的接口逻辑;掌握了对8259A的初始化编程方法,了解了8086是如何响应中断、退出中断的。
4.8237 DMA传输实验;
编制程序:将B4区SRAM中83000H~837FFH内数据通过DMA方式传输给86000H~867FFH,并对 83000H~837FFH与86000H~867FFH作比较。
由于DMA传输期间,8237只能生成地址线A15..A0,地址总线的高四位A19..A16由实验仪强制置位为“1000”,从而存贮器片选信号mCS1有效,选中B4区的16位SRAM。
编写、调试程序然后存贮器的83000H~837FFH与86000H~867FFH二块数据是否完全相同。
我认为这个实验的核心代码如下:
mov |
[si],al |
|
inc |
Si |
|
dec |
Al |
|
loop |
STAR3 |
|
mov |
al,04h |
|
mov |
dx,DMAaddr+8 |
|
out |
dx,al |
;禁止DMA操作 |
mov |
al,00 |
|
mov |
dx,DMAaddr+0dh |
|
out |
dx,al |
;复位 |
mov |
dx,DMAaddr+0ch |
|
out |
dx,al |
;清除先/后寄存器 |
mov |
dx,DMAaddr+0 |
;源启始地址3000H |
mov |
al,0 |
|
out |
dx,al |
|
mov |
al,30h |
|
out |
dx,al |
|
mov |
dx,DMAaddr+0ch |
|
out |
dx,al |
;清除先/后寄存器 |
mov |
dx,DMAaddr+2 |
;目的启始地址6000H |
mov |
al,0 |
|
out |
dx,al |
|
mov |
al,60h |
|
out |
dx,al |
|
mov |
dx,DMAaddr+0ch |
|
out |
dx,al |
;清除先/后寄存器 |
mov |
dx,DMAaddr+03h |
|
mov |
al,0ffh |
;长度0800H |
out |
dx,al |
|
mov |
al,07h |
|
out |
dx,al |
|
mov |
dx,DMAaddr+0bh |
|
mov |
al,88h |
|
out |
dx,al |
;通道0方式字 |
mov |
al,85h |
|
out |
dx,al |
;通道1方式字 |
mov |
dx,DMAaddr+8 |
|
mov |
al,41H |
|
out |
dx,al |
;允许8237工作、存贮器方式传送 |
这个实验让我了解了8237的内部结构、工作原理;了解了8237与8086的接口逻辑;掌握了使用8237,实现DMA传输数据。
5.ADC0809并行AD实验(数字电压表实验),并行DA实验DAC0832;
DA实验:编写程序:用0832输出正弦波,然后连线,运行程序,使用示波器观察实验结果。示波器的探头接D2区的OUT,观察实验结果,是否产生正弦波。
演示程序如下:
|
.MODEL |
TINY |
|
ADDR_0832 |
EQU |
0240H |
;0832输出口地址 |
|
.STACK |
100 |
|
|
.DATA |
|
|
TAB_1 DB 7FH,8BH,96H,0A1H,0ABH,0B6H,0C0H,0C9H,0D2H | |||
DB 0DAH,0E2H,0E8H,0EEH,0F4H,0F8H,0FBH,0FEH,0FFH,0FFH | |||
DB 0FFH,0FEH,0FBH,0F8H,0F4H,0EEH,0E8H,0E2H,0DAH,0D2H | |||
DB 0C9H,0C0H,0B6H,0ABH,0A1H,096H,08BH,07FH | |||
DB 74H,69H,5EH,54H,49H,40H,36H,2DH,25H,1DH,17H,11H,0BH,7,4,2,0,0 | |||
DB 0,2,4,7,0BH,11H,17H,1DH,25H,2DH,36H,40H,49H,54H,5EH,69H,74H | |||
|
.CODE |
|
|
START: |
MOV |
AX,@DATA |
|
|
MOV |
DS,AX |
|
|
NOP |
|
|
|
MOV |
DX,ADDR_0832 |
|
START1: |
LEA |
SI,TAB_1 |
|
|
MOV |
CX,72 |
|
START2: |
LODSB |
|
|
|
OUT |
DX,AL |
|
|
CALL |
DELAY |
|
|
LOOP |
START2 |
|
|
JMP |
START1 |
|
DELAY |
PROC |
NEAR |
|
|
PUSH |
CX |
|
|
MOV |
CX,80 |
|
|
LOOP |
$ |
|
|
POP |
CX |
|
|
RET |
|
|
DELAY |
ENDP |
|
|
|
|
|
|
|
END |
START |
|
可以观察到正弦波。
并行AD实验:ADC0809(C2区)(1) 模数转换器,8位精度,8路转换通道,1路并行输出(2) 转换时间100us,转换电压范围0~5V。
编写程序:制作一个电压表,测量0~5V,结果显示于数码管上。然后调节0~5V电位器(F6区)输出电压,显示在LED(最右边2位)上的电压数字量会随之改变。用万用表验证AD转换的结果。
我认为主要代码如下:
AD0809 |
PROC |
NEAR |
|
|
PUSH |
CX |
|
|
MOV |
AL,0 |
|
|
MOV |
DX,ADDR_0809 |
|
|
OUT |
DX,AL |
|
|
MOV |
CX,100 |
|
|
LOOP |
$ |
;延时,等待AD转换完成 |
|
MOV |
DX,ADDR_0809 |
|
|
IN |
AL,DX |
|
|
POP |
CX |
|
|
RET |
|
|
AD0809 |
ENDP |
|
|
这个子程序是对ADC0809的使用,实现AD转换。
这个实验让我了解了几种类型AD转换的原理;掌握了使用ADC0809进行模数转换;而且还了解了数模转换的原理;了解了0832与8086的接口逻辑,掌握了使用DAC0832进行数模转换。
6.串行通信:8250、8251可编程通信实验(与微机)。
8250可编程通信实验:
编写程序:通过初始化8250,设置波特率为4800bps(或其它,但与微机部分一致),数据格式为8数据位,1停止位,偶校验;然后打开PC机的串行通信测试软件,向8250发送一批数据,8250接收完数据之后,再将数据依次发送回去。连线,运行程序,观察实验结果,掌握8250的各项功能及编程方法。然后运行程序,运行“串口助手(ComPort.EXE)”,设置串口(波特率4800,8个数据位,一个停止位,偶校验),打开串口,选择“HEX发送”、“HEX显示”,向8250发送10个字节数据(输入数据之间用空格分隔),是否能接收到10个字节数据,接收到的数据是否与发送数据一致。改变传输数据的数目,重复实验,观察结果。
主要代码如下:
INIT8250 |
PROC |
NEAR |
|
|
MOV |
DX,ISR |
|
|
MOV |
AL,06H |
|
|
OUT |
DX,AL |
|
|
MOV |
DX,LCR |
|
|
MOV |
AL,83H |
;允许访问波特率因子寄存器 |
|
OUT |
DX,AL |
|
|
MOV |
DX,DLL |
|
|
MOV |
AL,40 |
|
;除数低位寄存器,波特率设为4800=(3.072*1000000/16)/DLMDLL | |||
|
OUT |
DX,AL |
|
|
MOV |
DX,DLM |
;00H送高字节寄存器 |
|
MOV |
AL,00H |
|
|
OUT |
DX,AL |
|
|
MOV |
DX,LCR |
;不允许访问波特率因子寄存器 |
|
MOV |
AL,1BH ;数据格式为8数据位,1停止位,偶校验 | |
|
OUT |
DX,AL |
|
|
RET |
|
|
INIT8250 |
ENDP |
|
|
8250和PC机通信,需要在PC上运行一个串口软件,并设置与8250相同的波特率。实验后发现能接收到10个字节数据,且接收到的数据是否与发送数据一致。
8251可编程通信实验:
实现8251A与PC机的串行通讯,使用8253作分频器提供8251的收发时钟。连接线路,从微机接收一批数据,接收完毕,再将它们回送给微机。
运行程序运行“串口助手(ComPort.EXE)”,设置串口(波特率4800,8个数据位,一个停止位,偶校验),打开串口,选择“HEX发送”、“HEX显示”,向8251发送10个字节数据(输入数据之间用空格分隔),是否能接收到10个字节数据,接收到的数据是否与发送数据一致。改变传输数据的数目,重复实验,观察结果。
演示程序如下:
|
.MODEL |
TINY |
|
;使用8253的计数器0,外接2Mhz,经26分频后,送给8251,产生4800bps | |||
CTL_ADDR |
EQU |
0241H |
;控制字或状态字 |
DATA_ADDR |
EQU |
0240H |
;读写数据 |
W_8253_T0 |
EQU |
0260H |
;计数器0地址 |
W_8253_C |
EQU |
0263H |
;控制字 |
|
.STACK |
100 |
|
|
.DATA |
|
|
Receive_Buffer |
DB |
10 DUP(0) |
;接受缓冲器 |
Send_Buffer |
EQU |
Receive_Buffer |
;发送缓冲器 |
|
.CODE |
|
|
START: |
MOV |
AX,@DATA |
|
|
MOV |
DS,AX |
|
|
MOV |
ES,AX |
|
|
NOP |
|
|
|
CALL |
INIT_8253 |
|
|
CALL |
INIT_8251 |
|
START1: |
MOV |
CX,10 |
|
|
CALL |
Receive_Group |
|
|
MOV |
CX,10 |
|
|
CALL |
Send_Group |
|
|
JMP |
START1 |
|
INIT_8253 |
PROC |
NEAR |
|
|
MOV |
DX,W_8253_C |
|
|
MOV |
AL,37H |
;定时器0,方式3 |
|
OUT |
DX,AL |
|
|
MOV |
DX,W_8253_T0 |
|
|
MOV |
AL,26H |
;BCD码26(2000000/26)=16*4800 |
|
OUT |
DX,AL |
|
|
MOV |
AL,0 |
|
|
OUT |
DX,AL |
|
|
RET |
|
|
INIT_8253 |
ENDP |
|
|
INIT_8251 |
PROC |
NEAR |
|
|
CALL |
RESET_8251 |
|
|
MOV |
DX,CTL_ADDR |
|
|
MOV |
AL,7EH |
;波特率系数为16,8个数据位 |
|
OUT |
DX,AL |
;一个停止位,偶校验 |
|
CALL |
DLTIME |
;延时 |
|
MOV |
AL,15H ;允许接收和发送发送数据,清错误标志 | |
|
OUT |
DX,AL |
|
|
CALL |
DLTIME |
|
|
RET |
|
|
INIT_8251 |
ENDP |
|
|
Reset_8251 |
PROC |
NEAR |
|
|
MOV |
DX,CTL_ADDR |
|
|
MOV |
AL,0 |
|
|
OUT |
DX,AL |
;向控制口写入"0" |
|
CALL |
DLTIME |
;延时,等待写操作完成 |
|
OUT |
DX,AL |
;向控制口写入"0" |
|
CALL |
DLTIME |
;延时 |
|
OUT |
DX,AL |
;向控制口写入"0" |
|
CALL |
DLTIME |
;延时 |
|
MOV |
AL,40H |
;向控制口写入复位字40H |
|
OUT |
DX,AL |
|
|
CALL |
DLTIME |
|
|
RET |
|
|
Reset_8251 |
ENDP |
|
|
;接受一组数据,CX--接受数目 | |||
Receive_Group |
PROC |
NEAR |
|
|
LEA |
DI,Receive_Buffer | |
Receive_Group1: |
CALL |
Receive_Byte |
|
|
STOSB |
|
|
|
LOOP |
Receive_Group1 |
|
|
RET |
|
|
Receive_Group |
ENDP |
|
|
;接受一个字节 | |||
Receive_Byte |
PROC |
NEAR |
|
|
MOV |
DX,CTL_ADDR |
|
Receive_Byte1: |
IN |
AL,DX |
;读入状态 |
|
TEST |
AL,2 |
|
|
JZ |
Receive_Byte1 |
;有数据吗? |
|
MOV |
DX,DATA_ADDR |
;有 |
|
IN |
AL,DX |
|
|
RET |
|
|
Receive_Byte |
ENDP |
|
|
;发送一组数据,CX--发送数目 | |||
Send_Group |
PROC |
NEAR |
|
|
LEA |
SI,Send_Buffer |
|
Send_Group1: |
LODSB |
|
|
|
CALL |
SendByte |
|
|
LOOP |
Send_Group1 |
|
|
RET |
|
|
Send_Group |
ENDP |
|
|
;发送一个字节 | |||
Sendbyte |
PROC |
NEAR |
|
|
PUSH |
AX |
|
|
MOV |
DX,CTL_ADDR |
;读入状态 |
Sendbyte1: |
IN |
AL,DX |
|
|
TEST |
AL,1 |
|
|
JZ |
Sendbyte1 |
;允许数据发送吗? |
|
POP |
AX |
;发送 |
|
MOV |
DX,DATA_ADDR |
|
|
OUT |
DX,AL |
|
|
RET |
|
|
Sendbyte |
ENDP |
|
|
;延时 | |||
DLTIME |
PROC |
NEAR |
|
|
MOV |
CX,10 |
|
|
LOOP |
$ |
|
|
RET |
|
|
DLTIME |
ENDP |
|
|
|
|
|
|
|
END |
START |
|
这个演示程序用了8253并使其定时器0在方式3下工作,也使用了8251。实验后发现能接收到10个字节数据,且接收到的数据是否与发送数据一致。
这个实验让我了解了8251的内部结构、工作原理;了解了8251与8086的接口逻辑;掌握了对8251的初始化编程方法,学会了使用8251实现设备之间的串行通信。同时了解了8250的内部结构、工作原理;了解了8250与8086的接口逻辑;掌握对了8250的初始化编程方法,学会使用8250实现设备之间的串行通信。