参考手册:Software Implementation of PMBus Over I2C for TMS320F2803x.pdf

例程代码下载地址在参考手册内。

一、PMBus 概览

1、PMbus 特点

PMBus的基本硬件协议是 I2C 协议,这是一种广泛使用的2线协议。 此外,PMBus还指定了另外两个可选线:控制和警报。 从机使用警报线来通知主机故障,而主机将控制线用作片选线以打开或关闭从机。 这些线是可选的; 如果需要,PMBus可以仅通过时钟和数据线作为2线协议运行。

有几个可选功能为PMBus规范增加了鲁棒性,这对于关键系统来说很重要。 像SMBus一样,PMBus实现超时功能。 如果时钟保持低电平的时间超过超时间隔,则设备必须在指定的时间段内重置通信。 强烈建议使用可提高鲁棒性的可选功能是数据包错误检查(PEC)。 PEC通过循环冗余校验8(CRC-8)算法来检查收到的数据包的有效性。

2、PMBus 格式

PMBus事务遵循以下六种格式之一:发送字节,读取字节,写入字节,读取/写入字节,读取字和读取/写入字。 对于所有事务,将首先发送每个字节的MSB(最高有效位)。

2.1 Send Byte 发送字节

2.2 Read Byte 读取字节

2.3 Write Byte 写入字节

2.4 Read/Write Byte 读取/写入字节

读/写字节命令用于在从设备中读或写一个字节的信息。 这些命令遵循读字节或写字节格式,读/写位确定事务处理方向。 通常,读/写字节命令用于访问可写入或读取的寄存器或参数。

2.5 Read Word 读取字

2.6 Read/Write Word 读取/写入字

读/写字命令用于将信息的一个字(两个字节)读取或写入从设备。 主机使用I2C传输命令字节,然后根据事务的方向向从设备读取或向从设备写入两个数据字节。

2.7 Packet Error Checking Protocol 错包检查协议

使用数据包错误检查时,在每个事务中的停止字节之前会添加一个附加字节。 对于读取,PEC 字节从从机读取,而主机将其与自己计算的 PEC 字节进行比较。 对于写操作,PEC 字节从主机发送到从机,从机将其与自己计算的 PEC 字节进行比较。

比较之后,如果 PEC 字节不同,则从设备将检测到 PEC 错误。 PMBus 协议中的首选响应是发送 NACK,通常针对硬件PMBus 和PEC 实现来完成。 但是, 由于此实现是通过 I2C 硬件而非专用 PMBus 硬件上的软件完成的,因此它无法及时计算和检查 NACK 的 PEC 字节,因此此处 PMBus 协议不需要NACK,而是根据PMBus规范采取以下措施:

  • 不响应命令或不执行命令
  • 刷新命令代码和所有收到的数据
  • 置位 STATUS_BYTE 寄存器中的 CML 位(此实现中的变量Status_Byte)
  • 置位 STATUS_CML 寄存器中的 PEC 失败位(此实现中的变量Status_Cml)
  • 通过将警报线拉低来通知主机故障情况

二、Scope and User Implementation

1、应用检查清单:

编写用户应用程序时,应对例程代码进行一些修改:

  • 更改PMBus.h中定义的PEC的值。 PEC = 0 不支持错包检查,PEC = 1 支持错包检查。
  • 正确选择设备的构建配置:master 主设备 或 slave 从设备。
  • 根据 PMBus 规范为应用选择合适的主频率,介于10 kHz至400 kHz之间。 应相应设置所需的预分频值(请参见 I2CMaster_Init()的功能描述)。
  • 您应该更改用于警报和控制线的GPIO,以匹配应用中使用的引脚。 对于主设备,警报线当前触发 xint1。 请参阅设备文档以正确配置所需的GPIO来触发 xint1。
  • 若要将C2000™设备用作 PMBus 从设备,代码中的某些部分标记为用户代码(User Code), 这些部分应根据为特定应用程序实现的PMBus 命令进行修改。
  • 虽然在PMBus.h文件中定义了所有PMBus命令的命令字节,但未响应命令执行的动作。 这取决于用户的应用程序和 PMBus 命令集。 对于从设备,必须更改代码以提供正确的数据字节,以便在被请求时发送给主设备,并采取适当的措施以响应收到的命令。 对于主设备,您必须添加代码以存储从从设备接收到的所有数据,并采取相应的措施。

2、实施准则

以下准则应有助于将示例代码与用户应用程序集成:

  • PMBus.h 文件包含所有 256 个 PMBus 命令的索引的符号定义,与 PMBus 规范第II部分中的命令名称匹配。 调用PMBusMaster_Transmit()函数时应使用这些索引。
    示例:PMBusMaster(STATUS_TEMPERATURE,…,…,…)
  • PMBus.h 文件还包含 PMBus 状态寄存器的结构,这些结构的位定义与 PMBus 规范第II部分一致。 这些寄存器以与 C280x C / C ++ 头文件相同的样式实现,以便轻松地访问寄存器中的每个位。 以这种方式进行定义还允许 Code Composer Studio™ 自动完成功能,从而使代码开发更加容易。 可以复制相同的结构来实现应用程序所需的任何其他 PMBus 寄存器。
  • 尽管可以与多个从设备进行通信,但示例代码的主设备侧旨在与一个从设备进行通信-通过调用具有下一个从设备地址的功能 PMBusMaster_Init(),主设备可以切换其所命令的从设备。
  • 在通信线路上选择适当的上拉电阻以及其他硬件注意事项,完全由用户决定。 请注意,C2000 GPIO上的内部上拉电阻不满足该要求,应添加外部上拉电阻。
  • GPIO配置为控制线。 但是,根据PMBus规范,控制线功能的真正实现是它对某些PMBus命令的影响。 由于这是应用程序层的一部分,因此由您自己决定将此功能作为命令实现的一部分来实现。 有关控制线如何使用不同命令进行操作的更多信息,请参见 http://pmbus.org。

三、函数描述

PMBusMaster.c 和 PMBusSlave.c 文件包含用于将PMBus实施为主设备或从设备的代码。 通过将 PMBus.h 中的 PEC 定义为0或1,可以构建带有或不带有 PEC 功能的实现。

1、主设备函数

以下描述适用于 PMBusMaster.c 文件中的功能。

1.1 PMBusMaster_Init(PMBusMaster_SlaveAddress, PMBusMaster_Prescale)

这个函数应该在 PMBus 操作开始前被调用。设备使用 I2CMaster_Init()  函数配置基础 I2C,并为警报和控制线配置另外两个GPIO引脚。警报线引脚也被配置为触发 XINT1 中断。 可以针对特定于应用程序的警报线响应修改中断 xint1_isr。PMBusMaster_Prescale 通过在初始化基础 I2C 时传递此值来配置主机以所需的频率进行通信。有关选择预分频值的建议,请参见 I2CMaster_Init()  。退出功能之前,主设备通过调用 I2CMaster_SlavePresent() 函数等待从设备准备就绪。

PMBusMaster_Init() 参数描述
参数名 描述
PMBusMaster_SlaveAddress 从设备地址
PMBusMaster_Prescale 达到所需主频率的预分频值
void PMBusMaster_Init(unsigned char PMBusMaster_SlaveAddress, unsigned char PMBusMaster_Prescale)
{// Control Line functionality GPIO0GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; //Enable pullup on GPIO0GpioDataRegs.GPASET.bit.GPIO0 = 1; //Drive line highGpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;   //GPIO0 = GPIO0GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; //GPIO0 = output// SMBUS Alert functionality (GPIO2 = Alert line)GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0;      //Enable pullup on GPIO2GpioDataRegs.GPASET.bit.GPIO2 = 1;     //Drive line highGpioCtrlRegs.GPAQSEL1.bit.GPIO2 = 0;  //SYNC to SYSCLKOUTGpioCtrlRegs.GPACTRL.bit.QUALPRD0 = 0;  //no qualification (SYNC to SYSCLKOUT)GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;      //GPIO2 = GPIO2GpioCtrlRegs.GPADIR.bit.GPIO2 = 0;     //GPIO2 = input//setup interrupt triggered by Alert line EALLOW;                                   // This is needed to write to EALLOW protected registersPieVectTable.XINT1 = &xint1_isr;EDIS;                                  // This is needed to disable write to EALLOW protected registers GpioIntRegs.GPIOXINT1SEL.all = 2;     //Make GPIO2 input source for XINT1XIntruptRegs.XINT1CR.bit.POLARITY = 2;  //XINT1 triggered by falling edge (high-to-low-transition)slave_address = PMBusMaster_SlaveAddress;I2CMaster_Init(PMBusMaster_SlaveAddress, PMBusMaster_Prescale);     // Initialize USCI modulewhile(!I2CMaster_SlavePresent(slave_address));     //check if slave device present// Enable Alert line interruptXIntruptRegs.XINT1CR.bit.ENABLE = 1;  //Enable XINT1 interrupt  // Enable XINT1 interrupt in the PIE: Group 1 interrupt 4PieCtrlRegs.PIEIER1.bit.INTx4 = 1;// Enable CPU INT1 which is connected to PIE group 1IER |= M_INT1;while (I2CMaster_NotReady());           // Is the bus free?
}

1.2 PMBusMaster(PMBusMaster_CommandByte, PMBusMaster_RWFlag, PMBusMaster_Message,*PMBusMaster_ReceivedValue)

该函数通过 I2C 硬件作为主机执行 PMBus 事务。

PMBusMaster_CommandByte 包含PMBus命令的索引。该索引用于确定要发送的 PMBus 命令字节,以及确定需要哪种类型的命令(读字节,写字节等),并因此确定通过 I2C 发送和接收的字节数。 对于读/写命令,参数 PMBusMaster_RWFlag 确定主机是在读取还是在写从机。对于写命令,PMBusMaster_Message 包含要发送的消息; 它是 int 类型的,因此它可以包含一个或两个字节的消息,具体取决于命令。 对于读取命令,*PMBusMaster_ReceivedValue 是将存储读取的数据并将其传递回应用程序级别的指针。

如果将 PEC 定义为 1,则在 PMBusMaster() 中实现数据包错误检查功能。 请注意,在主 switch 语句中,有些部分以 #if !PEC 和 #else 开头。 这些部分分别实现了不使用 PEC 和使用 PEC 的功能。如果实现了PEC,则此功能将根据其自身在读命令中的计算结果来检查从机中的 PEC,并在写命令时发送一个要由从机检查的 PEC 字节。 该函数将命令字节、从机地址、读/写标志以及发送或接收的任何字节传递给 PMBusMaster_CRC8MakeBitwise(),以进行 PEC 字节计算。 该函数返回 PEC 比较的结果(1 =成功,0 =失败)。

PMBusMaster() 参数描述
参数名 描述
PMBusMaster_CommandByte  从 PMBus.h 中定义的命令列表(例如STATUS_WORD)中传递的 PMBus 命令。 这是包含 PMBus 规范中定义的包含 PMBus 命令代码的表的索引。
PMBusMaster_RWFlag 达到所需主频率的预分频值
PMBusMaster_Message PMBus读/写标志。 读/写字节和读/写字命令仅需要指示主机是从从机读取还是向从机写入。
0:写
1:读
*PMBusMaster_ReceivedValue 对于读取功能,这是指向包含从设备接收的字节的数组的指针。
unsigned char PMBusMaster(unsigned char PMBusMaster_CommandByte, unsigned char PMBusMaster_RWFlag, unsigned int PMBusMaster_Message,unsigned char *PMBusMaster_ReceivedValue)
{     unsigned char PMBusMaster_TransmitBuffer[4];unsigned char PMBusMaster_ReceiveBuffer[5];unsigned char PMBusMaster_RxCount = 0;unsigned int PMBusMaster_Temp = 0;unsigned char PMBusMaster_Index;unsigned char PMBusMaster_CommandGroup;#if PEC  //PEC variablesunsigned char PMBusMaster_CrcMsgSize = 0;unsigned char PMBusMaster_CrcMsg[5];unsigned char PMBusMaster_CrcMasterGenerated = 0;unsigned char PMBusMaster_CrcSlaveGenerated = 0;unsigned char PMBusMaster_Result = 0;PMBusMaster_CrcMsg[0] = slave_address << 1;     // 1st CRC byte = slave address...#endifPMBusMaster_Index = PMBusMaster_CommandByte;                      // Store PMBus command byte as ...PMBusMaster_TransmitBuffer[0] = PMBus_Commands[PMBusMaster_Index];   //...1st byte in Tx buffer  PMBusMaster_Temp = PMBusMaster_Message;PMBusMaster_TransmitBuffer[1] = PMBusMaster_Message & 0x00FF;  //store lower byte of messagePMBusMaster_Temp = (PMBusMaster_Message) >> 8;PMBusMaster_TransmitBuffer[2] = PMBusMaster_Temp;                // store higher byte of messageif(PMBusMaster_Index > 0 && PMBusMaster_Index < 13)            //read byte from slave devicePMBusMaster_CommandGroup = READBYTE;if(PMBusMaster_Index > 12 && PMBusMaster_Index < 40)        // read word from slave devicePMBusMaster_CommandGroup = READWORD;if(PMBusMaster_Index > 39 && PMBusMaster_Index < 44)       // write byte to slave devicePMBusMaster_CommandGroup = WRITEBYTE;if(PMBusMaster_Index > 43 && PMBusMaster_Index < 49)       // send byte to slave devicePMBusMaster_CommandGroup = SENDBYTE;/* Read or write one byte of data. R/W oprn. decided based on RWFlag *******/if(PMBusMaster_Index > 48 && PMBusMaster_Index < 69) {if (PMBusMaster_RWFlag == 0)                // write bytePMBusMaster_CommandGroup = WRITEBYTE;else                                     // read bytePMBusMaster_CommandGroup = READBYTE;}/* Read or write one word of data. R/W oprn. decided based on RWFlag *******/if(PMBusMaster_Index > 68 && PMBusMaster_Index < 120)      // R/W Word{if (PMBusMaster_RWFlag == 0)              // write word (new command group)PMBusMaster_CommandGroup = WRITEWORD;else                                     // read wordPMBusMaster_CommandGroup = READWORD; }if(PMBusMaster_Index >= 120)while(1);                        //illegal index - invalid command trapswitch(PMBusMaster_CommandGroup){#if !PECcase READBYTE: // read bytePMBusMaster_RxCount = 1;while (I2CMaster_NotReady());I2CMaster_Transmit(1,PMBusMaster_TransmitBuffer,1,PMBusMaster_ReceiveBuffer);      break;           case READWORD:  // read wordPMBusMaster_RxCount = 2;while (I2CMaster_NotReady());I2CMaster_Transmit(1,PMBusMaster_TransmitBuffer,2,PMBusMaster_ReceiveBuffer);                         break;case WRITEBYTE: // write bytewhile (I2CMaster_NotReady() );I2CMaster_Transmit(2,PMBusMaster_TransmitBuffer,0,0);        break;case SENDBYTE:  // send byte   while (I2CMaster_NotReady());I2CMaster_Transmit(1,PMBusMaster_TransmitBuffer,0,0);       break;case WRITEWORD:  // write wordwhile (I2CMaster_NotReady());I2CMaster_Transmit(3,PMBusMaster_TransmitBuffer,0,0);      break;#elsecase READBYTE:                   // read bytePMBusMaster_RxCount = 1;while (I2CMaster_NotReady());I2CMaster_Transmit(1,PMBusMaster_TransmitBuffer,2,PMBusMaster_ReceiveBuffer);  /* Assembling bit stream for CRC check*/PMBusMaster_CrcMsg[1] = PMBusMaster_TransmitBuffer[0];        // store first tx bytePMBusMaster_CrcMsg[2] = (slave_address << 1) + 1;             // store slave addres + R/W=1PMBusMaster_CrcMsg[3] = PMBusMaster_ReceiveBuffer[0];           // store rx byte 1PMBusMaster_CrcSlaveGenerated = PMBusMaster_ReceiveBuffer[1];    //store PEC byte from slavePMBusMaster_CrcMsgSize = 4;                                     // # of bytes/* CRC function call, generate CRC byte to compare with slave CRC*/PMBusMaster_CrcMasterGenerated = PMBusMaster_Crc8MakeBitwise(CRC8_INIT_REM,CRC8_POLY,PMBusMaster_CrcMsg,PMBusMaster_CrcMsgSize);if (PMBusMaster_CrcMasterGenerated == PMBusMaster_CrcSlaveGenerated) //compare the PEC bytesPMBusMaster_Result = PEC_PASS;            // PEC byte was validatedelsePMBusMaster_Result = PEC_FAIL;            // failed PEC test   break;           case READWORD:                      // read wordPMBusMaster_RxCount = 2;while (I2CMaster_NotReady());I2CMaster_Transmit(1,PMBusMaster_TransmitBuffer,3,PMBusMaster_ReceiveBuffer);  /* Assembling bit stream for CRC check*/PMBusMaster_CrcMsg[1] = PMBusMaster_TransmitBuffer[0];PMBusMaster_CrcMsg[2] = (slave_address << 1) + 1;               // store slave address + R/W=1PMBusMaster_CrcMsg[3] = PMBusMaster_ReceiveBuffer[0];PMBusMaster_CrcMsg[4] = PMBusMaster_ReceiveBuffer[1];PMBusMaster_CrcSlaveGenerated = PMBusMaster_ReceiveBuffer[2];  //store PEC byte from slavePMBusMaster_CrcMsgSize = 5;/* CRC function call, generate CRC byte to compare with slave CRC*/PMBusMaster_CrcMasterGenerated = PMBusMaster_Crc8MakeBitwise(CRC8_INIT_REM,CRC8_POLY,PMBusMaster_CrcMsg,PMBusMaster_CrcMsgSize);             if (PMBusMaster_CrcMasterGenerated == PMBusMaster_CrcSlaveGenerated)PMBusMaster_Result = PEC_PASS;elsePMBusMaster_Result = PEC_FAIL;                       break;case WRITEBYTE:                        // write byte/* CRC function call, generate CRC byte to transmit to slave device*/PMBusMaster_CrcMsg[1] = PMBusMaster_TransmitBuffer[0];PMBusMaster_CrcMsg[2] = PMBusMaster_TransmitBuffer[1];PMBusMaster_CrcMsgSize = 3;PMBusMaster_CrcMasterGenerated = PMBusMaster_Crc8MakeBitwise(CRC8_INIT_REM,CRC8_POLY,PMBusMaster_CrcMsg,PMBusMaster_CrcMsgSize);PMBusMaster_TransmitBuffer[2] = PMBusMaster_CrcMasterGenerated;while (I2CMaster_NotReady() );I2CMaster_Transmit(3,PMBusMaster_TransmitBuffer,0,0); //check if the slave verified the PEC byteif(alert == 0) PMBusMaster_Result = PEC_PASS;elsePMBusMaster_Result = PEC_FAIL;              break;case SENDBYTE:                        // send byte  /* CRC function call, generate CRC byte to transmit to slave device*/PMBusMaster_CrcMsg[1] = PMBusMaster_TransmitBuffer[0];PMBusMaster_CrcMsgSize = 2;PMBusMaster_CrcMasterGenerated = PMBusMaster_Crc8MakeBitwise(CRC8_INIT_REM,CRC8_POLY,PMBusMaster_CrcMsg,PMBusMaster_CrcMsgSize);PMBusMaster_TransmitBuffer[1] = PMBusMaster_CrcMasterGenerated; while (I2CMaster_NotReady());I2CMaster_Transmit(2,PMBusMaster_TransmitBuffer,0,0);  //check if the slave verified the PEC byteif(alert == 0)  PMBusMaster_Result = PEC_PASS;elsePMBusMaster_Result = PEC_FAIL; break;case WRITEWORD:                        // write word/* CRC function call, generate CRC byte to transmit to slave device*/PMBusMaster_CrcMsg[1] = PMBusMaster_TransmitBuffer[0];PMBusMaster_CrcMsg[2] = PMBusMaster_TransmitBuffer[1];PMBusMaster_CrcMsg[3] = PMBusMaster_TransmitBuffer[2];PMBusMaster_CrcMsgSize = 4;PMBusMaster_CrcMasterGenerated = PMBusMaster_Crc8MakeBitwise(CRC8_INIT_REM,CRC8_POLY,PMBusMaster_CrcMsg,PMBusMaster_CrcMsgSize);PMBusMaster_TransmitBuffer[3] = PMBusMaster_CrcMasterGenerated;while (I2CMaster_NotReady());I2CMaster_Transmit(4,PMBusMaster_TransmitBuffer,0,0);//check if the slave verified the PEC byteif(alert == 0)    PMBusMaster_Result = PEC_PASS;elsePMBusMaster_Result = PEC_FAIL; break;#endifdefault:break;}if (PMBusMaster_ReceivedValue !=0){*PMBusMaster_ReceivedValue++ = PMBusMaster_ReceiveBuffer[0];if (PMBusMaster_RxCount > 1)*PMBusMaster_ReceivedValue = PMBusMaster_ReceiveBuffer[1];}#if PECreturn PMBusMaster_Result;   //When PEC is implemented, return the result of the packet error checking (0 = failure, 1 = success)#elsereturn 1;    //When PEC is not implemented, return a 1 for completed communication#endif
}

