PCF8591读写

 

PCF85918bitA/DD/A芯片,采用i2c接口,它有四路模拟输入口和一个模拟输出口,采样速率取决于i2c的速率。数据传输是高位在前低位在后(不论是主机写入数据,还是主机读取的数据)。

写入数据时:起始信号->器件地址->应答信号->控制字节->写入的数据->应答信号(从机)->写入的数据->应答信号(从机)。。。。->停止信号

读取数据时:起始信号->器件地址()->应答信号(从机)->控制字节->应答信号(从机)->停止信号(这个前提是设置读取的是哪一个通道,采用的哪种模式)    接着再是:起始信号->器件地址()->读取的字节->非应答信号(主机)->停止信号

下图是AD通道自动增量模式采集数据时的数据格式:

具体指令格式请参考PCF8591的数据手册。

 

下面是PCF8591的模拟输出和模拟输入的程序:

/************************************************************************
**Describe:PCF85891数模和模数转换
**    Time: 2015.5.20
**  Author: zys
*************************************************************************/
#include <reg52.h>
#include <intrins.h>

sbit SCL = P1^5;
sbit SDA = P3^6;

#define ADONE 0.0198  //5.06/256V	PCF8591的Vref电压是5.06V

/***本程序数码管是共阴极的***/
const unsigned char smg_dp_yin[ 16 ] = {0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 0x87, 0xff, 0xef,
										0xf7, 0xfc, 0xb9, 0xde, 0xfb, 0xf1};//0. 1. 2. 3......f.
										//共阴极,显示小数点
										//不显示小数点:  smg_dp_yin[x] & 0x7f
									//共阳极显示小数点: ~smg_dp_yin[x]
								  //共阳极不显示小数点: ~(smg_dp_yin[x] | 0x80)

/****数码管的位是通过74LS138控制的****/
const unsigned char smg_8_pos[ 8 ] = { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; //对应P20,P21,P22,高位都为1,则与的时候P2的其他位不变
const unsigned char smg_sum = 8;  //8位数码管

void i2c_start( void );
void i2c_stop( void );
void i2c_ack( void );
void master_ack();
void master_notAck();
void i2c_writeByte( unsigned char byte);
unsigned char i2c_readByte( void );
void PCF8591_wirteCommand( unsigned char addr, unsigned char command );
void PCF8591_AOUT(unsigned char byte);
unsigned char i2c_readADResult( void );
void PCF8591_displayADResult( unsigned int ADResult);

void delay( void );
void i2c_delay( void );
void delay_xms(unsigned int );

/********************************************************
**  函数名: void main( void )
**输入参数:无
**返回参数:无
********************************************************/
void main( void )
{
	int  i = 0;
	int ch = 0;	
	while(1)
	{
		/*for(i = 0; i <= 255; i++)  //DA输出,呼吸灯效果
		{
			PCF8591_AOUT(i);
			delay();
		}
		for(i = 255; i >= 0; i--)
		{
			PCF8591_AOUT(i);
			delay();	   
		} */
		for(ch = 0; ch < 4; ch++) //循环采集四路电压
		{
			PCF8591_wirteCommand(0x90, 0x00+ch);
			for(i = 0; i < 1000; i++)
			{
				PCF8591_displayADResult(i2c_readADResult());	
			}
		}		
	}
	
}

/********************************************************
**  函数名: void i2c_start( void ),i2c起始信号
**输入参数:无
**返回参数:无
********************************************************/
void i2c_start( void )
{
	SCL = 1;
	SDA = 1;
	i2c_delay();
	SDA = 0;
	i2c_delay();
	SCL = 0;
	i2c_delay();	
}

/********************************************************
**  函数名: void i2c_stop( void ),i2c停止信号
**输入参数:无
**返回参数:无
********************************************************/
void i2c_stop( void )
{
	SDA = 0;
	i2c_delay();
	SCL = 1;
	i2c_delay();
	SDA = 1;
	i2c_delay();	
}

/********************************************************
**  函数名: void i2c_ack( void ),i2c应答信号(从机)
**输入参数:无
**返回参数:无
********************************************************/
void i2c_ack( void )
{
	int i = 0;
	SCL = 0;
	i2c_delay();
	SDA = 1; 
	i2c_delay();
	SCL = 1;
	i2c_delay();
	while(SDA == 1);
	/*while((SDA == 1) && ((i++) < 10))
	{
		_nop_();
	}*/	
} 

/********************************************************
**  函数名: void master_ack( void ),主机应答信号,在读取数据时
**输入参数:无
**返回参数:无
********************************************************/
void master_ack( void )
{
	SCL = 0;
	i2c_delay();  
	SDA = 0;
	i2c_delay();
	SCL = 1;
	i2c_delay();
	SCL = 0;
	i2c_delay();
	SDA = 1;
	i2c_delay();	
}

/********************************************************
**  函数名: void master_notAck( void ),主机非应答信号,在读取数据时
**输入参数:无
**返回参数:无
********************************************************/
void master_notAck( void )
{
	SCL = 0;
	i2c_delay();
	SDA = 1;
	i2c_delay();
	SCL = 1;
	i2c_delay();  // 没下面四句程序读取不正常
	SCL = 0;	  //
	i2c_delay();  //
	SDA = 0;	  //	
}

/********************************************************
**  函数名: void i2c_writeByte,i2c写一个字节
**输入参数:unsigned char byte
**返回参数:无
********************************************************/
void i2c_writeByte( unsigned char byte )
{
	char loop;
	for(loop = 0; loop < 8; loop++)
	{
		SCL = 0;
		i2c_delay();
		if((byte<<loop)&0x80)  //数据是从高位到低位传输
		{
			SDA = 1;
		}
		else
		{
			SDA = 0;
		}
		i2c_delay();
		SCL = 1;
		i2c_delay();		
	}
}

unsigned char i2c_readByte( void )
{
	int loop = 0;
	unsigned char temp = 0;
	unsigned char tempData = 0;
	//SDA = 0;
	for(loop = 7; loop >= 0; loop--)
	{	
		SCL = 0;
		i2c_delay();	
		temp = SDA;
		i2c_delay();
		SCL = 1;
		i2c_delay();
		tempData += (temp<<loop);
		temp = 0;	
	}
	return tempData;			
}

/********************************************************
**  函数名: void PCF8591_wirteCommand( unsigned char addr, unsigned char command ),PCF8591写控制指令
**输入参数:unsigned char addr, unsigned char command
**返回参数:无
********************************************************/
void PCF8591_wirteCommand( unsigned char addr, unsigned char command )
{								    
	i2c_start();
	i2c_writeByte(addr);
	i2c_ack();
	i2c_writeByte(command);
	i2c_ack();
	i2c_delay();	
	i2c_stop();
}

/********************************************************
**  函数名: unsigned char i2c_readADResult( void ),i2c读出一个字节
**输入参数:无
**返回参数:unsigned char
********************************************************/
unsigned char i2c_readADResult( void )
{	
	unsigned char temp = 0;
	i2c_start();
	i2c_writeByte(0x91);
	i2c_ack();
	temp = i2c_readByte();
	master_notAck();
	i2c_stop();
	return temp;	
}

/********************************************************
**  函数名: void PCF8591_displayADResult( unsigned int ADResult),显示AD采集的数据
**输入参数:unsigned int ADResult
**返回参数:无
********************************************************/
void PCF8591_displayADResult( unsigned int ADResult)
{
	char loop = 0;
	unsigned int temp = ADONE * ADResult * 100; //两位小数取出来
	unsigned int dec = 1;
	for(loop = 7; loop >= 5; loop--)
	{
		if(loop == 5)
		{
			P0 = smg_dp_yin[temp/dec%10];
		}
		else
		{
			P0 = smg_dp_yin[temp/dec%10]&0x7f;
		}
		P2 = smg_8_pos[loop];
		delay_xms(1);
		dec *= 10;
	}

}

/********************************************************
**  函数名: void PCF8591_AOUT( unsigned char byte ),DA输出
**输入参数:unsigned char byte
**返回参数:无
********************************************************/
void PCF8591_AOUT( unsigned char byte )
{
	i2c_start();
	i2c_writeByte(0x90);
	i2c_ack();
	i2c_writeByte(0x40); //只有模拟输出AOUT
	i2c_ack();
	i2c_writeByte(byte);
	i2c_ack();
	i2c_stop();
}

/************************************************************************
**函数名:void i2c_delay( void ),i2c专用延时
**  功能:无
**  参数: 无
*************************************************************************/
void i2c_delay( void )
{
	char loop;
	for(loop = 0; loop < 5; loop++)
	{
		_nop_();
	}
}

/************************************************************************
**函数名:void delay_xms( unsigned int x )
**  功能:延时xms
**  参数: 无
*************************************************************************/
void delay_xms( unsigned int x )
{
	unsigned char j = 0;
	while( x-- )
	{
		while( (j++) < 100 );
		j = 0;
	}
}

/************************************************************************
**函数名:void delay( void ),在输出DA数据时使用的延时
**  功能:无
**  参数: 无
*************************************************************************/
void delay( void )
{
	unsigned int loop;
	for(loop = 0; loop < 30; loop++)
	{
		_nop_();
	}
}


 

不负自己
原文地址:https://www.cnblogs.com/v-BigdoG-v/p/7398656.html