简述

为规范DFRobot I2C产品线的通信方式,将I2C总线中的主控制器称为系统主设备,其余均称为系统从设备,注意与I2C通信时主从的区别。不论在I2C通讯中,以什么身份出现在总线上,从系统主设备到系统从设备的数据传输,均称为输出,反之,则称为输入。本文将一个完整的I2C通讯称为一个事务,事务由一个或多个包构成,而每个包又由域构成。

约定

(输入) (输出)

协议内容

DFI2C-V10-1.jpg

DFI2C-V10-Write.jpg

DFI2C-V10-Read.jpg

DFI2C-V10-Hand.jpg

DFI2C-V10-Error.jpg

事务

寄存器写操作包 +
寄存器读操作包 +
(异常反馈包)

Arduino 库

简述

使用该库,只需在实例化对象时,指定数据缓冲区的首地址和大小,注意缓冲区的大小应比实际寄存器数多1。

只要将待发送的数据写入用户定义的数据缓冲区中,然后调用Write方法,指定系统从设备地址、用户寄存器起始地址和连续操作的寄存器数,即可。若调用该方法返回0,说明写操作成功,反之,操作失败。

调用Read方法,指定系统从设备地址、用户寄存器起始地址和连续操作的寄存器数,即可。若调用该方法返回0,说明读操作成功,反之,操作失败。当操作成功时,用户即可从自己定义的缓冲区中,从首地址开始读取相应字节数的数据。

DFI2C_V10.h

#ifndef _DFI2C_V10_H #define _DFI2C_V10_H

#define DFI2C_PID_HAND 0x7e #define DFI2C_PID_ERROR 0x7f #define DFI2C_SYS_MASTER 127

class DFI2CV10 { private: unsigned char *BufStartAddr; unsigned char BufSize; unsigned char Front; unsigned char Rear; unsigned char GeneratePID(unsigned char PID); unsigned char CheckPID(unsigned char PID);

public: DFI2CV10(unsigned char *BufAddr,unsigned char Num); unsigned char Write(unsigned char SSA,unsigned char RegAddr,unsigned char Num); unsigned char Read(unsigned char SSA,unsigned char RegAddr,unsigned char Num); unsigned char DetectError(void); };

#endif

DFI2C_V10.c

#include "DFI2C_V10.h" #include <Wire.h>

unsigned char Error[5];

/*DFI2C系统主设备接收到系统从设备发来的异常包*/ void DFI2CV10_ReceiveEvent(int Num) { unsigned char i; for(i=0;i<Num;i++) { if(Num<=sizeof(Error)) Error[i]=Wire.read(); } }

/*构造函数*/ DFI2CV10::DFI2CV10(unsigned char *BufAddr,unsigned char Num) { Wire.begin(DFI2C_SYS_MASTER); Wire.onReceive(DFI2CV10_ReceiveEvent); this->BufStartAddr=BufAddr; this->BufSize=Num; }

/*生成PID*/ unsigned char DFI2CV10::GeneratePID(unsigned char PID) { unsigned char count=0,temp=PID; while(temp) { temp&=(temp-1); count++; } if(count%2) return (PID<<1); else return ((PID<<1)+1); }

/*校验PID*/ unsigned char DFI2CV10::CheckPID(unsigned char PID) { unsigned char count=0,temp=PID; while(temp) { temp&=(temp-1); count++; } if(count%2) return PID; else return 0xff; }

/*写寄存器操作,SSA-模块地址,RegAddr-寄存器起始地址,Num-连续操作的字节数*/ unsigned char DFI2CV10::Write(unsigned char SSA,unsigned char RegAddr,unsigned char Num) { unsigned char i,temp,check=0;

//写寄存器PID+Data+Check Wire.beginTransmission(SSA); Wire.write(this->GeneratePID(RegAddr)); for(i=0;i<Num;i++) { temp=*(this->BufStartAddr+i); Wire.write(temp); check+=temp; } Wire.write(check); Wire.endTransmission();

//写握手PID Wire.beginTransmission(SSA); Wire.write(this->GeneratePID(DFI2C_PID_HAND)); Wire.endTransmission();

//读校验字节 Wire.requestFrom((int)SSA,1,true); if(Wire.read()==check) return 0; else return 0xff; }

/*读寄存器操作,SSA-模块地址,RegAddr-寄存器起始地址,Num-连续操作的字节数*/ unsigned char DFI2CV10::Read(unsigned char SSA,unsigned char RegAddr,unsigned char Num) { unsigned char temp,check=0;

//写寄存器PID Wire.beginTransmission(SSA); Wire.write(this->GeneratePID(RegAddr)); Wire.endTransmission();

//读寄存器Data Wire.requestFrom((int)SSA,(int)Num,true); this->Front=0; this->Rear=0; while(Wire.available()) { temp=Wire.read(); check+=temp; //允许覆盖 *(this->BufStartAddr+this->Rear)=temp; this->Rear=(this->Rear+1)%this->BufSize; }

//写握手PID Wire.beginTransmission(SSA); Wire.write(this->GeneratePID(DFI2C_PID_HAND)); Wire.endTransmission();

//读校验字节 Wire.requestFrom((int)SSA,1,true); if(Wire.read()==check) { if((this->Rear+this->BufSize-this->Front)%this->BufSize==Num) return 0; else return 0xff; } return 0xff; }

/*异常检测,若收到正确的异常包,则返回0,否则返回0xff*/ unsigned char DFI2CV10::DetectError(void) { if(Error[0]==this->GeneratePID(DFI2C_PID_ERROR)) { if(Error[1]!=0) { if(Error[4]=Error[1]+Error[2]+Error[3]) return 0; } } return 0xff; }