在最近的项目中需要用到一主多从多个单片机进行数据传输(非强时序),最开始打算使用USART串口来实现,但是串口在连接的时候多个单片机相连会导致数据无法收发的问题,综合考虑SPI和IIC后选择I2C
常见的I2C器件有AT24C02/MPU6050等等,这些都是默认从机,单片机部分从来都是作为主机去实现数据的读写,第一次把单片机做从机来使用就特别迷糊
我个人的理解是,IIC从机可以简单的理解为一个存储器,不能主动读写,受到从机控制,在一段存储范围内,可通过主机的读写函数来实现数据的更替
下面列一下STC的程序吧,其它单片机也是想通的,逻辑一样
sbit SDA = P3^3;
sbit SCL = P3^2;
void Wait()
{
while(!(I2CMSST & 0x40));
I2CMSST &= ~0x40;
}
void Start()
{
I2CMSCR = 0x01; //发送 START 命令
Wait();
}
void SendData(char dat)
{
I2CTXD = dat; //写数据到数据缓冲区
I2CMSCR = 0x02; //发送 SEND 命令
Wait();
}
void RecvACK()
{
I2CMSCR = 0x03; //发送读 ACK 命令
Wait();
}
char RecvData()
{
I2CMSCR = 0x04; //发送 RECV 命令
Wait();
return(I2CRXD);
}
void SendACK()
{
I2CMSST = 0x00; //设置 ACK 信号
I2CMSCR = 0x05; //发送 ACK 命令
Wait();
}
void SendNAK()
{
I2CMSST = 0x01; //设置 NAK 信号
I2CMSCR = 0x05; //发送 ACK 命令
Wait();
}
void Stop()
{
I2CMSCR = 0x06; //发送 STOP 命令
Wait();
}
void Delay()
{
int i;
for(i = 0; i < 3000; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
uchar REC_data(uchar device,char addr)
{
uchar buf1,buf2;
Start(); //发送起始命令
SendData(device); //发送设备地址 + 写命令
RecvACK();
SendData(addr-1); //发送存储地址高字节
RecvACK();
Start(); //发送起始命令
SendData(device+1); //发送设备地址 + 读命令
RecvACK();
buf1 = RecvData(); //读取数据 1
SendACK();
buf2 = RecvData(); //读取数据 2
SendNAK();
Stop(); //发送停止命令
return buf2;
/*
SendByte((char)(buf2/1000 + '0'));
SendByte((char)(buf2/100%10 + '0'));
SendByte((char)(buf2/10%10 + '0'));
SendByte((char)(buf2%10 + '0'));
SendByte('\r');
SendByte('\n');
*/
}
void main()
{
P_SW2 |= 0x30; //SCL_4/P3.2, SDA_4/P3.3
EA = 1;
P_SW2 |= 0x80;
I2CCFG = 0xe0; //使能 I2C 主机模式
I2CMSST = 0x00;
while(1);
}