基于51单片机Proteus的压力传感器MPX4115仿真技术

  1. 一、 压力传感器MPX4115

MPX4115 是一款常用的压力传感器型号,它可以测量压力并将其转换为电信号输出。显示屏上的 “101.1”是当前测量到的压力值,单位是kPa 。引脚用于连接外部电路,以实现信号传输和供电等功能。

引脚说明:引脚1输出测量压力得到的电压,引脚2接地,引脚3常接5V工作电压,引脚4、5、6可以悬空。

输出电压与压力的关系:

图表 1 压力(参考:密封真空环境下),单位为千帕(kpa)

(1)压力值,电压值,指工作电压。选择典型曲线,我们可以得知转换公式:

(2)压力信号范围:15 ~115(kpa);

(3)A/D转换后传输的数据范围为13~243(243是压力值为115时所对应的A/D转换后的数据,13是压力值为15时所对应的A/D转换后的数据);

(4)线性区间变换公式:

其中,x 为A/D转换后的数据,y 为压力值,9.3 为修正值。

二、 Proteus仿真

图表 2 MPX4115压力传感器Proteus仿真

 三、Keil编程

主程序:

void main()
{
	uchar adc = 0;
	uint ADC;
	uint temp;
	float press = 0;
	uchar ADC_show_1[16] = {"   ADC:        "};//ADC显示缓冲
	uchar PRE_show_2[16] = {" Press:     Kpa"};//电压显示缓冲
	Init_LCD1602();//1602初始化
	while(1)
	{
		adc = Adc0832(0);//读取adc值
		if(0<adc<243)
		{
			ADC_show_1[7]  = adc / 100 + '0';		    //取adc百位
		  ADC_show_1[8]  = adc % 100 / 10 + '0';	//取adc十位
		  ADC_show_1[9]  = adc % 10 + '0';		    //取adc个位
			
			press = (115.0-15.0)/(243.0-13.0)*adc+9.3;//将adc值换算成压力值
			temp=(int)(press*10);//取整,显示4位数
			PRE_show_2[7]  =  temp /1000+'0' ;		 
		  PRE_show_2[8]  =  (temp%1000)/100+'0'  ;	 
		  PRE_show_2[9]  =  ((temp%1000)%100)/10+'0' ;	
      PRE_show_2[10]  =  '.';		
			PRE_show_2[11] =  temp%10+'0' ;
			
			LCD1602_Dis_Str(0, 0, &ADC_show_1[0]);	//在第一行显示ADC
			LCD1602_Dis_Str(0, 1, &PRE_show_2[0]);	//在第二行显示压力
		}
	}
}

四、 联合仿真结果

图表 3 联合仿真结果
#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
#define uchar unsigned char //宏定义
#define uint unsigned int   //宏定义

/***************引脚定义**************/
//LM016L液晶屏的引脚
  sbit rs=P2^0;  //液晶数据命令选择端
  sbit rw=P2^1;  //液晶读写选择端
  sbit en=P2^2;  //液晶使能端
//ADC0832的引脚
 sbit ADCS =P2^3;  //ADC0832 低电平片选使能
 sbit ADDI =P2^5;  //ADC0832 数据信号输入
 sbit ADCLK =P2^4;  //ADC0832 芯片时钟输入
 sbit ADDO =P2^5;  //ADC0832 数据信号输出

/***************函数声明**************/
void xiemingling(uchar mingling);//写命令函数声明
void xieshuju(uchar shuju);//写数据函数声明
void delay(uint ms);//延时函数声明
		
/**************************************************
                 LCD1602 写命令
***************************************************/
void xiemingling(uchar mingling)
{
  en=0;//初始状态E设置为0
	
	//RW为读写信号,高电平时进行读操作,低电平时进行写操作
  rw=0;//低电平进行写操作
	
	//RS数据、命令选择,高电平时选择数据寄存器,低电平时选择指令寄存器
  rs=0;//指令寄存器
	
  P0=mingling;//将要写的命令送到P0口
  en=1;
  delay(5);//延时 5ms
  en=0;
}
/***************************************************
                  LCD1602 写数据
***************************************************/
void xieshuju(uchar shuju)
{   
  en=0;
	rw=0;
  rs=1;//数据寄存器
  P0=shuju;//将要写的数据送到P0口
  en=1;
  delay(5);//延时 5ms
  en=0;
}

//**************延时 1毫秒*******************
void delay(uint ms) //延时 1ms
{
	uint i,j;
	for(i=ms;i>0;i--)
		for(j=120;j>0;j--);
}
/**************************************************
                 在指定位置显示字符串
***************************************************/
void LCD1602_Dis_Str(uchar x, uchar y, uchar *str)
{
	if(y) x |= 0x40;//将数据指针设置到第一行的起始地址(0x40)
	x |= 0x80;      //将数据指针设置到第二行的起始地址(0x80)
	xiemingling(x);
	while(*str != '\0')
	{
		xieshuju(*str++);
	}
}
/*************************************************
                   LCD1602 初始化
**************************************************/
void Init_LCD1602()
{
	 xiemingling(0x01); //清屏指令
	 xiemingling(0x06); //光标向右移动
	 xiemingling(0x0c); //显示功能,无光标,不闪烁
	 xiemingling(0x38); //数据总线8位,显示两行数据
}

/*****************************************
             读ADC0832函数
****************************************/
//采集并返回
unsigned int Adc0832(uchar channel)     //AD转换,返回结果
{
    unsigned char i=0;
    unsigned char j;
    unsigned int dat=0;
    unsigned char ndat=0;
	
    if(channel==0)channel=2;
	  if(channel==1)channel=3;
	
//------第1次下降沿之前 DI 置高,启动信号---------
	  ADDI=1;//在第1个时钟脉冲的下沉之前 DI 端必须是高电平,表示启始信号
    _nop_();//用于短暂延时,确保芯片能够正确识别控制命令结束的状态
    _nop_();
    ADCS=0;//拉低CS端,低电平开始A/D转换
    _nop_();
    _nop_();
    ADCLK=1;//拉高CLK端
    _nop_();
    _nop_();
    ADCLK=0;//拉低CLK端,形成第1个时钟脉冲的下沉
    _nop_();
    _nop_();
    ADCLK=1;//拉高CLK端
//------在第2、3个脉冲下沉之前DI端应输入2位数据用于选择通道功能---------
    ADDI=channel&0x1;//按位与操作,将channel的最低位(第0位)发送到ADDI引脚,用于选择通道功能
    _nop_();
    _nop_();
    ADCLK=0;//拉低CLK端,形成第2个时钟脉冲的下沉
    _nop_();
    _nop_();
    ADCLK=1;//拉高CLK端
		 ADDI=(channel>>1)&0x1;//右移按位与操作,将channel的第1位发送到ADDI引脚,用于选择通道功能。
    _nop_();
    _nop_();
    ADCLK=0;//拉低CLK端,形成第3个时钟脉冲的下沉
//------第四个下降沿之前,DI置高,准备接收数------
    ADDI=1;//控制命令结束 
    _nop_();
    _nop_();
		dat=0;//初始化变量dat,用于存储从ADC0832读取的8位数据
//------第4~11共8个下降沿读数据,从最高有效位(MSB)到最低有效位(LSB)的顺序读取------
		for(i=0;i<8;i++) 
		 {
        dat|=ADDO;//ADDO读取到的数据位与dat进行按位或操作,收数据
        ADCLK=1;
        _nop_();
        _nop_();
        ADCLK=0;//形成一次时钟脉冲
        _nop_();
        _nop_();
        dat<<=1;//将dat左移一位
        if(i==7)dat|=ADDO;//即读取第 8 位数据时,再次将ADDO的值与dat进行按位或操作
    }  
//------第11~18共8个下降沿读数据,读取顺序是从最低有效位(LSB)到最高有效位(MSB)------
		for(i=0;i<8;i++)
    {
        j=0;
        j=j|ADDO;//收数据
        ADCLK=1;
        _nop_();
        _nop_();
        ADCLK=0;//形成一次时钟脉冲
        _nop_();
        _nop_();
        j=j<<7;
        ndat=ndat|j;
        if(i<7)ndat>>=1;
    }
		ADCS=1;//拉低CS端
    ADCLK=0;//拉低CLK端
    ADDO=1;//拉高数据端,回到初始状态
    dat<<=8;
    dat|=ndat;
    return(dat);            
}

void main()
{
	uchar adc = 0;
	uint ADC;
	uint temp;
	float press = 0;
	uchar ADC_show_1[16] = {"   ADC:        "};//ADC显示缓冲
	uchar PRE_show_2[16] = {" Press:     Kpa"};//电压显示缓冲
	Init_LCD1602();//1602初始化
	while(1)
	{
		adc = Adc0832(0);//读取adc值
		if(0<adc<243)
		{
			ADC_show_1[7]  = adc / 100 + '0';		    //取adc百位
		  ADC_show_1[8]  = adc % 100 / 10 + '0';	//取adc十位
		  ADC_show_1[9]  = adc % 10 + '0';		    //取adc个位
			
			press = (115.0-15.0)/(243.0-13.0)*adc+9.3;//将adc值换算成压力值
			temp=(int)(press*10);//取整,显示4位数
			PRE_show_2[7]  =  temp /1000+'0' ;		 
		  PRE_show_2[8]  =  (temp%1000)/100+'0'  ;	 
		  PRE_show_2[9]  =  ((temp%1000)%100)/10+'0' ;	
      PRE_show_2[10]  =  '.';		
			PRE_show_2[11] =  temp%10+'0' ;
			
			LCD1602_Dis_Str(0, 0, &ADC_show_1[0]);	//在第一行显示ADC
			LCD1602_Dis_Str(0, 1, &PRE_show_2[0]);	//在第二行显示压力
		}
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值