AD转换概念:

AD转换即模拟信号(Analog) 转换成数字信号(Digital)

温湿度一般都以模拟信号存在,所以显示出来需要进行AD转换

PCF8591:是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件,PCF8591具有4个模拟输入、1个模拟输出和1个串行I2C总线接口。pcf8591常用作ADDA转换。


PCF8591原理图:


PCF8591具有4个模拟输入(AIN0~AIN3)、1个模拟输出(AOUT)和1个串行I²C总线接口(SDA、SCL)。 
PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。 
OSC:外部时钟输入端,内部时钟 
EXT:内部、外部时钟选择线,使用内部时钟时 EXT 接地。 
VDD、VSS:电源端。 
AGND:模拟信号地。 
VREF:基准电源端。


程序显示案例:

动态数码管显示电压值,通过调节变阻器改变电压值

使用到了I2C总线驱动程序,PCF8591驱动程序。

I2C程序:

#include"I2C.H"
//-----------起动总线函数--------------
void I2C_start() 
{
   SCL=1;
   SDA=1;
   Timenop();
   SDA=0;
   Timenop();
}
//-----------结束总线函数--------------
void I2C_stop()  
{  
   SDA=0;
   SCL=1;
   Timenop();
   SDA=1;
   Timenop();
}
//-----------应答函数--------------
void I2C_ack()
{
  uchar i=0;
  SCL=1;
  Timenop();
  while((SDA==1)&&(i<250))i++;
  SCL=0;
  Timenop();
}
//-----------字节数据发送函数--------------
void I2C_write_byte(uchar dat) 
{
   uchar i,b=0;
   for(i=0;i<8;i++)
   {
       SCL=0;  
  Timenop();   
  SDA=(bit)(dat&0x80);
  dat<<=1;
  SCL=1;
  Timenop();   
   }
   SCL=0;
   Timenop(); 
   SDA=1;  
   Timenop();
   SCL=1;
   _nop_();
   SCL=0;
   _nop_();   
}
//-----------字节数据接收函数--------------
uchar I2C_read_byte() 
{
   uchar i,dat=0;
   SCL=0;
   Timenop();
    SDA=1;
   _nop_();
   for(i=0;i<8;i++)
   {
      SCL=1;
_nop_();
_nop_();
 dat<<=1;
 if(SDA==1)
    dat=dat|0x01;
      _nop_();
 SCL=0;
 Timenop();
    }
SDA=1;
_nop_();
SCL=1;
_nop_();
SCL=0;
_nop_();
 return dat;
}
//-----------起动总线函数--------------
void I2C_start() 
{
   SCL=1;
   SDA=1;
   Timenop();
   SDA=0;
   Timenop();
}
//-----------结束总线函数--------------
void I2C_stop()  
{  
   SDA=0;
   SCL=1;
   Timenop();
   SDA=1;
   Timenop();
}
//-----------应答函数--------------
void I2C_ack()
{
  uchar i=0;
  SCL=1;
  Timenop();
  while((SDA==1)&&(i<250))i++;
  SCL=0;
  Timenop();
}
//-----------字节数据发送函数--------------
void I2C_write_byte(uchar dat) 
{
   uchar i,b=0;
   for(i=0;i<8;i++)
   {
       SCL=0;  
  Timenop();   
  SDA=(bit)(dat&0x80);
  dat<<=1;
  SCL=1;
  Timenop();   
   }
   SCL=0;
   Timenop(); 
   SDA=1;  
   Timenop();
   SCL=1;
   _nop_();
   SCL=0;
   _nop_();   
}
//-----------字节数据接收函数--------------
uchar I2C_read_byte() 
{
   uchar i,dat=0;
   SCL=0;
   Timenop();
    SDA=1;
   _nop_();
   for(i=0;i<8;i++)
   {
      SCL=1;
_nop_();
_nop_();
 dat<<=1;
 if(SDA==1)
    dat=dat|0x01;
      _nop_();
 SCL=0;
 Timenop();
    }
SDA=1;
_nop_();
SCL=1;
_nop_();
SCL=0;
_nop_();
 return dat;
}

#ifndef __I2C_H_
#define __I2C_H_
#include<reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
#define Timenop() _nop_(),_nop_(),_nop_(),_nop_(),_nop_()
sbit SCL=P2^1;   //I2C时钟 
sbit SDA=P2^0;   //I2C数据 
void I2C_start();//起动总线函数
void I2C_stop(); //结束总线函数
void I2C_ack();  //应答函数
void I2C_write_byte(uchar dat); //字节数据发送函数
uchar I2C_read_byte(); //字节数据接收函数
#endif

pcf8591驱动程序:

#include"I2C.H"
#include<reg51.h>
#define uchar unsigned char
#define uint  unsigned int
#define  WRITEADDR 0x90  //写地址
#define  READADDR  0x91  //读地址
#define  PCF8591   0x90   //PCF8591地址
uchar Wxuan[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar Dxuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar MY_Data[8];
uint adNum;
//-----------延时函数--------------
void delay(uint z)
{
  uint x,y;
  for(x=z;x>0;x--)
   for(y=110;y>0;y--);
}
//-----------AD发送字节数据函数--------------
void PCF8591_send(uchar channel)
{
   I2C_start();
   I2C_write_byte(WRITEADDR);
   I2C_ack();
   I2C_write_byte(0x40);
   I2C_ack();
   I2C_write_byte(channel);
   I2C_ack();
   I2C_stop();
}
//-----------AD读字节数据函数--------------
uchar PCF8591_read()
{
   uchar num;
   I2C_start();
   I2C_write_byte(WRITEADDR);
   I2C_ack();
   I2C_write_byte(0x40);
   I2C_ack();
   I2C_stop();
   delay(100);
   I2C_start();
   I2C_write_byte(READADDR);
   I2C_start();
   num=I2C_read_byte();  
   I2C_stop();
   return num;
}
//-----------进行DA转化数据函数--------------
void PCF8591_conversion()
{
   float value;
   PCF8591_send(3);              //发送电位器转换命令
   adNum=PCF8591_read()*2;       //将转换结果读走
   //--我们8591每读取到一个1就表示5/256V(8位字节),所以要知道电压值就乘以0.01953--//
   value = adNum / 2 * 0.01953;  //转为电压值
   adNum = value * 100;          //保留两位小数
}
void main()
{
   uint i;
   PCF8591_conversion();
   MY_Data[0] = Dxuan[adNum / 1000];             //发送显示数据
   MY_Data[1] = Dxuan[adNum % 1000 / 100] | 0x80; //或上0x80是加小数点
   MY_Data[2] = Dxuan[adNum % 100 / 10];
   MY_Data[3] = Dxuan[adNum % 10];
   MY_Data[4] = Dxuan[adNum / 1000];             //发送显示数据
   MY_Data[5] = Dxuan[adNum % 1000 / 100] | 0x80; //或上0x80是加小数点
   MY_Data[6] = Dxuan[adNum % 100 / 10];
   MY_Data[7] = Dxuan[adNum % 10];
  //-----------数码管显示--------------
   while(1)
   {
     for(i=0;i++;i<8)
     {
     P0=Wxuan[i];
     P1=MY_Data[i];
     delay(5); 
     }
   }
}








Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