基于8086的压力检测器设计(Proteus8仿真)

一、实验名称

基于 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。
基于8086的压力检测器设计(Proteus8仿真)_第1张图片
基于8086的压力检测器设计(Proteus8仿真)_第2张图片
如图2为压力检测器总体设计图,以 8086 为处理器,利用用于地址锁存的 74LS373、译码器 74154、可编程并行 接口 8255A、中断控制器 8259A、压力传感器件 MPX4115、模数转换器 ADC0808、七段显示译码器 4511、状态指示灯、四个共阴极二极管显示器 7SEA- MPX4-CC。测量得到的压力值可以在数码管精准显示。 当压力值处于正常值范围内时,绿色指示灯亮。 当压力值大于正常值最大值时,红色指示灯亮。 当压力值小于正常值最小值时,黄色指示灯亮。本次实验的芯片及其功能如下:

  1. 8086 为处理器:用于协调各芯片协同工作,完成选通可编程并行接口 8255A、中断控制器 8259A、处理中断服务程序等任务
  2. 利用用于地址锁存的 74LS373: 两片 74LS373 的 D0~D7 用于接收 CPU 的地址信号; Q0~Q7 用于输出该芯片锁存后的结果。
  3. 译码器 74154:该芯片是 4-16 译码器,但是在此系统中,只用到了两个输出口; IOY0 用于选通 8255A,IOY1 用于选通 8259。
  4. 可编程并行 接口 8255A:在本系统中,8255A 通过 74154 的 IOY0 引脚信号选通; A 口用来接收数字信号; D0~D7 实现数据线和地址线的复用,传递和接受 CPU 处理前后的数据; B 口输出 CPU 传输来的处理之后的数据,并将输出; C 口用来输出控制信息; PC0 用于管理模数转换器 ADC0808 的启动; PC1~PC3 用来管理状态指示灯的三种指示情况。
  5. 中断控制器 8259A:在本系统中,8259A 通过 74154 的 IOY1 引脚信号选通;通过 IR0 引脚接收模数转换器 ADC0808 的 EOC 中断源,并对此中断进行 管理;AD 是地址线与数据线复用,通过 AD 将中断类型码传递给 CPU;INTR 用于向 CPU 提出中断请求;INTA 用于接收 CPU 的信号。
  6. 压力传感器件 MPX4115:在本系统中作为一个模拟的传感器、能够感受压力;压力通过此装置传入该工程系统。MPX4115 的量程下限为 25kPa,在 00kPa、输入电压为 5V 时,此时的模 拟电压输出为+0.2579V;MPX4115 的量程上限为 110kPa,在 100kPa、输入电压为 5V 时,模拟电 压输出为+4.0920V。
  7. 模数转换器 ADC0808:该装置由 8255A 的 PC0 引脚信号启动;通过 IN0 接收压力传感器的模拟信号,并将其转化为数字信号;将数字信号通过 OUT1~OUT8 传输到 8255A 的 A 口的 PA0~PA7; 在 EOC 引脚输出一个中断源给 8259A;3 位地址输入线 ADDA、ADDB、ADDC 的值设置为 000,硬件上将它们 接地即可;时钟频率不高于 640KHZ,采用 10kHz 即可
  8. 七段显示译码器 4511:4-7 译码器,输出每个七段数码管的控制信号给共阴极二极管显示器;
  9. 状态指示灯:接收 8255A 的输出信号 PC1、PC2、PC3,及时用 LED 的亮灯情况反馈所测量的压力值是否在正常量程内。
  10. 四个共阴极二极管显示器 7SEA- MPX4-CC:实时显示所测压力的数值;通过 QA~QG 控制七段数码管的信号,通过 L1~L4 选择指定的七段数码管。

四、实验结果


如图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);
    }
 }
 

你可能感兴趣的:(微机原理与接口技术,单片机,物联网,嵌入式硬件)