/*! * @file apm32f10x_can.c * * @brief This file provides all the CAN firmware functions * * @version V1.0.1 * * @date 2021-03-23 * */ #include "apm32f10x_can.h" #include "apm32f10x_rcm.h" /** @addtogroup Peripherals_Library Standard Peripheral Library @{ */ /** @addtogroup CAN_Driver CAN Driver @{ */ /** @addtogroup CAN_Fuctions Fuctions @{ */ /*! * @brief Reset CAN registers * * @param can: Select the CAN peripheral. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_Reset(CAN_T* can) { if (can == CAN1) { RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_CAN1); RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_CAN1); } else if (can == CAN2) { RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_CAN2); RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_CAN2); } } /*! * @brief Initialization parameter configuration * * @param can: Select the CAN peripheral which can be CAN1 or CAN2. * * @param canConfig: Point to a CAN_Config_T structure. * * @retval ERROR or SUCCEESS * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_Config(CAN_T* can, CAN_Config_T* canConfig) { uint8_t initStatus = ERROR; uint32_t wait_ack = 0x00000000; /** Exit from sleep mode */ can->MCTRL_B.SLEEPREQ = BIT_RESET; /** Request initialisation */ can->MCTRL_B.INITREQ = BIT_SET; /** Wait the acknowledge */ while(((can->MSTS_B.INITFLG) != BIT_SET) && (wait_ack != 0x0000FFFF)) { wait_ack++; } /** Check acknowledge */ if(((can->MSTS_B.INITFLG) != BIT_SET)) { initStatus = ERROR; } else { if(canConfig->timeTrigComMode == ENABLE) { can->MCTRL_B.TTCM = BIT_SET; } else { can->MCTRL_B.TTCM = BIT_RESET; } if(canConfig->autoBusOffManage == ENABLE) { can->MCTRL_B.ALBOFFM = BIT_SET; } else { can->MCTRL_B.ALBOFFM = BIT_RESET; } if(canConfig->autoWakeUpMode == ENABLE) { can->MCTRL_B.AWUPCFG = BIT_SET; } else { can->MCTRL_B.AWUPCFG = BIT_RESET; } if(canConfig->nonAutoRetran == ENABLE) { can->MCTRL_B.ARTXMD = BIT_SET; } else { can->MCTRL_B.ARTXMD = BIT_RESET; } if(canConfig->rxFIFOLockMode == ENABLE) { can->MCTRL_B.RXFLOCK = BIT_SET; } else { can->MCTRL_B.RXFLOCK = BIT_RESET; } if(canConfig->txFIFOPriority == ENABLE) { can->MCTRL_B.TXFPCFG = BIT_SET; } else { can->MCTRL_B.TXFPCFG = BIT_RESET; } /** Set the bit timing register */ can->BITTIM &= (uint32_t)0x3fffffff; can->BITTIM |= (uint32_t)canConfig->mode << 30; can->BITTIM_B.RSYNJW = canConfig->syncJumpWidth; can->BITTIM_B.TIMSEG1 = canConfig->timeSegment1; can->BITTIM_B.TIMSEG2 = canConfig->timeSegment2; can->BITTIM_B.BRPSC = canConfig->prescaler - 1; /** Request leave initialisation */ can->MCTRL_B.INITREQ = BIT_RESET; wait_ack = 0; /** Wait the acknowledge */ while(((can->MSTS_B.INITFLG) != BIT_RESET) && (wait_ack != 0x0000FFFF)) { wait_ack++; } /** Check acknowledge */ if(((can->MSTS_B.INITFLG) != BIT_RESET)) { initStatus = ERROR; } else { initStatus = SUCCESS; } } return initStatus; } /*! * @brief Congig the CAN peripheral according to the specified parameters in the filterConfig. * * @param can: Select the CAN peripheral which can be CAN1 or CAN2. * * @param filterConfig :Point to a CAN_FILTER_CONFIG_T structure. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_ConfigFilter(CAN_T* can, CAN_FILTER_CONFIG_T* filterConfig) { can->FCTRL_B.FINITEN = BIT_SET; can->FACT &= ~(1 << filterConfig->filterNumber); /** Filter Scale */ if(filterConfig->filterScale == CAN_FILTER_SCALE_16BIT) { /** 16-bit scale for the filter */ can->FSCFG &= ~(1 << filterConfig->filterNumber); can->sFilterRegister[filterConfig->filterNumber].FBANK1 = ((0x0000FFFF & filterConfig->filterMaskIdLow) << 16) | (0x0000FFFF & filterConfig->filterIdLow); can->sFilterRegister[filterConfig->filterNumber].FBANK2 = ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) | (0x0000FFFF & filterConfig->filterIdHigh); } if(filterConfig->filterScale == CAN_FILTER_SCALE_32BIT) { can->FSCFG |= (1 << filterConfig->filterNumber); can->sFilterRegister[filterConfig->filterNumber].FBANK1 = ((0x0000FFFF & filterConfig->filterIdHigh) << 16) | (0x0000FFFF & filterConfig->filterIdLow); can->sFilterRegister[filterConfig->filterNumber].FBANK2 = ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) | (0x0000FFFF & filterConfig->filterMaskIdLow); } /** Filter Mode */ if(filterConfig->filterMode == CAN_FILTER_MODE_IDMASK) { can->FMCFG &= ~(1 << filterConfig->filterNumber); } else { can->FMCFG |= (1 << filterConfig->filterNumber); } /** Filter FIFO assignment */ if(filterConfig->filterFIFO == CAN_FILTER_FIFO_0) { can->FFASS &= ~(1 << filterConfig->filterNumber); } if(filterConfig->filterFIFO == CAN_FILTER_FIFO_1) { can->FFASS |= (1 << filterConfig->filterNumber); } /** Filter activation */ if(filterConfig->filterActivation == ENABLE) { can->FACT |= (1 << filterConfig->filterNumber); } can->FCTRL_B.FINITEN = BIT_RESET; } /*! * @brief Initialize a CAN_Config_T structure with the initial value. * * @param canConfig :Point to a CAN_Config_T structure. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_ConfigStructInit(CAN_Config_T* canConfig) { canConfig->timeTrigComMode = DISABLE; canConfig->autoBusOffManage = DISABLE; canConfig->autoWakeUpMode = DISABLE; canConfig->nonAutoRetran = DISABLE; canConfig->rxFIFOLockMode = DISABLE; canConfig->txFIFOPriority = DISABLE; canConfig->mode = CAN_MODE_NORMAL; canConfig->syncJumpWidth = CAN_SJW_1; canConfig->timeSegment1 = CAN_TIME_SEGMENT1_4; canConfig->timeSegment2 = CAN_TIME_SEGMENT2_3; canConfig->prescaler = 1; } /*! * @brief Enables the DBG Freeze for CAN. * * @param can: Select the CAN peripheral. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_EnableDBGFreeze(CAN_T* can) { can->MCTRL_B.DBGFRZE = ENABLE; } /*! * @brief Disable the DBG Freeze for CAN. * * @param can: Select the CAN peripheral. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_DisableDBGFreeze(CAN_T* can) { can->MCTRL_B.DBGFRZE = DISABLE; } /*! * @brief Enables the CAN Time TriggerOperation communication mode. * * @param can: Select the CAN peripheral. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_EnableTTCComMode(CAN_T* can) { can->MCTRL_B.TTCM = ENABLE; can->sTxMailBox[0].TXDLEN_B.TXTS = BIT_SET; can->sTxMailBox[1].TXDLEN_B.TXTS = BIT_SET; can->sTxMailBox[2].TXDLEN_B.TXTS = BIT_SET; } /*! * @brief Disable the CAN Time TriggerOperation communication mode. * * @param can: Select the CAN peripheral. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_DisableTTCComMode(CAN_T* can) { can->MCTRL_B.TTCM = DISABLE; can->sTxMailBox[0].TXDLEN_B.TXTS = BIT_RESET; can->sTxMailBox[1].TXDLEN_B.TXTS = BIT_RESET; can->sTxMailBox[2].TXDLEN_B.TXTS = BIT_RESET; } /*! * @brief Initiates the transmission of a message. * * @param can: Select the CAN peripheral. * * @param TxMessage: pointer to a CAN_TX_MESSAGE_T structure. * * @retval The number of the mailbox which is used for transmission or 3 if No mailbox is empty. * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_TxMessage(CAN_T* can, CAN_TX_MESSAGE_T* TxMessage) { uint8_t transmit_milbox = 0; /** Select one empty transmit mailbox */ if((can->TXSTS & 0x04000000) == 0x04000000) { transmit_milbox = 0; } else if((can->TXSTS & 0x08000000) == 0x08000000) { transmit_milbox = 1; } else if((can->TXSTS & 0x10000000) == 0x10000000) { transmit_milbox = 2; } else { return 3; //!< No mailbox is empty } /** Set up the Id */ can->sTxMailBox[transmit_milbox].TXMID &= 0x00000001; if(TxMessage->typeID == CAN_TYPEID_STD) { can->sTxMailBox[transmit_milbox].TXMID |= (TxMessage->stdID << 21) | (TxMessage->remoteTxReq); } else { can->sTxMailBox[transmit_milbox].TXMID |= (TxMessage->extID << 3) | (TxMessage->typeID) | (TxMessage->remoteTxReq); } /** Set up the TXDLEN */ TxMessage->dataLengthCode &= 0x0F; can->sTxMailBox[transmit_milbox].TXDLEN &= (uint32_t)0xFFFFFFF0; can->sTxMailBox[transmit_milbox].TXDLEN |= TxMessage->dataLengthCode; /** Set up the data field */ can->sTxMailBox[transmit_milbox].TXMDL = ((uint32_t)TxMessage->data[3] << 24) | ((uint32_t)TxMessage->data[2] << 16) | ((uint32_t)TxMessage->data[1] << 8) | ((uint32_t)TxMessage->data[0]); can->sTxMailBox[transmit_milbox].TXMDH = ((uint32_t)TxMessage->data[7] << 24) | ((uint32_t)TxMessage->data[6] << 16) | ((uint32_t)TxMessage->data[5] << 8) | ((uint32_t)TxMessage->data[4]); /** Request transmission */ can->sTxMailBox[transmit_milbox].TXMID |= 0x00000001; return transmit_milbox; } /*! * @brief Checks the transmission of a message. * * @param can: Select the CAN peripheral. * * @param transmitMailbox: the number of the mailbox * * @retval state: 0: Status of transmission is Failed * 1: Status of transmission is Ok * 2: transmit pending * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_TxMessageStatus(CAN_T* can, CAN_TX_MAILBIX_T TxMailbox) { uint32_t state = 0; switch (TxMailbox) { case (CAN_TX_MAILBIX_0): state = can->TXSTS & (0x00000001 | 0x00000002 | 0x04000000); break; case (CAN_TX_MAILBIX_1): state = can->TXSTS & (0x00000100 | 0x00000200 | 0x08000000); break; case (CAN_TX_MAILBIX_2): state = can->TXSTS & (0x00010000 | 0x00020000 | 0x10000000); break; default: state = 0; break; } switch (state) { /** transmit pending */ case (0x0): state = 2; break; /* transmit failed */ case (0x00000001 | 0x04000000): state = 0; break; case (0x00000100 | 0x08000000): state = 0; break; case (0x00010000 | 0x10000000): state = 0; break; /* transmit succeeded */ case (0x00000001 | 0x00000002 | 0x04000000):state = 1; break; case (0x00000100 | 0x00000200 | 0x08000000):state = 1; break; case (0x00010000 | 0x00020000 | 0x10000000):state = 1; break; default: state = 0; break; } return (uint8_t) state; } /*! * @brief Cancels a transmit request. * * @param can: Select the CAN peripheral. * * @param mailBox: the number of the mailbox * This parameter can be one of the following values: * @arg CAN_TX_MAILBIX_0 : Tx mailbox 0 * @arg CAN_TX_MAILBIX_1 : Tx mailbox 1 * @arg CAN_TX_MAILBIX_2 : Tx mailbox 2 * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_CancelTxMailbox(CAN_T* can, CAN_TX_MAILBIX_T TxMailbox) { switch (TxMailbox) { case CAN_TX_MAILBIX_0: can->TXSTS_B.ABREQFLG0 = BIT_SET; break; case CAN_TX_MAILBIX_1: can->TXSTS_B.ABREQFLG1 = BIT_SET; break; case CAN_TX_MAILBIX_2: can->TXSTS_B.ABREQFLG2 = BIT_SET; break; default: break; } } /*! * @brief Receives a message and save to a CAN_RX_MESSAGE_T structure. * * @param can: Select the CAN peripheral. * * @param FIFONumber: Receive FIFO number. * This parameter can be one of the following values: * @arg CAN_RX_FIFO_0 : Receive FIFO 0 * @arg CAN_RX_FIFO_1 : Receive FIFO 1 * * @param RxMessage: pointer to a structure to receive the message. * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_RxMessage(CAN_T* can, CAN_RX_FIFO_T FIFONumber, CAN_RX_MESSAGE_T* RxMessage) { /* Get the Id */ RxMessage->typeID = ((uint8_t)0x04 & (can->sRxMailBox[FIFONumber].RXMID)); if(RxMessage->typeID == CAN_TYPEID_STD) { RxMessage->stdID = (can->sRxMailBox[FIFONumber].RXMID >> 21) & 0x000007FF; } else { RxMessage->extID = (can->sRxMailBox[FIFONumber].RXMID >> 3) & 0x1FFFFFFF; } RxMessage->remoteTxReq = can->sRxMailBox[FIFONumber].RXMID_B.RFTXREQ; RxMessage->dataLengthCode = can->sRxMailBox[FIFONumber].RXDLEN_B.DLCODE; RxMessage->filterMatchIndex = can->sRxMailBox[FIFONumber].RXDLEN_B.FMIDX; /** Get the data field */ RxMessage->data[0] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE1; RxMessage->data[1] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE2; RxMessage->data[2] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE3; RxMessage->data[3] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE4; RxMessage->data[4] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE5; RxMessage->data[5] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE6; RxMessage->data[6] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE7; RxMessage->data[7] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE8; if(FIFONumber == CAN_RX_FIFO_0) { can->RXF0_B.RFOM0 = BIT_SET; } else { can->RXF1_B.RFOM1 = BIT_SET; } } /*! * @brief Releases the specified FIFO. * * @param can: Select the CAN peripheral. * * @param FIFONumber: Receive FIFO number * This parameter can be one of the following values: * @arg CAN_RX_FIFO_0 : Receive FIFO 0 * @arg CAN_RX_FIFO_1 : Receive FIFO 1 * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_ReleaseFIFO(CAN_T* can, CAN_RX_FIFO_T FIFONumber) { if(FIFONumber == CAN_RX_FIFO_0) { can->RXF0_B.RFOM0 = BIT_SET; } else { can->RXF1_B.RFOM1 = BIT_SET; } } /*! * @brief Returns the number of pending messages. * * @param can: Select the CAN peripheral. * * @param FIFONumber: Receive FIFO number * This parameter can be one of the following values: * @arg CAN_RX_FIFO_0 : Receive FIFO 0 * @arg CAN_RX_FIFO_1 : Receive FIFO 1 * * @retval The number of pending message. * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_PendingMessage(CAN_T* can, CAN_RX_FIFO_T FIFONumber) { if(FIFONumber == CAN_RX_FIFO_0) { return can->RXF0 & 0x03; } else { return can->RXF1 & 0x03; } } /*! * @brief Select the CAN Operation mode * * @param can: Select the CAN peripheral. * * @param operatingMode: CAN Operating Mode * This parameter can be one of the following values: * @arg CAN_OPERATING_MODE_INIT : Initialization mode * @arg CAN_OPERATING_MODE_NORMAL: Normal mode * @arg CAN_OPERATING_MODE_SLEEP : sleep mode * * @retval modeState:status of the requested mode * 0:CAN failed entering the specific mode * 1:CAN Succeed entering the specific mode * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_OperatingMode(CAN_T* can, CAN_OPERATING_MODE_T operatingMode) { uint8_t states = 0; uint32_t time_out = 0x0000FFFF; if(operatingMode == CAN_OPERATING_MODE_INIT) { can->MCTRL_B.SLEEPREQ = BIT_RESET; can->MCTRL_B.INITREQ = BIT_SET; while((can->MSTS_B.INITFLG != BIT_SET && can->MSTS_B.SLEEPFLG != BIT_RESET) && (time_out != 0)) { time_out --; } if((can->MSTS_B.INITFLG == BIT_SET && can->MSTS_B.SLEEPFLG == BIT_RESET)) { states = 1; } } else if(operatingMode == CAN_OPERATING_MODE_NORMAL) { can->MCTRL_B.SLEEPREQ = BIT_RESET; can->MCTRL_B.INITREQ = BIT_RESET; time_out = 0x0000FFFF; while((can->MSTS_B.INITFLG != BIT_RESET || can->MSTS_B.SLEEPFLG != BIT_RESET) && (time_out != 0)) { time_out --; } if((can->MSTS_B.INITFLG == BIT_RESET || can->MSTS_B.SLEEPFLG == BIT_RESET)) { states = 1; } } else if(operatingMode == CAN_OPERATING_MODE_SLEEP) { can->MCTRL_B.SLEEPREQ = BIT_SET; can->MCTRL_B.INITREQ = BIT_RESET; time_out = 0x0000FFFF; while((can->MSTS_B.INITFLG != BIT_RESET && can->MSTS_B.SLEEPFLG != BIT_SET) && (time_out != 0)) { time_out --; } if((can->MSTS_B.INITFLG == BIT_RESET && can->MSTS_B.SLEEPFLG == BIT_SET)) { states = 1; } } return states ; } /*! * @brief Into the low power mode. * * @param can: Select the CAN peripheral. * * @retval status: Status of entering sleep mode. * 0: Enter sleep fail * 1: Enter sleep success * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_SleepMode(CAN_T* can) { can->MCTRL_B.SLEEPREQ = BIT_SET; can->MCTRL_B.INITREQ = BIT_RESET; if((can->MSTS_B.INITFLG == BIT_RESET && can->MSTS_B.SLEEPFLG == BIT_SET)) { return 1; } return 0; } /*! * @brief Wakes the CAN up. * * @param can: Select the CAN peripheral. * * @retval status: Status of waking the CAN up * 0: WakeUp CAN fail, * 1: WakeUp CAN success * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_WakeUpMode(CAN_T* can) { uint32_t time_out = 0x0000FFFF; can->MCTRL_B.SLEEPREQ = BIT_RESET; while((can->MSTS_B.SLEEPFLG != BIT_RESET) && (time_out != 0)) { time_out --; } if(can->MSTS_B.SLEEPFLG == BIT_RESET) { return 1; } return 0; } /*! * @brief Read the can's last error code (LERRC) * * @param can: Select the CAN peripheral. * * @retval The Last Error Code. * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_ReadLastErrorCode(CAN_T* can) { return can->ERRSTS_B.LERRC; } /*! * @brief Read the can Receive Error Counter(RXERRCNT) * * @param can: Select the CAN peripheral. * * @retval CAN Receive Error Counter. * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_ReadRxErrorCounter(CAN_T* can) { return can->ERRSTS_B.RXERRCNT; } /*! * @brief Read the LSB of the 9-bit can Transmit Error Counter(TXERRCNT). * * @param can: Select the CAN peripheral. * * @retval Least Significant Byte Of The 9-Bit Transmit Error Counter. * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_ReadLSBTxErrorCounter(CAN_T* can) { return can->ERRSTS_B.TXERRCNT; } /*! * @brief Enables the specified can interrupts. * * @param can: Select the CAN peripheral. * * @param interrupts: specifies the CAN interrupt sources * This parameter can be any combination of the following values: * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt * @arg CAN_INT_ERRW : Error warning Interrupt * @arg CAN_INT_ERRP : Error passive Interrupt * @arg CAN_INT_BOF : Bus-off Interrupt * @arg CAN_INT_LEC : Last error record code Interrupt * @arg CAN_INT_ERR : Error Interrupt * @arg CAN_INT_WUP : Wake-up Interrupt * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_EnableInterrupt(CAN_T* can, uint32_t interrupts) { can->INTEN |= interrupts; } /*! * @brief Disable the specified can interrupts. * * @param can: Select the CAN peripheral. * * @param interrupts: specifies the CAN interrupt sources * This parameter can be any combination of the following values: * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt * @arg CAN_INT_ERRW : Error warning Interrupt * @arg CAN_INT_ERRP : Error passive Interrupt * @arg CAN_INT_BOF : Bus-off Interrupt * @arg CAN_INT_LEC : Last error record code Interrupt * @arg CAN_INT_ERR : Error Interrupt * @arg CAN_INT_WUP : Wake-up Interrupt * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_DisableInterrupt(CAN_T* can, uint32_t interrupts) { can->INTEN &= ~interrupts; } /*! * @brief Read whether the specified CAN flag is set or not. * * @param can: Select the CAN peripheral. * * @param flag: specifies the CAN flag. * This parameter can be one of the following values: * @arg CAN_FLAG_ERRW : Error Warning Flag * @arg CAN_FLAG_ERRP : Error Passive Flag * @arg CAN_FLAG_BOF : Bus-Off Flag * @arg CAN_FLAG_LERRC : Last error record code Flag * @arg CAN_FLAG_WUPI : Wake up Flag * @arg CAN_FLAG_SLEEP : Sleep acknowledge Flag * @arg CAN_FLAG_F0MP : FIFO 0 Message Pending Flag * @arg CAN_FLAG_F0FULL : FIFO 0 Full Flag * @arg CAN_FLAG_F0OVR : FIFO 0 Overrun Flag * @arg CAN_FLAG_F1MP : FIFO 1 Message Pending Flag * @arg CAN_FLAG_F1FULL : FIFO 1 Full Flag * @arg CAN_FLAG_F1OVR : FIFO 1 Overrun Flag * @arg CAN_FLAG_REQC0 : Request MailBox0 Flag * @arg CAN_FLAG_REQC1 : Request MailBox1 Flag * @arg CAN_FLAG_REQC2 : Request MailBox2 Flag * * @retval flag staus: RESET or SET * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_ReadStatusFlag(CAN_T* can, CAN_FLAG_T flag) { uint8_t status = 0; if((flag & 0x00F00000) != RESET ) { if((can->ERRSTS & (flag & 0x000FFFFF)) != RESET) { status = SET; } else { status = RESET; } } else if((flag & 0x01000000) != RESET ) { if((can->MSTS & (flag & 0x000FFFFF)) != RESET ) { status = SET; } else { status = RESET ; } } else if((flag & 0x08000000) != RESET ) { if((can->TXSTS & (flag & 0x000FFFFF)) != RESET ) { status = SET; } else { status = RESET; } } else if((flag & 0x02000000) != RESET ) { if((can->RXF0 & (flag & 0x000FFFFF)) != RESET ) { status = SET; } else { status = RESET; } } else { if((can->RXF1 & (flag & 0x000FFFFF)) != RESET) { status = SET; } else { status = RESET; } } return status; } /*! * @brief Clears the CAN's pending flags. * * @param can: Select the CAN peripheral. * * @param flag: specifies the CAN flag. * This parameter can be one of the following values: * @arg CAN_FLAG_LERRC : Last error record code Flag * @arg CAN_FLAG_WUPI : Wake up Flag * @arg CAN_FLAG_SLEEP : Sleep acknowledge Flag * @arg CAN_FLAG_F0FULL: FIFO 0 Full Flag * @arg CAN_FLAG_F0OVR : FIFO 0 Overrun Flag * @arg CAN_FLAG_F1FULL: FIFO 1 Full Flag * @arg CAN_FLAG_F1OVR : FIFO 1 Overrun Flag * @arg CAN_FLAG_REQC0 : Request MailBox0 Flag * @arg CAN_FLAG_REQC1 : Request MailBox1 Flag * @arg CAN_FLAG_REQC2 : Request MailBox2 Flag * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_ClearStatusFlag(CAN_T* can, CAN_FLAG_T flag) { uint32_t flagtmp = 0; /** ERRSTS register */ if(flag == 0x30F00070) { can->ERRSTS = RESET; } else { flagtmp = flag & 0x000FFFFF; if((flag & 0x02000000) != RESET) { can->RXF0 = flagtmp; } else if((flag & 0x04000000) != RESET) { can->RXF1 = flagtmp; } else if((flag & 0x08000000) != RESET) { can->TXSTS = flagtmp; } else { can->MSTS = flagtmp; } } } /*! * @brief Read whether the specified can interrupt has occurred or not. * * @param can: Select the CAN peripheral. * * @param flag: specifies the CAN interrupt sources * This parameter can be one of the following values: * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt * @arg CAN_INT_ERRW : Error warning Interrupt * @arg CAN_INT_ERRP : Error passive Interrupt * @arg CAN_INT_BOF : Bus-off Interrupt * @arg CAN_INT_LEC : Last error record code Interrupt * @arg CAN_INT_ERR : Error Interrupt * @arg CAN_INT_WUP : Wake-up Interrupt * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt * * @retval status : SET or RESET * * @note CAN2 applies only to APM32F103xC device. */ uint8_t CAN_ReadIntFlag(CAN_T* can, CAN_INT_T flag) { uint8_t status = 0; if((can->INTEN & flag) != RESET) { switch (flag) { case CAN_INT_TXME: status = can->TXSTS_B.REQCFLG0 | can->TXSTS_B.REQCFLG1 | can->TXSTS_B.REQCFLG2; break; case CAN_INT_F0MP: status = can->RXF0_B.FMNUM0; break; case CAN_INT_F0FULL: status = can->RXF0_B.FFULLFLG0; break; case CAN_INT_F0OVR: status = can->RXF0_B.FOVRFLG0; break; case CAN_INT_F1MP: status = can->RXF1_B.FMNUM1; break; case CAN_INT_F1FULL: status = can->RXF1_B.FFULLFLG1; break; case CAN_INT_F1OVR: status = can->RXF1_B.FOVRFLG1; break; case CAN_INT_WUP: status = can->MSTS_B.WUPIFLG; break; case CAN_INT_SLEEP: status = can->MSTS_B.SLEEPIFLG; break; case CAN_INT_ERRW: status = can->ERRSTS_B.ERRWFLG; break; case CAN_INT_ERRP: status = can->ERRSTS_B.ERRPFLG; break; case CAN_INT_BOF: status = can->ERRSTS_B.BOFLG; break; case CAN_INT_LEC: status = can->ERRSTS_B.LERRC; break; case CAN_INT_ERR: status = can->MSTS_B.ERRIFLG; break; default: status = RESET; break; } } else { status = RESET; } return status; } /*! * @brief Clears the can's interrupt flag. * * @param can: Select the CAN peripheral. * * @param flag: Interrupt pending bit to clear * This parameter can be one of the following values: * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt * @arg CAN_INT_ERRW : Error warning Interrupt * @arg CAN_INT_ERRP : Error passive Interrupt * @arg CAN_INT_BOF : Bus-off Interrupt * @arg CAN_INT_LEC : Last error record code Interrupt * @arg CAN_INT_ERR : Error Interrupt * @arg CAN_INT_WUP : Wake-up Interrupt * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt * * @retval None * * @note CAN2 applies only to APM32F103xC device. */ void CAN_ClearIntFlag(CAN_T* can, CAN_INT_T flag) { switch (flag) { case CAN_INT_TXME: can->TXSTS_B.REQCFLG0 = BIT_SET; can->TXSTS_B.REQCFLG1 = BIT_SET; can->TXSTS_B.REQCFLG2 = BIT_SET; break; case CAN_INT_F0FULL: can->RXF0_B.FFULLFLG0 = BIT_SET; break; case CAN_INT_F0OVR: can->RXF0_B.FOVRFLG0 = BIT_SET; break; case CAN_INT_F1FULL: can->RXF1_B.FFULLFLG1 = BIT_SET; break; case CAN_INT_F1OVR: can->RXF1_B.FOVRFLG1 = BIT_SET; break; case CAN_INT_WUP: can->MSTS_B.WUPIFLG = BIT_SET; break; case CAN_INT_SLEEP: can->MSTS_B.SLEEPIFLG = BIT_SET; break; case CAN_INT_ERRW: can->MSTS_B.ERRIFLG = BIT_SET; break; case CAN_INT_ERRP: can->MSTS_B.ERRIFLG = BIT_SET; break; case CAN_INT_BOF: can->MSTS_B.ERRIFLG = BIT_SET; break; case CAN_INT_LEC: can->ERRSTS_B.LERRC = BIT_RESET; can->MSTS_B.ERRIFLG = BIT_SET; break; case CAN_INT_ERR: can->ERRSTS_B.LERRC = BIT_RESET; can->MSTS_B.ERRIFLG = BIT_SET; break; default: break; } } /**@} end of group CAN_Fuctions*/ /**@} end of group CAN_Driver*/ /**@} end of group Peripherals_Library*/