📄 can.c
字号:
//
// Loop always copies 1 or 2 bytes per iteration.
//
for(iIdx = 0; iIdx < iSize; )
{
//
// Read out the data 16 bits at a time since this is how the registers
// are aligned in memory.
//
ulValue = CANRegRead((unsigned long)(pulRegister++));
//
// Store the first byte.
//
pucData[iIdx++] = (unsigned char)ulValue;
//
// Only read the second byte if needed.
//
if(iIdx < iSize)
{
pucData[iIdx++] = (unsigned char)(ulValue >> 8);
}
}
}
//*****************************************************************************
//
//! Initializes the CAN controller after reset.
//!
//! \param ulBase is the base address of the CAN controller.
//!
//! After reset, the CAN controller is left in the disabled state. However,
//! the memory used for message objects contains undefined values and must be
//! cleared prior to enabling the CAN controller the first time. This prevents
//! unwanted transmission or reception of data before the message objects are
//! configured. This function must be called before enabling the controller
//! the first time.
//!
//! \return None.
//
//*****************************************************************************
void
CANInit(unsigned long ulBase)
{
int iMsg;
//
// Check the arguments.
//
ASSERT(CANBaseValid(ulBase));
//
// Place CAN controller in init state, regardless of previous state. This
// will put controller in idle, and allow the message object RAM to be
// programmed.
//
CANRegWrite(ulBase + CAN_O_CTL, CAN_CTL_INIT);
//
// Wait for busy bit to clear
//
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
{
}
//
// Clear the message value bit in the arbitration register. This indicates
// the message is not valid and is a "safe" condition to leave the message
// object. The same arb reg is used to program all the message objects.
//
CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB |
CAN_IF1CMSK_CONTROL);
CANRegWrite(ulBase + CAN_O_IF1ARB2, 0);
CANRegWrite(ulBase + CAN_O_IF1MCTL, 0);
//
// Loop through to program all 32 message objects
//
for(iMsg = 1; iMsg <= 32; iMsg++)
{
//
// Wait for busy bit to clear
//
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
{
}
//
// Initiate programming the message object
//
CANRegWrite(ulBase + CAN_O_IF1CRQ, iMsg);
}
//
// Make sure that the interrupt and new data flags are updated for the
// message objects.
//
CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_NEWDAT |
CAN_IF1CMSK_CLRINTPND);
//
// Loop through to program all 32 message objects
//
for(iMsg = 1; iMsg <= 32; iMsg++)
{
//
// Wait for busy bit to clear.
//
while(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
{
}
//
// Initiate programming the message object
//
CANRegWrite(ulBase + CAN_O_IF1CRQ, iMsg);
}
//
// Acknowledge any pending status interrupts.
//
CANRegRead(ulBase + CAN_O_STS);
}
//*****************************************************************************
//
//! Enables the CAN controller.
//!
//! \param ulBase is the base address of the CAN controller to enable.
//!
//! Enables the CAN controller for message processing. Once enabled, the
//! controller will automatically transmit any pending frames, and process any
//! received frames. The controller can be stopped by calling CANDisable().
//! Prior to calling CANEnable(), CANInit() should have been called to
//! initialize the controller and the CAN bus clock should be configured by
//! calling CANBitTimingSet().
//!
//! \return None.
//
//*****************************************************************************
void
CANEnable(unsigned long ulBase)
{
//
// Check the arguments.
//
ASSERT(CANBaseValid(ulBase));
//
// Clear the init bit in the control register.
//
CANRegWrite(ulBase + CAN_O_CTL,
CANRegRead(ulBase + CAN_O_CTL) & ~CAN_CTL_INIT);
}
//*****************************************************************************
//
//! Disables the CAN controller.
//!
//! \param ulBase is the base address of the CAN controller to disable.
//!
//! Disables the CAN controller for message processing. When disabled, the
//! controller will no longer automatically process data on the CAN bus. The
//! controller can be restarted by calling CANEnable(). The state of the CAN
//! controller and the message objects in the controller are left as they were
//! before this call was made.
//!
//! \return None.
//
//*****************************************************************************
void
CANDisable(unsigned long ulBase)
{
//
// Check the arguments.
//
ASSERT(CANBaseValid(ulBase));
//
// Set the init bit in the control register.
//
CANRegWrite(ulBase + CAN_O_CTL,
CANRegRead(ulBase + CAN_O_CTL) | CAN_CTL_INIT);
}
//*****************************************************************************
//
//! Reads the current settings for the CAN controller bit timing.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param pClkParms is a pointer to a structure to hold the timing parameters.
//!
//! This function reads the current configuration of the CAN controller bit
//! clock timing, and stores the resulting information in the structure
//! supplied by the caller. Refer to CANBitTimingSet() for the meaning of the
//! values that are returned in the structure pointed to by \e pClkParms.
//!
//! This function replaces the original CANGetBitTiming() API and performs the
//! same actions. A macro is provided in <tt>can.h</tt> to map the original
//! API to this API.
//!
//! \return None.
//
//*****************************************************************************
void
CANBitTimingGet(unsigned long ulBase, tCANBitClkParms *pClkParms)
{
unsigned int uBitReg;
//
// Check the arguments.
//
ASSERT(CANBaseValid(ulBase));
ASSERT(pClkParms != 0);
//
// Read out all the bit timing values from the CAN controller registers.
//
uBitReg = CANRegRead(ulBase + CAN_O_BIT);
//
// Set the phase 2 segment.
//
pClkParms->uPhase2Seg = ((uBitReg & CAN_BIT_TSEG2_M) >> 12) + 1;
//
// Set the phase 1 segment.
//
pClkParms->uSyncPropPhase1Seg = ((uBitReg & CAN_BIT_TSEG1_M) >> 8) + 1;
//
// Set the synchronous jump width.
//
pClkParms->uSJW = ((uBitReg & CAN_BIT_SJW_M) >> 6) + 1;
//
// Set the pre-divider for the CAN bus bit clock.
//
pClkParms->uQuantumPrescaler =
((uBitReg & CAN_BIT_BRP_M) |
((CANRegRead(ulBase + CAN_O_BRPE) & CAN_BRPE_BRPE_M) << 6)) + 1;
}
//*****************************************************************************
//
//! This function is used to set the CAN bit timing values to a nominal setting
//! based on a desired bit rate.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulSourceClock is the system clock for the device in Hz.
//! \param ulBitRate is the desired bit rate.
//!
//! This function will set the CAN bit timing for the bit rate passed in the
//! \e ulBitRate parameter based on the \e ulSourceClock parameter. Since the
//! CAN clock is based off of the system clock the calling function should pass
//! in the source clock rate either by retrieving it from SysCtlClockGet() or
//! using a specific value in Hz. The CAN bit clock is calculated to be an
//! average timing value that should work for most systems. If tighter timing
//! requirements are needed, then the CANBitTimingSet() function is available
//! for full customization of all of the CAN bit timing values. Since not all
//! bit rates can be matched exactly, the bit rate is set to the value closest
//! to the desired bit rate without being higher than the \e ulBitRate value.
//!
//! \note On some devices the source clock is fixed at 8MHz so the
//! \e ulSourceClock should be set to 8000000.
//!
//! \return This function returns the bit rate that the CAN controller was
//! configured to use or it returns 0 to indicate that the bit rate was not
//! changed because the requested bit rate was not valid.
//!
//*****************************************************************************
unsigned long
CANBitRateSet(unsigned long ulBase, unsigned long ulSourceClock,
unsigned long ulBitRate)
{
unsigned long ulDesiredRatio;
unsigned long ulCANBits;
unsigned long ulPreDivide;
unsigned long ulRegValue;
unsigned short usCANCTL;
ASSERT(ulBitRate != 0);
//
// Calculate the desired clock rate.
//
ulDesiredRatio = ulSourceClock / ulBitRate;
//
// If the ratio of CAN bit rate to processor clock is too small or too
// large then return 0 indicating that no bit rate was set.
//
ASSERT(ulDesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR));
ASSERT(ulDesiredRatio >= (CAN_MIN_PRE_DIVISOR * CAN_MIN_BIT_DIVISOR));
//
// Make sure that the Desired Ratio is not too large. This enforces the
// requirement that the bit rate is larger than requested.
//
if((ulSourceClock / ulDesiredRatio) > ulBitRate)
{
ulDesiredRatio += 1;
}
//
// Check all possible values to find a matching value.
//
while(ulDesiredRatio <= CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR)
{
//
// Loop through all possible CAN bit divisors.
//
for(ulCANBits = CAN_MAX_BIT_DIVISOR; ulCANBits >= CAN_MIN_BIT_DIVISOR;
ulCANBits--)
{
//
// For a given CAN bit divisor save the pre divisor.
//
ulPreDivide = ulDesiredRatio / ulCANBits;
//
// If the calculated divisors match the desired clock ratio then
// return these bit rate and set the CAN bit timing.
//
if((ulPreDivide * ulCANBits) == ulDesiredRatio)
{
//
// Start building the bit timing value by adding the bit timing
// in time quanta.
//
ulRegValue = g_usCANBitValues[ulCANBits - CAN_MIN_BIT_DIVISOR];
//
// To set the bit timing register, the controller must be placed
// in init mode (if not already), and also configuration change
// bit enabled. The state of the register should be saved
// so it can be restored.
//
usCANCTL = CANRegRead(ulBase + CAN_O_CTL);
CANRegWrite(ulBase + CAN_O_CTL, usCANCTL | CAN_CTL_INIT |
CAN_CTL_CCE);
//
// Now add in the pre-scalar on the bit rate.
//
ulRegValue |= ((ulPreDivide - 1)& CAN_BIT_BRP_M);
//
// Set the clock bits in the and the lower bits of the
// pre-scalar.
//
CANRegWrite(ulBase + CAN_O_BIT, ulRegValue);
//
// Set the divider upper bits in the extension register.
//
CANRegWrite(ulBase + CAN_O_BRPE,
((ulPreDivide - 1) >> 6) & CAN_BRPE_BRPE_M);
//
// Restore the saved CAN Control register.
//
CANRegWrite(ulBase + CAN_O_CTL, usCANCTL);
//
// Return the computed bit rate.
//
return(ulSourceClock / ( ulPreDivide * ulCANBits));
}
}
//
// Move the divisor up one and look again. Only in rare cases are
// more than 2 loops required to find the value.
//
ulDesiredRatio++;
}
return(0);
}
//*****************************************************************************
//
//! Configures the CAN controller bit timing.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param pClkParms points to the structure with the clock parameters.
//!
//! Configures the various timing parameters for the CAN bus bit timing:
//! Propagation segment, Phase Buffer 1 segment, Phase Buffer 2 segment, and
//! the Synchronization Jump Width. The values for Propagation and Phase
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -