单片机普通IO口模拟IIC多机通信本人已测试通过.docx
《单片机普通IO口模拟IIC多机通信本人已测试通过.docx》由会员分享,可在线阅读,更多相关《单片机普通IO口模拟IIC多机通信本人已测试通过.docx(13页珍藏版)》请在冰豆网上搜索。
![单片机普通IO口模拟IIC多机通信本人已测试通过.docx](https://file1.bdocx.com/fileroot1/2023-1/26/da24cba9-7504-41cf-bf02-10ec984c322e/da24cba9-7504-41cf-bf02-10ec984c322e1.gif)
单片机普通IO口模拟IIC多机通信本人已测试通过
/*
说明,该程序是模拟IIC的通信思想,但也不全是,首先本人设计的不是从机与主机的通信,而是两单片机是平等的,单片机A可以向B或其他任何单片机发送数据(通过各个单片机所设置的地址来加以区分),同时单片机A可以也向B或其他任何单片机读取数据。
反之单片机B或其他单片机也可以向A发送数据或读取A的数据,所以各个单片机的代码基本上是一样的,只需根据具体不同的需要调用就行。
由于本人初学单片机,代码写的并不是很好。
望各位多多指教!
!
!
*/
//单片机A的代码
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLOC_address0x48
sbitsda=P1^0;
sbitscl=P1^1;
sbitSTROBE=P1^2;
bitR_W;
bitSTART_flag=0;
ucharDEV_address;
voiddelay()
{
uinti;
for(i=0;i<=100;i++);
}
voidinit()
{
sda=1;
scl=1;
STROBE=1;
}
voidstart()//启动I2C总线
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
//此处scl不能拉低,否则两单片机通信时时序无法保持一致
}
/*
voidstart_scan()
{
bitPreState;
bitNowState;
charNN=10;
PreState=sda;//记录当前SDA状态,用作比较
while(scl==1&&NN--)
{
NowState=sda;
if(PreState==1&&NowState==0)//如果为下降沿则为开始信号
{
START_flag=1;
}
}
}
*/
voidSend_Date(ucharj)
{
unsignedchari;
bittemp;
scl=1;
while(STROBE);
if(STROBE==0)
{delay();
delay();
delay();
for(i=0;i<8;i++)
{
if((j<
elsetemp=0;
sda=temp;、
delay();
scl=0;
delay();
scl=1;
delay();
}
scl=0;
sda=1;//释放数据线
delay();
STROBE=1;
}
STROBE=1;
}
ucharReceive_Date()
{
uchari,j,k=0xff;
scl=1;
STROBE=0;
delay();
if((!
scl)&&(sda))
{
returnk;
}
if(STROBE==0)
{
while(scl);
for(i=0;i<8;i++)
{
while(!
scl);
if(sda==1)
j=1;
else
j=0;
k=(k<<1)|j;
delay();
delay();
while(scl);
}
P2=k;
returnk;
}
returnk;
}
/*
voidChackRdd()
{
uchari,j,k=0xff;
scl=1;
STROBE=0;
delay();
if(!
STROBE)
{
while(scl);
for(i=0;i<8;i++)
{
while(!
scl);
if(sda==1)
j=1;
else
j=0;
k=(k<<1)|j;
delay();
delay();
while(scl);
}
P0=k;
R_W=k&0x01;
DEV_address=(k&0xfe);
STROBE=1;
}
STROBE=1;
}
voidB_work()
{
if(STROBE)
{
ChackRdd();
if(DEV_address==LOC_address)
{
if(R_W)
{
STROBE=(~STROBE);
Send_Date(0x55);
}
elseif(!
R_W)
{
STROBE=(~STROBE);
Receive_Date();
}
}
}
}
*/
voidmain()
{
init();
while
(1)//以下为测试代码。
{
while(STROBE)
{
while(STROBE)
{
start();
}
while(!
STROBE);
/*while(STROBE)
{
Send_Date(0xaa);//发送地址和写指令
}
while(!
STROBE)
{
Send_Date(0x99);//发送数据0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90
}
*/
while(STROBE)
{
Send_Date(0xab);//发送地址和读指令
}
}
while(!
STROBE)
{
STROBE=1;
Receive_Date();
}
}
}
//单片机B的代码
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineLOC_address0xaa
sbitsda=P1^0;
sbitscl=P1^1;
sbitSTROBE=P1^2;
bitR_W;
bitSTART_flag=0;
ucharDEV_address;
voiddelay()
{
uinti;
for(i=0;i<=100;i++);
}
/*
voidstart()//启动I2C总线
{
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
*/
voidstart_scan()
{
bitPreState;
bitNowState;
charNN=10;
PreState=sda;//记录当前SDA状态,用作比较
while(scl==1&&NN--)
{
NowState=sda;
if(PreState==1&&NowState==0)//如果为下降沿则为开始信号
{
START_flag=1;
}
}
}
voidSend_Date(ucharj)
{
unsignedchari;
bittemp;
scl=1;
while(STROBE);
if(STROBE==0)
{delay();
delay();
delay();
for(i=0;i<8;i++)
{
if((j<
elsetemp=0;
sda=temp;
delay();
scl=0;
delay();
scl=1;
delay();
}
scl=0;
sda=1;//释放数据线
delay();
STROBE=1;
}
STROBE=1;
}
ucharReceive_Date()
{
uchari,j,k=0xff;
scl=1;
STROBE=0;
delay();
if((!
scl)&&(sda))
{
returnk;
}
if(STROBE==0)
{
while(scl);
for(i=0;i<8;i++)
{
while(!
scl);
if(sda==1)
j=1;
else
j=0;
k=(k<<1)|j;
delay();
delay();
while(scl);
}
P2=k;
returnk;
}
returnk;
}
voidChackRdd()
{
uchari,j,k=0xff;
scl=1;
STROBE=0;//置低信号告诉单片机A、单片机B已做好准备接收
delay();
if(!
STROBE)
{
while(scl);//等待A响应
for(i=0;i<8;i++)
{
while(!
scl);
if(sda==1)
j=1;
else
j=0;
k=(k<<1)|j;
delay();
delay();
while(scl);
}
P0=k;
R_W=k&0x01;
DEV_address=(k&0xfe);
STROBE=1;
}
STROBE=1;
}
voidB_work()
{
if(STROBE)
{
start_scan();
if(START_flag)
{
START_flag=0;
STROBE=0;
delay();
STROBE=1;
ChackRdd();
if(DEV_address==LOC_address)
{
if(R_W)
{
STROBE=(~STROBE);
STROBE=1;//必须再次置高,使得两单片机在发送和接收数据时时序保持一致
Send_Date(0x80);
}
elseif(!
R_W)
{
STROBE=(~STROBE);
Receive_Date();
}
}
}
}
}
voidmain()
{
STROBE=1;
scl=1;
while
(1)
{
B_work();
}
}