📄 drvcan.c
字号:
/* the user should be call DrvCAN_EnterTestMode(CAN_TESTR_BASIC) and let CAN controller enter */
/* basic mode of test mode. Please notice IF1 Registers used as Tx Buffer in basic mode */
/*---------------------------------------------------------------------------------------------------------*/
int32_t DrvCAN_BasicSendMsg(STR_CANMSG_T* pCanMsg)
{
uint32_t i=0;
while(CAN->sMsgObj[0].CREQ.BUSY==1);
CAN->STATUS.TXOK = 0;
CAN->sMsgObj[0].u32CMASK = CAN_CMASK_WRRD;
if (pCanMsg->IdType == CAN_STD_ID)
{
/* standard ID*/
CAN->sMsgObj[0].u32ARB1 = 0;
CAN->sMsgObj[0].u32ARB2 = (((pCanMsg->Id)&0x7FF)<<2) ;
}
else
{
/* extended ID*/
CAN->sMsgObj[0].u32ARB1 = (pCanMsg->Id)&0xFFFF;
CAN->sMsgObj[0].u32ARB2 = ((pCanMsg->Id)&0x1FFF0000)>>16 | CAN_ARB2_XTD;
}
CAN->sMsgObj[0].ARB2.DIR = (pCanMsg->FrameType)?1:0;
CAN->sMsgObj[0].MCON.DLC = pCanMsg->DLC ;
CAN->sMsgObj[0].u32DAT_A1 = ((uint16_t)pCanMsg->Data[1]<<8) | pCanMsg->Data[0];
CAN->sMsgObj[0].u32DAT_A2 = ((uint16_t)pCanMsg->Data[3]<<8) | pCanMsg->Data[2];
CAN->sMsgObj[0].u32DAT_B1 = ((uint16_t)pCanMsg->Data[5]<<8) | pCanMsg->Data[4];
CAN->sMsgObj[0].u32DAT_B2 = ((uint16_t)pCanMsg->Data[7]<<8) | pCanMsg->Data[6];
/* request transmission*/
CAN->sMsgObj[0].CREQ.BUSY = 0;
if ( CAN->sMsgObj[0].CREQ.BUSY ==1 ) {
DEBUG_PRINTF("Cannot clear busy for sending ...\n");
return E_DRVCAN_ERR_TIMEOUT;
}
CAN->sMsgObj[0].CREQ.BUSY =1; // sending
for ( i=0; i<0xFFFFF; i++) {
if ( CAN->sMsgObj[0].CREQ.BUSY ==0) break;
}
if ( i >= 0xFFFFF ) {
DEBUG_PRINTF("Cannot send out...\n");
return E_DRVCAN_ERR_TIMEOUT;
}
return E_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvCAN_BasicReceiveMsg */
/* */
/* Parameter: */
/* pCanMsg: pointer to the message structure where message is copied. */
/* Returns: */
/* - E_SUCCESS: Reception OK */
/* - E_DRVCAN_NO_PENDING_MSG: No any message received */
/* Description: */
/* Get a message information in BASIC mode. This mode does not use the message RAM */
/* Using IF2 to get receive message information */
/*---------------------------------------------------------------------------------------------------------*/
int32_t DrvCAN_BasicReceiveMsg(STR_CANMSG_T* pCanMsg)
{
if (CAN->sMsgObj[1].MCON.NEWDAT == 0) /* In basic mode, receive data always save in IF2 */
{
return E_DRVCAN_NO_PENDING_MSG;
}
CAN->STATUS.RXOK = 0;
CAN->sMsgObj[1].u32CMASK = CAN_CMASK_ARB
| CAN_CMASK_CONTROL
| CAN_CMASK_DATAA
| CAN_CMASK_DATAB;
if (CAN->sMsgObj[1].ARB2.XTD == 0)
{
/* standard ID*/
pCanMsg->IdType = CAN_STD_ID;
pCanMsg->Id = (CAN->sMsgObj[1].u32ARB2 >> 2) & 0x07FF;
}
else
{
/* extended ID*/
pCanMsg->IdType = CAN_EXT_ID;
pCanMsg->Id = (CAN->sMsgObj[1].u32ARB2 & 0x1FFF)<<16;
pCanMsg->Id |= (uint32_t)CAN->sMsgObj[1].u32ARB1;
}
CAN->sMsgObj[1].ARB2.DIR = pCanMsg->FrameType?0:1;
pCanMsg->DLC = CAN->sMsgObj[1].MCON.DLC;
pCanMsg->Data[0] = CAN->sMsgObj[1].DAT_A1.DATA0;
pCanMsg->Data[1] = CAN->sMsgObj[1].DAT_A1.DATA1;
pCanMsg->Data[2] = CAN->sMsgObj[1].DAT_A2.DATA2;
pCanMsg->Data[3] = CAN->sMsgObj[1].DAT_A2.DATA3;
pCanMsg->Data[4] = CAN->sMsgObj[1].DAT_B1.DATA4;
pCanMsg->Data[5] = CAN->sMsgObj[1].DAT_B1.DATA5;
pCanMsg->Data[6] = CAN->sMsgObj[1].DAT_B2.DATA6;
pCanMsg->Data[7] = CAN->sMsgObj[1].DAT_B2.DATA7;
return E_SUCCESS;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvCAN_EnterInitMode */
/* */
/* Parameter: */
/* None */
/* Returns: */
/* None. */
/* Description: */
/* This function is used to set CAN to enter initialization mode and enable access bit timing */
/* register. After bit timing configuration ready, user must call DrvCAN_LeaveInitMode() */
/* to leave initialization mode and lock bit timing register to let new configuration */
/* take effect. */
/*---------------------------------------------------------------------------------------------------------*/
void DrvCAN_EnterInitMode(void)
{
CAN->CON.INIT = 1;
CAN->CON.CCE = 1;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvCAN_LeaveInitMode */
/* */
/* Parameter: */
/* None */
/* Returns: */
/* None. */
/* Description: */
/* This function is used to set CAN to leave initialization mode to let */
/* bit timing configuration take effect after configuration ready. */
/*---------------------------------------------------------------------------------------------------------*/
void DrvCAN_LeaveInitMode(void)
{
CAN->CON.INIT = 0;
CAN->CON.CCE = 0;
while ( CAN->CON.INIT==1); /* Check INIT bit is released */
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvCAN_EnterTestMode */
/* */
/* Parameter: */
/* u8TestMask: specifies the configuration in test modes */
/* CAN_TESTR_BASIC : Enable basic mode of test mode */
/* CAN_TESTR_SILENT : Enable silent mode of test mode */
/* CAN_TESTR_LBACK : Enable Loop Back Mode of test mode */
/* CAN_TESTR_TX0/CAN_TESTR_TX1: Control CAN_TX pin bit feild */
/* */
/* Returns: */
/* None. */
/* Description: */
/* Switchs the CAN into test mode. There are four test mode (BASIC/SILENT/LOOPBACK/ */
/* LOOPBACK combined SILENT/CONTROL_TX_PIN)could be selected. After setting test mode,user */
/* must call DrvCAN_LeaveInitMode() to let the setting take effect. */
/*---------------------------------------------------------------------------------------------------------*/
void DrvCAN_EnterTestMode(uint8_t u8TestMask)
{
CAN->CON.TEST = 1;
CAN->u32TEST = u8TestMask;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvCAN_LeaveTestMode */
/* */
/* Parameter: */
/* None. */
/* Returns: */
/* None. */
/* Description: */
/* This function is used to Leave the current test mode (switch into normal mode). */
/*---------------------------------------------------------------------------------------------------------*/
void DrvCAN_LeaveTestMode(void)
{
CAN->CON.TEST = 1;
CAN->u32TEST &= ~(CAN_TESTR_LBACK | CAN_TESTR_SILENT | CAN_TESTR_BASIC);
CAN->CON.TEST = 0;
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvCAN_IsNewDataReceived */
/* */
/* Parameter: */
/* u8MsgObj: specifies the Message object number, from 0 to 31. */
/* Returns: */
/* A non-zero value if the corresponding message object has a new data bit is set, else 0.*/
/* Description: */
/* This function is used to get the waiting status of a received message. */
/*---------------------------------------------------------------------------------------------------------*/
uint32_t DrvCAN_IsNewDataReceived(uint8_t u8MsgObj)
{
return (u8MsgObj < 16 ? CAN->u32NDAT1 & (1 << u8MsgObj) : CAN->u32NDAT2 & (1 << (u8MsgObj-16)));
}
/*---------------------------------------------------------------------------------------------------------*/
/* Function: DrvCAN_IsTxRqstPending */
/* */
/* Parameter: */
/* u8MsgObj: specifies the Message object number, from 0 to 31. */
/* Returns: */
/* A non-zero value if the corresponding message has an tx request pending, else 0. */
/* Description: */
/* This function is used to get the request pending status of a transmitted message. */
/*---------------------------------------------------------------------------------------------------------*/
uint32_t DrvCAN_IsTxRqstPending(uint8_t u8MsgObj)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -