/**
******************************************************************************
* @file xl_mcan.c
* @author Kirk ,xu.wang
* @version 4.5.2
* @date Fri Mar 26 17:29:12 2021
* @brief This file provide function about MCAN firmware program
******************************************************************************
* @attention
*
* 2019 by Chipways Communications,Inc. All Rights Reserved.
* This software is supplied under the terms of a license
* agreement or non-disclosure agreement with Chipways.
* Passing on and copying of this document,and communication
* of its contents is not permitted without prior written
* authorization.
*
*
© COPYRIGHT 2019 Chipways
******************************************************************************
*/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/* Includes ---------------------------------------------------------------*/
#include "xl_mcan.h"
/** @addtogroup XL6600_StdPeriph_Driver
* @{
*/
/** @defgroup MCAN MCAN Module
* @brief MCAN Driver Modules Library
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup MCAN_Private_Functions
* @{
*/
/**
* @brief ½«MCANÍâÉè¼Ä´æÆ÷È¥³õʼ»¯,¸´Î».
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @retval None.
*/
void MCAN_DeInit(MCAN_Type* MCANx)
{
/* Deinitializes to default reset values */
MCANx->CANMOD = 0x01;
MCANx->CANCMR = 0x00;
MCANx->CANBTR0 = 0x00;
MCANx->CANBTR1 = 0x00;
MCANx->CANIER = 0x00;
}
/**
* @brief ¸ù¾ÝÔÚMCAN_InitStructÖÐÖ¸¶¨²ÎÊý³õʼ»¯MCANÍâÉè.
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param MCAN_InitStruct: MCAN³õʼ»¯ÅäÖýṹÌå
* @retval None
*/
void MCAN_Init(MCAN_Type* MCANx, const MCAN_InitTypeDef* MCAN_InitStruct)
{
/* enter reset mode */
MCAN_SetMode(MCANx,MCAN_RESETMODE);
/* Set the nominal bit timing register */
MCANx->CANBTR0 &= ~(MCAN_CANBTR0_BRP_MASK | MCAN_CANBTR0_SJW_MASK);
MCANx->CANBTR0 |= ((MCAN_InitStruct->MCAN_BRP) | (MCAN_InitStruct->MCAN_SJW << MCAN_CANBTR0_SJW_SHIFT));
MCANx->CANBTR1 &= ~(MCAN_CANBTR1_TSEG1_MASK | MCAN_CANBTR1_TSEG2_MASK |\
MCAN_CANBTR1_SAMP_MASK);
MCANx->CANBTR1 |= ((MCAN_InitStruct->MCAN_TSEG1) | (MCAN_InitStruct->MCAN_TSEG2 << MCAN_CANBTR1_TSEG2_SHIFT)|\
(MCAN_InitStruct->MCAN_SAMP << MCAN_CANBTR1_SAMP_SHIFT));
/* Set the FD data bit timing register */
MCANx->CANFDBTR0 &= ~(MCAN_CANFDBTR0_FDBRP_MASK | MCAN_CANFDBTR0_FDSJW_MASK);
MCANx->CANFDBTR0 |= ((MCAN_InitStruct->MCAN_FDBRP) | (MCAN_InitStruct->MCAN_FDSJW << MCAN_CANFDBTR0_FDSJW_SHIFT));
MCANx->CANFDBTR1 &= ~(MCAN_CANFDBTR1_FDTSEG1_MASK | MCAN_CANFDBTR1_FDTSEG2_MASK |\
MCAN_CANFDBTR1_FDSAMP_MASK);
MCANx->CANFDBTR1 |= ((MCAN_InitStruct->MCAN_FDTSEG1) | (MCAN_InitStruct->MCAN_FDTSEG2 << MCAN_CANFDBTR1_FDTSEG2_SHIFT)|\
(MCAN_InitStruct->MCAN_FDSAMP << MCAN_CANFDBTR1_FDSAMP_SHIFT));
/* clear reset mode if in this mode*/
MCANx->CANMOD &= ~MCAN_CANMOD_RM_MASK;
}
/**
* @brief MCANxʹÄÜ
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param State: MCANxʹÄÜ״̬
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg ENABLE: MCANxʹÄÜ
* @arg DISABLE: MCANxʧÄÜ
* @retval None.
*/
void MCAN_Enable(MCAN_Type* MCANx, FunctionalState NewState)
{
if(NewState == ENABLE)
{
MCANx->CANCMR |= MCAN_CANCMR_EN_MASK;
}
else
{
MCANx->CANCMR &= ~MCAN_CANCMR_EN_MASK;
}
}
/**
* @brief ÆôÓûò½ûÓÃMCAN FD
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param State: MCANx FDʹÄÜ״̬
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg ENABLE: MCANx FDʹÄÜ
* @arg DISABLE: MCANx FDʧÄÜ
* @retval None.
*/
void MCAN_FDCmd(MCAN_Type* MCANx, FunctionalState NewState)
{
if(NewState != DISABLE )
{
/* Enable the can FD */
MCANx->CANMOD |= MCAN_CANMOD_FDM_MASK ;
}
else
{
/* Disable the can FD */
MCANx->CANMOD &= ~MCAN_CANMOD_FDM_MASK ;
}
}
/**
* @brief ÔÚFDģʽÏÂÑ¡Ôñ·¢Ë͸ñʽÀàÐÍ¡£
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param FdFormat: ÔÚFDģʽÏÂÑ¡Ôñ·¢Ë͸ñʽÀàÐÍ¡£
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg MCAN_FDM_NOMFrame: ·¢ËÍ֡ΪÆÕͨCANÊý¾ÝÖ¡
* @arg MCAN_FDM_FDFrame: ·¢ËÍ֡ΪCAN FDÖ¡
* @retval None.
*/
void MCAN_FDSendFormatSel(MCAN_Type* MCANx, uint8_t FdFormat)
{
if(FdFormat == MCAN_FDM_FDFrame )
{
/* send the FD frame in FD mode */
MCANx->CANMOD |= MCAN_CANMOD_FDTREN_MASK ;
}
else
{
/* send the nominal frame in FD mode */
MCANx->CANMOD &= ~MCAN_CANMOD_FDTREN_MASK ;
}
}
/**
* @brief ÉèÖò¹³¥Ê±¼ä¡£
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param CompensateTime:ÉèÖ÷¢ËÍÑÓʱ²¹³¥µÄʱ¼ä,·¶Î§Îª0x00~0x1F
* @retval None.
*/
void MCAN_FDTDCSet(MCAN_Type* MCANx, uint32_t CompensateTime)
{
/* set the compensation time */
MCANx->CANTDCS &= ~MCAN_CANTDCS_TDCT_MASK;
MCANx->CANTDCS |= (CompensateTime & (uint32_t)0x1F);
}
/**
* @brief ÆôÓûò½ûÓÃMCAN FDÑÓʱ²¹³¥¹¦ÄÜ
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param NewState: Ñ¡Ôñ״̬
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg ENABLE: ʹÄÜMCAN FDÑÓʱ²¹³¥¹¦ÄÜ
* @arg DISABLE: ʧÄÜMCAN FDÑÓʱ²¹³¥¹¦ÄÜ
* @retval None.
*/
void MCAN_FDTDCENCmd(MCAN_Type* MCANx, FunctionalState NewState)
{
if(NewState != DISABLE )
{
/* Enable the FD time delay compensation feature */
MCANx->CANMOD |= MCAN_CANMOD_FDTDCEN_MASK ;
}
else
{
/* Disable the FD time delay compensation feature */
MCANx->CANMOD &= ~MCAN_CANMOD_FDTDCEN_MASK ;
}
}
/**
* @brief ÉèÖÿª¹Øµã²¹³¥Ê±¼ä.
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param CompensateTime: ²¹³¥É趨ʱ¼ä,·¶Î§Îª0x00~0x7F.
* @retval None.
*/
void MCAN_FDHFCSet(MCAN_Type* MCANx, uint32_t CompensateTime)
{
/* set the compensation time */
MCANx->CANHFC &= ~MCAN_CANHFC_HFCT_MASK;
MCANx->CANHFC |= (CompensateTime & (uint32_t)0x7F);
}
/**
* @brief ¸ù¾ÝÔÚMCAN_FilterStructÖеÄÖ¸¶¨²ÎÊýÅäÖÃMCANÍâÉè¹ýÂËģʽ.
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param MCAN_FilterStruct:Ö¸Ïò°üº¬MCANÍâÉèÅäÖÃÐÅÏ¢µÄMCAN_FilterDef ½á¹¹µÄÖ¸Õë.
* @retval None.
*/
void MCAN_FilterConfig(MCAN_Type* MCANx, const MCAN_FilterDef* MCAN_FilterStruct)
{
uint32_t MCAN_Mask;
uint32_t MCAN_ID;
/* enter reset mode */
MCAN_SetMode(MCANx,MCAN_RESETMODE);
/* Set the filter mode */
MCANx->CANMOD &=~MCAN_CANMOD_AFM_MASK;
MCANx->CANMOD |= (MCAN_FilterStruct->MCAN_FiltMode << MCAN_CANMOD_AFM_SHIFT);
/* config the accept and mask register */
/* if use single filter, 32bit filter */
if(MCAN_FilterStruct->MCAN_FiltMode==MCAN_Single_Filter)
{
/* ID(standard )+RTR=12 bit*/
if(MCAN_FilterStruct->MCAN_IDMode==MCAN_Standard_Frame)
{
MCAN_ID=(uint32_t)((MCAN_FilterStruct->MCAN_IDAR)<<21);
MCAN_Mask=(uint32_t)((MCAN_FilterStruct->MCAN_IDMR)<<21);
/* according to the accept rule */
MCANx->CANAR.CANACR[0]=(MCAN_ID>>24);
MCANx->CANAR.CANAMR[0]=(MCAN_Mask>>24);
MCANx->CANAR.CANACR[1]=(MCAN_ID>>16);
MCANx->CANAR.CANAMR[1]=(MCAN_Mask>>16);
MCANx->CANAR.CANACR[2]=(MCAN_ID>>8);
MCANx->CANAR.CANAMR[2]=0xFF; //data bytes1 do not care
MCANx->CANAR.CANACR[3]=(MCAN_ID);
MCANx->CANAR.CANAMR[3]=0xFF; //data bytes2 do not care
}
/* ID( extended)+RTR=30 bit*/
else if(MCAN_FilterStruct->MCAN_IDMode==MCAN_Extended_Frame)
{
MCAN_ID=(uint32_t)((MCAN_FilterStruct->MCAN_IDAR)<<3);
MCAN_Mask=(uint32_t)((MCAN_FilterStruct->MCAN_IDMR)<<3);
/* according to the accept rule */
MCANx->CANAR.CANACR[0]=(MCAN_ID>>24);
MCANx->CANAR.CANAMR[0]=(MCAN_Mask>>24);
MCANx->CANAR.CANACR[1]=(MCAN_ID>>16);
MCANx->CANAR.CANAMR[1]=(MCAN_Mask>>16);
MCANx->CANAR.CANACR[2]=(MCAN_ID>>8);
MCANx->CANAR.CANAMR[2]=(MCAN_Mask>>8);
MCANx->CANAR.CANACR[3]=(MCAN_ID);
MCANx->CANAR.CANAMR[3]=(MCAN_Mask);
}
else
{
MCAN_ID=(uint32_t)(MCAN_FilterStruct->MCAN_IDAR);
MCAN_Mask=(uint32_t)(MCAN_FilterStruct->MCAN_IDMR);
/* according to the accept rule */
MCANx->CANAR.CANACR[0]=(MCAN_ID>>24);
MCANx->CANAR.CANAMR[0]=(MCAN_Mask>>24);
MCANx->CANAR.CANACR[1]=(MCAN_ID>>16);
MCANx->CANAR.CANAMR[1]=(MCAN_Mask>>16);
MCANx->CANAR.CANACR[2]=(MCAN_ID>>8);
MCANx->CANAR.CANAMR[2]=(MCAN_Mask>>8);
MCANx->CANAR.CANACR[3]=(MCAN_ID);
MCANx->CANAR.CANAMR[3]=(MCAN_Mask);
}
}
/* else use dual filter, 16bit filter */
else
{
/* ID(standard )+RTR=12 bit*/
if(MCAN_FilterStruct->MCAN_IDMode==MCAN_Standard_Frame)
{
MCAN_ID=(uint32_t)((MCAN_FilterStruct->MCAN_IDAR)<<5);
MCAN_Mask=(uint32_t)((MCAN_FilterStruct->MCAN_IDMR)<<5);
/* according to the accept rule */
MCANx->CANAR.CANACR[0]=(MCAN_ID>>8);
MCANx->CANAR.CANAMR[0]=(MCAN_Mask>>8);
MCANx->CANAR.CANACR[1]=(MCAN_ID);
MCANx->CANAR.CANAMR[1]=(MCAN_Mask | 0x0000000Fu);
MCAN_ID=(uint32_t)((MCAN_FilterStruct->MCAN_DIDAR)<<5);
MCAN_Mask=(uint32_t)((MCAN_FilterStruct->MCAN_DIDMR)<<5);
MCANx->CANAR.CANACR[2]=(MCAN_ID>>8);
MCANx->CANAR.CANAMR[2]=(MCAN_Mask>>8);
MCANx->CANAR.CANACR[3]=(MCAN_ID);
MCANx->CANAR.CANAMR[3]=(MCAN_Mask| 0x0000000Fu);
}
/* ID( extended)+RTR=30 bit*/
else if(MCAN_FilterStruct->MCAN_IDMode==MCAN_Extended_Frame)
{
MCAN_ID=(uint32_t)((MCAN_FilterStruct->MCAN_IDAR)<<3);
MCAN_Mask=(uint32_t)((MCAN_FilterStruct->MCAN_IDMR)<<3);
/* according to the accept rule */
MCANx->CANAR.CANACR[0]=(MCAN_ID>>24);
MCANx->CANAR.CANAMR[0]=(MCAN_Mask>>24);
MCANx->CANAR.CANACR[1]=(MCAN_ID>>16);
MCANx->CANAR.CANAMR[1]=((MCAN_Mask>>16) | 0x0000000Fu);
MCAN_ID=(uint32_t)((MCAN_FilterStruct->MCAN_DIDAR)<<3);
MCAN_Mask=(uint32_t)((MCAN_FilterStruct->MCAN_DIDMR)<<3);
MCANx->CANAR.CANACR[2]=(MCAN_ID>>24);
MCANx->CANAR.CANAMR[2]=(MCAN_Mask>>24);
MCANx->CANAR.CANACR[3]=(MCAN_ID>>16);
MCANx->CANAR.CANAMR[3]=((MCAN_Mask>>16)| 0x0000000Fu);
}
else
{
MCAN_ID=(uint32_t)(MCAN_FilterStruct->MCAN_IDAR);
MCAN_Mask=(uint32_t)(MCAN_FilterStruct->MCAN_IDMR);
/* according to the accept rule */
MCANx->CANAR.CANACR[0]=(MCAN_ID>>24);
MCANx->CANAR.CANAMR[0]=(MCAN_Mask>>24);
MCANx->CANAR.CANACR[1]=(MCAN_ID>>16);
MCANx->CANAR.CANAMR[1]=(MCAN_Mask>>16);
MCANx->CANAR.CANACR[2]=(MCAN_ID>>8);
MCANx->CANAR.CANAMR[2]=(MCAN_Mask>>8);
MCANx->CANAR.CANACR[3]=(MCAN_ID);
MCANx->CANAR.CANAMR[3]=(MCAN_Mask);
}
}
/* clear reset mode if in this mode*/
MCANx->CANMOD &=~MCAN_CANMOD_RM_MASK;
}
/**
* @brief ¼ÓÔØ´«Êäµ½TX»º³åÇøËùÐèµÄÊý¾Ý¡£
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param TxMessage: Ö¸ÏòÒ»¸ö°üº¬MCAN Id£¬MCAN DLCºÍMCANÊý¾ÝµÄ½á¹¹¡£
* @retval None.
*/
void MCAN_LoadTransmitData(MCAN_Type *MCANx, const MCAN_MsgTypeDef* TxMessage)
{
uint8_t i = 0;
uint32_t datasize = 0;
/* Set up the Tx frame information */
MCANx->CANTB[0]= (0x000000FFu&((TxMessage->MCAN_FF << 7) | (TxMessage->MCAN_RTR << 6) | (TxMessage->MCAN_FDBRS << 5)| \
(TxMessage->MCAN_FDESI << 4) | (TxMessage->MCAN_DLC)));
/* get actually data size */
if((TxMessage->MCAN_DLC) < MCAN_DLC_DATASIZE12)
{
datasize=(TxMessage->MCAN_DLC);
}
else if ((TxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE12)
{
datasize=12;
}
else if ((TxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE16)
{
datasize=16;
}
else if ((TxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE20)
{
datasize=20;
}
else if ((TxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE24)
{
datasize=24;
}
else if ((TxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE32)
{
datasize=32;
}
else if ((TxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE48)
{
datasize=48;
}
else
{
datasize=64;
}
/* Set up the ID */
if (TxMessage->MCAN_FF == MCAN_Standard_Frame)
{
MCANx->CANTB[1]=(0xFFu&(TxMessage->MCAN_ID>>3));
MCANx->CANTB[2]=(0xF0u&((TxMessage->MCAN_ID<<5)|(TxMessage->MCAN_RTR<<4)));
/* Set up the data field */
for (i=0;iCANTB[i+3u] = (uint32_t)TxMessage->MCAN_Data[i];
}
}
else
{
MCANx->CANTB[1]=(0xFFu&(TxMessage->MCAN_ID>>21));
MCANx->CANTB[2]=(0xFFu&(TxMessage->MCAN_ID>>13));
MCANx->CANTB[3]=(0xFFu&(TxMessage->MCAN_ID>>5));
MCANx->CANTB[4]=(0xFCu&((TxMessage->MCAN_ID<<3)|(TxMessage->MCAN_RTR<<2)));
/* Set up the data field */
for (i=0;iCANTB[i+5u] = (uint32_t)TxMessage->MCAN_Data[i];
}
}
}
/**
* @brief ½ÓÊÕÊý¾Ý
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param RxMessage: Ö¸Ïò°üº¬MCAN Id, MCAN DLC, MCANÊý¾ÝµÄ½á¹¹½ÓÊÕÏûÏ¢µÄÖ¸Õë¡£
* @retval None.
*/
void MCAN_ReceiveData(MCAN_Type *MCANx, MCAN_MsgTypeDef* RxMessage)
{
uint8_t i=0;
uint32_t temp=0;
uint32_t datasize = 0;
/* Get the FF */
RxMessage->MCAN_FF = ((0x80u & MCANx->CANRB[0]) >> 7);
/* Get the RTR */
RxMessage->MCAN_RTR = (0x40u & MCANx->CANRB[0]);
/* Get the BRS */
RxMessage->MCAN_FDBRS = (0x20u & MCANx->CANRB[0]);
/* Get the ESI */
RxMessage->MCAN_FDESI = (0x10u & MCANx->CANRB[0]);
/* Get the DLC */
RxMessage->MCAN_DLC = (0x0Fu & MCANx->CANRB[0]);
/* get actually data size */
if((RxMessage->MCAN_DLC) < MCAN_DLC_DATASIZE12)
{
datasize=(RxMessage->MCAN_DLC);
}
else if ((RxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE12)
{
datasize=12;
}
else if ((RxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE16)
{
datasize=16;
}
else if ((RxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE20)
{
datasize=20;
}
else if ((RxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE24)
{
datasize=24;
}
else if ((RxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE32)
{
datasize=32;
}
else if ((RxMessage->MCAN_DLC) == MCAN_DLC_DATASIZE48)
{
datasize=48;
}
else
{
datasize=64;
}
/* Get the Id and data */
if (RxMessage->MCAN_FF == MCAN_Standard_Frame)
{
/* Get the Id */
temp = MCANx->CANRB[1]<<8;
RxMessage->MCAN_ID = (0x7FFu & ((temp| MCANx->CANRB[2])>>5));
/* Get the data field */
for (i=0;iMCAN_Data[i] = (uint8_t)MCANx->CANRB[i+3u];
}
}
else
{
/* Get the Id */
temp = MCANx->CANRB[1]<<24;
temp |= MCANx->CANRB[2]<<16;
temp |= MCANx->CANRB[3]<<8;
temp |= MCANx->CANRB[4];
temp >>=3;
RxMessage->MCAN_ID = 0x1FFFFFFFu & temp;
/* Get the data field */
for (i=0;iMCAN_Data[i] = (uint8_t)MCANx->CANRB[i+5u];
}
}
/* RX finished, return to Normal Operating Mode */
MCAN_SetCmd(MCANx,MCAN_ReleaseReceiveBuffer); //Aaron he add 20180328
}
/**
* @brief ÅäÖÃCAN¿ØÖÆÆ÷µÄģʽ
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param MCAN_ModeType: ģʽѡÔñ
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg MCAN_NORMALMODE: ˯Ãßģʽ
* @arg MCAN_RESETMODE: seltestģʽ
* @arg MCAN_LISTENONLYMODE: listen nolyģʽ
* @arg MCAN_SELFTESTMODE: ÖØÖÃģʽ
* @arg MCAN_SLEEPMODE: Õý³£²Ù×÷ģʽ
* @retval None.
*/
void MCAN_SetMode(MCAN_Type *MCANx, uint8_t MCAN_ModeType)
{
switch(MCAN_ModeType)
{
case MCAN_NORMALMODE: /* enable the normal mode */
/* clear reset mode if in this mode*/
MCANx->CANMOD &=~MCAN_CANMOD_RM_MASK;
/* clear listen only mode if in this mode*/
MCANx->CANMOD &=~MCAN_CANMOD_LOM_MASK;
/* clear self test mode if in this mode*/
MCANx->CANMOD &=~MCAN_CANMOD_STM_MASK;
/* clear sleep mode if in this mode*/
MCANx->CANMOD &=~MCAN_CANMOD_SM_MASK;
break;
case MCAN_RESETMODE:
/* set the reset mode*/
MCANx->CANMOD |= MCAN_CANMOD_RM_MASK;
break;
case MCAN_LISTENONLYMODE:
/* set the listen only mode*/
MCANx->CANMOD |=MCAN_CANMOD_LOM_MASK;
break;
case MCAN_SELFTESTMODE:
/* set the self test mode*/
MCANx->CANMOD |=MCAN_CANMOD_STM_MASK;
break;
case MCAN_SLEEPMODE:
/* enable wakeup interrupt */
MCAN_InterruptEn(MCANx,MCAN_WakeUpInterruptEn,ENABLE);
/* set the sleep mode */
MCANx->CANMOD |= MCAN_CANMOD_SM_MASK;
break;
default:
/* error if do not set mode */
break;
}
}
/**
* @brief »½ÐÑMCAN.
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @retval None.
*/
void MCAN_WakeUp(MCAN_Type *MCANx)
{
/* clear sleep mode */
MCANx->CANMOD &=~MCAN_CANMOD_SM_MASK;
}
/**
* @brief ÉèÖÃÃüÁîλÒÔÆô¶¯MCAN¿ØÖÆÆ÷´«Êä²ãÄڵIJÙ×÷
* @param MCANx: Ñ¡ÔñCANÍâÉè
* @param ÃüÁîÀàÐÍ£ºÖжÏÀàÐÍ
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg MCAN_TransmissionRequest: ·¢ËÍÇëÇó
* @arg MCAN_AbortTransmission£º´«ÊäÖÐÖ¹
* @arg MCAN_ReleaseReceiveBuffer£º ÊͷŽÓÊÕ»º³å
* @arg MCAN_ClearDataOverrun£º ÇåÁãÊý¾ÝÒç³ö
* @arg MCAN_SelfReceptionRequest£º×Ô½ÓÊÕÇëÇó
* @retval None
*/
void MCAN_SetCmd(MCAN_Type *MCANx, uint8_t MCAN_CommandType)
{
/* set the selected command */
MCANx->CANCMR |= MCAN_CommandType;
}
/**
* @brief Çå³ý½ÓÊÕÖжÏ.
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @retval None.
*/
void MCAN_ClearReceiveInterrupt(MCAN_Type *MCANx)
{
/* there is no further data to read in the Receive Buffer.*/
/* then realse the receive buffer meantime clear receive interrupt*/
MCAN_SetCmd(MCANx,MCAN_ReleaseReceiveBuffer);
}
/**
* @brief »ñÈ¡MCANxÍâÉèÖ¸¶¨×´Ì¬
* @param MCANx: Ñ¡ÔñMCANÍâÉè
* @param UART_StatusType: ״̬ÀàÐÍ
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg MCAN_ReceiveBufferStatus: ½ÓÊÕ»º³åÇø×´Ì¬
* @arg MCAN_DataOverrunStatus: Êý¾ÝÒç³ö״̬
* @arg MCAN_TransBufferStatus: ·¢ËÍ»º³åÇø×´Ì¬
* @arg MCAN_TransCompleteStatus: ´«ÊäÍê³É״̬
* @arg MCAN_ReceiveStatus: ½ÓÊÕ״̬
* @arg MCAN_TransmitStatus: ·¢ËÍ״̬
* @arg MCAN_ErrorStatus: ´íÎó״̬
* @arg MCAN_BusStatus: ×ÜÏß״̬
* @retval µ±Ç°×´Ì¬(TRUE or FALSE)
*/
FlagStatus MCAN_GetStatus(const MCAN_Type *MCANx, MCAN_StatusTypeDef MCAN_StatusType)
{
return (((MCANx->CANSR >> (uint8_t)MCAN_StatusType)&(uint32_t)0x01) != (uint32_t)0);
}
/**
* @brief »ñÈ¡MCANxÖ¸¶¨ÖжÏԴ״̬
* @param MCANx: Ñ¡ÔñMCANÍâÉè
* @param MCAN_InterruptFlgDef: ÖжÏÀàÐÍ
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg MCAN_ReceiveInterrupt: ½ÓÊÕÖжÏ
* @arg MCAN_TransmitInterrupt: ·¢ËÍÖжÏ
* @arg MCAN_ErrorWarningInterrupt: ´íÎ󾯸æÖжÏ
* @arg MCAN_DataOverrunInterrupt: Êý¾ÝÒç³öÖжÏ
* @arg MCAN_WakeUpInterrupt: »½ÐÑÖжÏ
* @arg MCAN_ErrorPassiveInterrupt: ´íÎó±»¶¯ÖжÏ
* @arg MCAN_ArbitrationLostInterrupt: ÖٲöªÊ§ÖжÏ
* @arg MCAN_BusErrorInterrupt: ×ÜÏß´íÎóÖжÏ
* @retval µ±Ç°×´Ì¬(TRUE or FALSE)
*/
ITStatus MCAN_GetInterruptFlg(const MCAN_Type *MCANx, MCAN_InterruptFlgDef MCAN_InterruptFlg)
{
return (((MCANx->CANIR >> (uint8_t)MCAN_InterruptFlg)&(uint32_t)0x01) != (uint32_t)0);
}
/**
* @brief ʹÄÜMCANÖ¸¶¨ÖжÏ
* @param MCANx: Ñ¡ÔñMCANÍâÉè
* @param MCAN_InterruptFlgDef: ÖжÏÀàÐÍ
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg MCAN_ReceiveInterruptEn: ½ÓÊÕÖжÏ
* @arg MCAN_TransmitInterruptEn: ·¢ËÍÖжÏ
* @arg MCAN_ErrorWarningInterruptEn: ´íÎ󾯸æÖжÏ
* @arg MCAN_DataOverrunInterruptEn: Êý¾ÝÒç³öÖжÏ
* @arg MCAN_WakeUpInterruptEn: »½ÐÑÖжÏ
* @arg MCAN_ErrorPassiveInterruptEn: ´íÎó±»¶¯ÖжÏ
* @arg MCAN_ArbitrationLostInterruptEn: ÖٲöªÊ§ÖжÏ
* @arg MCAN_BusErrorInterruptEn: ×ÜÏß´íÎóÖжÏ
* @param State: ÖжÏʹÄÜ״̬
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
* @arg ENABLE: ÖжÏʹÄÜ
* @arg DISABLE: ÖжÏʧÄÜ
* @retval None
*/
void MCAN_InterruptEn(MCAN_Type *MCANx, MCAN_InterruptEnDef MCAN_Interrupt, FunctionalState NewState)
{
if (NewState != DISABLE)
{
/* Enable the selected MCAN interrupts */
MCANx->CANIER |= ((uint32_t)1<<(uint8_t)MCAN_Interrupt);
}
else
{
/* Disable the selected MCAN interrupts */
MCANx->CANIER &= ~((uint32_t)1<<(uint8_t)MCAN_Interrupt);
}
}
/**
* @brief ·µ»ØMCANxÖٲöªÊ§²¶»ñ(ALC).
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @retval Arbitration Lost position.·µ»ØÖٲöªÊ§Î»Öá£
*/
uint8_t MCAN_ArbitrationLostCap(const MCAN_Type *MCANx)
{
/* Return the Arbitration Lost*/
return (uint8_t)MCANx->CANALC;
}
/**
* @brief ·µ»ØÓйØ×ÜÏßÉÏ´íÎóÀàÐͺÍλÖõÄÐÅÏ¢¡£
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param MCAN_BusErrorCapture: Ö¸Ïò°üº¬MCANÍâÉèÅäÖÃÐÅÏ¢µÄMCAN_BusErrorCaptureDef½á¹¹µÄÖ¸Õë¡£
* @retval None.
*/
uint8_t MCAN_GetBusErrorType(const MCAN_Type *MCANx, MCAN_BusErrorCaptureDef MCAN_BusErrorCapture)
{
uint8_t errorcap=0;
/* Get the error position */
if(MCAN_BusErrorCapture==MCAN_BusErrorPosition)
{
errorcap = (uint8_t)(MCANx->CANECC & MCAN_CANECC_SEGMENT_MASK);
}
/* Get the error direction */
else if(MCAN_BusErrorCapture==MCAN_BusErrorDirection)
{
errorcap = (uint8_t)((MCANx->CANECC & MCAN_CANECC_DIR_MASK)>>5);
}
/* Get the error type */
else //(Can_BusErrorCapture==MCAN_BusErrorType)
{
errorcap = (uint8_t)((MCANx->CANECC & MCAN_CANECC_ERROR_MASK)>>6);
}
/* Return the Error Information on the bus*/
return errorcap;
}
/**
* @brief ·µ»ØMCANx½ÓÊÕ´íÎó¼ÆÊýÆ÷ (RXERR).
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @retval Receive Error Counter.·µ»Ø½ÓÊÕµ½µÄ´íÎó¼ÆÊýÆ÷ ¡£
*/
uint8_t MCAN_GetReceiveErrorCounter(const MCAN_Type *MCANx)
{
/* Return the Receive Error Counter*/
return (uint8_t)MCANx->CANRXERR;
}
/**
* @brief ·µ»ØMCANx Tramsmit´íÎó¼ÆÊýÆ÷ (TXERR).
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @retval Transmit Error Counter.·µ»ØCANx Tramsmit´íÎó¼ÆÊýÆ÷ ¡£
*/
uint8_t MCAN_GetTransmitErrorCounter(const MCAN_Type *MCANx)
{
/* Return the Transmit Error Counter*/
return (uint8_t)(MCANx->CANTXERR);
}
/**
* @brief ·µ»ØMCANx½ÓÊÕÐÅÏ¢¼ÆÊýÆ÷(RMC).
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @retval Receive Message Counter.·µ»Ø½ÓÊÕÐÅÏ¢¼ÆÊýÆ÷¡£
*/
uint8_t MCAN_GetReceiveMessageCounter(const MCAN_Type *MCANx)
{
/* Return the Receive Message Counter*/
return (uint8_t)(MCANx->CANRMC);
}
/**
* @brief ÔÚÖØÖÃģʽ¸Ä±ä´íÎóÉèÖÃ.
* @param MCANx: Ñ¡ÔñMCANÍâÉè.
* @param MCAN_ErrorSetting: Ö¸Ïò°üº¬MCANÍâÉèÅäÖÃÐÅÏ¢µÄMCAN_ErrorSettingDef½á¹¹µÄÖ¸Õë¡£
* @retval None.
*/
void MCAN_ErrorSettingModify(MCAN_Type *MCANx, const MCAN_ErrorSettingDef *MCAN_ErrorSetting)
{
/* modify the error warning limit in Reset Mode */
MCANx->CANEWLR &= ~MCAN_CANEWLR_EWL_MASK;
MCANx->CANEWLR |= (MCAN_ErrorSetting->MCAN_ErrorWarningLimit);
/* modify the receive error in Reset Mode */
MCANx->CANRXERR &= ~MCAN_CANRXERR_RXERR_MASK;
MCANx->CANRXERR |= (MCAN_ErrorSetting->MCAN_ReceiveErrorCount);
/* modify the transimit error in Reset Mode */
MCANx->CANTXERR &= ~MCAN_CANTXERR_TXERR_MASK;
MCANx->CANTXERR |= (MCAN_ErrorSetting->MCAN_TranmitErrorCount);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */