找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8376|回复: 6
收起左侧

单片机+MPX4115气压测量仪的仿真与设计含源程序、Proteus图、文档

  [复制链接]
ID:443136 发表于 2018-12-20 20:25 | 显示全部楼层 |阅读模式
压力测量仪的仿真与设计

  • 设计要求:
设计一个数字气压测量仪,要求测量范围为15Kpa~115Kpa,分辨力为0.1Kpa,误差不超过1.5%。

  • 构思:
Protues仿真软件提供了MPX4115和MPX4250,因此可以采用这两种芯片进行设计。压力传感器对于系统至关重要,需要综合实际的需求和各类压力传感器的性能参数加以选择。一般要选用有温度补偿作用的压力传感器,因为温度补偿特性可以克服半导体压力传感器件存在的温度漂移问题。
本设计要实现的数字气压计显示的是绝对气压值,同时为了简化电路,提高稳定性和抗干扰能力,要求使用具有温度补偿能力的压力传感器。经过综合考虑,选择使用MPX4115,可以产生高精度模拟输出电压。

  • 设计:
1、设计整体思想:
              基于MPX4115的数字气压计包括软硬件的设计与调试。软件部分通过对C语言的学习和对单片机知识的了解,根据系统的特点编写出单片机程序。硬件部分分为四大块,包括非电信号数据的采集、转换、处理以及显示:。通过对设计的了解,选择适合的器件,画出原理图。

  • 系统总体设计框图:
    0.png

  • 硬件设计:
(1)数据采集模块:
数据采集模块由压力传感器MPX4115构成。其中1脚是输出信号端,输出的是与气压值相对应的模拟电压信号。数据采集模块的原理如图:

MPX4115系列压电电阻传感器是一个硅压力传感器。这个传感器结合了高级的微电机技术,薄膜镀金属。还能为高水准模拟输出信号提供一个均衡压力。在0℃-85℃的温度下误差不超过1.5%,温度补偿是-40℃-125℃。

  • 单片机控制模块
AT89C52 P为40 脚双列直插封装的8 位通用微处理器,采用工业标准的C51内核,在内部功能及管脚排布上与通用的8xc52 相同,其主要用于会聚调整时的功能控制。功能包括对会聚主IC 内部寄存器、数据RAM及外部接口等功能部件的初始化,会聚调整控制,会聚测试图控制,红外遥控信号IR的接收解码及与主板CPU通信等。主要管脚有:XTAL1(19 脚)和XTAL2(18 脚)为振荡器输入输出端口,外接12MHz 晶振。RST/Vpd(9 脚)为复位输入端口,外接电阻电容组成的复位电路。VCC(40 脚)和VSS(20 脚)为供电端口,分别接+5V电源的正负端。P0~P3 为可编程通用I/O 脚,其功能用途由软件定义,在本设计中,P0 端口(32~39 脚)被定义为N1 功能控制端口,分别与N1的相应功能管脚相连接,13 脚定义为IR输入端,10 脚和11脚定义为I2C总线控制端口,分别连接N1的SDAS(18脚)和SCLS(19脚)端口,12 脚、27 脚及28 脚定义为握手信号功能端口,连接主板CPU 的相应功能端,用于当前制式的检测及会聚调整状态进入的控制功能。

  • A/D转换模块
ADC0832 为8位分辨率A/D转换芯片,其最高分辨可达256级,可以适应一般的模拟量转换要求。其内部电源输入与参考电压的复用,使得芯片的模拟电压输入在0~5V之间。芯片转换时间仅为32μS,据有双数据输出可作为数据校验,以减少数据误差,转换速度快且稳定性能强。独立的芯片使能输入,使多器件挂接和处理器控制变的更加方便。通过DI 数据输入端,可以轻易的实现通道功能的选择。正常情况下ADC0832 与单片机的接口应为4条数据线,分别是CS、CLK、DO、DI。但由于DO端与DI端在通信时并未同时有效并与单片机的接口是双向的,所以电路设计时可以将DO和DI 并联在一根数据线上使用。当ADC0832未工作时其CS输入端应为高电平,此时芯片禁用,CLK 和DO/DI 的电平可任意。当要进行A/D转换时,须先将CS使能端置于低电平并且保持低电平直到转换完全结束。此时芯片开始转换工作,同时由处理器向芯片时钟输入端CLK 输入时钟脉冲,DO/DI端则使用DI端输入通道功能选择的数据信号。在第1 个时钟脉冲的下沉之前DI端必须是高电平,表示启始信号。
作为单通道模拟信号输入时ADC0832的输入电压是0~5V且8位分辨率时的电压精度为19.53mV。如果作为由IN+与IN-输入的输入时,可是将电压值设定在某一个较大范围之内,从而提高转换的宽度。但值得注意的是,在进行IN+与IN-的输入时,如果IN-的电压大于IN+的电压则转换后的数据结果始终为00H。

  • 显示模块
首先要了解的是此数码管为共阳极数码管,即三极管Q1、Q2、Q3、Q4导通时数码管才能点亮,亦即相应的单片机P2.3、P2.、P2.、P2.0为低电平。
采用LED动态扫描显示原理如下:
  • P23P22P21P20输出高电平,关闭所有数码管;
  • 显示个位——把要显示的数据送到P0.0-P0.7P23送低电平,延时5毫秒(时间不能太长,否则数码管会闪烁),P23送高电平;
  • 显示十位——把要显示的数据送到P0.0-P0.7P22送低电平,延时5毫秒(时间不能太长,否则数码管会闪烁),P22送高电平;
  • 显示百位——把要显示的数据送到P0.0-P0.7P21送低电平,延时5毫秒(时间不能太长,否则数码管会闪烁),P21送高电平;
  • 显示千位——把要显示的数据送到P0.0-P0.7,P20送低电平,延时5毫秒(时间不能太长,否则数码管会闪烁),P20送高电平。
  • 以此顺序循环,把它做成子程序,在主循环中调用。

  • 晶振电路
MCS-51系列单片机的时钟信号通常用两种电路形式得到,即内部震荡方式和外部振荡方式,本设计才用内部震荡方式。在引脚XTAL1和XTAL2外接晶体振荡器,就构成了内部振荡电路,如上图所示,图中C1 、C2起稳定震荡频率、快速起振的作用,电容值一般在5PF到30PF。晶体常选用6MHz 、12MHz 或24MHz采用串口时常使用11.0592MHz。内部震荡方式所得到的时钟信号比较稳定。

  • 复位电路
复位操作通常有两种形式:上电复位和按钮复位,本设计采用的是上电复位,如右图所示。其工作原理为:上电瞬间RC电路充电,RST引脚端出现正脉冲,只要RST端保持在两个时钟周期以上的高电平,就能使单片机有效复位。

  •   原理图
  • 仿真
仿真结果如下,顺利完成实验:


  • 心得体会
1、选择芯片和传感器时,够用易用就可以,综合考虑选择性价比最好的。
2、在进行电路实际制作之前,应该用仿真软件进行仿真,可以使开发进程加快。
3、在实际制作电路时,需要注意电源端和地端要检测过不导通后才能通电检测,防止烧坏芯片。

单片机源程序如下:
  1. #include<reg52.h>
  2. #include "intrins.h"
  3. #define uint unsigned int
  4. #define uchar unsigned char

  5. //ADC0832的引脚
  6. sbit ADCS =P3^1;  //ADC0832 chip seclect
  7. sbit ADDI =P3^2;  //ADC0832 k in
  8. sbit ADDO =P3^2;  //ADC0832 k out
  9. sbit ADCLK =P3^0;  //ADC0832 clock signal080307208

  10. unsigned char dispbitcode[8]={
  11.         0xf1,0xf2,0xf4,0xf8,0xef,0xdf,0xbf,0x7f
  12.         };  //位扫描
  13. unsigned char dispcode[11]={
  14.         0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff
  15.         };  //共阳数码管字段码
  16. unsigned char dispbuf[4];
  17. uint temp;
  18. uchar getdata; //获取ADC转换回来的值

  19. void delay_1ms(void)  //12mhz delay 1.01ms
  20. {
  21.         unsigned char x,y;   
  22.         x=3;
  23.         while(x--)
  24.         {
  25.         y=40;
  26.         while(y--);
  27.         }
  28. }

  29. void display(void)  //数码管显示函数
  30. {
  31.         char k;
  32.         for(k=0;k<4;k++)
  33.         {
  34.                 P2 = dispbitcode[k];
  35.                 P0 = dispcode[dispbuf[k]];
  36.                 if(k==1)      //加上数码管的dp小数点
  37.                 P0&=0x7f;
  38.                 delay_1ms();      
  39.         }
  40. }

  41. /*读ADC0832函数*/
  42. //采集并返回
  43. unsigned int Adc0832(unsigned char channel)     //AD转换,返回结果
  44. {
  45.         uchar i=0;
  46.         uchar j;
  47.         uint dat=0;
  48.         uchar ndat=0;
  49.         if(channel==0)channel=2;
  50.         if(channel==1)channel=3;
  51.         ADDI=1;
  52.         _nop_();
  53.         _nop_();
  54.         ADCS=0;//拉低CS端
  55.         _nop_();
  56.         _nop_();
  57.         ADCLK=1;//拉高CLK端
  58.         _nop_();
  59.         _nop_();
  60.         ADCLK=0;//拉低CLK端,形成下降沿1
  61.         _nop_();
  62.         _nop_();
  63.         ADCLK=1;//拉高CLK端
  64.         ADDI=channel&0x1;
  65.         _nop_();
  66.         _nop_();
  67.         ADCLK=0;//拉低CLK端,形成下降沿2
  68.         _nop_();
  69.         _nop_();
  70.         ADCLK=1;//拉高CLK端
  71.         ADDI=(channel>>1)&0x1;
  72.         _nop_();
  73.         _nop_();
  74.         ADCLK=0;//拉低CLK端,形成下降沿3
  75.         ADDI=1;//控制命令结束
  76.         _nop_();
  77.         _nop_();
  78.         dat=0;
  79.         for(i=0;i<8;i++)
  80.         {
  81.                 dat|=ADDO;//收数据
  82.                 ADCLK=1;
  83.                 _nop_();
  84.                 _nop_();
  85.                 ADCLK=0;//形成一次时钟脉冲
  86.                 _nop_();
  87.                 _nop_();
  88.                 dat<<=1;
  89.                 if(i==7)dat|=ADDO;
  90.         }  
  91.         for(i=0;i<8;i++)
  92.         {
  93.         j=0;
  94.         ADDO=1;//收数据
  95.         ADCLK=1;
  96.         _nop_();
  97.         _nop_();
  98.         ADCLK=0;//形成一次时钟脉冲
  99.         _nop_();
  100.         _nop_();
  101.         j=j<<7;
  102.         ndat=ndat|j;
  103.         if(i<7)ndat>>=1;
  104.         }
  105.         ADCS=1;//拉低CS端
  106.         ADCLK=0;//拉低CLK端
  107.         ADDO=1;//拉高数据端,回到初始状态
  108.         dat<<=8;
  109.         dat|=ndat;
  110.         return(dat);            //return ad k
  111. }

  112. /*主程序*/
  113. void main(void)
  114. {  
  115.         while(1)
  116.         {      unsigned int temp;
  117.                 float  press;                 
  118.                 getdata=Adc0832(0);
  119.                 if(14<getdata<243)                           //当压力值介于15kpa到115kpa之间时,遵循线性变换
  120.                 {               
  121.                         int vary=getdata;                        //y=(115-15)/(243-13)*X+15kpa            
  122.                         press=((10.0/23.0)*vary)+9.3;            //测试时补偿值为9.3
  123.                         temp=(int)(press*10);                    //放大10倍,便于后面的计算
  124.                         dispbuf[3]=temp/1000;                     //取压力值百位
  125.                         dispbuf[2]=(temp%1000)/100;                //取压力值十位
  126.                         dispbuf[1]=((temp%1000)%100)/10;            //取压力值个位

  127. ……………………

  128. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
0.png
所有资料51hei提供下载:
压力测量仪的仿真与设计.rar (672.72 KB, 下载次数: 201)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:236336 发表于 2019-3-25 10:38 | 显示全部楼层
有用,帮大忙了
回复

使用道具 举报

ID:513208 发表于 2019-5-17 10:25 | 显示全部楼层
挺有帮助的,谢谢楼主大大
回复

使用道具 举报

ID:544477 发表于 2019-5-22 15:51 | 显示全部楼层
MPX4250和4115在使用上有没有区别诶 就是代码和电路连线上
回复

使用道具 举报

ID:707851 发表于 2020-3-13 19:25 | 显示全部楼层
为什么我把程序导入后,显示器不工作呢
回复

使用道具 举报

ID:413568 发表于 2020-3-26 14:01 | 显示全部楼层
第四个三极管为什么和前三个不一样
回复

使用道具 举报

ID:733895 发表于 2020-5-2 15:36 | 显示全部楼层
感谢楼主
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表