Tool/software: TI C/C++ Compiler
Hi all,
I am new to using TI microcontrollers and code composer studio, I have usually used MATLAB and it can be fairly acceptable. However, I am implementing a PMBUs over I2C following the document "Software Implementation of PMBus Over I2C for TMS320F2803x" and the sample files available through and the TI website. I combined all the files in one main.c file to make my life easier.
Now I am making sure that the code works without errors, so I am not initiating any communication, I am only initializing peripherals and just making sure the code does something. I increment the value of a variable called "MyVariable" every one second.
Below is my code, from the debugger window, I can easily see that the variable "MyVariable" gets stuck at 5, the system spends forever at step 3 PMBusMaster_Init(I2C_SLAVE_ADDR, CLK_PRESCALE);
And the while loop is never implemented. Checking on the registers for I2C, the slave never acknowledges anything. However, the address of the slave device is correct, It acknowledges trash commands from MATLAB, and it also follows the PMBus specifications for a smart battery charger.
//---------------------------------------------------------------------------
#include "DSP2803x_Device.h" // DSP280x Headerfile Include File
#include "DSP2803x_Examples.h" // DSP280x Examples Include File
#include "DSP2803x_I2C_defines.h"
#include "PMBUS.h"
//the user should change these values to match those required for their application
#define I2C_SLAVE_ADDR 9 //the device address of the slave
#define CLK_PRESCALE 39 //the prescale value for the I2C master frequency (I need a frequency in the range 10K - 100K) - 39 gives me 60kHz
//master frequency = 60000/[(prescale+1)*25] kHz
/*Include the I2CMaster headers */
void 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();
interrupt void i2c_master_int1a_isr(void);
interrupt void cpu_timer0_isr(void);
/*I2CMaster Variables */
static unsigned char *I2CMaster_ReceiveField;
static unsigned char *I2CMaster_TransmitField;
/*Include the PmBusMaster headers */
/*------------------------------------------------------------------------------
This function is used to implement PMBus functionality without PEC
------------------------------------------------------------------------------*/
unsigned char PMBusMaster(unsigned char PMBusMaster_CommandByte, unsigned char PMBusMaster_RWFlag,unsigned int PMBusMaster_Message,unsigned char *PMBusMaster_ReceivedValue);
/*------------------------------------------------------------------------------
This function is used to initialize PMBus master device
------------------------------------------------------------------------------*/
void PMBusMaster_Init(unsigned char PMBusMaster_SlaveAddress, unsigned char PMBusMaster_Prescale);
static unsigned char PMBusMaster_Crc8MakeBitwise(unsigned char PMBusMaster_CRC, unsigned char PMBusMaster_Poly, unsigned char *PMBusMaster_Pmsg, unsigned int PMBusMaster_MsgSize);
/*PMBUS Variables */
/* This is the PMBus command look-up table. Do not modify---------------------*/
const unsigned char PMBus_Commands[120] =
{
0x00, // dummy byte
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,0x44,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
};
static unsigned char slave_address;
unsigned char alert = 0;
// Note: I2C Macros used in this example can be found in the
// DSP280x_I2C_defines.h file
// Prototype statements for functions found within this file.
void MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr);
unsigned char Temp[1] = {0};
unsigned char Oprn[1] = {0};
unsigned char 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)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP280x_SysCtrl.c file.
InitSysCtrl();
// Copy time critical code and Flash setup code to RAM
// The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart
// symbols are created by the linker. Refer to the linker files.
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
// Step 2. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP280x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP280x_DefaultIsr.c.
// This function is found in DSP280x_PieVect.c.
InitPieVectTable();
// Step 3. Initialize the Device Peripherals:
MyVariable=5;
PMBusMaster_Init(I2C_SLAVE_ADDR, CLK_PRESCALE);
MyVariable=0;
EINT;
// Application loop
while(1)
{
MyVariable++;
DELAY_US(1000000);// Wait for one second before doing anything
//reads
//pass_fail = PMBusMaster(STATUS_TEMPERATURE, 1, 0, Temp); //read byte
//pass_fail = PMBusMaster(OPERATION, 1, 0, Oprn); //r/w byte (read)
//pass_fail = PMBusMaster(STATUS_WORD, 1, 0, Stat); //read word
//pass_fail = PMBusMaster(VOUT_COMMAND, 1, 0, VCmd); //r/w word (read)
//writes
//pass_fail = PMBusMaster(STORE_DEFAULT_CODE, 0, 0xAA, 0); //write byte
//pass_fail = PMBusMaster(OPERATION, 0, 0xBB, 0); //r/w byte (write)
//pass_fail = PMBusMaster(VOUT_COMMAND, 0, 0xCCDD, 0); //r/w word (write)
//Status = (Stat[1] << 8) | Stat[0]; //unpacking the two data bytes into one word
//Vout_Command = (VCmd[1] << 8) | VCmd[0]; //the lowest order byte is received first
}
} // end of main
/***
// This function will copy the specified memory contents from
// one location to another.
//
// Uint16 *SourceAddr Pointer to the first word to be moved
// SourceAddr < SourceEndAddr
// Uint16* SourceEndAddr Pointer to the last word to be moved
// Uint16* DestAddr Pointer to the first destination word
//
// No checks are made for invalid memory locations or that the
// end address is > then the first start address.
**/
void MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr)
{
while(SourceAddr < SourceEndAddr)
{
*DestAddr++ = *SourceAddr++;
}
return;
}
/***************************************************************************//**
* @brief Initialize I2C module in master mode
* @param I2CMaster_SlaveAddress The address of the slave device
* @param I2CMaster_Prescale The prescale value to set master communication speed.
* Master frequency = 60000/[(prescale+1)*25] MHz
* @return None
******************************************************************************/
void I2CMaster_Init(Uint16 I2CMaster_SlaveAddress, Uint16 I2CMaster_Prescale)
{
//Setup I2C interrupts and Cpu Timer 0 interrupt
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.I2CINT1A = &i2c_master_int1a_isr;
PieVectTable.TINT0 = &cpu_timer0_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
// Enable TINT0 in the PIE: Group 1 interrupt 7
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// Enable CPU INT8 which is connected to PIE group 8
IER |= M_INT8;
// Enable CPU int1 which is connected to CPU-Timer 0
IER |= M_INT1;
InitI2CGpio();
InitCpuTimers();
ConfigCpuTimer(&CpuTimer0, 60, 35000); //CPU Timer 0 interrupt after 35 ms (at 60MHz CPU freq.)
// Initialize I2C
I2caRegs.I2CSAR = I2CMaster_SlaveAddress; // Slave Address.
I2caRegs.I2COAR = 0x002D; // address as Master.
I2caRegs.I2CPSC.all = I2CMaster_Prescale; // Prescaler - need 7-12 Mhz on module clk
I2caRegs.I2CCLKL = 10; // NOTE: must be non zero
I2caRegs.I2CCLKH = 5; // NOTE: must be non zero
I2caRegs.I2CIER.all = 0x2C; // Enable SCD & ARDY interrupts
I2caRegs.I2CMDR.bit.IRS = 1; // Take I2C out of reset
// Stop I2C when suspended
I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO
return;
}
/***************************************************************************//**
* @brief Performs transmit and receive transactions in master mode
* @param I2CMaster_ByteCountTx The number of bytes to transmit.
* @param *I2CMaster_TxArray Pointer to the data to transmit.
* @param I2CMaster_ByteCountRx The number of bytes to receive.
* @param *I2CMaster_RxArray Pointer to structure to store received data.
* @return None
******************************************************************************/
void I2CMaster_Transmit(Uint16 I2CMaster_ByteCountTx, unsigned char *I2CMaster_TxArray, Uint16 I2CMaster_ByteCountRx, unsigned char *I2CMaster_RxArray)
{
/***************Write******************/
if(I2CMaster_ByteCountTx != 0)
{
I2CMaster_TransmitField = I2CMaster_TxArray;
I2caRegs.I2CCNT = I2CMaster_ByteCountTx;
while(I2CMaster_ByteCountTx > 0) //check that there are still bytes to send
{
I2caRegs.I2CDXR = *I2CMaster_TransmitField;
I2CMaster_TransmitField++;
I2CMaster_ByteCountTx--;
}
I2caRegs.I2CMDR.all = 0x2E20; // Set up the control register:
// bit 14 FREE = 1
// bit 13 STT = 1 (Start condition)
// bit 11 STP = 1 (Stop condition after
// transfer of bytes.)
// bit 10 MST = 1 Master
// bit 9 TRX = 1 Transmit
// bit 5 IRS = 1 to Reset I2C bus.
StartCpuTimer0(); // Start the timer
I2CMaster_Wait(); // Wait for I2C bus to clear
StopCpuTimer0(); //No timeout, so stop the timer
ReloadCpuTimer0(); //Reload the period value (35 ms timeout)
}
/****************Read*******************/
if(I2CMaster_ByteCountRx != 0)
{
I2CMaster_ReceiveField = I2CMaster_RxArray;
I2caRegs.I2CCNT = I2CMaster_ByteCountRx;
I2caRegs.I2CMDR.all = 0x2C20; // Send "repeated" Start with Read (TRX off)
// and Stop.
StartCpuTimer0(); // Start the timer
I2CMaster_Wait(); // Wait for I2C bus to clear
}
}
/***************************************************************************//**
* @brief Wait for previous I2C transaction to clear.
* @param None
* @return None
******************************************************************************/
void I2CMaster_Wait(void)
{
// Wait until the STP bit is cleared from any previous master communication.
// Clearing of this bit by the module is delayed until after the SCD bit is
// set. If this bit is not checked prior to initiating a new message, the
// I2C could get confused.
while (I2caRegs.I2CMDR.bit.STP == 1); // Wait for Stop condition bit to be zero.
while (I2caRegs.I2CSTR.bit.BB == 1); // Wait for Bus Busy to be zero.
}
/***************************************************************************//**
* @brief Checks if a slave is present and operational on the I2C lines.
* @param I2CMaster_SlaveAddress The slave we are checking.
* @return Slave presence (1 if present, 0 if not)
******************************************************************************/
unsigned char I2CMaster_SlavePresent(unsigned char I2CMaster_SlaveAddress)
{
unsigned char ACKStatus;
I2caRegs.I2CSAR = I2CMaster_SlaveAddress;
I2caRegs.I2CCNT = 0x01; //prepare to send a dummy byte
I2caRegs.I2CDXR = 0x00; //dummy byte to be written
I2caRegs.I2CMDR.all = 0x2E20; // I2C TX, start condition
while (I2caRegs.I2CMDR.bit.STP == 1); // wait for STOP condition
ACKStatus = !I2caRegs.I2CSTR.bit.NACK;
return ACKStatus; // return whether or not
// a NACK occured
}
/***************************************************************************//**
* @brief See if the I2C master is ready to communicate.
* @param None
* @return Busy Bit (Busy = 1, Free = 0)
******************************************************************************/
unsigned char I2CMaster_NotReady()
{
return I2caRegs.I2CSTR.bit.BB;
}
/***************************************************************************//**
* @brief Handles I2C interrupts.
* @param None
* @return None
******************************************************************************/
interrupt void i2c_master_int1a_isr(void) // I2C-A
{
Uint16 I2CMaster_IntSource;
// Read interrupt source
I2CMaster_IntSource = I2caRegs.I2CISRC.bit.INTCODE & 0x7;
switch(I2CMaster_IntSource)
{
case I2C_NO_ISRC: // =0
break;
case I2C_ARB_ISRC: // =1
break;
case I2C_NACK_ISRC: // =2
break;
case I2C_ARDY_ISRC: // =3
break;
case I2C_RX_ISRC: // =4
StopCpuTimer0(); //No timeout, so stop the timer
ReloadCpuTimer0(); //Reload the period value (35 ms timeout)
*I2CMaster_ReceiveField = I2caRegs.I2CDRR;
I2CMaster_ReceiveField++;
break;
case I2C_TX_ISRC: // =5
break;
case I2C_SCD_ISRC: // =6
break;
case I2C_AAS_ISRC: // =7
break;
default:
asm(" ESTOP0"); // Halt on invalid number.
}
// Enable future I2C (PIE Group 8) interrupts
PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
}
/***************************************************************************//**
* @brief Handles timeouts. Triggered if clock held low > 35ms.
* @param None
* @return None
******************************************************************************/
interrupt void cpu_timer0_isr(void)
{
// Timed out. Reset module.
I2caRegs.I2CMDR.bit.IRS = 0; //reset
// Acknowledge this interrupt to receive more interrupts from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
/***************************************************************************//**
* @brief Configure the C2000 device as a PMBus master
* @param PMBusMaster_SlaveAddress The address of the slave device
* @param PMBusMaster_Prescale The prescale value to set master communication speed.
* Master frequency = 60000/[(prescale+1)*25] MHz
* @return None
******************************************************************************/
void PMBusMaster_Init(unsigned char PMBusMaster_SlaveAddress, unsigned char PMBusMaster_Prescale)
{
// You may have to change these values "Change the GPIOs used for Alert and Control lines to match the desired GPIOs for the application."
// Control Line functionality GPIO0
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; //Enable pullup on GPIO0
GpioDataRegs.GPASET.bit.GPIO0 = 1; //Drive line high
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0; //GPIO0 = GPIO0
GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; //GPIO0 = output
// SMBUS Alert functionality (GPIO2 = Alert line)
GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0; //Enable pullup on GPIO2
GpioDataRegs.GPASET.bit.GPIO2 = 1; //Drive line high
GpioCtrlRegs.GPAQSEL1.bit.GPIO2 = 0; //SYNC to SYSCLKOUT
GpioCtrlRegs.GPACTRL.bit.QUALPRD0 = 0; //no qualification (SYNC to SYSCLKOUT)
GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0; //GPIO2 = GPIO2
GpioCtrlRegs.GPADIR.bit.GPIO2 = 0; //GPIO2 = input
//setup interrupt triggered by Alert line
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.XINT1 = &xint1_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
GpioIntRegs.GPIOXINT1SEL.all = 2; //Make GPIO2 input source for XINT1
XIntruptRegs.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 module
while(!I2CMaster_SlavePresent(slave_address)); //check if slave device present
// Enable Alert line interrupt
XIntruptRegs.XINT1CR.bit.ENABLE = 1; //Enable XINT1 interrupt
// Enable XINT1 interrupt in the PIE: Group 1 interrupt 4
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;
// Enable CPU INT1 which is connected to PIE group 1
IER |= M_INT1;
while (I2CMaster_NotReady()); // Is the bus free?
}
/***************************************************************************//**
* @brief Perform a PMBus transaction as a master.
* @param PMBusMaster_CommandByte PMBus command index.
* @param PMBusMaster_RWFlag The Read/Write flag (R = 1, W = 0)
* @param PMBusMaster_Message The message to write, if any.
* @param *PMBusMaster_ReceivedValue Pointer to structure to store received data.
* @return Success/Failure (Success = 1, Failure = 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 variables - You can modify it from 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; // 1st CRC byte = slave address...
#endif
PMBusMaster_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 message
PMBusMaster_Temp = (PMBusMaster_Message) >> 8;
PMBusMaster_TransmitBuffer[2] = PMBusMaster_Temp; // store higher byte of message
if(PMBusMaster_Index > 0 && PMBusMaster_Index < 13) //read byte from slave device
PMBusMaster_CommandGroup = READBYTE;
if(PMBusMaster_Index > 12 && PMBusMaster_Index < 40) // read word from slave device
PMBusMaster_CommandGroup = READWORD;
if(PMBusMaster_Index > 39 && PMBusMaster_Index < 44) // write byte to slave device
PMBusMaster_CommandGroup = WRITEBYTE;
if(PMBusMaster_Index > 43 && PMBusMaster_Index < 49) // send byte to slave device
PMBusMaster_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 byte
PMBusMaster_CommandGroup = WRITEBYTE;
else // read byte
PMBusMaster_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 word
PMBusMaster_CommandGroup = READWORD;
}
if(PMBusMaster_Index >= 120)
while(1); //illegal index - invalid command trap
switch(PMBusMaster_CommandGroup)
{
#if !PEC
case READBYTE: // read byte
PMBusMaster_RxCount = 1;
while (I2CMaster_NotReady());
I2CMaster_Transmit(1,PMBusMaster_TransmitBuffer,1,PMBusMaster_ReceiveBuffer);
break;
case READWORD: // read word
PMBusMaster_RxCount = 2;
while (I2CMaster_NotReady());
I2CMaster_Transmit(1,PMBusMaster_TransmitBuffer,2,PMBusMaster_ReceiveBuffer);
break;
case WRITEBYTE: // write byte
while (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 word
while (I2CMaster_NotReady());
I2CMaster_Transmit(3,PMBusMaster_TransmitBuffer,0,0);
break;
#else
case READBYTE: // read byte
PMBusMaster_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 byte
PMBusMaster_CrcMsg[2] = (slave_address << 1) + 1; // store slave addres + R/W=1
PMBusMaster_CrcMsg[3] = PMBusMaster_ReceiveBuffer[0]; // store rx byte 1
PMBusMaster_CrcSlaveGenerated = PMBusMaster_ReceiveBuffer[1]; //store PEC byte from slave
PMBusMaster_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 bytes
PMBusMaster_Result = PEC_PASS; // PEC byte was validated
else
PMBusMaster_Result = PEC_FAIL; // failed PEC test
break;
case READWORD: // read word
PMBusMaster_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=1
PMBusMaster_CrcMsg[3] = PMBusMaster_ReceiveBuffer[0];
PMBusMaster_CrcMsg[4] = PMBusMaster_ReceiveBuffer[1];
PMBusMaster_CrcSlaveGenerated = PMBusMaster_ReceiveBuffer[2]; //store PEC byte from slave
PMBusMaster_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;
else
PMBusMaster_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 byte
if(alert == 0)
PMBusMaster_Result = PEC_PASS;
else
PMBusMaster_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 byte
if(alert == 0)
PMBusMaster_Result = PEC_PASS;
else
PMBusMaster_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 byte
if(alert == 0)
PMBusMaster_Result = PEC_PASS;
else
PMBusMaster_Result = PEC_FAIL;
break;
#endif
default:
break;
}
if (PMBusMaster_ReceivedValue !=0)
{
*PMBusMaster_ReceivedValue++ = PMBusMaster_ReceiveBuffer[0];
if (PMBusMaster_RxCount > 1)
*PMBusMaster_ReceivedValue = PMBusMaster_ReceiveBuffer[1];
}
#if PEC
return PMBusMaster_Result; //When PEC is implemented, return the result of the packet error checking (0 = failure, 1 = success)
#else
return 1; //When PEC is not implemented, return a 1 for completed communication
#endif
}
#if PEC
/***************************************************************************//**
* @brief Calculate the Packet Error Checking byte.
* @param PMBusMaster_CRC Initial value.
* @param PMBusMaster_Poly The polynomial to use for the calculation.
* @param *PMBusMaster_PMsg Pointer to the bytes from the PMBus transaction.
* @param PMBusMaster_MsgSize Number of bytes in the last transaction.
* @return The PEC byte.
******************************************************************************/
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 crc
if(carry) PMBusMaster_CRC ^= PMBusMaster_Poly; // If MSB = 1, perform XOR
msg <<= 1; // Shift left msg byte by 1
msg &= 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);
}
#endif
/***************************************************************************//**
* @brief Handles the Alert line interrupt.
* Code should be altered by user to implement application-appropriate fault handling
* @param None
* @return None
******************************************************************************/
interrupt void xint1_isr(void)
{
// warn "The user should alter the ISR to implement application-appropriate fault handling."
alert = 1; //received an alert
XIntruptRegs.XINT1CR.bit.ENABLE = 0; //Disable XINT1 interrupt
while(1); //Trap for fault. User can add code to service the fault instead, according to their application
}
I really appreciate any help or comments!
Thanks
Mohamed