基于 proteus 设计压力检测计
深刻理解并掌握基于 8086 处理器的系统工程的工作原理和流程;
深刻理解并掌握 8086 处理器的工作原理、引脚功能;
深刻理解并掌握压力传感器件 MPX4115 的工作原理、引脚功能;
深刻理解并掌握模数转换器 ADC0808 的工作原理、引脚功能;
深刻理解并掌握可编程并行接口 8255A 的工作原理、引脚功能;
深刻理解并掌握中断控制器 8259A 的工作原理、引脚功能;
深刻理解并掌握用于地址锁存的 74LS373 的工作原理、引脚功能;
深刻理解并掌握译码器 74154 的工作原理、引脚功能;
深刻理解并掌握七段显示译码器 4511 的工作原理、引脚功能;
深刻理解并掌握状态指示灯的工作原理、引脚功能;
深刻理解并掌握二极管显示器 7SEA-MPX4-CC 的工作原理、引脚功能;
本工程的设计内容是压力检测计,以8086CPU为处理器,利用8255A、8259A、ADC0808、74LS373、74154、MPX4115、4511、状态指示灯和7SEA-MPX4-CC协调工作完成任务。实现功能:采集压力传感器模拟电压信号,并输出在7SEA-MPX4-CC数码管上,设置压力阈值,正常工作,压力过低,压力过高三种状态分别显示在状态指示灯上。工程流程:首先,向8086中写入中断向量,并且初始化8259与8255,然后CPU调用8255PC0引脚启动ADC0808,压力传感器件输出模拟电压传送到模数转换器ADC0808转化为二进制数;然后,将二进制数传送到8255的A端口进行锁存,并向8259申请中断;接着,CPU处理完中断程序后,将更新后的模拟值输出到8255的B端口和C端口,B端口的数据配合4511输出到压力显示器,C端口的数据输出到状态指示灯,循环上述过程,工作流程如图1。
如图2为压力检测器总体设计图,以 8086 为处理器,利用用于地址锁存的 74LS373、译码器 74154、可编程并行 接口 8255A、中断控制器 8259A、压力传感器件 MPX4115、模数转换器 ADC0808、七段显示译码器 4511、状态指示灯、四个共阴极二极管显示器 7SEA- MPX4-CC。测量得到的压力值可以在数码管精准显示。 当压力值处于正常值范围内时,绿色指示灯亮。 当压力值大于正常值最大值时,红色指示灯亮。 当压力值小于正常值最小值时,黄色指示灯亮。本次实验的芯片及其功能如下:
如图3-图6分别为压力过小,压力正常,压力过大,超过量程的结果,压力正常时,闪烁绿灯,压力过小时,闪烁黄灯,压力过大时,闪烁红灯。
本次实验让我熟悉了8086CPU处理器,8255A、8259A、ADC0808、74LS373、74154、MPX4115、4511、状态指示灯和7SEA-MPX4-CC等原件的工作方式和原理。将他们真正联系起来,而不是一个个单独的个体。本次实验我们编码采用的是C语言和汇编语言,以前从未使用过 C 语言和汇编语言混合使用的操作,通过编程也进一步加深了我们对整个系统和每个芯片的工作原理的细节,包括写中断向量表、定义中断服务程序、各种控制字的设计等等。在设计过程中,也遇到了很多困难,比如器件之间的连接不准确,软件使用不太熟悉,编码过程报错,通过查阅资料和同学帮助,这些问题都成功得到了解决。本次设计实验不仅让我将掌握器件的原理,更重要的是将器件通过代码联系起来,书本学习的理论知识赋予了实践。最后,我认为学好微机接口应该做到理论实际相结合。不能一味只看书,轻视具体编程体验,撇开实际空谈理论,最终一无所获;也不能完全脱离理论,在实验原理一知半解的情况下就动手连接电路然后敲上相应代码,好比囫囵吞枣。微机接口课以及微机接口课程设计有着独有的特点,初学者要处理好理论与实际、硬件与软件等的关系。既要掌握书上的基本原理,又要运用所学的汇编语言以及C语言去获得相应的编程体验。最后,感谢高老师这学期以来的教导。
#define IOY0 0000H //片选IOY0对应的端口始地址 0000 0000 0000 0000
#define IOY1 0100H //片选IOY1对应的端口始地址 0000 0001 0000 0000
#define MY8255_A IOY0 //8255的A口地址 //0000 0000 0000 0000
#define MY8255_B IOY0+01H*4 //8255的B口地址 //0000 0000 0000 0100
#define MY8255_C IOY0+02H*4 //8255的C口地址 //0000 0000 0000 1000
#define MY8255_MODE IOY0+03H*4 //8255的控制寄存器地址//0000 0000 0000 1100
#define ICW1 0100H //0000 0001 0000 0000 偶地址
#define ICW2 0104H //0000 0001 0000 0100 奇地址
#define ICW3 0104H //0000 0001 0000 0100 奇地址
#define ICW4 0104H //0000 0001 0000 0100 奇地址
#define OCW1 0104H //0000 0001 0000 0100 奇地址
#define OCW2 0100H //0000 0001 0000 0000 偶地址
#define OCW3 0100H //0000 0001 0000 0000 偶地址
char LED_ADDR[4] = {14,13,11,7}; //选择数码管1,2,3,4
char LED_NUM[10] = {0,1,2,3,4,5,6,7,8,9}; //数码管显示数字
unsigned int ADC_DATA = 0; //电压值
unsigned int data_num[4]; //十进制数
void Init_8255();
void Init_8259();
void InterruputConfig(void);
void LED_out(char addr, char num);
void LED_set(unsigned int data);
void ADC_begin(void);
unsigned int PRESS_GET();
void delayms(unsigned int j);
//输出函数,向装载地址输出数据
void outp(unsigned int addr, char data)
{ __asm
{ mov dx, addr
mov al, data
out dx, al
}
}
//输入函数,从装载地址获取数据
char inp(unsigned int addr)
{ char result;
__asm
{ mov dx, addr
in al, dx
mov result, al
}
return result;
}
//8255初始化
void Init_8255()
{
__asm
{
MOV DX,MY8255_MODE
MOV AL,98H //工作方式0,A口输入,B口输出,C口输出
OUT DX,AL
}
}
//8259初始化
void Init_8259(void)
{
//icw初始化命令字 ICW1(入偶地址A0=0) 和 ICW2 (入奇地址A0=1)
outp(ICW1, 13H); // ICW1 00010011B D3=0边沿触发, D1=1单片, D0=0 有 ICW4 ,A0=0
outp(ICW2, 80H); // ICW2 10000000B 中断类型号为80H,A0=1
outp(ICW4, 01H); // ICW4 00000001B
outp(OCW1, 00H); // OCW1 置 IMR = 0000,0000B
}
//中断服务函数: 从8255A端口读的压力值,更新ADC_DATA
void Interrupt0(void)
{
_asm
{
CLI
PUSH AX
PUSH BX
PUSH CX
}
ADC_DATA = PRESS_GET(); //ADC_DATA存的是从8255A端口读的压力值
_asm
{
MOV DX,OCW2 //OCW2
MOV AL,20H //发出EOI命令,值ISR 0号中断为0
OUT DX,AL
POP DX
POP CX
POP AX
STI
}
}
//中断配置函数,装载中断向量
void InterruputConfig(void)
{
_asm
{
//80号,装中断向量表(保存中断服务程序的入口地址到中断向量表中)
MOV AX,0
MOV ES,AX
MOV SI,80H*4 //设置中断向量 中断类型号80H
MOV AX,OFFSET Interrupt0 //OFFSET获取偏移地址
MOV ES:[SI],AX // IP
MOV AX,SEG Interrupt0 //SEG获取段地址
MOV ES:[SI+2],AX // CS
}
}
//输出数码管
void LED_out(char addr, char num)
{
char temp = LED_NUM[num]*16 + LED_ADDR[addr-1]; //左移4位加上位置
__asm
{
MOV DX,MY8255_B
MOV AL,temp
OUT DX,AL
}
}
//设置数码管和警报器
void LED_set(unsigned int data)
{
data /= 3;
data += 25;
data_num[3] = data%10; //获得十进制数个位值
data /= 10;
data_num[2] = data%10; //获得十进制数十位值
data /= 10;
data_num[1] = data; //获得十进制数百位值
data_num[0] = 0;
for(int i = 0; i < 3; i++) //输出个位,十位,百位
{
LED_out(i+2,data_num[i+1]); //输出数码管
if((data_num[1] == 1)) //输出报警器
{
outp(MY8255_C,02H);
}
else if((data_num[2] == 2))
{
outp(MY8255_C,08H);
}
else
{
outp(MY8255_C,04H);
}
delayms(10);
}
}
//8255C PC0从1->0 开启ADC0808
void ADC_begin(void)
{
outp(MY8255_C,1);
delayms(5);
outp(MY8255_C,0);
}
//从8255A端口读取压力值(二进制表示)
unsigned int PRESS_GET()
{
unsigned int temp = 0;
__asm
{
MOV AH,0H
MOV DX,MY8255_A
IN AL,DX
MOV temp,AX
}
return temp;
}
//延时函数
void delayms(unsigned int j)
{
unsigned char i;
for(; j>0; j--)
{
i = 120;
while(i--) {;}
}
}
void main(void)
{
_asm
{
cli
}
InterruputConfig();//写中断向量
Init_8259();
_asm
{
sti
}
Init_8255();
while (1)
{
ADC_begin();
LED_set(ADC_DATA);
}
}