#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit I2C_SCL = P2^6; //模拟I2C总线的引脚定义
sbit I2C_SDA = P2^7;
#define I2C_DELAY_VALUE 12 //定义I2C总线时钟的延时值,要根据实际情况修改,取值1~255
//SCL信号周期约为(I2C_DELAY_VALUE*4+15)个机器周期
#define I2C_STOP_WAIT_VALUE 120 //定义I2C总线停止后在下一次开始之前的等待时间,取值1~65535
//等待时间约为(I2C_STOP_WAIT_VALUE*8)个机器周期
#define I2C_Delay() // 延时,模拟I2C总线专用
{
I2C_Delay_t = (I2C_DELAY_VALUE);
while ( --I2C_Delay_t != 0 );
}
unsigned char data I2C_Delay_t;
void I2C_Init()
{
I2C_SCL = 1;
I2C_Delay();
I2C_SDA = 1;
I2C_Delay();
}
void I2C_Start() //SCL处于高电平期间,当SDA出现下降沿时启动I2C总线
{
I2C_SDA = 1; //不论SDA和SCL处于什么电平状态,本函数总能正确产生起始状态
I2C_Delay(); //本函数也可以用来产生重复起始状态
I2C_SCL = 1; //本函数执行后,I2C总线处于忙状态
I2C_Delay();
I2C_SDA = 0;
I2C_Delay();
I2C_SCL = 0;
I2C_Delay();
}
void I2C_Write(char dat) //向I2C总线写1个字节的数据
{
unsigned char t = 8; //dat:要写到总线上的数据
do
{
I2C_SCL = 1;
I2C_Delay();
I2C_SCL = 0;
I2C_Delay();
I2C_SDA = (bit)(dat & 0x80);
dat <<= 1;
} while ( --t != 0 );
}
bit I2C_GetAck() //读取从机应答位
{
bit ack; //从机在收到每个字节的数据后,要产生应答位
I2C_SDA = 1; //从机在收到最后1个字节的数据后,一般要产生非应答位
I2C_Delay();
I2C_SCL = 1;
I2C_Delay();
ack = I2C_SDA;
I2C_SCL = 0;
I2C_Delay();
return ack; //0:从机应答 //1:从机非应答
}
void I2C_Stop() //产生I2C总线的停止状态
{
unsigned int t = I2C_STOP_WAIT_VALUE;
I2C_SDA = 0;
I2C_Delay(); //SCL处于高电平期间,当SDA出现上升沿时停止I2C总线
I2C_SCL = 1; //不论SDA和SCL处于什么电平状态,本函数总能正确产生停止状态
I2C_Delay(); //本函数执行后,I2C总线处于空闲状态
I2C_SDA = 1;
I2C_Delay();
while ( --t != 0 ); //在下一次产生Start之前,要加一定的延时
}
bit I2C_Puts( uchar SlaveAddr, uint SubAddr, uchar SubMod, char *dat, uint Size)
{ //I2C总线综合发送函数,向从机发送多个字节的数据
unsigned char i; //*dat:要发送的数据
char a[3]; //Size:数据的字节数
if ( Size == 0 ) return 0; //检查长度
a[0] = (SlaveAddr << 1); //SlaveAddr:从机地址(7位纯地址,不含读写位)
if ( SubMod > 2 ) SubMod = 2; //SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址
switch ( SubMod ) //确定子地址
{
case 0:
break;
case 1: a[1] = (char)(SubAddr); //SubAddr:从机的子地址
break;
case 2: a[1] = (char)(SubAddr >> 8);
a[2] = (char)(SubAddr);
break;
default:
break;
}
SubMod++; //发送从机地址,接着发送子地址(如果有子地址的话)
I2C_Start();
for ( i=0; i<SubMod; i++ )
{
I2C_Write(a[i]);
if ( I2C_GetAck() )
{
I2C_Stop();
return 1;
}
}
do //发送数据
{
I2C_Write(*dat++);
if ( I2C_GetAck() ) break;
} while ( --Size != 0 );
I2C_Stop(); //发送完毕,停止I2C总线,并返回结果
if ( Size == 0 )
{
return 0;
}
else
{
return 1; //0:发送成功 1:在发送过程中出现异常
}
}
#define MAX517_I2C_ADDR 0X58 //MAX517 器件地址
unsigned char num_v ; //MAX517 输出数字量
bit complete_flag; //I2C 通信成功标志
void Delay(unsigned int t) reentrant //延时子程序
{
while(--t)
{
unsigned int j = 110;
while(--j);
}
}
char code DX516[3] _at_ 0x3b; //保留0x3b开始的3个字节
main(void)
{
I2C_Init();
Delay(1000);
num_v = 0;
complete_flag = I2C_Puts(MAX517_I2C_ADDR,0,1,&num_v,1);
Delay(1000);
while(1)
{
num_v ++;
complete_flag = I2C_Puts(MAX517_I2C_ADDR,0,1,&num_v,1);
Delay(100);
}
}