Skip to content

_通信协议_PB00005 DFRobot_I2C模块协议V1.0

Angelo edited this page Dec 30, 2019 · 1 revision

简述

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

约定

  • S : I2C起始信号
  • P : I2C停止信号
  • A : I2C确认信号
  • NA : I2C非确认信号
  • W : I2C写控制位
  • R : I2C读控制位
  • SSA : 系统从设备地址(1-126)
  • SMA :系统主设备地址(固定为127)
  • RSA : 寄存器起始地址(0-99)
  • ODD : 奇校验位
  • DI_x : 输入数据
  • DO_x : 输出数据
  • MCSDO : 系统主设备对输出数据的校验和
  • SCSDO : 系统从设备对输出数据的校验和
  • SCSDI : 系统从设备对输入数据的校验和
  • SH : 系统从设备状态高字节(每个模块最多可定义16个状态)
  • SL : 系统从设备状态低字节
(输入) (输出)

协议内容

  • 起始域 :I2C 起始信号
  • 应答域 :ACK或NACK
  • 停止域 :I2C停止信号
  • 地址域(SSA+W/R) :7位从设备地址加上读或写控制位。所有I2C的有效通讯事务,皆由地址域开始。
  • 标识域(PID) :标识域中高7位为有效位,最低位为7位有效位的奇校验位,以实现本字节自身校验。

DFI2C-V10-1.jpg

  • 数据域(DATA):凡是从主设备到从设备的数据,称为输出数据,反之,则称为输入数据。
  • 校验域(CHECK):将数据域中的所有数据相加,取其低8位。

  • 寄存器写操作包:

DFI2C-V10-Write.jpg

  • 寄存器读操作包(虚线框中的停止域可有可无,目前编者还不知如何在Arduino平台上实现不放弃总线控制权的前提下发送重复起始条件)

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; }

Clone this wiki locally