DSP TMS320F28374S配置CAN通讯(个人使用总结笔记)

使用的CANB

大致流程

1.初始化GPIO

2.CANInit(can_base);

3.CANClkSourceSelect(can_base, 0);

4.CANIntEnable(can_base, CAN_INT_IE0 | CAN_INT_STATUS);

5.PieCtrlRegs.PIEIER9.bit.INTx7 = 1;//使能第1组中断的第7个小中断,即CANB_0

6.CANEnable(can_base);

7.CANGlobalIntEnable(can_base, CAN_GLB_INT_CANINT0);

8.CanInit();

// Initialize the message object that will be used for sending CAN messages.

// Initialize the message object that will be used for recieving CAN messages.

9.CanSingleRxIsr(void)

10.收发数据函数等

例程

//###########################################################################
//
// FILE:   can_loopback_interrupts.c
//
// TITLE:  Example to demonstrate basic CAN setup and use.
//
//! \addtogroup cpu01_example_list
//! <h1>CAN External Loopback with Interrupts (can_loopback_interrupts)</h1>
//!
//! This example, using driverlib, shows the basic setup of CAN in order to 
//! transmit and receive messages on the CAN bus.  The CAN peripheral is 
//! configured to transmit messages with a specific CAN ID.  A message is then 
//! transmitted once per second, using a simple delay loop for timing.  The 
//! message that is sent is a 4 byte message that contains an incrementing 
//! pattern.  A CAN interrupt handler is used to confirm message transmission 
//! and count the number of messages that have been sent.
//!
//! This example sets up the CAN controller in External Loopback test mode.
//! Data transmitted is visible on the CAN0TX pin and can be received with
//! an appropriate mailbox configuration.
//!
//! This example uses the following interrupt handlers:\n
//! - INT_CANA0 - CANIntHandler
//!
//
//###########################################################################
// $TI Release: F2837xS Support Library v210 $
// $Release Date: Tue Nov  1 15:35:23 CDT 2016 $
// $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################//
// Included Files
//
#include "F28x_Project.h"
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_can.h"
#include "driverlib/can.h"//
// Globals
//
volatile unsigned long g_ulTxMsgCount = 0; // A counter that keeps track of the// number of times the TX interrupt// has occurred, which should match// the number of TX messages that// were sent.
volatile unsigned long g_ulRxMsgCount = 0;
unsigned long u32CanAErrorStatus;
volatile unsigned long g_bErrFlag = 0;     // A flag to indicate that some// transmission error occurred.
tCANMsgObject sTXCANMessage;
tCANMsgObject sRXCANMessage;
unsigned char ucTXMsgData[8] ={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00 };
unsigned char ucRXMsgData[8];
unsigned long u32CntTXMsgData = 0x12345678;//
// CANIntHandler - This function is the interrupt handler for the CAN
//                 peripheral. It checks for the cause of the interrupt, and
//                 maintains a count of all messages that have been
//                 transmitted.
//
interrupt void
CANIntHandler(void)
{unsigned long ulStatus;//// Read the CAN interrupt status to find the cause of the interrupt//ulStatus = CANIntStatus(CANA_BASE, CAN_INT_STS_CAUSE);//// If the cause is a controller status interrupt, then get the status//if(ulStatus == CAN_INT_INT0ID_STATUS){//// Read the controller status.  This will return a field of status// error bits that can indicate various errors.  Error processing// is not done in this example for simplicity.  Refer to the// API documentation for details about the error status bits.// The act of reading this status will clear the interrupt.  If the// CAN peripheral is not connected to a CAN bus with other CAN devices// present, then errors will occur and will be indicated in the// controller status.//ulStatus = CANStatusGet(CANA_BASE, CAN_STS_CONTROL);////Check to see if an error occurred.//if(((ulStatus  & ~(CAN_ES_TXOK | CAN_ES_RXOK)) != 7) &&((ulStatus  & ~(CAN_ES_TXOK | CAN_ES_RXOK)) != 0)){//// Set a flag to indicate some errors may have occurred.//g_bErrFlag = 1;}}//// Check if the cause is message object 1, which what we are using for// sending messages.//else if(ulStatus == 1){//// Getting to this point means that the TX interrupt occurred on// message object 1, and the message TX is complete.  Clear the// message object interrupt.//CANIntClear(CANA_BASE, 1);//// Increment a counter to keep track of how many messages have been// sent.  In a real application this could be used to set flags to// indicate when a message is sent.//g_ulTxMsgCount++;//// Since the message was sent, clear any error flags.//g_bErrFlag = 0;}//// Check if the cause is message object 1, which what we are using for// receiving messages.//else if(ulStatus == 2){//// Get the received message//CANMessageGet(CANA_BASE, 2, &sRXCANMessage, true);//// Getting to this point means that the TX interrupt occurred on// message object 1, and the message TX is complete.  Clear the// message object interrupt.//CANIntClear(CANA_BASE, 2);//// Increment a counter to keep track of how many messages have been// sent.  In a real application this could be used to set flags to// indicate when a message is sent.//g_ulRxMsgCount++;//// Since the message was sent, clear any error flags.//g_bErrFlag = 0;}//// Otherwise, something unexpected caused the interrupt.  This should// never happen.//else{//// Spurious interrupt handling can go here.//}CANGlobalIntClear(CANA_BASE, CAN_GLB_INT_CANINT0);PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}//
// Main
//
int main(void)
{//// Step 1. Initialize System Control:// PLL, WatchDog, enable Peripheral Clocks// This example function is found in the F2837xS_SysCtrl.c file.//InitSysCtrl();//// Step 2. Initialize GPIO:// This example function is found in the F2837xS_Gpio.c file and// illustrates how to set the GPIO to its default state.//InitGpio();GPIO_SetupPinMux(73, GPIO_MUX_CPU1, 3); // GPIO 73 - XCLKOUTGPIO_SetupPinOptions(73, GPIO_OUTPUT, GPIO_PUSHPULL); // SYSCLOCK/8 = 25MHzGPIO_SetupPinMux(30, GPIO_MUX_CPU1, 1); // GPIO30 - CANRXAGPIO_SetupPinMux(31, GPIO_MUX_CPU1, 1); // GPIO31 - CANTXAGPIO_SetupPinOptions(30, GPIO_INPUT, GPIO_ASYNC);GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);//// Initialize the CAN controller//CANInit(CANA_BASE);//// Setup CAN to be clocked off the PLL output clock (500kHz CAN-Clock)//CANClkSourceSelect(CANA_BASE, 0);//// Set up the bit rate for the CAN bus.  This function sets up the CAN// bus timing for a nominal configuration.  You can achieve more control// over the CAN bus timing by using the function CANBitTimingSet() instead// of this one, if needed.// In this example, the CAN bus is set to 500 kHz.  In the function below,// the call to SysCtlClockGet() is used to determine the clock rate that// is used for clocking the CAN peripheral.  This can be replaced with a// fixed value if you know the value of the system clock, saving the extra// function call.  For some parts, the CAN peripheral is clocked by a fixed// 8 MHz regardless of the system clock in which case the call to// SysCtlClockGet() should be replaced with 8000000.  Consult the data// sheet for more information about CAN peripheral clocking.//CANBitRateSet(CANA_BASE, 200000000, 500000);//// Enable interrupts on the CAN peripheral.  This example uses static// allocation of interrupt handlers which means the name of the handler// is in the vector table of startup code.  If you want to use dynamic// allocation of the vector table, then you must also call CANIntRegister()// here.//CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);//// Step 3. Clear all interrupts and initialize PIE vector table:// Disable CPU interrupts//DINT;//// Initialize the 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 F2837xS_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 F2837xS_DefaultIsr.c.// This function is found in F2837xS_PieVect.c.//InitPieVectTable();//// Interrupts that are used in this example are re-mapped to// ISR functions found within this file.// Register interrupt handler in RAM vector table//EALLOW;PieVectTable.CANA0_INT = CANIntHandler;EDIS;//// Enable the CAN interrupt on the processor (PIE).//PieCtrlRegs.PIEIER9.bit.INTx5 = 1;IER |= 0x0100;   // M_INT9EINT;//// Enable test mode and select external loopback//HWREG(CANA_BASE + CAN_O_CTL) |= CAN_CTL_TEST;HWREG(CANA_BASE + CAN_O_TEST) = CAN_TEST_EXL;//// Enable the CAN for operation.//CANEnable(CANA_BASE);//// Enable CAN Global Interrupt line0//CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT0);//// Initialize the message object that will be used for sending CAN// messages.  The message will be 4 bytes that will contain an incrementing// value.  Initially it will be set to 0x12345678.//ucTXMsgData[0] = (u32CntTXMsgData>>24) & 0xFF;ucTXMsgData[1] = (u32CntTXMsgData>>16) & 0xFF;ucTXMsgData[2] = (u32CntTXMsgData>>8) & 0xFF;ucTXMsgData[3] = (u32CntTXMsgData) & 0xFF;sTXCANMessage.ui32MsgID = 1;                      // CAN message ID - use 1sTXCANMessage.ui32MsgIDMask = 0;                  // no mask needed for TXsTXCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;  // enable interrupt on TXsTXCANMessage.ui32MsgLen = sizeof(ucTXMsgData);   // size of message is 8sTXCANMessage.pucMsgData = ucTXMsgData;           // ptr to message content//// Initialize the message object that will be used for receiving CAN// messages.//*(unsigned long *)ucRXMsgData = 0;sRXCANMessage.ui32MsgID = 1;                      // CAN message ID - use 1sRXCANMessage.ui32MsgIDMask = 0;                  // no mask needed for TXsRXCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE;  // enable interrupt on RXsRXCANMessage.ui32MsgLen = sizeof(ucRXMsgData);   // size of message is 8sRXCANMessage.pucMsgData = ucRXMsgData;           // ptr to message content//// Setup the message object being used to receive messages//CANMessageSet(CANA_BASE, 2, &sRXCANMessage, MSG_OBJ_TYPE_RX);//// Send the CAN message using object number 1 (not the same thing as// CAN ID, which is also 1 in this example).  This function will cause// the message to be transmitted right away.//ucTXMsgData[0] = (u32CntTXMsgData>>24) & 0xFF;ucTXMsgData[1] = (u32CntTXMsgData>>16) & 0xFF;ucTXMsgData[2] = (u32CntTXMsgData>>8) & 0xFF;ucTXMsgData[3] = (u32CntTXMsgData) & 0xFF;//// Enter loop to send messages.  A new message will be sent once per// second.  The 4 bytes of message content will be treated as an unsigned// long and incremented by one each time.//for(;;){//// Check the error flag to see if errors occurred//if(g_bErrFlag){asm("   ESTOP0");}if(g_ulTxMsgCount == g_ulRxMsgCount){//// Transmit Message//CANMessageSet(CANA_BASE, 1, &sTXCANMessage, MSG_OBJ_TYPE_TX);}else{g_bErrFlag = 1;}//// Now wait 1 second before continuing//DELAY_US(1000*1000);//// Increment the value in the transmitted message data.//(*(unsigned long *)ucTXMsgData)++;}
}//
// End of file
//
//###########################################################################
//
// FILE:   can.c
//
// TITLE:  F2837xS CAN Initialization & Support Functions.
//
// NOTE: The CAN bus bridge uses a different addressing scheme in order to
//       allow byte accesses. Because of this, 32-bit reads/writes can execute
//       abnormally at higher optimization levels. The CAN driver functions
//       have been adjusted to explicitly use two 16-bit read/writes to access
//       the full 32-bit register where HWREGH(base + offset) represents the
//       lower 16-bits and HWREGH(base + offset + 2) represents the upper
//       16-bits.
//
//###########################################################################
// $TI Release: F2837xS Support Library v210 $
// $Release Date: Tue Nov  1 15:35:23 CDT 2016 $
// $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################//*****************************************************************************
//! \addtogroup can_api
//! @{
//*****************************************************************************#include "F28x_Project.h"
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h"//*****************************************************************************
// This is the maximum number that can be stored as an 11bit Message
// identifier.
//*****************************************************************************
#define CAN_MAX_11BIT_MSG_ID    (0x7ff)//*****************************************************************************
// This is used as the loop delay for accessing the CAN controller registers.
//*****************************************************************************// The maximum CAN bit timing divisor is 13.
#define CAN_MAX_BIT_DIVISOR     (13)// The minimum CAN bit timing divisor is 5.
#define CAN_MIN_BIT_DIVISOR     (5)// The maximum CAN pre-divisor is 1024.
#define CAN_MAX_PRE_DIVISOR     (1024)// The minimum CAN pre-divisor is 1.
#define CAN_MIN_PRE_DIVISOR     (1)//*****************************************************************************
// This table is used by the CANBitRateSet() API as the register defaults for
// the bit timing values.
//*****************************************************************************static const uint16_t g_ui16CANBitValues[] =
{0x1100, // TSEG2 2, TSEG1 2, SJW 1, Divide 50x1200, // TSEG2 2, TSEG1 3, SJW 1, Divide 60x2240, // TSEG2 3, TSEG1 3, SJW 2, Divide 70x2340, // TSEG2 3, TSEG1 4, SJW 2, Divide 80x3340, // TSEG2 4, TSEG1 4, SJW 2, Divide 90x3440, // TSEG2 4, TSEG1 5, SJW 2, Divide 100x3540, // TSEG2 4, TSEG1 6, SJW 2, Divide 110x3640, // TSEG2 4, TSEG1 7, SJW 2, Divide 120x3740  // TSEG2 4, TSEG1 8, SJW 2, Divide 13
};//*****************************************************************************
//! \internal
//! Checks a CAN base address.
//!
//! \param ui32Base is the base address of the CAN controller.
//!
//! This function determines if a CAN controller base address is valid.
//!
//! \return Returns \b true if the base address is valid and \b false
//! otherwise.
//
//*****************************************************************************
#ifdef DEBUG
static bool
CANBaseValid(uint32_t ui32Base)
{return((ui32Base == CANA_BASE) || (ui32Base == CANB_BASE));
}#endif//*****************************************************************************
//! \internal
//!
//! Returns the CAN controller interrupt number.
//!
//! \param ui32Base is the base address of the selected CAN controller
//! \param ucNumber is the interrupt line number requested, valid values are 0
//! or 1
//!
//! Given a CAN controller base address and interrupt line number, returns the
//! corresponding interrupt number.
//!
//! \return Returns a CAN interrupt number, or -1 if \e ui32Port is invalid.
//
//*****************************************************************************
static int32_t
CANIntNumberGet(uint32_t ui32Base, unsigned char ucNumber)
{int32_t lIntNumber;// Return the interrupt number for the given CAN controller.switch(ui32Base){// Return the interrupt number for CAN 0case CANA_BASE:{switch(ucNumber){case 0:{lIntNumber = INT_CANA_0;break;}case 1:{lIntNumber = INT_CANA_1;break;}default:{lIntNumber = -1;break;}}break;}// Return the interrupt number for CAN 1case CANB_BASE:{switch(ucNumber){case 0:{lIntNumber = INT_CANB_0;break;}case 1:{lIntNumber = INT_CANB_1;break;}default:{lIntNumber = -1;break;}}break;}// Return -1 to indicate a bad address was passed in.default:{lIntNumber = -1;}}return(lIntNumber);
}//*****************************************************************************
//! \internal
//!
//! Copies data from a buffer to the CAN Data registers.
//!
//! \param pucData is a pointer to the data to be written out to the CAN
//! controller's data registers.
//! \param pui32Register is an uint32_t pointer to the first register of the
//! CAN controller's data registers.  For example, in order to use the IF1
//! register set on CAN controller A, the value would be: \b CANA_BASE \b +
//! \b CAN_O_IF1DATA.
//! \param iSize is the number of bytes to copy into the CAN controller.
//!
//! This function takes the steps necessary to copy data from a contiguous
//! buffer in memory into the non-contiguous data registers used by the CAN
//! controller.  This function is rarely used outside of the CANMessageSet()
//! function.
//!
//! This function replaces the original CANWriteDataReg() 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.
//
//*****************************************************************************
static void
CANDataRegWrite(unsigned char *pucData, uint32_t *pui32Register, int16_t iSize)
{int16_t iIdx;unsigned char * pucRegister = (unsigned char *) pui32Register;// Loop always copies 1 or 2 bytes per iteration.for(iIdx = 0; iIdx < iSize; iIdx++ ){// Write out the data 8 bits at a time.HWREGB(pucRegister++) = pucData[iIdx];}
}//*****************************************************************************
//! \internal
//!
//! Copies data from a buffer to the CAN Data registers.
//!
//! \param pucData is a pointer to the location to store the data read from the
//! CAN controller's data registers.
//! \param pui32Register is an uint32_t pointer to the first register of the
//! CAN controller's data registers.  For example, in order to use the IF1
//! register set on CAN controller A, the value would be: \b CANA_BASE \b +
//! \b CAN_O_IF1DATA.
//! \param iSize is the number of bytes to copy from the CAN controller.
//!
//! This function takes the steps necessary to copy data to a contiguous buffer
//! in memory from the non-contiguous data registers used by the CAN
//! controller.  This function is rarely used outside of the CANMessageGet()
//! function.
//!
//! This function replaces the original CANReadDataReg() 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.
//
//*****************************************************************************
static void
CANDataRegRead(unsigned char *pucData, uint32_t *pui32Register, int16_t iSize)
{int16_t iIdx;unsigned char * pucRegister = (unsigned char *) pui32Register;// Loop always copies 1 or 2 bytes per iteration.for(iIdx = 0; iIdx < iSize; iIdx++ ){// Read out the datapucData[iIdx] = HWREGB(pucRegister++);}
}//*****************************************************************************
//
//! Initializes the CAN controller after reset.
//!
//! \param ui32Base 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(uint32_t ui32Base)
{int16_t iMsg;// Check the arguments.ASSERT(CANBaseValid(ui32Base));// 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.HWREGH(ui32Base + CAN_O_CTL) = CAN_CTL_INIT;HWREGH(ui32Base + CAN_O_CTL) = CAN_CTL_SWR;// Wait for busy bit to clearwhile(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_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.HWREGH(ui32Base + CAN_O_IF1CMD + 2) = (CAN_IF1CMD_DIR | CAN_IF1CMD_ARB |CAN_IF1CMD_CONTROL) >> 16;HWREGH(ui32Base + CAN_O_IF1ARB) = 0;HWREGH(ui32Base + CAN_O_IF1ARB + 2) = 0;HWREGH(ui32Base + CAN_O_IF1MCTL) = 0;HWREGH(ui32Base + CAN_O_IF1MCTL + 2) = 0;HWREGH(ui32Base + CAN_O_IF2CMD + 2) = (CAN_IF2CMD_DIR | CAN_IF2CMD_ARB |CAN_IF2CMD_CONTROL) >> 16;HWREGH(ui32Base + CAN_O_IF2ARB) = 0;HWREGH(ui32Base + CAN_O_IF2ARB + 2) = 0;HWREGH(ui32Base + CAN_O_IF2MCTL) = 0;HWREGH(ui32Base + CAN_O_IF2MCTL + 2) = 0;// Loop through to program all 32 message objectsfor(iMsg = 1; iMsg <= 32; iMsg+=2){// Wait for busy bit to clearwhile(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY){}// Initiate programming the message objectHWREGH(ui32Base + CAN_O_IF1CMD) = iMsg;// Wait for busy bit to clearwhile(HWREGH(ui32Base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY){}// Initiate programming the message objectHWREGH(ui32Base + CAN_O_IF2CMD) = iMsg + 1;}// Make sure that the interrupt and new data flags are updated for the// message objects.HWREGH(ui32Base + CAN_O_IF1CMD + 2) = (CAN_IF1CMD_TXRQST |CAN_IF1CMD_CLRINTPND) >> 16;HWREGH(ui32Base + CAN_O_IF2CMD + 2) = (CAN_IF2CMD_TXRQST |CAN_IF2CMD_CLRINTPND) >> 16;// Loop through to program all 32 message objectsfor(iMsg = 1; iMsg <= 32; iMsg+=2){// Wait for busy bit to clear.while(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY){}// Initiate programming the message objectHWREGH(ui32Base + CAN_O_IF1CMD) = iMsg;// Wait for busy bit to clear.while(HWREGH(ui32Base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY){}// Initiate programming the message objectHWREGH(ui32Base + CAN_O_IF2CMD) = iMsg + 1;}// Acknowledge any pending status interrupts.HWREG(ui32Base + CAN_O_ES);
}//*****************************************************************************
//
//! Enables the CAN controller.
//!
//! \param ui32Base 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(uint32_t ui32Base)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));// Clear the init bit in the control register.HWREGH(ui32Base + CAN_O_CTL) = HWREGH(ui32Base + CAN_O_CTL) &~CAN_CTL_INIT;
}//*****************************************************************************
//
//! Disables the CAN controller.
//!
//! \param ui32Base 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(uint32_t ui32Base)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));// Set the init bit in the control register.HWREGH(ui32Base + CAN_O_CTL) = HWREGH(ui32Base + CAN_O_CTL) |CAN_CTL_INIT;
}//*****************************************************************************
//
//! Select CAN peripheral clock source
//!
//! \param ui32Base is the base address of the CAN controller to disable.
//! \param ui16Source is the clock source to select for the given CAN
//!        peripheral: \n
//!        0 - Selected CPU SYSCLKOUT (CPU1.Sysclk or CPU2.Sysclk)
//!           (default at reset) \n
//!        1 - External Oscillator (OSC) clock (direct from X1/X2) \n
//!        2 - AUXCLKIN = GPIOn(GPIO19)
//!
//! Selects the desired clock source for use with a given CAN peripheral.
//!
//! \return None.
//
//*****************************************************************************
void CANClkSourceSelect(uint32_t ui32Base, uint16_t ui16Source)
{EALLOW;switch(ui32Base){case CANA_BASE:{ClkCfgRegs.CLKSRCCTL2.bit.CANABCLKSEL = ui16Source;}case CANB_BASE:{ClkCfgRegs.CLKSRCCTL2.bit.CANBBCLKSEL = ui16Source;}default:break;}EDIS;
}//*****************************************************************************
//
//! Reads the current settings for the CAN controller bit timing.
//!
//! \param ui32Base 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(uint32_t ui32Base, tCANBitClkParms *pClkParms)
{uint32_t uBitReg;// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT(pClkParms != 0);uBitReg = HWREG(ui32Base + CAN_O_BTR);// Set the phase 2 segment.pClkParms->uPhase2Seg = ((uBitReg & CAN_BTR_TSEG2_M) >> 12) + 1;// Set the phase 1 segment.pClkParms->uSyncPropPhase1Seg = ((uBitReg & CAN_BTR_TSEG1_M) >> 8) + 1;// Set the synchronous jump width.pClkParms->uSJW = ((uBitReg & CAN_BTR_SJW_M) >> 6) + 1;// Set the pre-divider for the CAN bus bit clock.pClkParms->uQuantumPrescaler = ((uBitReg & CAN_BTR_BRP_M) |((uBitReg & CAN_BTR_BRPE_M) >> 10)) + 1;
}//*****************************************************************************
//
//! This function is used to set the CAN bit timing values to a nominal setting
//! based on a desired bit rate.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32SourceClock is the clock frequency for the CAN peripheral in Hz.
//! \param ui32BitRate is the desired bit rate.
//!
//! This function will set the CAN bit timing for the bit rate passed in the
//! \e ui32BitRate parameter based on the \e ui32SourceClock parameter. 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 ui32BitRate value.
//!
//! \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.
//
//*****************************************************************************
uint32_t
CANBitRateSet(uint32_t ui32Base, uint32_t ui32SourceClock, uint32_t ui32BitRate)
{uint32_t ui32DesiredRatio;uint32_t ui32CANBits;uint32_t ui32PreDivide;uint32_t ui32RegValue;uint16_t ui16CANCTL;ASSERT(ui32BitRate != 0);// Calculate the desired clock rate.ui32DesiredRatio = ui32SourceClock / ui32BitRate;// 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(ui32DesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR));ASSERT(ui32DesiredRatio >= (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((ui32SourceClock / ui32DesiredRatio) > ui32BitRate){ui32DesiredRatio += 1;}// Check all possible values to find a matching value.while(ui32DesiredRatio <= CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR){// Loop through all possible CAN bit divisors.for(ui32CANBits = CAN_MAX_BIT_DIVISOR;ui32CANBits >= CAN_MIN_BIT_DIVISOR;ui32CANBits--){// For a given CAN bit divisor save the pre divisor.ui32PreDivide = ui32DesiredRatio / ui32CANBits;// If the calculated divisors match the desired clock ratio then// return these bit rate and set the CAN bit timing.if((ui32PreDivide * ui32CANBits) == ui32DesiredRatio){// Start building the bit timing value by adding the bit timing// in time quanta.ui32RegValue =g_ui16CANBitValues[ui32CANBits - 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.ui16CANCTL = HWREGH(ui32Base + CAN_O_CTL);HWREGH(ui32Base + CAN_O_CTL) = ui16CANCTL | CAN_CTL_INIT |CAN_CTL_CCE;// Now add in the pre-scalar on the bit rate.ui32RegValue |= ((ui32PreDivide - 1) & CAN_BTR_BRP_M) |(((ui32PreDivide - 1) << 10) & CAN_BTR_BRPE_M);// Set the clock bits in the and the bits of the// pre-scalar.HWREGH(ui32Base + CAN_O_BTR) = (ui32RegValue &CAN_REG_WORD_MASK);HWREGH(ui32Base + CAN_O_BTR + 2) = (ui32RegValue >> 16);// Restore the saved CAN Control register.HWREGH(ui32Base + CAN_O_CTL) = ui16CANCTL;// Return the computed bit rate.return(ui32SourceClock / ( ui32PreDivide * ui32CANBits));}}// Move the divisor up one and look again.  Only in rare cases are// more than 2 loops required to find the value.ui32DesiredRatio++;}return(0);
}//*****************************************************************************
//
//! Configures the CAN controller bit timing.
//!
//! \param ui32Base 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
//! Buffer 1 segments are derived from the combination
//! \e pClkParms->uSyncPropPhase1Seg parameter.  Phase Buffer 2 is determined
//! from the \e pClkParms->uPhase2Seg parameter.  These two parameters, along
//! with \e pClkParms->uSJW are based in units of bit time quanta.  The actual
//! quantum time is determined by the \e pClkParms->uQuantumPrescaler value,
//! which specifies the divisor for the CAN module clock.
//!
//! The total bit time, in quanta, will be the sum of the two Seg parameters,
//! as follows:
//!
//! bit_time_q = uSyncPropPhase1Seg + uPhase2Seg + 1
//!
//! Note that the Sync_Seg is always one quantum in duration, and will be added
//! to derive the correct duration of Prop_Seg and Phase1_Seg.
//!
//! The equation to determine the actual bit rate is as follows:
//!
//! CAN Clock /
//! ((\e uSyncPropPhase1Seg + \e uPhase2Seg + 1) * (\e uQuantumPrescaler))
//!
//! This means that with \e uSyncPropPhase1Seg = 4, \e uPhase2Seg = 1,
//! \e uQuantumPrescaler = 2 and an 8 MHz CAN clock, that the bit rate will be
//! (8 MHz) / ((5 + 2 + 1) * 2) or 500 Kbit/sec.
//!
//! \return None.
//
//*****************************************************************************
void
CANBitTimingSet(uint32_t ui32Base, tCANBitClkParms *pClkParms)
{uint32_t uBitReg;uint16_t uSavedInit;// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT(pClkParms != 0);// The phase 1 segment must be in the range from 2 to 16.ASSERT((pClkParms->uSyncPropPhase1Seg >= 2) &&(pClkParms->uSyncPropPhase1Seg <= 16));// The phase 2 segment must be in the range from 1 to 8.ASSERT((pClkParms->uPhase2Seg >= 1) && (pClkParms->uPhase2Seg <= 8));// The synchronous jump windows must be in the range from 1 to 4.ASSERT((pClkParms->uSJW >= 1) && (pClkParms->uSJW <= 4));// The CAN clock pre-divider must be in the range from 1 to 1024.ASSERT((pClkParms->uQuantumPrescaler <= 1024) &&(pClkParms->uQuantumPrescaler >= 1));// To set the bit timing register, the controller must be placed in init// mode (if not already), and also configuration change bit enabled.  State// of the init bit should be saved so it can be restored at the end.uSavedInit = HWREGH(ui32Base + CAN_O_CTL);HWREGH(ui32Base + CAN_O_CTL) = uSavedInit | CAN_CTL_INIT | CAN_CTL_CCE;// Set the bit fields of the bit timing register according to the parms.uBitReg = ((pClkParms->uPhase2Seg - 1) << 12) & CAN_BTR_TSEG2_M;uBitReg |= ((pClkParms->uSyncPropPhase1Seg - 1) << 8) & CAN_BTR_TSEG1_M;uBitReg |= ((pClkParms->uSJW - 1) << 6) & CAN_BTR_SJW_M;uBitReg |= (pClkParms->uQuantumPrescaler - 1) & CAN_BTR_BRP_M;uBitReg |= ((pClkParms->uQuantumPrescaler - 1) << 10)& CAN_BTR_BRPE_M;HWREGH(ui32Base + CAN_O_BTR) = uBitReg & CAN_REG_WORD_MASK;HWREGH(ui32Base + CAN_O_BTR + 2) = uBitReg >> 16;// Clear the config change bit, and restore the init bit.uSavedInit &= ~CAN_CTL_CCE;// If Init was not set before, then clear it.if(uSavedInit & CAN_CTL_INIT){uSavedInit &= ~CAN_CTL_INIT;}HWREGH(ui32Base + CAN_O_CTL) = uSavedInit;
}//*****************************************************************************
//
//! Registers an interrupt handler for the CAN controller.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ucIntNumber is the interrupt line to register (0 or 1).
//! \param pfnHandler is a pointer to the function to be called when the
//! enabled CAN interrupts occur.
//!
//! This function registers the interrupt handler in the interrupt vector
//! table, and enables CAN interrupts on the interrupt controller; specific CAN
//! interrupt sources must be enabled using CANIntEnable().  The interrupt
//! handler being registered must clear the source of the interrupt using
//! CANIntClear().
//!
//! If the application is using a static interrupt vector table stored in
//! flash, then it is not necessary to register the interrupt handler this way.
//! Instead, IntEnable() should be used to enable CAN interrupts on the
//! interrupt controller.
//!
//! \sa IntRegister() for important information about registering interrupt
//! handlers.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntRegister(uint32_t ui32Base, unsigned char ucIntNumber,void (*pfnHandler)(void))
{uint32_t ui32IntNumber;// Check the arguments.ASSERT(CANBaseValid(ui32Base));// Get the actual interrupt number for this CAN controller.ui32IntNumber = CANIntNumberGet(ui32Base, ucIntNumber);// Register the interrupt handler.IntRegister(ui32IntNumber, pfnHandler);// Enable the CAN interrupt.IntEnable(ui32IntNumber);
}//*****************************************************************************
//! Unregisters an interrupt handler for the CAN controller.
//!
//! \param ui32Base is the base address of the controller.
//! \param ucIntNumber is the interrupt line to un-register (0 or 1).
//!
//! This function unregisters the previously registered interrupt handler and
//! disables the interrupt on the interrupt controller.
//!
//! \sa IntRegister() for important information about registering interrupt
//! handlers.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntUnregister(uint32_t ui32Base, unsigned char ucIntNumber)
{uint32_t ui32IntNumber;// Check the arguments.ASSERT(CANBaseValid(ui32Base));// Get the actual interrupt number for this CAN controller.ui32IntNumber = CANIntNumberGet(ui32Base, ucIntNumber);// Register the interrupt handler.IntUnregister(ui32IntNumber);// Disable the CAN interrupt.IntDisable(ui32IntNumber);
}//*****************************************************************************
//
//! Enables individual CAN controller interrupt sources.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled.
//!
//! Enables specific interrupt sources of the CAN controller.  Only enabled
//! sources will cause a processor interrupt.
//!
//! The \e ui32IntFlags parameter is the logical OR of any of the following:
//!
//! - \b CAN_INT_ERROR - a controller error condition has occurred
//! - \b CAN_INT_STATUS - a message transfer has completed, or a bus error has
//! been detected
//! - \b CAN_INT_IE0 - allow CAN controller to generate interrupts on interrupt
//! line 0
//! - \b CAN_INT_IE1 - allow CAN controller to generate interrupts on interrupt
//! line 1
//!
//! In order to generate status or error interrupts, \b CAN_INT_IE0 must be
//! enabled.
//! Further, for any particular transaction from a message object to generate
//! an interrupt, that message object must have interrupts enabled (see
//! CANMessageSet()).  \b CAN_INT_ERROR will generate an interrupt if the
//! controller enters the ``bus off'' condition, or if the error counters reach
//! a limit.  \b CAN_INT_STATUS will generate an interrupt under quite a few
//! status conditions and may provide more interrupts than the application
//! needs to handle.  When an interrupt occurs, use CANIntStatus() to determine
//! the cause.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32IntFlags & ~(CAN_INT_ERROR | CAN_INT_STATUS | CAN_INT_IE0 |CAN_INT_IE1)) == 0);// Enable the specified interrupts.HWREGH(ui32Base + CAN_O_CTL) = (HWREGH(ui32Base + CAN_O_CTL) |(ui32IntFlags & CAN_REG_WORD_MASK));HWREGH(ui32Base + CAN_O_CTL + 2) = (HWREGH(ui32Base + CAN_O_CTL + 2) |(ui32IntFlags >> 16));
}//*****************************************************************************
//
//! Disables individual CAN controller interrupt sources.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be disabled.
//!
//! Disables the specified CAN controller interrupt sources.  Only enabled
//! interrupt sources can cause a processor interrupt.
//!
//! The \e ui32IntFlags parameter has the same definition as in the
//! CANIntEnable() function.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32IntFlags & ~(CAN_INT_ERROR | CAN_INT_STATUS | CAN_INT_IE0 |CAN_INT_IE1)) == 0);// Disable the specified interrupts.HWREGH(ui32Base + CAN_O_CTL) = HWREGH(ui32Base + CAN_O_CTL) &~(ui32IntFlags & CAN_REG_WORD_MASK);HWREGH(ui32Base + CAN_O_CTL + 2) = HWREGH(ui32Base + CAN_O_CTL + 2) &~(ui32IntFlags >> 16);
}//*****************************************************************************
//
//! Returns the current CAN controller interrupt status.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param eIntStsReg indicates which interrupt status register to read
//!
//! Returns the value of one of two interrupt status registers.  The interrupt
//! status register read is determined by the \e eIntStsReg parameter, which
//! can have one of the following values:
//!
//! - \b CAN_INT_STS_CAUSE - indicates the cause of the interrupt
//! - \b CAN_INT_STS_OBJECT - indicates pending interrupts of all message
//! objects
//!
//! \b CAN_INT_STS_CAUSE returns the value of the controller interrupt register
//! and indicates the cause of the interrupt.  It will be a value of
//! \b CAN_INT_INT0ID_STATUS if the cause is a status interrupt.  In this case,
//! the status register should be read with the CANStatusGet() function.
//! Calling this function to read the status will also clear the status
//! interrupt.  If the value of the interrupt register is in the range 1-32,
//! then this indicates the number of the highest priority message object that
//! has an interrupt pending.  The message object interrupt can be cleared by
//! using the CANIntClear() function, or by reading the message using
//! CANMessageGet() in the case of a received message.  The interrupt handler
//! can read the interrupt status again to make sure all pending interrupts are
//! cleared before returning from the interrupt.
//!
//! \b CAN_INT_STS_OBJECT returns a bit mask indicating which message objects
//! have pending interrupts.  This can be used to discover all of the pending
//! interrupts at once, as opposed to repeatedly reading the interrupt register
//! by using \b CAN_INT_STS_CAUSE.
//!
//! \return Returns the value of one of the interrupt status registers.
//
//*****************************************************************************
uint32_t
CANIntStatus(uint32_t ui32Base, tCANIntStsReg eIntStsReg)
{uint32_t ui32Status;// Check the arguments.ASSERT(CANBaseValid(ui32Base));// See which status the caller is looking for.switch(eIntStsReg){// The caller wants the global interrupt status for the CAN controller// specified by ui32Base.case CAN_INT_STS_CAUSE:{ui32Status = HWREG(ui32Base + CAN_O_INT);break;}// The caller wants the current message status interrupt for all// messages.case CAN_INT_STS_OBJECT:{// Read message object interrupt statusui32Status = HWREG(ui32Base + CAN_O_IPEN_21);break;}// Request was for unknown status so just return 0.default:{ui32Status = 0;break;}}// Return the interrupt status valuereturn(ui32Status);
}//*****************************************************************************
//
//! Clears a CAN interrupt source.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntClr is a value indicating which interrupt source to clear.
//!
//! This function can be used to clear a specific interrupt source.  The
//! \e ui32IntClr parameter should be one of the following values:
//!
//! - \b CAN_INT_INTID_STATUS - Clears a status interrupt.
//! - 1-32 - Clears the specified message object interrupt
//!
//! It is not necessary to use this function to clear an interrupt.  This
//! should only be used if the application wants to clear an interrupt source
//! without taking the normal interrupt action.
//!
//! Normally, the status interrupt is cleared by reading the controller status
//! using CANStatusGet().  A specific message object interrupt is normally
//! cleared by reading the message object using CANMessageGet().
//!
//! \note Since there is a write buffer in the Cortex-M3 processor, it may take
//! several clock cycles before the interrupt source is actually cleared.
//! Therefore, it is recommended that the interrupt source be cleared early in
//! the interrupt handler (as opposed to the very last action) to avoid
//! returning from the interrupt handler before the interrupt source is
//! actually cleared.  Failure to do so may result in the interrupt handler
//! being immediately reentered (since NVIC still sees the interrupt source
//! asserted).
//!
//! \return None.
//
//*****************************************************************************
void
CANIntClear(uint32_t ui32Base, uint32_t ui32IntClr)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32IntClr == CAN_INT_INT0ID_STATUS) ||((ui32IntClr>=1) && (ui32IntClr <=32)));if(ui32IntClr == CAN_INT_INT0ID_STATUS){// Simply read and discard the status to clear the interrupt.HWREG(ui32Base + CAN_O_ES);}else{// Wait to be sure that this interface is not busy.while(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY){}// Only change the interrupt pending state by setting only the// CAN_IF1CMD_CLRINTPND bit.HWREGH(ui32Base + CAN_O_IF1CMD + 2) = CAN_IF1CMD_CLRINTPND >> 16;// Send the clear pending interrupt command to the CAN controller.HWREGH(ui32Base + CAN_O_IF1CMD) = ui32IntClr & CAN_IF1CMD_MSG_NUM_M;// Wait to be sure that this interface is not busy.while(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY){}}
}//*****************************************************************************
//
//! Sets the CAN controller automatic retransmission behavior.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param bAutoRetry enables automatic retransmission.
//!
//! Enables or disables automatic retransmission of messages with detected
//! errors.  If \e bAutoRetry is \b true, then automatic retransmission is
//! enabled, otherwise it is disabled.
//!
//! \return None.
//
//*****************************************************************************
void
CANRetrySet(uint32_t ui32Base, bool bAutoRetry)
{uint16_t ui16CtlReg;// Check the arguments.ASSERT(CANBaseValid(ui32Base));ui16CtlReg = HWREGH(ui32Base + CAN_O_CTL);// Conditionally set the DAR bit to enable/disable auto-retry.if(bAutoRetry){// Clearing the DAR bit tells the controller to not disable the// auto-retry of messages which were not transmitted or received// correctly.ui16CtlReg &= ~CAN_CTL_DAR;}else{// Setting the DAR bit tells the controller to disable the auto-retry// of messages which were not transmitted or received correctly.ui16CtlReg |= CAN_CTL_DAR;}HWREGH(ui32Base + CAN_O_CTL) = ui16CtlReg;
}//*****************************************************************************
//
//! Returns the current setting for automatic retransmission.
//!
//! \param ui32Base is the base address of the CAN controller.
//!
//! Reads the current setting for the automatic retransmission in the CAN
//! controller and returns it to the caller.
//!
//! \return Returns \b true if automatic retransmission is enabled, \b false
//! otherwise.
//
//*****************************************************************************
bool
CANRetryGet(uint32_t ui32Base)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));// Read the disable automatic retry setting from the CAN controller.if(HWREGH(ui32Base + CAN_O_CTL) & CAN_CTL_DAR){// Automatic data retransmission is not enabled.return(false);}// Automatic data retransmission is enabled.return(true);
}//*****************************************************************************
//
//! Reads one of the controller status registers.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param eStatusReg is the status register to read.
//!
//! Reads a status register of the CAN controller and returns it to the caller.
//! The different status registers are:
//!
//! - \b CAN_STS_CONTROL - the main controller status
//! - \b CAN_STS_TXREQUEST - bit mask of objects pending transmission
//! - \b CAN_STS_NEWDAT - bit mask of objects with new data
//! - \b CAN_STS_MSGVAL - bit mask of objects with valid configuration
//!
//! When reading the main controller status register, a pending status
//! interrupt will be cleared.  This should be used in the interrupt handler
//! for the CAN controller if the cause is a status interrupt.  The controller
//! status register fields are as follows:
//!
//! - \b CAN_STATUS_PDA - controller in local power down mode
//! - \b CAN_STATUS_WAKE_UP - controller initiated system wake up
//! - \b CAN_STATUS_PERR - parity error detected
//! - \b CAN_STATUS_BUS_OFF - controller is in bus-off condition
//! - \b CAN_STATUS_EWARN - an error counter has reached a limit of at least 96
//! - \b CAN_STATUS_EPASS - CAN controller is in the error passive state
//! - \b CAN_STATUS_RXOK - a message was received successfully (independent of
//! any message filtering).
//! - \b CAN_STATUS_TXOK - a message was successfully transmitted
//! - \b CAN_STATUS_LEC_NONE - no error
//! - \b CAN_STATUS_LEC_STUFF - stuffing error detected
//! - \b CAN_STATUS_LEC_FORM - a format error occurred in the fixed format part
//! of a message
//! - \b CAN_STATUS_LEC_ACK - a transmitted message was not acknowledged
//! - \b CAN_STATUS_LEC_BIT1 - dominant level detected when trying to send in
//! recessive mode
//! - \b CAN_STATUS_LEC_BIT0 - recessive level detected when trying to send in
//! dominant mode
//! - \b CAN_STATUS_LEC_CRC - CRC error in received message
//!
//! The remaining status registers are 32-bit bit maps to the message objects.
//! They can be used to quickly obtain information about the status of all the
//! message objects without needing to query each one.  They contain the
//! following information:
//!
//! - \b CAN_STS_TXREQUEST - if a message object's TxRequest bit is set, that
//! means that a transmission is pending on that object.  The application can
//! use this to determine which objects are still waiting to send a message.
//! - \b CAN_STS_NEWDAT - if a message object's NewDat bit is set, that means
//! that a new message has been received in that object, and has not yet been
//! picked up by the host application
//! - \b CAN_STS_MSGVAL - if a message object's MsgVal bit is set, that means
//! it has a valid configuration programmed.  The host application can use this
//! to determine which message objects are empty/unused.
//!
//! \return Returns the value of the status register.
//
//*****************************************************************************
uint32_t
CANStatusGet(uint32_t ui32Base, tCANStsReg eStatusReg)
{uint32_t ui32Status;// Check the arguments.ASSERT(CANBaseValid(ui32Base));switch(eStatusReg){// Just return the global CAN status register since that is what was// requested.case CAN_STS_CONTROL:{ui32Status = HWREG(ui32Base + CAN_O_ES);break;}// Return objects with valid transmit requestscase CAN_STS_TXREQUEST:{ui32Status = HWREG(ui32Base + CAN_O_TXRQ_21);break;}// Return messages objects with new datacase CAN_STS_NEWDAT:{ui32Status = HWREG(ui32Base + CAN_O_NDAT_21);break;}// Return valid message objectscase CAN_STS_MSGVAL:{ui32Status = HWREG(ui32Base + CAN_O_MVAL_21);break;}// Unknown CAN status requested so return 0.default:{ui32Status = 0;break;}}return(ui32Status);
}//*****************************************************************************
//
//! Reads the CAN controller error counter register.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param pui32RxCount is a pointer to storage for the receive error counter.
//! \param pui32TxCount is a pointer to storage for the transmit error counter.
//!
//! Reads the error counter register and returns the transmit and receive error
//! counts to the caller along with a flag indicating if the controller receive
//! counter has reached the error passive limit.  The values of the receive and
//! transmit error counters are returned through the pointers provided as
//! parameters.
//!
//! After this call, \e *pui32RxCount will hold the current receive error count
//! and \e *pui32TxCount will hold the current transmit error count.
//!
//! \return Returns \b true if the receive error count has reached the error
//! passive limit, and \b false if the error count is below the error passive
//! limit.
//
//*****************************************************************************
bool
CANErrCntrGet(uint32_t ui32Base, uint32_t *pui32RxCount,uint32_t *pui32TxCount)
{uint16_t ui16CANError;// Check the arguments.ASSERT(CANBaseValid(ui32Base));// Read the current count of transmit/receive errors.ui16CANError = HWREGH(ui32Base + CAN_O_ERRC);// Extract the error numbers from the register value.*pui32RxCount = (ui16CANError & CAN_ERRC_REC_M) >> CAN_ERRC_REC_S;*pui32TxCount = (ui16CANError & CAN_ERRC_TEC_M) >> CAN_ERRC_TEC_S;if(ui16CANError & CAN_ERRC_RP){return(true);}return(false);
}//*****************************************************************************
//
//! Configures a message object in the CAN controller.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32ObjID is the object number to configure (1-32).
//! \param pMsgObject is a pointer to a structure containing message object
//! settings.
//! \param eMsgType indicates the type of message for this object.
//!
//! This function is used to configure any one of the 32 message objects in the
//! CAN controller.  A message object can be configured as any type of CAN
//! message object as well as several options for automatic transmission and
//! reception.  This call also allows the message object to be configured to
//! generate interrupts on completion of message receipt or transmission.  The
//! message object can also be configured with a filter/mask so that actions
//! are only taken when a message that meets certain parameters is seen on the
//! CAN bus.
//!
//! The \e eMsgType parameter must be one of the following values:
//!
//! - \b MSG_OBJ_TYPE_TX - CAN transmit message object.
//! - \b MSG_OBJ_TYPE_TX_REMOTE - CAN transmit remote request message object.
//! - \b MSG_OBJ_TYPE_RX - CAN receive message object.
//! - \b MSG_OBJ_TYPE_RX_REMOTE - CAN receive remote request message object.
//! - \b MSG_OBJ_TYPE_RXTX_REMOTE - CAN remote frame receive remote, then
//! transmit message object.
//!
//! The message object pointed to by \e pMsgObject must be populated by the
//! caller, as follows:
//!
//! - \e ui32MsgID - contains the message ID, either 11 or 29 bits.
//! - \e ui32MsgIDMask - mask of bits from \e ui32MsgID that must match if
//! identifier filtering is enabled.
//! - \e ui32Flags
//!   - Set \b MSG_OBJ_TX_INT_ENABLE flag to enable interrupt on transmission.
//!   - Set \b MSG_OBJ_RX_INT_ENABLE flag to enable interrupt on receipt.
//!   - Set \b MSG_OBJ_USE_ID_FILTER flag to enable filtering based on the
//!   identifier mask specified by \e ui32MsgIDMask.
//! - \e ui32MsgLen - the number of bytes in the message data.  This should be
//! non-zero even for a remote frame; it should match the expected bytes of the
//! data responding data frame.
//! - \e pucMsgData - points to a buffer containing up to 8 bytes of data for a
//! data frame.
//!
//! \b Example: To send a data frame or remote frame(in response to a remote
//! request), take the following steps:
//!
//! -# Set \e eMsgType to \b MSG_OBJ_TYPE_TX.
//! -# Set \e pMsgObject->ui32MsgID to the message ID.
//! -# Set \e pMsgObject->ui32Flags. Make sure to set \b MSG_OBJ_TX_INT_ENABLE to
//! allow an interrupt to be generated when the message is sent.
//! -# Set \e pMsgObject->ui32MsgLen to the number of bytes in the data frame.
//! -# Set \e pMsgObject->pucMsgData to point to an array containing the bytes
//! to send in the message.
//! -# Call this function with \e ui32ObjID set to one of the 32 object buffers.
//!
//! \b Example: To receive a specific data frame, take the following steps:
//!
//! -# Set \e eMsgObjType to \b MSG_OBJ_TYPE_RX.
//! -# Set \e pMsgObject->ui32MsgID to the full message ID, or a partial mask to
//! use partial ID matching.
//! -# Set \e pMsgObject->ui32MsgIDMask bits that should be used for masking
//! during comparison.
//! -# Set \e pMsgObject->ui32Flags as follows:
//!   - Set \b MSG_OBJ_TX_INT_ENABLE flag to be interrupted when the data frame
//!   is received.
//!   - Set \b MSG_OBJ_USE_ID_FILTER flag to enable identifier based filtering.
//! -# Set \e pMsgObject->ui32MsgLen to the number of bytes in the expected data
//! frame.
//! -# The buffer pointed to by \e pMsgObject->pucMsgData  and
//! \e pMsgObject->ui32MsgLen are not used by this call as no data is present at
//! the time of the call.
//! -# Call this function with \e ui32ObjID set to one of the 32 object buffers.
//!
//! If you specify a message object buffer that already contains a message
//! definition, it will be overwritten.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageSet(uint32_t ui32Base, uint32_t ui32ObjID, tCANMsgObject *pMsgObject,tMsgObjType eMsgType)
{uint32_t ui32CmdMaskReg;uint32_t ui32MaskReg;uint32_t ui32ArbReg;uint32_t ui32MsgCtrl;bool bTransferData;bool bUseExtendedID;bTransferData = 0;// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32ObjID <= 32) && (ui32ObjID != 0));ASSERT((eMsgType == MSG_OBJ_TYPE_TX) ||(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||(eMsgType == MSG_OBJ_TYPE_RX) ||(eMsgType == MSG_OBJ_TYPE_RX_REMOTE) ||(eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||(eMsgType == MSG_OBJ_TYPE_RXTX_REMOTE));// Wait for busy bit to clearwhile(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY){}// See if we need to use an extended identifier or not.if((pMsgObject->ui32MsgID > CAN_MAX_11BIT_MSG_ID) ||(pMsgObject->ui32Flags & MSG_OBJ_EXTENDED_ID)){bUseExtendedID = 1;}else{bUseExtendedID = 0;}// This is always a write to the Message object as this call is setting a// message object.  This call will also always set all size bits so it sets// both data bits.  The call will use the CONTROL register to set control// bits so this bit needs to be set as well.ui32CmdMaskReg = (CAN_IF1CMD_DIR | CAN_IF1CMD_DATA_A | CAN_IF1CMD_DATA_B |CAN_IF1CMD_CONTROL);// Initialize the values to a known state before filling them in based on// the type of message object that is being configured.ui32ArbReg = 0;ui32MsgCtrl = 0;ui32MaskReg = 0;switch(eMsgType){// Transmit message object.case MSG_OBJ_TYPE_TX:{// Set the TXRQST bit and the reset the rest of the register.ui32MsgCtrl |= CAN_IF1MCTL_TXRQST;ui32ArbReg = CAN_IF1ARB_DIR;bTransferData = 1;break;}// Transmit remote request message objectcase MSG_OBJ_TYPE_TX_REMOTE:{// Set the TXRQST bit and the reset the rest of the register.ui32MsgCtrl |= CAN_IF1MCTL_TXRQST;ui32ArbReg = 0;break;}// Receive message object.case MSG_OBJ_TYPE_RX:{// This clears the DIR bit along with everything else.  The TXRQST// bit was cleared by defaulting ui32MsgCtrl to 0.ui32ArbReg = 0;break;}// Receive remote request message object.case MSG_OBJ_TYPE_RX_REMOTE:{// The DIR bit is set to one for remote receivers.  The TXRQST bit// was cleared by defaulting ui32MsgCtrl to 0.ui32ArbReg = CAN_IF1ARB_DIR;// Set this object so that it only indicates that a remote frame// was received and allow for software to handle it by sending back// a data frame.ui32MsgCtrl = CAN_IF1MCTL_UMASK;// Use the full Identifier by default.ui32MaskReg = CAN_IF1MSK_MSK_M;// Make sure to send the mask to the message object.ui32CmdMaskReg |= CAN_IF1CMD_MASK;break;}// Remote frame receive remote, with auto-transmit message object.case MSG_OBJ_TYPE_RXTX_REMOTE:{// Oddly the DIR bit is set to one for remote receivers.ui32ArbReg = CAN_IF1ARB_DIR;// Set this object to auto answer if a matching identifier is seen.ui32MsgCtrl = CAN_IF1MCTL_RMTEN | CAN_IF1MCTL_UMASK;// The data to be returned needs to be filled in.bTransferData = 1;break;}// This case should never happen due to the ASSERT statement at the// beginning of this function.default:{return;}}// Configure the Mask Registers.if(pMsgObject->ui32Flags & MSG_OBJ_USE_ID_FILTER){if(bUseExtendedID){// Set the 29 bits of Identifier mask that were requested.ui32MaskReg = pMsgObject->ui32MsgIDMask & CAN_IF1MSK_MSK_M;}else{// Put the 11 bit Mask Identifier into the upper bits of the field// in the register.ui32MaskReg = ((pMsgObject->ui32MsgIDMask << CAN_IF1ARB_STD_ID_S) &CAN_IF1ARB_STD_ID_M);}}// If the caller wants to filter on the extended ID bit then set it.if((pMsgObject->ui32Flags & MSG_OBJ_USE_EXT_FILTER) ==MSG_OBJ_USE_EXT_FILTER){ui32MaskReg |= CAN_IF1MSK_MXTD;}// The caller wants to filter on the message direction field.if((pMsgObject->ui32Flags & MSG_OBJ_USE_DIR_FILTER) ==MSG_OBJ_USE_DIR_FILTER){ui32MaskReg |= CAN_IF1MSK_MDIR;}if(pMsgObject->ui32Flags & (MSG_OBJ_USE_ID_FILTER | MSG_OBJ_USE_DIR_FILTER |MSG_OBJ_USE_EXT_FILTER)){// Set the UMASK bit to enable using the mask register.ui32MsgCtrl |= CAN_IF1MCTL_UMASK;// Set the MASK bit so that this gets transferred to the Message// Object.ui32CmdMaskReg |= CAN_IF1CMD_MASK;}// Set the Arb bit so that this gets transferred to the Message object.ui32CmdMaskReg |= CAN_IF1CMD_ARB;// Configure the Arbitration registers.if(bUseExtendedID){// Set the 29 bit version of the Identifier for this message object.// Mark the message as valid and set the extended ID bit.ui32ArbReg |= (pMsgObject->ui32MsgID & CAN_IF1ARB_ID_M) |CAN_IF1ARB_MSGVAL | CAN_IF1ARB_XTD;}else{// Set the 11 bit version of the Identifier for this message object.// The lower 18 bits are set to zero.// Mark the message as valid.ui32ArbReg |= ((pMsgObject->ui32MsgID << CAN_IF1ARB_STD_ID_S) &CAN_IF1ARB_STD_ID_M) | CAN_IF1ARB_MSGVAL;}// Set the data length since this is set for all transfers.  This is also a// single transfer and not a FIFO transfer so set EOB bit.ui32MsgCtrl |= (pMsgObject->ui32MsgLen & CAN_IF1MCTL_DLC_M);// Mark this as the last entry if this is not the last entry in a FIFO.if((pMsgObject->ui32Flags & MSG_OBJ_FIFO) == 0){ui32MsgCtrl |= CAN_IF1MCTL_EOB;}// Enable transmit interrupts if they should be enabled.if(pMsgObject->ui32Flags & MSG_OBJ_TX_INT_ENABLE){ui32MsgCtrl |= CAN_IF1MCTL_TXIE;}// Enable receive interrupts if they should be enabled.if(pMsgObject->ui32Flags & MSG_OBJ_RX_INT_ENABLE){ui32MsgCtrl |= CAN_IF1MCTL_RXIE;}// Write the data out to the CAN Data registers if needed.if(bTransferData){CANDataRegWrite(pMsgObject->pucMsgData,(uint32_t *)(ui32Base + CAN_O_IF1DATA),pMsgObject->ui32MsgLen);}// Write out the registers to program the message object.HWREGH(ui32Base + CAN_O_IF1CMD + 2) = ui32CmdMaskReg >> 16;HWREGH(ui32Base + CAN_O_IF1MSK) = ui32MaskReg & CAN_REG_WORD_MASK;HWREGH(ui32Base + CAN_O_IF1MSK + 2) = ui32MaskReg >> 16;HWREGH(ui32Base + CAN_O_IF1ARB) = ui32ArbReg & CAN_REG_WORD_MASK;HWREGH(ui32Base + CAN_O_IF1ARB + 2) = ui32ArbReg >> 16;HWREGH(ui32Base + CAN_O_IF1MCTL) = ui32MsgCtrl & CAN_REG_WORD_MASK;// Transfer the message object to the message object specific by ui32ObjID.HWREGH(ui32Base + CAN_O_IF1CMD) = ui32ObjID & CAN_IF1CMD_MSG_NUM_M;return;
}//*****************************************************************************
//
//! Reads a CAN message from one of the message object buffers.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32ObjID is the object number to read (1-32).
//! \param pMsgObject points to a structure containing message object fields.
//! \param bClrPendingInt indicates whether an associated interrupt should be
//! cleared.
//!
//! This function is used to read the contents of one of the 32 message objects
//! in the CAN controller, and return it to the caller.  The data returned is
//! stored in the fields of the caller-supplied structure pointed to by
//! \e pMsgObject.  The data consists of all of the parts of a CAN message,
//! plus some control and status information.
//!
//! Normally this is used to read a message object that has received and stored
//! a CAN message with a certain identifier.  However, this could also be used
//! to read the contents of a message object in order to load the fields of the
//! structure in case only part of the structure needs to be changed from a
//! previous setting.
//!
//! When using CANMessageGet, all of the same fields of the structure are
//! populated in the same way as when the CANMessageSet() function is used,
//! with the following exceptions:
//!
//! \e pMsgObject->ui32Flags:
//!
//! - \b MSG_OBJ_NEW_DATA indicates if this is new data since the last time it
//! was read
//! - \b MSG_OBJ_DATA_LOST indicates that at least one message was received on
//! this message object, and not read by the host before being overwritten.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageGet(uint32_t ui32Base, uint32_t ui32ObjID, tCANMsgObject *pMsgObject,bool bClrPendingInt)
{uint32_t ui32CmdMaskReg;uint32_t ui32MaskReg;uint32_t ui32ArbReg;uint32_t ui32MsgCtrl;// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32ObjID <= 32) && (ui32ObjID != 0));// This is always a read to the Message object as this call is setting a// message object.ui32CmdMaskReg = (CAN_IF2CMD_DATA_A | CAN_IF2CMD_DATA_B |CAN_IF2CMD_CONTROL | CAN_IF2CMD_MASK | CAN_IF2CMD_ARB);// Clear a pending interrupt and new data in a message object.if(bClrPendingInt){ui32CmdMaskReg |= CAN_IF2CMD_CLRINTPND | CAN_IF2CMD_TXRQST;}// Set up the request for data from the message object.HWREGH(ui32Base + CAN_O_IF2CMD + 2) =  ui32CmdMaskReg >> 16;// Transfer the message object to the message object specified by ui32ObjID.HWREGH(ui32Base + CAN_O_IF2CMD) = ui32ObjID & CAN_IF2CMD_MSG_NUM_M;// Wait for busy bit to clearwhile(HWREGH(ui32Base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY){}// Read out the IF Registers.ui32MaskReg = HWREG(ui32Base + CAN_O_IF2MSK);ui32ArbReg = HWREG(ui32Base + CAN_O_IF2ARB);ui32MsgCtrl = HWREG(ui32Base + CAN_O_IF2MCTL);pMsgObject->ui32Flags = MSG_OBJ_NO_FLAGS;// Determine if this is a remote frame by checking the TXRQST and DIR bits.if((!(ui32MsgCtrl & CAN_IF2MCTL_TXRQST) && (ui32ArbReg & CAN_IF2ARB_DIR)) ||((ui32MsgCtrl & CAN_IF2MCTL_TXRQST) && (!(ui32ArbReg & CAN_IF2ARB_DIR)))){pMsgObject->ui32Flags |= MSG_OBJ_REMOTE_FRAME;}// Get the identifier out of the register, the format depends on size of// the mask.if(ui32ArbReg & CAN_IF2ARB_XTD){// Set the 29 bit version of the Identifier for this message object.pMsgObject->ui32MsgID = ui32ArbReg & CAN_IF2ARB_ID_M;pMsgObject->ui32Flags |= MSG_OBJ_EXTENDED_ID;}else{// The Identifier is an 11 bit value.pMsgObject->ui32MsgID = (ui32ArbReg &CAN_IF2ARB_STD_ID_M) >> CAN_IF2ARB_STD_ID_S;}// Indicate that we lost some data.if(ui32MsgCtrl & CAN_IF2MCTL_MSGLST){pMsgObject->ui32Flags |= MSG_OBJ_DATA_LOST;}// Set the flag to indicate if ID masking was used.if(ui32MsgCtrl & CAN_IF2MCTL_UMASK){if(ui32ArbReg & CAN_IF2ARB_XTD){// The Identifier Mask is assumed to also be a 29 bit value.pMsgObject->ui32MsgIDMask = (ui32MaskReg & CAN_IF2MSK_MSK_M);// If this is a fully specified Mask and a remote frame then don't// set the MSG_OBJ_USE_ID_FILTER because the ID was not really// filtered.if((pMsgObject->ui32MsgIDMask != 0x1fffffff) ||((pMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0)){pMsgObject->ui32Flags |= MSG_OBJ_USE_ID_FILTER;}}else{// The Identifier Mask is assumed to also be an 11 bit value.pMsgObject->ui32MsgIDMask = ((ui32MaskReg & CAN_IF2MSK_MSK_M) >>18);// If this is a fully specified Mask and a remote frame then don't// set the MSG_OBJ_USE_ID_FILTER because the ID was not really// filtered.if((pMsgObject->ui32MsgIDMask != 0x7ff) ||((pMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0)){pMsgObject->ui32Flags |= MSG_OBJ_USE_ID_FILTER;}}// Indicate if the extended bit was used in filtering.if(ui32MaskReg & CAN_IF2MSK_MXTD){pMsgObject->ui32Flags |= MSG_OBJ_USE_EXT_FILTER;}// Indicate if direction filtering was enabled.if(ui32MaskReg & CAN_IF2MSK_MDIR){pMsgObject->ui32Flags |= MSG_OBJ_USE_DIR_FILTER;}}// Set the interrupt flags.if(ui32MsgCtrl & CAN_IF2MCTL_TXIE){pMsgObject->ui32Flags |= MSG_OBJ_TX_INT_ENABLE;}if(ui32MsgCtrl & CAN_IF2MCTL_RXIE){pMsgObject->ui32Flags |= MSG_OBJ_RX_INT_ENABLE;}// See if there is new data available.if(ui32MsgCtrl & CAN_IF2MCTL_NEWDAT){// Get the amount of data needed to be read.pMsgObject->ui32MsgLen = (ui32MsgCtrl & CAN_IF2MCTL_DLC_M);// Don't read any data for a remote frame, there is nothing valid in// that buffer anyway.if((pMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0){// Read out the data from the CAN registers.CANDataRegRead(pMsgObject->pucMsgData,(uint32_t *)(ui32Base + CAN_O_IF2DATA),pMsgObject->ui32MsgLen);}// Now clear out the new data flag.HWREGH(ui32Base + CAN_O_IF2CMD + 2) = CAN_IF2CMD_TXRQST >> 16;// Transfer the message object to the message object specified by// ui32ObjID.HWREGH(ui32Base + CAN_O_IF2CMD) = ui32ObjID & CAN_IF2CMD_MSG_NUM_M;// Wait for busy bit to clearwhile(HWREGH(ui32Base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY){}// Indicate that there is new data in this message.pMsgObject->ui32Flags |= MSG_OBJ_NEW_DATA;}else{// Along with the MSG_OBJ_NEW_DATA not being set the amount of data// needs to be set to zero if none was available.pMsgObject->ui32MsgLen = 0;}
}//*****************************************************************************
//
//! Clears a message object so that it is no longer used.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32ObjID is the message object number to disable (1-32).
//!
//! This function frees the specified message object from use.  Once a message
//! object has been ``cleared,'' it will no longer automatically send or
//! receive messages, or generate interrupts.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageClear(uint32_t ui32Base, uint32_t ui32ObjID)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32ObjID >= 1) && (ui32ObjID <= 32));// Wait for busy bit to clearwhile(HWREGH(ui32Base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY){}// Clear the message value bit in the arbitration register. This indicates// the message is not valid.HWREGH(ui32Base + CAN_O_IF1CMD + 2) = (CAN_IF1CMD_DIR |CAN_IF1CMD_ARB) >> 16;HWREGH(ui32Base + CAN_O_IF1ARB) = 0;HWREGH(ui32Base + CAN_O_IF1ARB + 2) = 0;// Initiate programming the message objectHWREGH(ui32Base + CAN_O_IF1CMD) = ui32ObjID & CAN_IF1CMD_MSG_NUM_M;
}//*****************************************************************************
//
//! CAN Global interrupt Enable function.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled.
//!
//! Enables specific CAN interrupt in the global interrupt enable register
//!
//! The \e ui32IntFlags parameter is the logical OR of any of the following:
//!
//! CAN_GLB_INT_CANINT0   -Global Interrupt Enable bit for CAN INT0
//! CAN_GLB_INT_CANINT1   -Global Interrupt Enable bit for CAN INT1
//!
//! \return None.
//
//*****************************************************************************
void
CANGlobalIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32IntFlags & ~(CAN_GLB_INT_CANINT0 |CAN_GLB_INT_CANINT1)) == 0);//enable the requested interruptsHWREGH(ui32Base + CAN_O_GLB_INT_EN) |= ui32IntFlags;
}//*****************************************************************************
//
//! CAN Global interrupt Disable function.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled.
//!
//! Disables the specific CAN interrupt in the global interrupt enable register
//!
//! The \e ui32IntFlags parameter is the logical OR of any of the following:
//!
//! CAN_GLB_INT_CANINT0   -Global Interrupt bit for CAN INT0
//! CAN_GLB_INT_CANINT1   -Global Interrupt bit for CAN INT1
//!
//! \return None.
//
//*****************************************************************************
void
CANGlobalIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32IntFlags & ~(CAN_GLB_INT_CANINT0 |CAN_GLB_INT_CANINT1)) == 0);//disable the requested interruptsHWREGH(ui32Base + CAN_O_GLB_INT_EN) &= ~ui32IntFlags;
}//*****************************************************************************
//
//! CAN Global interrupt Clear function.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled.
//!
//! Clear the specific CAN interrupt bit in the global interrupt flag register.
//!
//! The \e ui32IntFlags parameter is the logical OR of any of the following:
//!
//! CAN_GLB_INT_CANINT0   -Global Interrupt bit for CAN INT0
//! CAN_GLB_INT_CANINT1   -Global Interrupt bit for CAN INT1
//!
//! \return None.
//
//*****************************************************************************
void
CANGlobalIntClear(uint32_t ui32Base, uint32_t ui32IntFlags)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32IntFlags & ~(CAN_GLB_INT_CANINT0 |CAN_GLB_INT_CANINT1)) == 0);//clear the requested interruptsHWREGH(ui32Base + CAN_O_GLB_INT_CLR) = ui32IntFlags;
}//*****************************************************************************
//
//! CAN Global interrupt Status function.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be checked.
//!
//! Get the status of the specific CAN interrupt bits in the global interrupt
//! flag register.
//!
//! The \e ui32IntFlags parameter is the logical OR of any of the following:
//!
//! CAN_GLB_INT_CANINT0   -Global Interrupt bit for CAN INT0
//! CAN_GLB_INT_CANINT1   -Global Interrupt bit for CAN INT1
//!
//! \return True if any of the requested interrupt bit(s) is (are) set.
//
//*****************************************************************************
bool
CANGlobalIntstatusGet(uint32_t ui32Base, uint32_t ui32IntFlags)
{// Check the arguments.ASSERT(CANBaseValid(ui32Base));ASSERT((ui32IntFlags & ~(CAN_GLB_INT_CANINT0 |CAN_GLB_INT_CANINT1)) == 0);//enable the requested interruptsif(HWREGH(ui32Base + CAN_O_GLB_INT_FLG) & ui32IntFlags){return true;}else{return false;}
}//*****************************************************************************
// Close the Doxygen group.
//! @}
//*****************************************************************************

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/725223.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue-路由跳转和路由传参!!!

