This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/TMS320F28035:用于 TMS320F2803x 的 PMBus 通过 I2C 的软件实现不起作用

Guru**** 2346220 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/592053/compiler-tms320f28035-software-implementation-of-pmbus-over-i2c-for-tms320f2803x-not-working

器件型号:TMS320F28035

工具/软件:TI C/C++编译器

大家好、  

我不熟悉 TI 微控制器和 Code Composer Studio、我通常使用 MATLAB、这是相当可以接受的。 但是、我将按照文档" TMS320F2803x 的 PMBus 通过 I2C 的软件实现"以及和 TI 网站上提供的示例文件、通过 I2C 实施 PMBus。 我将所有文件合并到一个 main.c 文件中、使我的生活更轻松。  

现在、我正在确保代码正常工作、因此我不会发起任何通信、我只会初始化外设、只会确保代码能够执行某些操作。 我每秒递增一个名为"MyVariable"的变量的值。  

下面是我的代码、从调试器窗口中、我可以很容易地看到变量"MyVariable"卡在5、系统一直花费在步骤3  PMBusMaster_Init (I2C_SLAVE_ADDR、CLK_PREPcale);

而从未实现 while 环路。 通过检查 I2C 的寄存器、从器件从不确认任何内容。 但是、从器件的地址是正确的、它确认 MATLAB 发出的回收命令、并且它还遵循智能电池充电器的 PMBus 规范。

///-------------------------------------------------------
#include "DSP2803x_Device.h"// DSP280x 头文件包含文件
#include "DSP2803x_examples.h"// DSP280x 示例包含文件
#include "DSP2803x_I2C_defines.h"
#include "PMBus.h"
//用户应更改这些值以匹配其应用所需的值
#define I2C_SLAVE_ADDR 9 //从器件的地址
#define CLK_PRESCALE 39 // I2C 主频率的预分频值   (我需要10K - 100K 范围内的频率)- 39为我提供60kHz
//主频率= 60000//[(预分频+1)*25] kHz

/*包括 I2CMaster 头*/
空 I2CMaster_Init (UINT16 I2CMaster_SlaveAddress、UINT16 I2CMaster_Prescale);
void I2CMaster_transmit (UINT16 I2CMaster_ByteCountTx、unsigned char * I2CMaster_TxArray、UINT16 I2CMaster_ByteCountRx、unsigned char * I2CMaster_RxArray);
void I2CMaster_wait (void);
unsigned char I2CMaster_SlavePresent (unsigned char I2CMaster_SlaveAddress);
unsigned char I2CMaster_NotReady();
中断 void i2c_master_int1a_isr (void);
中断空 CPU_timer0_ISR (空);
/*I2CMaster 变量*/
静态无符号字符*I2CMaster_ReceiveField;
静态无符号字符*I2CMaster_TransmitField;

/*包括 PmBusMaster 头*/
/*------------------
此函数用于在没有 PEC 的情况下实现 PMBus 功能
-------------------------------------------------- *
unsigned char PMBusMaster (unsigned char PMBusMaster_CommandByte、unsigned char PMBusMaster_RWFlag、unsigned int PMBusMaster_Message、unsigned char * PMBusMaster_ReceivedValue);
/*------------------
此函数用于初始化 PMBus 主器件
-------------------------------------------------- *
void PMBusMaster_Init (unsigned char PMBusMaster_SlaveAddress、unsigned char PMBusMaster_Prescale);
静态无符号 char PMBusMaster_Crc8MakeBitwise (unsigned char PMBusMaster_CRC、unsigned char PMBusMaster_Poly、unsigned char * PMBusMaster_Pmsg、unsigned int PMBusMaster_MsgSize);
/*PMBus 变量*/

/*这是 PMBus 命令查找表。 不要修改---------------- *
const unsigned char PMBus_Commands[120]=

0x00、//虚拟字节
0x19、0x78、0x7A、0x7B、0x7C、0x7D、0x7E、0x7F、0x80、0x81、0x82、0x98、
0x79、0x88、0x89、0x8A、0x8B、0x8C、0x8D、0x8E、0x8F、0x90、0x91、0x92、
0x93、0x94、0x95、0x96、0x97、0xA0、0xA1、0xA2、0xA3、0xA4、0xA5、0xA6、
0xA7、0xA8、0xA9、0x13、0x14、0x17、0x18、0x3、0x11、0x12、0x15、0x16、
0x0、0x1、0x2、0x4、0x10、0x20、0x3A、0x3D、0x41、0x45、0x47、0x49、
0x4C、0x50、0x54、0x56、0x5A、0x5C、0x63、0x69、0x21、0x22、0x23、0x24、
0x25、0x26、0x27、0x28、0x29、0x2A、0x31、0x32、0x33、0x35、0x36、0x37、
0x38、0x39、0x3B、0x3C、0x3E、0x3F、0x40、0x42、0x43、0x46、0x48、
0x4A、0x4B、0x4F、0x51、0x52、0x53、0x55、0x57、0x58、0x59、0x5B、0x5D、
0x5E、0x5F、0x60、0x61、0x62、0x64、0x65、0x66、0x68、0x6A、0x6B
};

静态无符号 char slave_address;
unsigned char alert = 0;

//注:此示例中使用的 I2C 宏可在中找到
// DSP280x_I2C_defines.h 文件
//此文件中找到的函数的原型语句。
空 Memcopy (uint16 * SourceAddr、uint16* SourceEndAddr、uint16* DestAddr);
无符号字符 Temp[1]={0};
unsigned char Oprn[1]={0};
无符号字符 STAT[2]={0、0};
unsigned char VCmd[2]={0、0};
unsigned int Status = 0;
unsigned int Vout_Command = 0;
unsigned char pass_fail = 0;
unsigned int MyVariable=0;

void main (void)

//步骤1. 初始化系统控制:
// PLL、安全装置、启用外设时钟
//此示例函数位于 DSP280x_SYSCTRL.c 文件中。
InitSysCtrl();

//将时间关键代码和闪存设置代码复制到 RAM
// RamfuncsLoadStart、RamfuncsLoadEnd 和 RamfuncsRunStart
//符号由链接器创建。 请参阅链接器文件。
Memcopy (&RamfuncsLoadStart、&RamfuncsLoadEnd、&RamfuncsRunStart);

//步骤2. 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
Dint;

//将 PIE 控制寄存器初始化为默认状态。
//默认状态为禁用所有 PIE 中断和标志
//被清除。
//此函数位于 DSP280x_PIECTRL.c 文件中。
InitPieCtrl();

//禁用 CPU 中断并清除所有 CPU 中断标志:
IER = 0x0000;
IFR = 0x0000;

//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//这将填充整个表,即使是中断也是如此
//在本例中未使用。 这对于调试很有用。
//可以在 DSP280x_DefaultIsr.c 中找到 shell ISR 例程
//此函数可在 DSP280x_PieVect.c 中找到
InitPieVectTable();

//步骤3. 初始化器件外设:


MyVariable=5;

PMBusMaster_Init (I2C_SLAVE_ADDR、CLK_预 分频);

MyVariable=0;


EINT;

//应用程序循环
while (1)

MyVariable++;
DELAY_US (1000000);//在执行任何操作之前等待一秒钟
//读取
//pass 故障= PMBusMaster (STATUS_TEMPERATURE、1、0、Temp);//读取字节
//pass 故障= PMBusMaster (OPERATION、1、0、Oprn);//r/w 字节(读取)
//pass 故障= PMBusMaster (STATUS_WORD、1、0、STATT);//读取字
//pass 故障= PMBusMaster (VOUT_COMMAND、1、0、VCmd);//r/w 字(读取)
//写入
//pass 故障= PMBusMaster (STORE_DEFAULT_CODE、0、0xAA、0);//写入字节
//pass 故障= PMBusMaster (OPERATION、0、0xBB、0);//r/w 字节(WRITE)
//pass 故障= PMBusMaster (VOUT_COMMAND、0、0xCCDD、0);//r/w 字(写入)

//Status =(STAT[1]<< 8)| STAT[0];//将两个数据字节解压缩到一个字中
//Vout_Command =(VCmd[1]<< 8)| VCmd[0];//首先接收最低序字节

}// main 结束

/***
//此函数将从复制指定的存储器内容
//一个位置到另一个位置。
//
// uint16 *SourceAddr 指向要移动的第一个字的指针
// SourceAddr < SourceEndAddr
// uint16* SourceEndAddr 指向要移动的最后一个字的指针
// uint16* DestAddr 指向第一个目标字的指针
//
//不会对无效的内存位置或进行检查
//结束地址为>,然后是第一个起始地址。
**/
空 Memcopy (uint16 * SourceAddr、uint16* SourceEndAddr、uint16* DestAddr)

while (SourceAddr < SourceEndAddr)

*DestAddr++=*SourceAddr++;

返回;

/ //**
*@简要初始化主模式下的 I2C 模块
*@param I2CMaster_SlaveAddress 从器件的地址
*@param I2CMaster_Prescale 预分频值以设置主机通信速度。
*主频率= 60000/[(预分频+1)*25] MHz
*@返回无
秘书长的报告 /
空 I2CMaster_Init (UINT16 I2CMaster_SlaveAddress、UINT16 I2CMaster_Prescale)

//设置 I2C 中断和 CPU 定时器0中断
EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
PieVectTable.I2CINT1A =&i2c_master_int1a_ISR;
PieVectTable.TINT0 =&CPU_timer0_ISR;
EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的
//在 PIE:组8中断1中启用 I2C 中断1
PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
//在 PIE 中启用 TINT0:组1中断7
PieCtrlRegs.PIEIER1.bit.INTx7=1;
//启用连接到 PIE 组8的 CPU INT8
IER |= M_INT8;
//启用连接到 CPU 定时器0的 CPU INT1
IER |= M_INT1;

InitI2CGpio();
InitCpuTimer();

ConfigCpuTimer (&CpuTimer0、60、35000);//CPU Timer 0在35ms 后中断(在60MHz CPU 频率下)

//初始化 I2C
I2caRegs.I2CSAR = I2CMaster_SlaveAddress;//从地址。
I2caRegs.I2COAR = 0x002D;//作为主器件的地址。
I2caRegs.I2CPSC.all = I2CMaster_Prescale;//预分频器-模块时需要7-12MHz
I2caRegs.I2CCLKL = 10;//注意:必须为非零
I2caRegs.I2CCLKH = 5;//注意:必须为非零
I2caRegs.I2CIER.ALL = 0x2C;//启用 SCD 和 ARDY 中断

I2caRegs.I2CMDR.bit.IRS = 1;//使 I2C 退出复位
//挂起时停止 I2C

I2caRegs.I2CFFTX.ALL = 0x6000;//启用 FIFO 模式和 TXFIFO

返回;

/ //**
*@brief 在主机模式下执行发送和接收事务
*@param I2CMaster_ByteCountTx 要发送的字节数。
*@param * I2CMaster_TxArray 指向要发送的数据的指针。
*@param I2CMaster_ByteCountRx 要接收的字节数。
*@param * I2CMaster_RxArray 指向结构体的指针、用于存储接收到的数据。
*@返回无
秘书长的报告 /
空 I2CMaster_transmit (UINT16 I2CMaster_ByteCountTx、unsigned char * I2CMaster_TxArray、UINT16 I2CMaster_ByteCountRx、unsigned char * I2CMaster_RxArray)

/********* 写入'****** /
if (I2CMaster_ByteCountTx!= 0)

I2CMaster_TransmitField = I2CMaster_TxArray;

I2caRegs.I2CCNT = I2CMaster_ByteCountTx;
while (I2CMaster_ByteCountTx > 0)//检查是否仍有字节要发送

I2caRegs.I2CDXR =* I2CMaster_TransmitField;
I2CMaster_TransmitField++;
I2CMaster_ByteCountTx--;

I2caRegs.I2CMDR.ALL = 0x2E20;//设置控制寄存器:
//位14空闲= 1.
//位13 STT = 1 (启动条件)

//位11 STP=1 (之后的停止条件
//传输字节。)
//位10 MST = 1主器件
//位9 TRX = 1发送

//位5 IRS = 1复位 I2C 总线。

StartCpuTimer0();//启动计时器
I2CMaster_WAIT ();//等待 I2C 总线清零
StopCpuTimer0();//无超时,因此停止计时器
ReloadCpuTimer0 ();//重新加载周期值(35ms 超时)

/********* 阅读*** /
if (I2CMaster_ByteCountRx!= 0)

I2CMaster_ReceiveField = I2CMaster_RxArray;

I2caRegs.I2CCNT = I2CMaster_ByteCountRx;
I2caRegs.I2CMDR.ALL = 0x2C20;//发送"重复"从读取开始(TRX 关闭)
//和 Stop。

StartCpuTimer0();//启动计时器

I2CMaster_WAIT ();//等待 I2C 总线清零

/ //**
*@短暂等待前一个 I2C 事务清零。
*@param 无
*@返回无
秘书长的报告 /
空 I2CMaster_Wait (空)

//等待直到 STP 位从任何先前的主设备通信中清零。
//模块清除该位的操作被延迟到 SCD 位之后
//设置。 如果在启动新消息之前未选中此位
// I2C 可能会被混淆。

while (I2caRegs.I2CMDR.bit.STP = 1);//等待停止条件位为零。

while (I2caRegs.I2CSTR.bit.BB = 1);//等待总线忙为零。

/ //**
*@简要检查 I2C 线路上是否存在从器件并可正常工作。
*@param I2CMaster_SlaveAddress 是我们要检查的从器件。
*@返回从器件存在(如果存在则为1、否则为0)
秘书长的报告 /
unsigned char I2CMaster_SlavePresent (unsigned char I2CMaster_SlaveAddress)

unsigned char ACKStatus;
I2caRegs.I2CSAR = I2CMaster_SlaveAddress;
I2caRegs.I2CCNT = 0x01;//准备发送虚拟字节
I2caRegs.I2CDXR = 0x00;//待写入的虚拟字节
I2caRegs.I2CMDR.ALL = 0x2E20;// I2C TX、启动条件
while (I2caRegs.I2CMDR.bit.STP = 1);//等待 STOP 条件

ACKStatus =!I2cRegs.I2CSTR.bit.nack;
返回 ACKStatus;//返回是否
//发生 NACK

/ //**
*@简要了解 I2C 主设备是否已准备好进行通信。
*@param 无
*@返回 BUSY 位(BUSY = 1、Free = 0)
秘书长的报告 /
unsigned char I2CMaster_NotReady()

返回 I2caRegs.I2CSTR.bit.BB;

/ //**
*@brief 处理 I2C 中断。
*@param 无
*@返回无
秘书长的报告 /
中断 void i2c_master_int1a_ISR (void)// I2C-A

UINT16 I2CMaster_IntSource;

//读取中断源
I2CMaster_IntSource = I2caRegs.I2CISRC.bit.INTCODE & 0x7;

开关(I2CMaster_IntSource)

案例 I2C_NO_ISRC://=0
中断;

案例 I2C_ARB_ISRC://=1
中断;

案例 I2C_Nack_ISRC://=2
中断;

案例 I2C_ARDY_ISRC://=3
中断;

案例 I2C_RX_ISRC://=4
StopCpuTimer0();//无超时,因此停止计时器
ReloadCpuTimer0 ();//重新加载周期值(35ms 超时)
*I2CMaster_ReceiveField = I2caRegs.I2CDRR;
I2CMaster_ReceiveField++;
中断;

案例 I2C_TX_ISRC://=5
中断;

案例 I2C_SCD_ISRC://=6
中断;

案例 I2C_AAS_ISRC://=7
中断;

默认值:
asm (" ESTOP0");//在无效数字上停止。

//启用未来的 I2C (PIE 组8)中断
PieCtrlRegs.PIEACX.ALL = PIEACK_group8;

/ //**
*@简要处理超时。 如果时钟保持低电平> 35mS 则触发。
*@param 无
*@返回无
秘书长的报告 /
中断空 CPU_timer0_ISR (空)

//超时。 复位模块。
I2caRegs.I2CMDR.bit.IRS = 0;//复位
//确认此中断以从组1接收更多中断
PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;

/ //**
*@简要将 C2000器件配置为 PMBus 主器件
*@param PMBusMaster_SlaveAddress 从属器件的地址
*@param PMBusMaster_Prescale 预分频值以设置主通信速度。
*主频率= 60000/[(预分频+1)*25] MHz
*@返回无
秘书长的报告 /
void PMBusMaster_Init (unsigned char PMBusMaster_SlaveAddress、unsigned char PMBusMaster_Prescale)

//您可能必须更改这些值“更改用于警报和控制线路的 GPIO 以匹配应用所需的 GPIO”。

//控制线功能 GPIO0
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;//启用 GPIO0上的上拉
GpioDataRegs.GPASET.bit.GPIO0 = 1;//驱动线路高电平
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;//GPIO0 = GPIO0
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1;//GPIO0 =输出

// SMBus 警报功能(GPIO2 =警报线路)
GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0;//启用 GPIO2上的上拉
GpioDataRegs.GPASET.bit.GPIO2 = 1;//驱动线路高电平
GpioCtrlRegs.GPAQSEL1.bit.GPIO2 = 0;//同步到 SYSCLKOUT
GpioCtrlRegs.GPACTRL.bit.QUALPRD0 = 0;//无限定(同步到 SYSCLKOUT)
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;//GPIO2 = GPIO2
GpioCtrlRegs.GPADIR.bit.GPIO2 = 0;//GPIO2 =输入

//警报线路触发的设置中断
EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
PieVectTable.XINT1 =&XINT1_ISR;
EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的
GpioIntRegs.GPIOXINT1SEL.ALL = 2;//使 GPIO2输入源用于 XINT1
XIntertRegs.XINT1CR.BIT.POLARITY = 2;//XINT1由下降边沿触发(高电平到低电平转换)

Slave_address = PMBusMaster_SlaveAddress;
I2CMaster_Init (PMBusMaster_SlaveAddress、PMBusMaster_Prescale);//初始化 USCI 模块
while (!I2CMaster_SlavePresent (slave_address));//检查从设备是否存在

//启用警报线路中断
XIntertRegs.XINT1CR.bit.ENABLE = 1;//启用 XINT1中断
//在 PIE 中启用 XINT1中断:组1中断4
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;
//启用连接到 PIE 组1的 CPU INT1
IER |= M_INT1;

while (I2CMaster_NotReady());//总线是否空闲?

/ //**
*@简要执行 PMBus 处理作为主设备。
*@param PMBusMaster_CommandByte PMBus 命令索引。
*@param PMBusMaster_RWFlag 读取/写入标志(R = 1、W = 0)
*@param PMBusMaster_Message 要写入的消息(如果有)。
*@param * PMBusMaster_ReceivedValue 指针到结构体以存储接收到的数据。
*@返回成功/失败(成功= 1、失败= 0)
秘书长的报告 /
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 变量-您可以从 PMBus.h 修改它
unsigned 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;//第一个 CRC 字节=从器件地址...
#endif

PMBusMaster_Index = PMBusMaster_CommandByte;//将 PMBus 命令字节存储为...
PMBusMaster_TransmitBuffer[0]= PMBus_Commands[PMBusMaster_Index];//……Tx 缓冲器中的第一个字节
PMBusMaster_Temp = PMBusMaster_Message;

PMBusMaster_TransmitBuffer[1]= PMBusMaster_Message & 0x00FF;//存储消息的低字节
PMBusMaster_Temp =(PMBusMaster_Message)>> 8;
PMBusMaster_TransmitBuffer[2]= PMBusMaster_Temp;//存储较高的消息字节

if (PMBusMaster_Index > 0 && PMBusMaster_Index < 13)//从从器件读取字节
PMBusMaster_CommandGroup = READBYTE;
if (PMBusMaster_Index > 12 && PMBusMaster_Index < 40)//从从器件读取字
PMBusMaster_CommandGroup =自述;
if (PMBusMaster_Index > 39 && PMBusMaster_Index < 44)//向从器件写入字节
PMBusMaster_CommandGroup = WRITEBYTE;
if (PMBusMaster_Index > 43 && PMBusMaster_Index < 49)//向从器件发送字节
PMBusMaster_CommandGroup = SENDBYTE;
/*读取或写入一个字节的数据。 R/W 打印机 根据 RWFlag *****决定 /
if (PMBusMaster_Index > 48 && PMBusMaster_Index < 69)

if (PMBusMaster_RWFlag = 0)//写入字节
PMBusMaster_CommandGroup = WRITEBYTE;
else //读取字节
PMBusMaster_CommandGroup = READBYTE;

/*读取或写入一个数据字。 R/W 打印机 根据 RWFlag *****决定 /
if (PMBusMaster_Index > 68 && PMBusMaster_Index < 120)// R/W 字

if (PMBusMaster_RWFlag = 0)//写入字(新命令组)
PMBusMaster_CommandGroup = WRITEWORD;
否则//读取字
PMBusMaster_CommandGroup =自述;

if (PMBusMaster_Index >= 120)
while (1);//非法索引-无效的命令陷阱

开关(PMBusMaster_CommandGroup)

#if!PEC
case READBYTE://读取字节
PMBusMaster_RxCount = 1;
while (I2CMaster_NotReady());
I2CMaster_transmit (1、PMBusMaster_TransmitBuffer、1、PMBusMaster_ReceiveBuffer);
中断;

case READWORD://读取字
PMBusMaster_RxCount = 2;
while (I2CMaster_NotReady());
I2CMaster_transmit (1、PMBusMaster_TransmitBuffer、2、PMBusMaster_ReceiveBuffer);
中断;

案例 WRITEBYTE://写入字节
while (I2CMaster_NotReady());
I2CMaster_transmit (2、PMBusMaster_TransmitBuffer、0、0);
中断;
Case SENDBYTE://发送字节
while (I2CMaster_NotReady());
I2CMaster_transmit (1、PMBusMaster_TransmitBuffer、0、0);
中断;
案例 WRITEWORD://写入字
while (I2CMaster_NotReady());
I2CMaster_transmit (3、PMBusMaster_TransmitBuffer、0、0);
中断;
其他
case READBYTE://读取字节
PMBusMaster_RxCount = 1;
while (I2CMaster_NotReady());
I2CMaster_transmit (1、PMBusMaster_TransmitBuffer、2、PMBusMaster_ReceiveBuffer);

/*为 CRC 校验汇编位流*/
PMBusMaster_CrcMsg[1]= PMBusMaster_TransmitBuffer[0];//存储第一个 TX 字节
PMBusMaster_CrcMsg[2]=(slave_address << 1)+ 1;//存储从器件地址+ R/W=1
PMBusMaster_CrcMsg[3]= PMBusMaster_ReceiveBuffer[0];//存储 Rx 字节1
PMBusMaster_CrcSlaveGenerated = PMBusMaster_ReceiveBuffer[1];//存储从器件的 PEC 字节
PMBusMaster_CrcMsgSize = 4;//字节数

