使用下面代码,可以在51上用p1口模拟i2c。
/*电平模拟函数和基本读写函数
voidiic_start(void);
voidiic_stop(void);
voidsend_0(void);
voidsend_1(void);
bitcheck_acknowledge(void);
voidwrite_byte(ucharb)reentrant;
bitwrite_n_bytes(uchar*buffer,ucharn)reentrant;
bitread_n_bytes(ucharslaveadr,ucharn,uchar*buffer);
ucharread_byte(void)reentrant;
*/
#include<string.h>
#include<reg52.h>
#include<intrins.h>
#include"aiic_51.h"
sbitscl=p1^6;
sbitsda=p1^7;
voiddelay(uintt)
{
while(t!=0)
t--;
}
voidiic_start(void)
{
//启动i2c总线的函数,当scl为高电平时使sda产生一个负跳变
sda=1;
scl=1;
delay(delay_time);
sda=0;
delay(delay_time);
scl=0;
delay(delay_time);
}
voidiic_stop(void)
{
//终止i2c总线,当scl为高电平时使sda产生一个正跳变
sda=0;
scl=1;
delay(delay_time);
sda=1;
delay(delay_time);
scl=0;
delay(delay_time);
}
voidsend_0(void)
{
//发送0,在scl为高电平时使sda信号为低
sda=0;
scl=1;
delay(delay_time);
scl=0;
delay(delay_time);
}
voidsend_1(void)
{
//发送1,在scl为高电平时使sda信号为高
sda=1;
scl=1;
delay(delay_time);
scl=0;
delay(delay_time);
}
bitcheck_acknowledge(void)
{
//发送完一个字节后检验设备的应答信号
sda=1;
scl=1;
delay(delay_time/2);
f0=sda;
delay(delay_time/2);
scl=0;
delay(delay_time);
if(f0==1)
returnfalse;
returntrue;
}
voidwrite_byte(ucharb)reentrant
{
//向iic总线写一个字节
uchari;
for(i=0;i<8;i++)
if((b<<i)&0x80)
send_1();
else
send_0();
}
bitwrite_n_bytes(uchar*buffer,ucharn)reentrant
{
//向i2c总线写n个字节
uchari;
iic_start();
for(i=0;i<n;i++)
{
write_byte(buffer[i]);
if(!check_acknowledge())
{
iic_stop();
return(i==n);
}
}
iic_stop();
returntrue;
}
ucharread_byte(void)reentrant
{
//从i2c总线读一个字节
ucharb=0,i;
for(i=0;i<8;i++)
{
sda=1;//释放总线
scl=1;//接受数据
delay(10);
f0=sda;
delay(10);
scl=0;
if(f0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
returnb;
}
bitread_n_bytes(ucharslaveadr,ucharn,uchar*buffer)
{
//从i2c总线读n个字节
uchari;
iic_start();
write_byte(slaveadr);//向总线发送接收器地址
if(!check_acknowledge())//等待接收器应答信号
returnfalse;
for(i=0;i<n;i++)
{
buffer[i]=read_byte();
if(i!=n)
send_0();//发送应答
else
send_1();//发送非应答
}
iic_stop();
returntrue;
}