⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 CAN_FIFO收发例程
💻 C
📖 第 1 页 / 共 5 页
字号:

    //
    // 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 + -