1.实验内容
2.实验原理/预备知识
D/A转换器TLC7528是关键,其用法参见:
芯片部件汇总:常用功能部件大全-CSDN博客
直接找"TLC7528 D/A数模转换器"(实际上学校的讲义已经讲的很清楚,我只是给搬到了博客里)
3.实验电路图
本次实验的电路较简单,直接按照讲义连接即可。只是拓展实验由于需要使用外部中断,需要加一根线,将'KK1+'端口连接到一个外部中断端口(MIR6或MIR7):
4.实验代码(汇编和C语言版):
汇编语言:
基础实验:
A0832 EQU 0600H ; IOY0地址是0600H,IOY1地址是0640H,IOY2地址是0680H
CODE SEGMENT
ASSUME CS:CODE
START:
;产生锯齿波
MOV CX, 07H ;锯齿波周期数
JUCHI:
MOV DX, A0832 ;DAC0832接IOY0,0600H为控制端口地址
MOV AL, 00H ;AL为数字量
JC1:
OUT DX, AL ;转换为模拟量
CALL DELAY1 ;延时,此为短延时
CMP AL ,0FFH
JE JC2
INC AL ;AL步加1,直到等于0FFH
JMP JC1
JC2:
LOOP JUCHI
;产生矩形波
MOV CX, 05H ;矩形波周期数
JUXING:
MOV DX, A0832
MOV AL, 00H ;先输出00H的波形
OUT DX, AL
CALL DELAY2 ;长延时
MOV AL, 0FFH ;再输出0FFH的波形
OUT DX, AL
CALL DELAY2 ;长延时
LOOP JUXING
;产生三角波
MOV CX, 05H ;三角波周期数
SANJIAO:
SJ1:
MOV DX, A0832
OUT DX, AL
CALL DELAY1 ;短延时
CMP AX, 0FFH
JE SJ2
INC AL ;将AL从00H步加0FFH
JMP SJ1
SJ2:
MOV DX, A0832
OUT DX, AL
CALL DELAY1 ;短延时
CMP AL, 00H
JE SJ3
DEC AL ;将AL从0FFH步减至00H
JMP SJ2
SJ3:
LOOP SANJIAO
;产生阶梯波
MOV CX, 0FFFFH ;产生阶梯波的周期数为0FFFF次
MOV AX, 0FEH ;设置波形振幅最大值为0FEH
MOV BL,05H ;阶梯波中的阶梯数
DIV BL ;用最大振幅除以阶梯数,得到每个台阶的高度
MOV BL, AL ;将上述除法的商保存在BL中
MOV BH, 00H ;BH置0
JIETI:
MOV AX,0000H ;AX初始化0000H
JT1:
MOV DX, A0832
OUT DX, AL
CMP AX, 00FFH ;判断AX是否达到幅度上限
JAE JT2 ;达到上限,表示一次阶梯波完整生成,开始新一次生成
CALL DELAY2 ;长延时
ADD AX, BX ;用当前阶梯高度加上每个阶梯的高度得到下一阶梯的高度
JMP JT1
JT2:
LOOP JIETI
DELAY1: ;短延时
PUSH CX
MOV CX, 01FFH
D1:
PUSH AX
POP AX
LOOP D1
POP CX
RET
DELAY2: ;长延时
PUSH CX
MOV CX, 0FFFFH
D2:
PUSH AX
POP AX
LOOP D2
POP CX
RET
CODE ENDS
END START
扩展实验:
CODE SEGMENT
ASSUME CS:CODE
START:
MOV AX,0000H
MOV DS,AX
;设置中断向量
MOV AX,OFFSET MIR6
MOV SI,0038H ;MIR6中断的矢量地址
MOV [SI],AX
INC SI
INC SI
MOV AX,CS
MOV [SI],AX
CLI
MOV AL,11H
OUT 20H, AL ;命令字ICW1, 11H=00010001B
MOV AL, 08H
OUT 21H, AL ;命令字ICW2, 08H=00001000B
MOV AL, 04H
OUT 21H, AL ;命令字ICW3, 04H=00000100B
MOV AL, 03H
OUT 21H, AL ;命令字ICW4, 03H=00000011B
MOV AL, 0AFH ;OCW1, AF = 10101111B
OUT 21H, AL
STI
MOV BL,00H
A1:
CMP BL,00H
JZ JUCHI
CMP BL,01H
JZ JUXING
CMP BL,02H
JZ SANJIAO
JMP JIETI
JUCHI:
MOV DX, 0600H ;DAC0832接IOY0,0600H为控制端口地址
MOV AL, 00H ;AL为数字量
JC1:
OUT DX, AL ;转换为模拟量
CALL DELAY1 ;短延时
CMP AL ,0FFH
JE A1
INC AL ;AL步加1,直到等于0FFH
JMP JC1
JUXING:
MOV DX, 0600H
MOV AL, 00H ;先输出00H的波形
OUT DX, AL
CALL DELAY2 ;长延时
MOV AL, 0FFH ;再输出0FFH的波形
OUT DX, AL
CALL DELAY2 ;长延时
JMP A1
SANJIAO:
MOV AL, 00H
SJ1:
MOV DX, 0600H
OUT DX, AL
CALL DELAY3 ;短延时
CMP AL, 0FFH
JE SJ2
INC AL ;将AL从00H步加0FFH
JMP SJ1
SJ2:
MOV DX, 0600H
OUT DX, AL
CALL DELAY3 ;短延时
CMP AL, 00H
JE A1
DEC AL ;将AL从0FFH步减至00H
JMP SJ2
JIETI:
MOV AX, 0FEH ;设置波形振幅最大值为0FEH
MOV CL,05H ;阶梯波中的阶梯数
DIV CL ;用最大振幅除以阶梯数,得到每个台阶的高度
MOV CL, AL ;将上述除法的商保存在CL中
MOV CH, 00H ;CH置0
JT1:
MOV AX, 0000H ;AX初始化0000H
JT2:
MOV DX, 0600H
OUT DX, AL
CMP AX, 0FFH ;判断AX是否达到幅度上限
JAE A1 ;达到上限,表示一次阶梯波完整生成
CALL DELAY4 ;长延时
ADD AX, CX ;用当前阶梯高度加上每个阶梯的高度得到下一阶梯的高度
JMP JT2
DELAY1:
PUSH AX
PUSH CX
MOV AX, 01H ;调节循环次数来改变周期
D1:
MOV CX, 0FFH
DD1:
LOOP DD1
DEC AX
CMP AX, 00H
JNZ D1
POP CX
POP AX
RET
DELAY2:
PUSH AX
PUSH CX
MOV AX, 7FH ;调节循环次数来改变周期
D2:
MOV CX, 0FFH
DD2:
LOOP DD2
DEC AX
CMP AX, 00H
JNZ D2
POP CX
POP AX
RET
DELAY3:
PUSH AX
PUSH CX
MOV AX, 01H ;调节循环次数来改变周期
D3:
MOV CX, 0FFH
DD3:
LOOP DD3
DEC AX
CMP AX, 00H
JNZ D3
POP CX
POP AX
RET
DELAY4:
PUSH AX
PUSH CX
MOV AX, 7FH ;调节循环次数来改变周期
D4:
MOV CX, 0FFH
DD4:
LOOP DD4
DEC AX
CMP AX, 00H
JNZ D4
POP CX
POP AX
RET
MIR6:
INC BL
CMP BL, 03H
JA M
IRET
M:
MOV BL, 00H
IRET
CODE ENDS
END START
C语言版本:
我以前提过,只要在TDX-PITE软件中点左上方设置->语言->C,即可切换成C语言模式。
#include "conio.h"
typedef unsigned char u8;
typedef unsigned int u16;
u16 DAC = 0x0600;
u8 value = 0;
u8 time = 0;
void delay(u16 time);
void sawtooth();
void rectangle();
void triangle();
void ladder(u8 num);
void main() {
while(1) {
sawtooth();
rectangle();
triangle();
ladder(5);
}
}
void delay(u16 time)
{
int i=0;
for(;i<time;i++)
{
int j=0;
for(;j<50;j++);
}
}
void sawtooth() { //value连续变化,输入到DAC中,就是锯齿形状
int Loop = 5;
for(;Loop>0;Loop--)
{
value = 0;
for(;value <= 0x0FE;value++) {
outportb(DAC, value);
delay(10);
}
}
}
void rectangle() { //value一高一低两个离散的值输入到DAC,就是矩阵形状
int Loop = 5;
for(;Loop>0;Loop--)
{
value = 0;
outportb(DAC, value);
delay(500);
value = 0x0FF;
outportb(DAC, value);
delay(500);
}
}
void triangle() {//其实就是锯齿,先从低到高再从高到低
int Loop = 5;
for(;Loop>0;Loop--)
{
value = 0;
for(;value<=0x0FE;value++){
outportb(DAC, value);
delay(10);
}
for(;value>0;value--){
outportb(DAC, value);
delay(10);
}
}
}
void ladder(u8 num) { //num逐渐减小,step跳跃性的逐渐增大,形成阶梯状
int Loop = 5;
int num0 = num;
u8 step = 0x0FF / (num+1);
for(;Loop>0;Loop--)
{
num = num0;
value = 0;
for(;num>0; num--) {
outportb(DAC, value);
delay(100);
step = 0xFF / (num+1);
value += step;
}
}
}
必须提到一点,在 TDX-PITE 的编译器下,不能在for循环中定义一个变量,即不能写:
for(int i=0;i<10;i++);
这样写会报错,必须写:
int i = 0;
for(;i<10;i++);
原因尚不明确,网上相关资料太少,网上有很多关于C51的资料很多,但关于如何用C语言操作8086微机的资料较少,我也是参照了一位学长的博客:
吉林大学微机接口实验代码(五)_吉林大学微机系统实验-CSDN博客
如果你知道什么关于C语言在微机接口技术中的应用的资料,可以告诉我。
。