需求&#xff1a;在修改商品时&#xff0c;会进行页面跳转&#xff0c;通过点击修改按钮进行页面跳转。这时我们需要将商品的id携带过去 一、首先我们在查询页面实现路由跳转并携带参数。 1.1、修改按钮 <el-button type"primary" size"small" click&qu…

体验Node.js的安装和运行

Node.js概述 Node.js是一个基于Chrome V8引擎的JavaScript运行环境。它允许JavaScript代码在服务器端运行&#xff0c;使得开发人员可以使用同一种语言编写前端和后端的代码。Node.js使用事件驱动、非阻塞I/O模型&#xff0c;使其轻量且高效&#xff0c;非常适合数据密集型的实…

mpi4py的安装

一. MPI的安装 1. 下载MPI 安装包 到官网&#xff1a;http://www.mpich.org/downloads/ 下载mpi-3.2.1版本的MPI 包。 2. 解压安装包 到下载安装包的目录下&#xff0c;可以看到有mpi-3.2.1.tar.gz的压缩包&#xff0c;在终端运行如下命令&#xff1a; tar -zxvf mpich-3.…

Leetcode : 506. 相对名次

思路 &#xff1a; 遍历计算每个元素比它大的元素个数&#xff0c;并判断做出对应结果标签&#xff1b; #include <iostream> #include <vector>using namespace std;class Solution { public:vector<string> findRelativeRanks(vector<int>& scor…

短剧系统开发:一种新型的娱乐方式

一、引言 随着科技的快速发展&#xff0c;人们的生活方式也在逐渐改变。在娱乐领域&#xff0c;短剧作为一种新型的娱乐方式&#xff0c;正在受到越来越多人的喜爱。短剧以其短小精悍、情节紧凑、易于观看等特点&#xff0c;迅速占领了市场。因此&#xff0c;开发一款短剧系统…

自动统计日志文件中IP出现次数并添加iptables规则的实现方法

在网络安全领域&#xff0c;我们经常需要监控服务器的访问日志&#xff0c;并根据IP地址出现的频率来判断是否存在恶意访问。本文将介绍如何使用PHP编写一个脚本&#xff0c;自动统计日志文件中IP出现的次数&#xff0c;并根据设定的阈值自动添加iptables规则来阻止恶意IP的访问…

【自然语言处理】【大模型】BitNet:用1-bit Transformer训练LLM

BitNet&#xff1a;用1-bit Transformer训练LLM 《BitNet: Scaling 1-bit Transformers for Large Language Models》 论文地址&#xff1a;https://arxiv.org/pdf/2310.11453.pdf 相关博客 【自然语言处理】【大模型】BitNet&#xff1a;用1-bit Transformer训练LLM 【自然语言…

coqui-ai/TTS 安装使用

Coqui AI的TTS是一款开源深度学习文本转语音工具&#xff0c;以高质量、多语言合成著称。它提供超过1100种语言的预训练模型库&#xff0c;能够轻松集成到各种应用中&#xff0c;并允许用户通过简单API进行个性化声音训练与微调。其技术亮点包括但不限于低资源适应性&#xff0…

RabbitMQ是如何保证高可用的?

RabbitMQ可以通过多种方式来实现高可用性&#xff0c;以确保在硬件故障或其他不可预测的情况下&#xff0c;消息队列系统仍然能够正常 运行。RabbitMQ有三种模式&#xff1a;单机模式&#xff0c;普通集群模式&#xff0c;镜像集群模式。 其中单机模式一般用于demo搭建&#x…

STM32CubeMX学习笔记14 ---SPI总线

1. 简介 1.1 SPI总线介绍 SPI 是英语Serial Peripheral interface的缩写&#xff0c;顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。 SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在…

softmax和sigmoid的区别

sigmoid 公式&#xff1a; s i g m o i d ( x ) 1 1 e − x sigmoid(x) \frac{1}{1 e^{-x}} sigmoid(x)1e−x1​ 函数曲线如下&#xff1a; 导数公式&#xff1a; f ( x ) ′ e − x ( 1 e − x ) 2 f ( x ) ( 1 − f ( x ) ) f(x)\prime \frac{ e^{-x}}{(1 e^{-x})…

主流电商平台API接口太多?如何选择合适的接口你要的API 接口都给你整理好了~

接口太多不知道怎么选&#xff1f; &#x1f447; 看我给您整理的电商API接口就很一目了然啦 ~ 淘宝平台API商品采集接口 此API目前支持以下基本接口&#xff1a; item_get 获得淘宝商品详情item_get_pro 获得淘宝商品详情高级版item_review 获得淘宝商品评论item_fee 获得淘…

【CSP试题回顾】201604-1-折点计数

CSP-201604-1-折点计数 解题代码 #include <iostream> #include <vector> #include <algorithm> using namespace std;int n, pointSum;int main() {cin >> n;vector<int>myData(n);for (int i 0; i < n; i){cin >> myData[i];}// 统…

何为OOM(Out of Memory)?

OOM&#xff08;Out of Memory&#xff09; 是指程序运行过程中内存不足的情况。在 Spark 应用程序中&#xff0c;OOM 是一个非常常见的问题&#xff0c;尤其是在处理大规模数据集或执行资源密集型的操作时。当 Spark 作业尝试使用的内存超过了为其分配的内存限制时&#xff0c…

【MybatisPlus】QueryWrapper、UpdateWrappe、LambdaQueryWrapper、LambdaUpdateWrapper

一、Wrapper简介 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都是 MyBatis-Plus 框架中用于构建条件的工具类&#xff0c;它们之间的关系是继承关系。其中 QueryWrapper 和 UpdateWrapper 是基于普通的对象属性名来构建条件的&#xff0c;而 La…

SystemVerilog Constants、Processes

SystemVerilog提供了三种类型的精化时间常数&#xff1a; •参数&#xff1a;与最初的Verilog标准相同&#xff0c;可以以相同的方式使用。 •localparameter&#xff1a;与参数类似&#xff0c;但不能被上层覆盖模块。 •specparam&#xff1a;用于指定延迟和定时值&#x…

python+django+vue电影票订购系统dyvv4

电影院订票信息管理系统综合网络空间开发设计要求。目的是将电影院订票通过网络平台将传统管理方式转换为在网上操作&#xff0c;方便快捷、安全性高、交易规范做了保障&#xff0c;目标明确。电影院订票信息管理系统可以将功能划分为用户和管理员功能[10]。 语言&#xff1a;…

Leetcode 1

题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任…

mybatis在更新一行数据或者插入一条新数据后返回对应的主键id

今天在做项目的时候需要用到上次数据更新或者插入的id&#xff0c;学习了一下找到此方法&#xff0c;记录一下。 在MyBatis中&#xff0c;当插入一条新数据后&#xff0c;可以使用useGeneratedKeys属性和keyProperty属性来获取新插入数据的ID。useGeneratedKeys属性告诉MyBatis…

最小生成树的典型应用

2024-02-01&#xff08;最小生成树&#xff0c;二分图&#xff09;-CSDN博客 如何证明当前这条边可以被选&#xff1f; 假设不选当前边&#xff0c;得到了一棵树&#xff0c;然后将这条边加上&#xff0c;那么必然会出现一个环&#xff0c;在这个环上&#xff0c;一定可以找出一…