📄 can.c
字号:
/****************************************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 + -