/* CRC 函数调用,生成 CRC 字节与从器件 CRC*/进行比较
PMBusMaster_CrcMasterGenerated = PMBusMaster_Crc8MakeBitwise (CRC8_INIT_REM、CRC8_Poly、PMBusMaster_CrcMsg、PMBusMaster_CrcMsgSize);
if (PMBusMaster_CrcMasterGenerated => PMBusMaster_CrcSlaveGenerated)//比较 PEC 字节
PMBusMaster_result = PEC_PASS;// PEC 字节已验证
其他
PMBusMaster_result = PEC_FAIL;// PEC 测试失败
中断;

case READWORD://读取字
PMBusMaster_RxCount = 2;
while (I2CMaster_NotReady());
I2CMaster_transmit (1、PMBusMaster_TransmitBuffer、3、PMBusMaster_ReceiveBuffer);

/*为 CRC 校验汇编位流*/
PMBusMaster_CrcMsg[1]= PMBusMaster_TransmitBuffer[0];
PMBusMaster_CrcMsg[2]=(slave_address << 1)+ 1;//存储从器件地址+ R/W=1
PMBusMaster_CrcMsg[3]= PMBusMaster_ReceiveBuffer[0];
PMBusMaster_CrcMsg[4]= PMBusMaster_ReceiveBuffer[1];
PMBusMaster_CrcSlaveGenerated = PMBusMaster_ReceiveBuffer[2];//存储从器件的 PEC 字节
PMBusMaster_CrcMsgSize = 5;

/* CRC 函数调用,生成 CRC 字节与从器件 CRC*/进行比较
PMBusMaster_CrcMasterGenerated = PMBusMaster_Crc8MakeBitwise (CRC8_INIT_REM、CRC8_Poly、PMBusMaster_CrcMsg、PMBusMaster_CrcMsgSize);
IF (PMBusMaster_CrcMasterGenerated => PMBusMaster_CrcSlaveGenerated)
PMBusMaster_result = PEC_PASS;
其他
PMBusMaster_Result = PEC_FAIL;
中断;

案例 WRITEBYTE://写入字节
/* CRC 函数调用,生成 CRC 字节以发送到从属设备*/
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);

//检查从器件是否验证了 PEC 字节
if (ALERT ==0)
PMBusMaster_result = PEC_PASS;
其他
PMBusMaster_Result = PEC_FAIL;
中断;

Case SENDBYTE://发送字节
/* CRC 函数调用,生成 CRC 字节以发送到从属设备*/
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);

//检查从器件是否验证了 PEC 字节
if (ALERT ==0)
PMBusMaster_result = PEC_PASS;
其他
PMBusMaster_Result = PEC_FAIL;
中断;

案例 WRITEWORD://写入字
/* CRC 函数调用,生成 CRC 字节以发送到从属设备*/
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);

//检查从器件是否验证了 PEC 字节
if (ALERT ==0)
PMBusMaster_result = PEC_PASS;
其他
PMBusMaster_Result = PEC_FAIL;
中断;
#endif

默认值:
中断;

if (PMBusMaster_ReceivedValue!=0)

*PMBusMaster_ReceivedValue++= PMBusMaster_ReceiveBuffer[0];
IF (PMBusMaster_RxCount > 1)
*PMBusMaster_ReceivedValue = PMBusMaster_ReceiveBuffer[1];

#IF PEC
返回 PMBusMaster_Result;//执行 PEC 后、返回数据包错误检查的结果(0 =失败、1 =成功)
其他
返回1;//未实现 PEC 时,返回1以完成通信
#endif

#IF PEC
/ //**
*@简要计算数据包错误校验字节。
*@param PMBusMaster_CRC 初始值。
*@param PMBusMaster_Poly 要用于计算的多项式。
*@param * PMBusMaster_PMsg 指针指向 PMBus 事务中的字节。
*@param PMBusMaster_MsgSize 最后一个事务中的字节数。
*@返回 PEC 字节。
秘书长的报告 /
静态无符号字符 PMBusMaster_Crc8MakeBitwise (无符号字符 PMBusMaster_CRC、无符号字符 PMBusMaster_Poly、无符号字符* PMBusMaster_Pmsg、无符号 int PMBusMaster_MsgSize)