1.3 xint1_isr

外部中断“ 1”配置为在警报线下降至低压状态时触发。 您可以根据应用程序的所需功能更改此中断服务例程,以服务警报线。

2 从设备函数

2.1 PMBusSlave_Init(PMBusSlave_DeviceAddress)

这个函数应该在 PMBus 操作开始前被调用。该函数使用参数 PMBusSlave_DeviceAddress 指定的设备地址将基础 I2C 配置为从设备。 它还设置了用于I2C操作以及警报和控制线功能的 GPIO。

void PMBusSlave_Init(unsigned char PMBusSlave_DeviceAddress)
{   StatusRegs.StatusWord.all = 0;         //Clear status bits for the status registers we are usingStatusRegs.StatusCml.all = 0;// Control Line functionality GPIO0GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;       //Enable pullup on GPIO0GpioDataRegs.GPASET.bit.GPIO0 = 1;     //Drive line highGpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 0;  //SYNC to SYSCLKOUTGpioCtrlRegs.GPACTRL.bit.QUALPRD0 = 0;  //no qualification (SYNC to SYSCLKOUT)GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;      //GPIO0 = GPIO0GpioCtrlRegs.GPADIR.bit.GPIO0 = 0;     //GPIO0 = input// SMBUS Alert functionality (GPIO2 = Alert line)GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0;       //Enable pullup on GPIO2GpioDataRegs.GPASET.bit.GPIO2 = 1;     //Drive line highGpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;       //GPIO2 = GPIO2GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;     //GPIO2 = outputslave_address = PMBusSlave_DeviceAddress;I2CSlave_Init(slave_address);     // Initialize USCI module
}

2.2 PMBusSlave_DecodeCommand(PMBusSlave_RxCommand)

一旦接收到从主机发送的命令字节,就会从PMBusSlave() 函数调用此函数。 该函数在表中查找命令字节并确定命令的类型(读取字节,写入字节等)。 它还确定该命令是否是从设备支持的命令,并在必要时准备要发送的信息。

用户应该更改标记为“用户代码”的代码部分,以实施特定于应用程序的命令。

USER CODE
#warn "User should change code to implement their application's supported PMBus commands."
switch (PMBusSlave_Index) //should include all user supported commands
{
case STATUS_TEMPERATURE:
PMBusSlave_TransmitBuffer[0] = Temperature;
break;
...
default:
PMBusSlave_DummyCommand = 1; //command not supported by this slave
break;
}
参数名 描述
PMBusSlave_RxCommand 从设备收到的命令字节
unsigned char PMBusSlave_DecodeCommand(unsigned char PMBusSlave_RxCommand)
{unsigned char PMBusSlave_CommandGroup; for(PMBusSlave_Index = 0; PMBusSlave_Index < 120; PMBusSlave_Index++){if(PMBus_Commands[PMBusSlave_Index] == PMBusSlave_RxCommand)break;}USER CODE#warn "User should change code to implement their application's supported PMBus commands."switch (PMBusSlave_Index)    //should include all user supported commands{case STATUS_TEMPERATURE:PMBusSlave_TransmitBuffer[0] = Temperature;break;case STORE_DEFAULT_CODE:break;case OPERATION:PMBusSlave_TransmitBuffer[0] = Operation;break;case STATUS_WORD:PMBusSlave_TransmitBuffer[0] = Status_Word;   //lower bytePMBusSlave_TransmitBuffer[1] = Status_Word >> 8; //upper bytebreak;case VOUT_COMMAND:PMBusSlave_TransmitBuffer[0] = Vout_Command;   //lower bytePMBusSlave_TransmitBuffer[1] = Vout_Command >> 8;    //upper bytebreak;default:PMBusSlave_DummyCommand = 1; //command not supported by this slavebreak;}END USER CODE   if(PMBusSlave_Index == 0)//dummy byte to check if slave is presentPMBusSlave_DummyCommand = 1;if(PMBusSlave_Index > 0 && PMBusSlave_Index < 13)                  //read byte from slave devicePMBusSlave_CommandGroup = READBYTE;if(PMBusSlave_Index > 12 && PMBusSlave_Index < 40)                 // read word from slave devicePMBusSlave_CommandGroup = READWORD;if(PMBusSlave_Index > 39 && PMBusSlave_Index < 44)                 // write byte to slave devicePMBusSlave_CommandGroup = WRITEBYTE;if(PMBusSlave_Index > 43 && PMBusSlave_Index < 49)                 // send byte to slave devicePMBusSlave_CommandGroup = SENDBYTE;/* Read or write one byte of data. R/W oprn. decided based on RWFlag *******/if(PMBusSlave_Index > 48 && PMBusSlave_Index < 69) {PMBusSlave_CommandGroup = RWBYTE;}/* Read or write one word of data. R/W oprn. decided based on RWFlag *******/if(PMBusSlave_Index > 68 && PMBusSlave_Index < 120)                // R/W Word{PMBusSlave_CommandGroup = RWWORD;}if(PMBusSlave_Index >= 120)while(1);                               //illegal index - invalid command trapreturn PMBusSlave_CommandGroup;
}

