一、MPX4115型压力传感器介绍
1.1 引脚说明
即:1引脚为模拟量输出,2引脚接地,三引脚接电源,4、5、6引脚空
1.2 输出特性图
选择典型曲线,我们可以得知转换公式:压力值=(电压值/5.1+0.095)/0.009。
二、模拟IIC总线
因为本例子采用的为51单片机,因此需要自己模拟IIC总线协议。
2.1 IIC总线工作时序如下
2.2 根据上图所示IIC总线工作协议进行IIC工作模拟
2.2.1 IIC总线启动
void I2c_start()
{
sda=1;
scl=1;
Delay1(DELAY_TIME);
sda=0;
Delay1(DELAY_TIME);
scl=0;
}
2.2.2 IIC发送一个字节
void I2c_sendbyte(uchar byt)
{
uchar i;
for(i=0;i<8;i++)
{
scl=0;
Delay1(DELAY_TIME);
if(byt&0x80)
{
sda=1;
}
else
{
sda=0;
}
Delay1(DELAY_TIME);
scl=1;
byt <<= 1;
Delay1(DELAY_TIME);
}
scl=0;
}
2.2.3 IIC等待响应
uchar I2c_waitack()
{
uchar ackbit;
sda=1;//释放数据线
Delay1(DELAY_TIME);
scl=1;
Delay1(DELAY_TIME);
ackbit=sda;//获取响应信号,低电平为有效
scl=0;
Delay1(DELAY_TIME);
return sda;
}
2.2.4 IIC接收一个字节
uchar I2c_receivebyte()
{
uchar da;
uchar i;
for(i=0;i<8;i++)
{
scl=1;
Delay1(DELAY_TIME);
da<<=1;
if(sda)
{
da|=0x01;
}
scl=0;
Delay1(DELAY_TIME);
}
return da;
}
2.2.5 IIC发送响应
void I2c_sendack(uchar ackbit)
{
scl=0;
sda=ackbit; //0:发送应答信号;1:发送非应答信号
Delay1(DELAY_TIME);
scl=1;
Delay1(DELAY_TIME);
scl=0;
sda=1;
Delay1(DELAY_TIME);
}
2.2.6 IIC总线结束
void I2c_stop()
{
sda=0;
scl=1;
Delay1(DELAY_TIME);
sda=1;
Delay1(DELAY_TIME);
}
三、PCF8591型AD介绍
3.1 介绍
PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入、一个输出和一个串行I2C 总线接口。3 个地址引脚A0、A1 和A2 用于编程硬件地址,允许将最多8 个器件连接至I2C总线而不需要额外硬件。PCF8591由于其使用的简单方便和集成度高,在单片机应用系统中得到了广泛的应用。
3.2 引脚说明
3.3 器件地址说明
每一个IIC器件都有一个器件地址,来区分不同的IIC设备,下面是PCF8591的地址格式
在本例子中,我将A0、A1、A2全部接地,因此写地址为0x90,读地址为0x91。
3.4 控制字说明
在该例子中我们进行的是AD转换,因此第6位为0,不允许模拟电压输出;采用单端输入,因此第5、4位为0、0;该例子中只进行一个模拟输入量的AD转换,因此关闭自动增量使能,即第2位为0;模拟输入通道选择AIN3,因此第1位与第0位为1、1。因此,控制字为0x30。
3.5 输出特性曲线
在该例子中,我们让Vagnd=0V,Vref=5V。因此可得转换公式为:电压值=(5.0/256.0)*AD模块的读数。
四、Proteus仿真电路
五、完整例程(例程均为自己编写且在仿真中测试通过)
使用单片机为AT89C52,工作频率为12MHz
#include
#include
typedef unsigned char uchar;
typedef unsigned int uint;
#define DELAY_TIME 5
sbit scl = P2^0;//时钟总线接口
sbit sda = P2^1;//数据总线接口
sbit w2=P2^2;//位选2
sbit w3=P2^3;//位选3
sbit w4=P2^4;//位选4
void I2c_start(void);//IIC总线启动条件
void I2c_stop(void);//IIC总线结束条件
void I2c_sendbyte(uchar byt);//IIC总线发送一个字节
uchar I2c_receivebyte(void);//IIC总线接收一个字节
void I2c_sendack(uchar ackbit);//IIC总线发送应答
void Delay1(uchar t);//读写操作中的延时
void Delay2(uchar t);//等待初始化子函数
void Init_pcf8591(void);//PCF8951初始化
uchar I2c_waitack(void);//IIC等待回应子函数
uchar Read_value(void);//读取AD值
void Show(uchar Out);//显示压力值
void main()
{
uchar G_value;//AD值
float V_value,P_value;//电压值,压力值
uchar Out;//对压力值进行四舍五入后的输出值
Read_value();
G_value=Read_value();
V_value=(5.0/256.0)*G_value;
P_value=(V_value/5.1+0.095)/0.009;
Out=P_value;//进行四舍五入
if(P_value-Out>=0.5)
{
Out+=1;
}
Show(Out);
}
/****************************读取AD值******************************************/
uchar Read_value(void)
{
uchar result;
Init_pcf8591();
I2c_start();
I2c_sendbyte(0x91);//进行读操作(A0、A1、A2均接地)
I2c_waitack();
result=I2c_receivebyte();
I2c_sendack(1);
I2c_stop();
return result;
}
/**********************PCF8591初始化函数*************************************/
void Init_pcf8591(void)
{
I2c_start();
I2c_sendbyte(0x90);//进行写操作(A0、A1、A2均接地)
I2c_waitack();
I2c_sendbyte(0x03); //选择通道AIN3进行转化
I2c_waitack();
I2c_stop();
Delay2(10);
}
/**********************IIC总线启动*************************************/
void I2c_start()
{
sda=1;
scl=1;
Delay1(DELAY_TIME);
sda=0;
Delay1(DELAY_TIME);
scl=0;
}
/********************IIC发送一个字节***********************************/
void I2c_sendbyte(uchar byt)
{
uchar i;
for(i=0;i<8;i++)
{
scl=0;
Delay1(DELAY_TIME);
if(byt&0x80)
{
sda=1;
}
else
{
sda=0;
}
Delay1(DELAY_TIME);
scl=1;
byt <<= 1;
Delay1(DELAY_TIME);
}
scl=0;
}
/********************IIC等待回应***********************************/
uchar I2c_waitack()
{
uchar ackbit;
sda=1;//释放数据线
Delay1(DELAY_TIME);
scl=1;
Delay1(DELAY_TIME);
ackbit=sda;//获取响应信号,低电平为有效
scl=0;
Delay1(DELAY_TIME);
return sda;
}
/********************IIC接收一个字节******************************/
uchar I2c_receivebyte()
{
uchar da;
uchar i;
for(i=0;i<8;i++)
{
scl=1;
Delay1(DELAY_TIME);
da<<=1;
if(sda)
{
da|=0x01;
}
scl=0;
Delay1(DELAY_TIME);
}
return da;
}
/********************IIC发送回应***********************************/
void I2c_sendack(uchar ackbit)
{
scl=0;
sda=ackbit; //0:发送应答信号;1:发送非应答信号
Delay1(DELAY_TIME);
scl=1;
Delay1(DELAY_TIME);
scl=0;
sda=1;
Delay1(DELAY_TIME);
}
/**********************IIC总线结束*************************************/
void I2c_stop()
{
sda=0;
scl=1;
Delay1(DELAY_TIME);
sda=1;
Delay1(DELAY_TIME);
}
/**********************IIC中延时函数*************************************/
void Delay1(uchar t)
{
do
{
_nop_();
}
while(t--);
}
/**************************等待初始化延时***************************************/
void Delay2(uchar t)
{
unsigned char i;
while(t--)
{
for(i=0; i<112; i++);
}
}
/**********************显示函数*************************************/
void Show(uchar Out)
{
char code duan[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//段码
while(1)
{
w4=0;//显示第百位
w3=0;
w2=1;
Delay2(5);
P1=duan[(Out/100)%10];
Delay2(15);
P1=0xff;
w4=0;//显示第十位
w3=1;
w2=0;
Delay2(5);
P1=duan[(Out/10)%10];
Delay2(15);
P1=0xff;
w4=1;//显示第个位
w3=0;
w2=0;
Delay2(5);
P1=duan[Out%10];
Delay2(15);
P1=0xff;
}
}
左肩理想,右肩担当。君子不怨永远不会停下脚步!