unsigned int i、j、carry;
unsigned char msg;

PMBusMaster_CRC =* PMBusMaster_Pmsg++;//第一个字节加载到"CRC"中
for (i = 0;i < PMBusMaster_MsgSize-1;I ++)

MSG =* PMBusMaster_Pmsg++;//在"msg"中加载的下一个字节

for (j = 0;j < 8;j++)

进位= PMBusMaster_CRC 和0x80;//检查 MSB=1
PMBusMaster_CRC =(PMBusMaster_CRC << 1)|(msg >> 7);//将下一个字节的1位移入 CRC
if (carry) PMBusMaster_CRC ^= PMBusMaster_Poly;//如果 MSB = 1、执行 XOR
MSG <= 1;//将左侧 MSG 字节移1
MSG &= 0x00FF;


//前一个循环计算输入位流的 CRC。 为此、
//填充8个尾随零,结果值的 CRC 为
//已计算。 这给出了输入位流的最终 CRC。
for (j = 0;j < 8;j++)

进位= PMBusMaster_CRC 和0x80;
PMBusMaster_CRC <<= 1;
if (进位) PMBusMaster_CRC ^= PMBusMaster_Poly;

PMBusMaster_CRC &= 0x00FF;//我们只需要一个字节(较低)

返回(PMBusMaster_CRC);

#endif

/ //**
*@brief 处理警报线路中断。
*用户应修改代码以实现应用程序适用的故障处理
*@param 无
*@返回无
秘书长的报告 /

中断空 XINT1_ISR (空)

//警告“用户应更改 ISR 以实现应用程序适用的故障处理。”
警报= 1;//收到警报
XIntrauptRegs.XINT1CR.bit.ENABLE = 0;//禁用 XINT1中断
while (1);//Trap for fault。 用户可以根据其应用程序添加代码来处理故障

非常感谢您的任何帮助或意见!

谢谢

穆罕默德

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    [引用用户="Mohamed Ahmed3"]

    unsigned char I2CMaster_SlavePresent (unsigned char I2CMaster_SlaveAddress)

    unsigned char ACKStatus;
    I2caRegs.I2CSAR = I2CMaster_SlaveAddress;
    I2caRegs.I2CCNT = 0x01;//准备发送虚拟字节
    I2caRegs.I2CDXR = 0x00;//待写入的虚拟字节
    I2caRegs.I2CMDR.ALL = 0x2E20;// I2C TX、启动条件
    while (I2caRegs.I2CMDR.bit.STP = 1);//等待 STOP 条件

    ACKStatus =!I2cRegs.I2CSTR.bit.nack;
    返回 ACKStatus;//返回是否
    //发生 NACK

    [/报价]

    看起来它在等待从器件响应的 while 环路中发生故障。 上面的函数将在线路上推送从器件地址和虚拟字节(基本上是 一个发送字节命令、以0x0作为数据)并等待 ACK。 您是否能够观察线路并观察从端的任何活动?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您回复 Vishal;这是正确的、正是原因。 我将虚拟字节更改为0x13、这是一个可被从器件理解的命令。 确认位通过新的虚拟字节设置为1。 响应是0xFF、这不是从器件的预期值、因为默认情况下、第二个字节应为零"0x0F"。 我仍然不确定是主设备问题还是从设备问题。
    此致、
    穆罕默德