2.3 PMBusSlave()

该功能等待主机发送PMBus命令字节,然后执行PMBus读取和写入操作。

3 PMBus With PEC

3.1 PMBusMaster_Crc8MakeBitwise(PMBusMaster_CRC, PMBusMaster_Poly, *PMBusMaster_Pmsg, PMBusMaster_MsgSize)

此函数根据* PMBusMaster_Pmsg上的字节,根据PMBus规范生成 PEC 字节并返回 PEC 字节。

参数名 描述
PMBusMaster_CRC CRC 计算的初始值
PMBusMaster_Poly 多项式
*PMBusMaster_Pmsg 指向要在 CRC 计算中使用的数据的指针。 这应该包括从机地址,读/写位,命令字节以及主机刚刚发送或接收的所有数据字节。
PMBusMaster_MsgSize CRC 计算中使用的数据字节数
static unsigned char PMBusMaster_Crc8MakeBitwise(unsigned char PMBusMaster_CRC, unsigned char PMBusMaster_Poly, unsigned char *PMBusMaster_Pmsg, unsigned int PMBusMaster_MsgSize)
{unsigned int i, j, carry;unsigned char msg;PMBusMaster_CRC = *PMBusMaster_Pmsg++;           // first byte loaded in "crc"     for(i = 0 ; i < PMBusMaster_MsgSize-1 ; i ++){msg = *PMBusMaster_Pmsg++;                   // next byte loaded in "msg"for(j = 0 ; j < 8 ; j++){carry = PMBusMaster_CRC & 0x80;                               // check if MSB=1          PMBusMaster_CRC = (PMBusMaster_CRC << 1) | (msg >> 7);     // Shift 1 bit of next byte into crcif(carry) PMBusMaster_CRC ^= PMBusMaster_Poly;             // If MSB = 1, perform XORmsg <<= 1;                                            // Shift left msg byte by 1msg &= 0x00FF;}}// The previous loop computes the CRC of the input bit stream. To this, // 8 trailing zeros are padded and the CRC of the resultant value is // computed. This gives the final CRC of the input bit stream.for(j = 0 ; j < 8 ; j++){carry = PMBusMaster_CRC & 0x80;PMBusMaster_CRC <<= 1;if(carry) PMBusMaster_CRC ^= PMBusMaster_Poly;}PMBusMaster_CRC &= 0x00FF;      //We only want one byte (lower)return(PMBusMaster_CRC);
}

3.2 PMBusSlave_Crc8MakeBitwise(PMBusSlave_CRC, PMBusSlave_Poly, *PMBusSlave_Pmsg, PMBusSlave_MsgSize)

参数名 描述
PMBusSlave_CRC CRC 计算的初始值
PMBusSlave_Poly 多项式
*PMBusSlave_Pmsg 指向要在CRC计算中使用的数据的指针。 这应该包括从机地址,读/写位,命令字节以及从机刚刚发送或接收的所有数据字节。
PMBusSlave_MsgSize CRC 计算中使用的数据字节数
static unsigned short PMBusSlave_Crc8MakeBitwise(unsigned char PMBusSlave_CRC, unsigned char PMBusSlave_Poly, unsigned char *PMBusSlave_Pmsg, unsigned int PMBusSlave_MsgSize)
{unsigned int i, j, carry;unsigned char msg;PMBusSlave_CRC = *PMBusSlave_Pmsg++;         // first byte loaded in "crc"     for(i = 0 ; i < PMBusSlave_MsgSize-1 ; i ++){msg = *PMBusSlave_Pmsg++;                   // next byte loaded in "msg"for(j = 0 ; j < 8 ; j++){carry = PMBusSlave_CRC & 0x80;                          // check if MSB=1          PMBusSlave_CRC = (PMBusSlave_CRC << 1) | (msg >> 7);    // Shift 1 bit of next byte into crcif(carry) PMBusSlave_CRC ^= PMBusSlave_Poly;              // If MSB = 1, perform XORmsg <<= 1;                                            // Shift left msg byte by 1msg &= 0x00FF;}}// The previous loop computes the CRC of the input bit stream. To this, // 8 trailing zeros are padded and the CRC of the resultant value is // computed. This gives the final CRC of the input bit stream.for(j = 0 ; j < 8 ; j++){carry = PMBusSlave_CRC & 0x80;PMBusSlave_CRC <<= 1;if(carry) PMBusSlave_CRC ^= PMBusSlave_Poly;} PMBusSlave_CRC &= 0x00FF;  //We only want one byte (lower)return(PMBusSlave_CRC);
}

4 底层功能说明 —— I2C

PMBus的这种软件实现依赖于控制硬件的底层 I2C 层。 I2CMaster.c 文件包含控制 I2C 层的功能,而 PMBusSlave.c 文件包含用于初始化从属端 I2C 层的功能。

4.1 I2C主机

4.1.1 I2CMaster_Init(I2CMaster_SlaveAddress, I2CMaster_Prescale)

此功能将I2C模块配置为I2C主设备,将两个GPIO配置为I2C时钟和数据线,并设置适当的 I2C 中断。 它使用 I2CMaster_Prescale 为所需的通信频率设置模块时钟。

I2CMaster_Prescale中传递的值与主通信频率之间的关系可以用以下公式表示:

4.1.2 I2CMaster_Transmit(I2CMaster_ByteCountTx, *I2CMaster_TxArray, I2CMaster_ByteCountRx,
*I2CMaster_RxArray)

每当主机进行I2C事务时,都应调用此函数。 该函数从* I2CMaster_TxArray传递的结构中的数据中发送指定数量的字节,然后从从设备接收由* I2CMaster_RxArray传递的结构中的指定字节数。

参数名 描述
I2CMaster_ByteCountTx 要发送的字节数
*I2CMaster_TxArray 指向发送缓冲区的指针
I2CMaster_ByteCountRx 要接收的字节数
*I2CMaster_RxArray 指向接收缓冲区的指针

4.1.3 I2CMaster_SlavePresent(I2CMaster_SlaveAddress)

此功能检查是否有 I2C 从设备连接到时钟和数据线。 它通过向从机发送一个虚拟字节并获取其 ACK 状态来实现。 如果接收到 ACK,则函数返回“ 1”;如果接收到 NACK,则函数返回“ 0”。

4.1.4 I2CMaster_NotReady()

此函数返回繁忙位的值(I2caCtrlRegs.I2CSTR.bit.BB)。

4.1.5 I2CMaster_Wait()

从 I2CMaster_Transmit() 函数中调用此函数。它通过轮询停止位和繁忙位(I2caRegs.I2CSTR.bit.STP 和 I2caRegs.I2CSTR.bit.BB)来等待主服务器完成事务。

4.1.6 i2c_master_int1a_isr

这是 I2C 主中断服务程序。 当主机从机接收数据时,它由读-就绪(RRDY)中断触发。 它将数据存储在位于* I2CMaster_ReceiveField 的接收缓冲区中,并递增指针。

4.2  I2C 从机

4.2.1  I2CSlave_Init(I2CSlave_OwnAddress)

此功能将I2C模块配置为I2C从设备,将两个GPIO配置为I2C时钟和数据线,并设置适当的I2C中断。 它将从站的地址设置为I2CSlave_OwnAddress。

