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

📄 can.c

📁 LPC11C14 CAN 代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************Copyright (c)****************************************************
**                               Guangzhou ZHIYUAN electronics Co.,LTD.
**
**                                 http://www.embedtools.com
**
**--------------File Info---------------------------------------------------------------------------------
** File Name:               can.c
** Last modified Date:      2010.02.25
** Last Version:            1.0
** Description:             CAN 寄存器级驱动程序
**--------------------------------------------------------------------------------------------------------
** Created By:              张展威
** Created date:            2010.02.25
** Version:                 1.0
** Descriptions:            The original version 初始版本
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
#include "LPC11xx.h"                                                    /* LPC11xx Peripheral Registers */
#include "type.h"
#include "dataType.h"
#include "can_reg_cfg.h"                                                
#include "can.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.
//
//*****************************************************************************
#define CAN_RW_DELAY            (5)

//*****************************************************************************
//
//! \internal
//! Checks a CAN base address.
//!
//! \param ptBase 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
tBoolean CANBaseValid(unsigned long ulBaseAddr)
{
    return(ptBase == LPC_CAN_BASE);
}
#endif

void ASSERT (long ulData)
{
    ;
}
int CANBaseValid(unsigned long ulBaseAddr)
{
    if (ulBaseAddr == LPC_CAN_BASE) {
        return 1;
    }
    return -1;
}



/*********************************************************************************************************
** Function name:           __ENTER_CIRTICAL, __EXIT_CIRTICAL
** Descriptions:            临界区代码保护宏
** input parameters:        返回总中断标志  , 原总中断标志
** Descriptions:            必须成对调用,这对宏之间的操作将关闭总中断,退出临界区后恢复原总中断设置
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
#if defined(__arm__) && defined(__ARMCC_VERSION)                        /* 对应KEIL/RVMDK               */
__asm unsigned char __enterCirtical(void) {
    MRS     R0,PRIMASK                                                  /* 返回原总中断的状态           */
    CPSID   I                                                           /* 关闭总中断                   */
    BX      LR
}
__asm void __intEnable() {
    CPSIE   I                                                           /* 打开总中断                   */
    BX      LR
}
#define __ENTER_CIRTICAL()          __enterCirtical()                   /* 进入临界区关闭总中断         */
#define __EXIT_CIRTICAL(isEnable)   if(isEnable == 0) {__intEnable();}  /* 根据isEnable检查是否开中断   */

#elif defined (__IAR_SYSTEMS_ICC__)                                     /* 对应IAR集成开发工具          */
__enterCirtical(void)
{
    asm("MRS R0,PRIMASK");                                              /* 返回总中断状态               */
    asm("CPSID I");                                                     /* 关闭总中断                   */
}
#define __ENTER_CIRTICAL()         __enterCirtical()                    /* 进入临界区关闭总中断         */
#define __EXIT_CIRTICAL(isEnable)  if(isEnable == 0) {asm("CPSIE I");}  /* 根据isEnable检查是否开中断   */

#else                                                                   /* 对应GCC开发工具              */
__enterCirtical(void)
{
    asm("MRS R0,PRIMASK");                                              /* 返回总中断状态               */
    asm("CPSID I");                                                     /* 关闭总中断                   */
}
#define __ENTER_CIRTICAL()         __enterCirtical()                    /* 进入临界区关闭总中断         */
#define __EXIT_CIRTICAL(isEnable)  if(isEnable == 0) {asm("CPSIE I");}  /* 根据isEnable检查是否开中断   */
#endif




/*********************************************************************************************************
** Function name:           __canIntNumberGet
** Descriptions:            获取CAN中断号
** input parameters:        ulRegAddress:CAN寄存器地址
** output parameters:       无
** Returned value:          >0:CAN中断号 -1:无效的CAN寄存器地址
** Created By:              张展威
** Created date:            2009.10.23
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Descriptions:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
IRQn_Type __canIntNumberGet(unsigned long ulBase)
{
    IRQn_Type lIntNumber;
    switch(ulBase) {
        case LPC_CAN_BASE:{
            lIntNumber = CAN_IRQn;
            break;
        }
        
        default:{
            lIntNumber = (IRQn_Type)-1;                                 /* 基址错误                     */
        }
    }
    return(lIntNumber);
}


/*********************************************************************************************************
** Function name:           __canRegWrite
** Descriptions:            CAN寄存器读操作
** input parameters:        ulRegAddress:CAN寄存器地址
** output parameters:       无
** Returned value:          unsigned long:寄存器值
** Created By:              张展威
** Created date:            2009.10.23
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Descriptions:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
unsigned long __canRegRead(unsigned long ulRegAddress)
{
    volatile int iDelay;
    unsigned long ulRetVal;
    //unsigned long ulReenableInts;
    unsigned char ucEnable;
    
    //unsigned long ulIntNumber;
    //ulIntNumber = ____canIntNumberGet(ulRegAddress & 0xfffff000);
    //ulReenableInts = HWREG(NVIC_EN1) & (1 << (ulIntNumber - 48));
    
    ucEnable = __ENTER_CIRTICAL();                                      /* 进入临界区                   */
    
    HWREG(ulRegAddress);
    for(iDelay = 0; iDelay < 5; iDelay++)
    {
    }
    
    ulRetVal = HWREG(ulRegAddress);
    __EXIT_CIRTICAL(ucEnable);                                          /* 退出临界区                   */
    return(ulRetVal);
    
}


/*********************************************************************************************************
** Function name:           __canRegWrite
** Descriptions:            CAN寄存器写操作
** input parameters:        ulRegAddress:CAN寄存器地址
**                          ulRegValue:需要写的数据
** output parameters:       无
** Returned value:          无
** Created By:              张展威
** Created date:            2009.10.23
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Descriptions:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void __canRegWrite(unsigned long ulRegAddress, unsigned long ulRegValue)
{
    volatile int iDelay;
    HWREG(ulRegAddress) = ulRegValue;
    for(iDelay = 0; iDelay < 5; iDelay++)
    {
    }
}


//*****************************************************************************
//
//! \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 pulRegister is an unsigned long 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 0, the value would be: \b CAN0_BASE \b +
//! \b CAN_O_IF1DA1.
//! \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.
//
//*****************************************************************************
void CANDataRegWrite(unsigned char *pucData, unsigned long *pulRegister, int iSize)
{
    int iIdx;
    unsigned long ulValue;
    
    //
    // Loop always copies 1 or 2 bytes per iteration.
    //
    for(iIdx = 0; iIdx < iSize; )
    {
        
        //
        // Write out the data 16 bits at a time since this is how the registers
        // are aligned in memory.
        //
        ulValue = pucData[iIdx++];
        
        //
        // Only write the second byte if needed otherwise it will be zero.
        //
        if(iIdx < iSize)
        {
            ulValue |= (pucData[iIdx++] << 8);
        }
        canRegWrite((unsigned long)(pulRegister++), ulValue);
    }
}

//*****************************************************************************
//
//! \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 pulRegister is an unsigned long 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 1, the value would be: \b CAN0_BASE \b +
//! \b CAN_O_IF1DA1.
//! \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.
//
//*****************************************************************************
void CANDataRegRead(unsigned char *pucData, unsigned long *pulRegister, int iSize)
{
    int iIdx;
    unsigned long ulValue;
    
    //
    // 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 ptBase 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 ulBaseAddr)
{
    int iMsg;
    LPC_CAN_TypeDef *ptBase = (LPC_CAN_TypeDef *)ulBaseAddr;
    
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid((unsigned long)ptBase));
    
    //
    // 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((unsigned long)&ptBase->CNTL, CAN_CTL_INIT);
    
    //
    // Wait for busy bit to clear
    //
    while(canRegRead((unsigned long)&ptBase->IF1_CMDREQ) & 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((unsigned long)&ptBase->IF1_CMDMSK, CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB |
    CAN_IF1CMSK_CONTROL);
    canRegWrite((unsigned long)&ptBase->IF1_ARB2, 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -