单片机普通IO口模拟IIC多机通信,本人已测试通过

  • 格式:doc
  • 大小:41.00 KB
  • 文档页数:10

/*说明,该程序是模拟IIC的通信思想,但也不全是,首先本人设计的不是从机与主机的通信,而是两单片机是平等的,单片机A可以向B或其他任何单片机发送数据(通过各个单片机所设置的地址来加以区分),同时单片机A可以也向B或其他任何单片机读取数据。

反之单片机B或其他单片机也可以向A发送数据或读取A的数据,所以各个单片机的代码基本上是一样的,只需根据具体不同的需要调用就行。

由于本人初学单片机,代码写的并不是很好。

望各位多多指教!!!*///单片机A 的代码#include<reg52.h>#define uchar unsigned char#define uint unsigned int#define LOC_address 0x48sbit sda=P1^0;sbit scl=P1^1;sbit STROBE = P1^2;bit R_W;bit START_flag=0;uchar DEV_address;void delay(){uint i;for(i=0;i<=100;i++);}void init(){sda=1;scl=1;STROBE=1;}void start() //启动I2C总线{sda = 1;delay();scl = 1;delay();sda = 0;delay();// 此处scl不能拉低,否则两单片机通信时时序无法保持一致}/*void start_scan(){bit PreState;bit NowState;char NN = 10;PreState = sda; //记录当前SDA状态,用作比较while(scl == 1 && NN--){NowState = sda;if(PreState == 1 && NowState == 0) //如果为下降沿则为开始信号{START_flag = 1;}}}*/void Send_Date(uchar j){unsigned char i;bit temp;scl = 1;while(STROBE);if(STROBE==0){ delay();delay();delay();for (i = 0 ;i < 8 ;i++){if((j<<i)&0x80)temp=1;else temp=0;sda = temp; 、delay();scl = 0;delay();scl = 1;delay();}scl = 0;sda = 1; //释放数据线delay();STROBE=1;}STROBE=1;}uchar Receive_Date(){uchar i,j,k=0xff;scl = 1;STROBE=0;delay();if((!scl)&&(sda)){return k;}if(STROBE==0){while(scl);for(i=0;i<8;i++){while(!scl);if(sda==1)j=1;elsej=0;k=(k<<1)|j;delay();delay();while(scl);}P2=k;return k;}return k;}/*void ChackRdd(){uchar i,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;elsej=0;k=(k<<1)|j;delay();delay();while(scl);}P0=k;R_W=k&0x01;DEV_address=(k&0xfe);STROBE=1;}STROBE=1;}void B_work(){if(STROBE){ChackRdd();if(DEV_address==LOC_address){if(R_W){STROBE=(~STROBE);Send_Date(0x55);}else if(!R_W){STROBE=(~STROBE);Receive_Date();}}}}*/void main(){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<reg52.h>#define uchar unsigned char#define uint unsigned int#define LOC_address 0xaasbit sda=P1^0;sbit scl=P1^1;sbit STROBE = P1^2;bit R_W;bit START_flag=0;uchar DEV_address;void delay(){uint i;for(i=0;i<=100;i++);}/*void start() //启动I2C总线{sda = 1;delay();scl = 1;delay();sda = 0;delay();}*/void start_scan(){bit PreState;bit NowState;char NN = 10;PreState = sda; //记录当前SDA状态,用作比较while(scl == 1 && NN--){NowState = sda;if(PreState == 1 && NowState == 0) //如果为下降沿则为开始信号{START_flag = 1;}}}void Send_Date(uchar j){unsigned char i;bit temp;scl = 1;while(STROBE);if(STROBE==0){ delay();delay();delay();for (i = 0 ;i < 8 ;i++){if((j<<i)&0x80)temp=1;else temp=0;sda = temp;delay();scl = 0;delay();scl = 1;delay();}scl = 0;sda = 1; //释放数据线delay();STROBE=1;}STROBE=1;}uchar Receive_Date(){uchar i,j,k=0xff;scl = 1;STROBE=0;delay();if((!scl)&&(sda)){return k;}if(STROBE==0){while(scl);for(i=0;i<8;i++){while(!scl);if(sda==1)j=1;elsej=0;k=(k<<1)|j;delay();delay();while(scl);}P2=k;return k;}return k;}void ChackRdd(){uchar i,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)elsej=0;k=(k<<1)|j;delay();delay();while(scl);}P0=k;R_W=k&0x01;DEV_address=(k&0xfe);STROBE=1;}STROBE=1;}void B_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);}else if(!R_W){STROBE=(~STROBE);Receive_Date();}}}}void main() {STROBE=1; scl=1; while(1) {B_work(); }}。