DSP 基于 TMS320F2803x 的 I2C 上的 PMBus 的软件应用相关推荐

  1. 三相锁相 c 语言 程序,轻松玩转DSP——基于TMS320F2833x(Word+PDF+ePub+PPT)

    作者:马骏杰(作者),尹艳浩(作者),王旭东(作者)&0更多 出版:机械工业出版社; 第1版 (2018年12月5日) 服务:人工校对0错代录+录完后精校排版 此为收费服务:会收取文档代录之人 ...

  2. 基于距离传感器的I2C通信(一)

    基于距离传感器的I2C通信(一) 一.软硬件准备 (一)硬件 (二)软件 ST-Link驱动的下载安装 二.keil软件的配置 (一)初始配置 (二)程序下载及调试 三.器件的初步了解 四.接线方法 ...

  3. 基于APB与I2C的多主多从架构设计

    目录 1. Design Spec 1.1. Function Description 1.2. Feature List 1.3. Block Diagram 1.4. FSM Operation ...

  4. R语言with函数和within函数:with函数基于表达式在dataframe上计算、within函数基于表达式在dataframe上计算并修改原始数据

    R语言with函数和within函数:with函数基于表达式在dataframe上计算.within函数基于表达式在dataframe上计算并修改原始数据 目录

  5. DockOne微信分享( 九十):猎豹移动基于CoreOS在AWS上的项目实践

    本文讲的是DockOne微信分享( 九十):猎豹移动基于CoreOS在AWS上的项目实践[编者的话]本次分享介绍基于AWS的EC2服务如何设计和搭建适合自己业务的架构方案实现全球多region部署,介 ...

  6. 教你精确计算 I2C 上拉电阻阻值

    I2C 总线能挂多少设备? 理论上: 7-bit address :2 的 7 次方,能挂 128 个设备. 10-bit address :2 的 10 次方,能挂 1024 个设备. 当然,要把预 ...

  7. 基于docker在Ubuntu上搭建TensorFlow-GPU计算环境

    这里转载一篇Docker安装TF GPU的版本 基于docker在Ubuntu上搭建TensorFlow-GPU计算环境 由于实验室的服务器有多人共享使用,而不同人的代码对应的keras和tensor ...

  8. android jni arm x86,使用houdini(Android模拟器)在基于x86的AVD上运行ARM库

    我有一个ARM编译库.我无法访问源代码.我想在我自己的应用程序中使用这个库.该应用程序应该在基于x86的AVD上运行(出于性能原因).使用houdini(Android模拟器)在基于x86的AVD上运 ...

  9. 基于android的团购app设计与实现,基于Android的掌上团购App设计与实现

    摘要: 传统的商品交易模式受到时间和空间的限制,各种缺陷开始出现,已经不能适应现代互联网时代的需要.移动互联网与智能手机技术为人们生活带来了极大的便捷,通过移动互联网用户可以随时随地的获取信息,或者是 ...

  10. 基于JAVA政府采购线上招投标平台计算机毕业设计源码+系统+数据库+lw文档+部署

    基于JAVA政府采购线上招投标平台计算机毕业设计源码+系统+数据库+lw文档+部署 基于JAVA政府采购线上招投标平台计算机毕业设计源码+系统+数据库+lw文档+部署 本源码技术栈: 项目架构:B/S ...

最新文章

  1. @Bean 与@Component的区别
  2. “人脸识别”是一柄双刃剑 如何趋利避害?
  3. java swing jar 字体不一样_终于读完了腾讯T4架构师整理的Java深度学习笔记
  4. 冒泡排序python例题_零基础学python 15 经典算法:冒泡排序法(课后习题答案)...
  5. 具有Spring Boot和Yeoman的单页Angularjs应用程序
  6. 重磅!央行启动企业信息联网核查系统
  7. 如何做一个国产数据库(六) 网络传输 nodejs做测试客户端
  8. clickhouse原理解析与应用实践 pdf_阿里专家分享内部绝密RocketMQ核心原理与最佳实践PDF...
  9. ant-Design------select的option 随页面滚动的问题
  10. L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误...
  11. distcp用于集群中数据传输解读
  12. Identityserver4配置证书
  13. java 并发集合_《Java 7并发编程实战手册》第六章并发集合
  14. 说说 XcodeGhost 这个事
  15. Deskpins—窗口置顶软件
  16. JAVA 正则表达式(大全)
  17. 50台电脑文件服务器,50台电脑云桌面用什么服务器
  18. 音频系统POP音的原理和解决方法
  19. 【历史上的今天】5 月 21 日:Simula 67 发布;微软推出 Xbox One;计算机先驱诞生日
  20. 如何设置开机启动程序

热门文章

  1. java课程设计 扫雷_java扫雷游戏课程设计报告
  2. 电影院售票系统mysql表格_电影院售票数据库系统设计.doc
  3. 诺基亚n9用linux软件,Nokia N9 卸载国行N9自带的第三方软件
  4. android应用程序开发另解及Android SDK工具集的另类用法 .
  5. linux 服务器 硬盘测试工具,linux硬盘检测工具:Smartmontools使用指南
  6. unity透明通道加颜色_Unity的Gamma颜色空间和Linear颜色空间的小研究
  7. 免费在线SQL数据库SQL Fiddle使用简介
  8. html模仿登陆页面,登陆注册页面html代码(仿知乎)
  9. 开发工具篇 程序员计算器
  10. Activity (一)工作流简介 :概念与由来