rt-thread-official/bsp/mm32f327x/Libraries/MM32F327x/HAL_Lib/Src/hal_can.c

697 lines
30 KiB
C

////////////////////////////////////////////////////////////////////////////////
/// @file hal_can.c
/// @author AE TEAM
/// @brief THIS FILE PROVIDES ALL THE CAN FIRMWARE FUNCTIONS.
////////////////////////////////////////////////////////////////////////////////
/// @attention
///
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
///
/// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
////////////////////////////////////////////////////////////////////////////////
// Define to prevent recursive inclusion
#define __HAL_CAN_C
// Files includes
#include "hal_can.h"
#include "hal_rcc.h"
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup MM32_Hardware_Abstract_Layer
/// @{
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup CAN_HAL
/// @{
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup CAN_Exported_Functions
/// @{
////////////////////////////////////////////////////////////////////////////////
/// @brief Deinitializes the CAN peripheral registers to their default reset
/// values.
/// @param can: select the CAN peripheral.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_DeInit(CAN_TypeDef* can)
{
exRCC_APB1PeriphReset(RCC_APB1ENR_CAN);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Initializes the CAN peripheral according to the specified
/// parameters in the CAN_InitStruct.
/// @param can: select the CAN peripheral.
/// @param CAN_InitStruct: pointer to a CAN_InitTypeDef structure that
/// contains the configuration information for the CAN peripheral.
/// @retval Constant indicates initialization succeed which will be
/// CANINITFAILED or CANINITOK.
////////////////////////////////////////////////////////////////////////////////
u8 CAN_Init(CAN_TypeDef* can, CAN_Basic_InitTypeDef* init_struct)
{
u8 InitStatus = CANINITFAILED;
can->BTR0 = ((u32)(init_struct->SJW) << 6) | ((u32)(init_struct->BRP));
can->BTR1 = ((u32)(init_struct->SAM) << 7) | ((u32)(init_struct->TESG2) << 4) | ((u32)(init_struct->TESG1));
if (init_struct->GTS == ENABLE) {
can->CMR |= (u32)CAN_SleepMode;
InitStatus = CANINITFAILED;
}
else {
can->CMR &= ~(u32)CAN_SleepMode;
InitStatus = CANINITOK;
}
(init_struct->GTS == ENABLE) ? (can->CMR |= (u32)CAN_SleepMode) : (can->CMR &= ~(u32)CAN_SleepMode);
can->CDR |=
((init_struct->CBP) << 6) | ((init_struct->RXINTEN) << 5) | ((init_struct->CLOSE_OPEN_CLK) << 3) | (init_struct->CDCLK);
return InitStatus;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Configures the CAN_Basic reception filter according to the specified
/// parameters in the basic_filter_init_struct.
/// @param basic_filter_init_struct: pointer to a CAN_Basic_FilterInitTypeDef
/// structure that contains the configuration information.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_FilterInit(CAN_Basic_FilterInitTypeDef* basic_filter_init_struct)
{
// Filter Mode
CAN1->ACR = basic_filter_init_struct->CAN_FilterId;
CAN1->AMR = basic_filter_init_struct->CAN_FilterMaskId;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Fills each init_struct member with its default value.
/// @param init_struct : pointer to a CAN_Basic_InitTypeDef structure which will be initialized.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_StructInit(CAN_Basic_InitTypeDef* init_struct)
{
// Reset CAN_Basic init structure parameters values
// initialize the BRP member(where can be set with (0..63))
init_struct->BRP = 0x0;
// initialize the SJW member(where can be set with (0..3))
init_struct->SJW = 0x0;
// Initialize the TESG1 member(where can be set with (0..15))
init_struct->TESG1 = 0x0;
// Initialize the TESG2 member(where can be set with(0..7))
init_struct->TESG2 = 0x0;
// Initialize the SAM member(where can be set (SET or RESET))
init_struct->SAM = RESET;
// Initialize the GTS member to Sleep Mode(where can be set (ENABLE or
// DISABLE))
init_struct->GTS = DISABLE;
// Initialize the external pin CLKOUT frequence
init_struct->CDCLK = 0x0;
// Initialize the external clk is open or close
init_struct->CLOSE_OPEN_CLK = 0x0;
// Initialize the TX1 pin work as rx interrupt output
init_struct->RXINTEN = 0x0;
// Initialize the CBP of CDR register
init_struct->CBP = 0x0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Enables or disables the specified CAN interrupts.
/// @param can: select the CAN peripheral.
/// @param it: specifies the CAN interrupt sources to be enabled or
/// disabled.
/// This parameter can be: CAN_IT_OIE, CAN_IT_EIE, CAN_IT_TIE,
/// CAN_IT_RIE.
/// @param state: new state of the CAN interrupts.
/// This parameter can be: ENABLE or DISABLE.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_ITConfig(CAN_TypeDef* can, u32 it, FunctionalState state)
{
(state) ? (can->CR |= it) : (can->CR &= ~it);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Initiates and transmits a CAN frame message.
/// @param can:select the CAN peripheral.
/// @param TxMessage: pointer to a structure which contains CAN Id, CAN DLC and
/// CAN data.
/// @retval CANTXOK if the CAN driver transmits the message
////////////////////////////////////////////////////////////////////////////////
u8 CAN_Transmit(CAN_TypeDef* can, CanBasicTxMsg* basic_transmit_message)
{
can->TXID0 = (basic_transmit_message->IDH);
can->TXID1 = (basic_transmit_message->IDL << 5) | (basic_transmit_message->RTR << 4) | (basic_transmit_message->DLC);
if ((FunctionalState)(basic_transmit_message->RTR) != ENABLE) {
can->TXDR0 = basic_transmit_message->Data[0];
can->TXDR1 = basic_transmit_message->Data[1];
can->TXDR2 = basic_transmit_message->Data[2];
can->TXDR3 = basic_transmit_message->Data[3];
can->TXDR4 = basic_transmit_message->Data[4];
can->TXDR5 = basic_transmit_message->Data[5];
can->TXDR6 = basic_transmit_message->Data[6];
can->TXDR7 = basic_transmit_message->Data[7];
}
can->CMR = CAN_CMR_TR;
return (can->SR & 0x01);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Cancels a transmit request.
/// @param can: select the CAN peripheral.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_CancelTransmit(CAN_TypeDef* can)
{
// abort transmission
can->CMR = CAN_AT;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Releases the specified receive FIFO.
/// @param can: select the CAN peripheral.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_FIFORelease(CAN_TypeDef* can)
{
// Release FIFO
can->CMR |= (u32)CAN_RRB;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Receives a correct CAN frame.
/// @param can: select the CAN peripheral.
/// @param RxMessage: pointer to a structure receive frame which contains CAN
/// Id,CAN DLC, CAN data and FMI number.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Receive(CAN_TypeDef* can, CanBasicRxMsg* basic_receive_message)
{
u16 tempid;
basic_receive_message->RTR = (u8)((can->RXID1) >> 4) & 0x1;
basic_receive_message->DLC = (u8)((can->RXID1) & 0xf);
tempid = (u16)(((can->RXID1) & 0xe0) >> 5);
tempid |= (u16)(can->RXID0 << 3);
basic_receive_message->ID = tempid;
basic_receive_message->Data[0] = CAN1->RXDR0;
basic_receive_message->Data[1] = CAN1->RXDR1;
basic_receive_message->Data[2] = CAN1->RXDR2;
basic_receive_message->Data[3] = CAN1->RXDR3;
basic_receive_message->Data[4] = CAN1->RXDR4;
basic_receive_message->Data[5] = CAN1->RXDR5;
basic_receive_message->Data[6] = CAN1->RXDR6;
basic_receive_message->Data[7] = CAN1->RXDR7;
CAN_FIFORelease(can);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Select the Sleep mode or not in Basic workmode
/// @param state to go into the Sleep mode or go out
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
u8 CAN_Sleep(CAN_TypeDef* can)
{
can->CMR |= CAN_SleepMode;
// At this step, sleep mode status
return (u8)((can->CMR & 0x10) == CAN_SleepMode) ? CANSLEEPOK : CANSLEEPFAILED;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Wakes the CAN up.
/// @param can: where x can be 1 to select the CAN peripheral.
/// @retval CANWAKEUPOK if sleep mode left, CANWAKEUPFAILED in an other case.
////////////////////////////////////////////////////////////////////////////////
u8 CAN_WakeUp(CAN_TypeDef* can)
{
// Wake up request
can->CMR &= ~CAN_SleepMode;
return (u8)((can->CMR & 0x01) == 0) ? CANWAKEUPOK : CANWAKEUPFAILED;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks whether the specified CAN flag is set or not.
/// @param can: select the CAN peripheral.
/// @param flag: specifies the flag to check.
/// This parameter can be one of the following values:
/// @arg CAN_STATUS_RBS: Receive buffer status
/// @arg CAN_STATUS_DOS: Data overflow status
/// @arg CAN_STATUS_TBS: Transmit buffer status
/// @arg CAN_STATUS_TCS: Transmit complete status
/// @arg CAN_STATUS_RS: Receiving status
/// @arg CAN_STATUS_TS: Transmiting status
/// @arg CAN_STATUS_ES: Error status
/// @arg CAN_STATUS_BS: bus status, close or open
/// @retval The new state of CAN_FLAG (SET or RESET).
////////////////////////////////////////////////////////////////////////////////
FlagStatus CAN_GetFlagStatus(CAN_TypeDef* can, u32 flag)
{
return (FlagStatus)(((can->SR & flag) == flag) ? SET : RESET);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks whether the specified CAN interrupt has occurred or not.
/// @param can: where x can be 1 to select the CAN peripheral.
/// @param it: specifies the CAN interrupt source to check.
/// This parameter can be one of the following values:
/// @arg CAN_IT_RI: Receive FIFO not empty Interrupt
/// @arg CAN_IT_TI: Transmit Interrupt
/// @arg CAN_IT_EI: ERROR Interrupt
/// @arg CAN_IT_DOI: Data voerflow Interrupt
/// @arg CAN_IT_WUI: Wakeup Interrupt
/// @arg CAN_IT_ALL: use it can enble all Interrupt
/// @retval The current state of it (SET or RESET).
////////////////////////////////////////////////////////////////////////////////
ITStatus CAN_GetITStatus(CAN_TypeDef* can, u32 it)
{
return (ITStatus)((can->IR & it) != it) ? RESET : SET;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Select the can work as peli mode or basic mode
/// @param can: where x can be 1 or 2 to to select the CAN peripheral.
/// @param CAN_MODE: specifies the work mode:CAN_BASICMode,CAN_PELIMode
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Mode_Cmd(CAN_TypeDef* can, u32 mode)
{
can->CDR |= mode;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Select the Reset mode or not
/// @param can: where x can be 1 or 2 to to select the CAN peripheral.
/// @param state to go into the Reset mode or go out
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_ResetMode_Cmd(CAN_TypeDef* can, FunctionalState state)
{
(state == ENABLE) ? (can->CR |= CAN_ResetMode) : (can->CR &= ~CAN_ResetMode);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Clear the data overflow.
/// @param can: where x can be 1 or 2 to to select the CAN peripheral.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_ClearDataOverflow(CAN_TypeDef* can)
{
can->CMR |= (u32)CAN_CDO;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Clears the CAN's IT pending.
/// @param can: where x can be 1 or 2 to to select the CAN peripheral.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_ClearITPendingBit(CAN_TypeDef* can)
{
u32 temp = 0;
temp = temp;
temp = can->IR; // read this register clear all interrupt
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Select the Sleep mode or not in Peli workmode
/// @param state to go into the Sleep mode or go out
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_SleepMode_Cmd(FunctionalState state)
{
(state == ENABLE) ? (CAN1_PELI->MOD |= CAN_SleepMode) : (CAN1_PELI->MOD &= ~CAN_SleepMode);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Fills each CAN1_PELI_InitStruct member with its default value.
/// @param init_struct : pointer to a CAN_Peli_InitTypeDef structure
/// which will be initialized.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_StructInit(CAN_Peli_InitTypeDef* init_struct)
{
//--------------- Reset CAN_Peli init structure parameters values
//---------------
init_struct->BRP = 0x0; // initialize the BRP member(where can be set with (0..63))
init_struct->SJW = 0x0; // initialize the SJW member(where can be set with (0..3))
init_struct->TESG1 = 0x0; // Initialize the TESG1 member(where can be set with (0..15))
init_struct->TESG2 = 0x0; // Initialize the TESG2 member(where can be set with(0..7))
init_struct->SAM = RESET; // Initialize the SAM member(where can be set (SET or RESET))
init_struct->LOM = DISABLE; // Initialize the LOM member
init_struct->STM = DISABLE; // Initialize the STM member
init_struct->SM = DISABLE; // Initialize the SM member
init_struct->SRR = DISABLE;
init_struct->EWLR = 0x96;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Initializes the CAN_Peli peripheral according to the specified
/// parameters in the init_struct.
/// @param init_struct: pointer to a CAN_Peli_InitTypeDef structure that
/// contains the configuration information for the CAN peripheral in the peli workmode.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_Init(CAN_Peli_InitTypeDef* init_struct)
{
CAN1_PELI->BTR0 = ((u32)init_struct->SJW << 6) | ((u32)init_struct->BRP);
CAN1_PELI->BTR1 = ((u32)init_struct->SAM << 7) | ((u32)init_struct->TESG2 << 4) | ((u32)init_struct->TESG1);
if (init_struct->LOM == ENABLE)
CAN1_PELI->MOD |= (u32)CAN_ListenOnlyMode;
else
CAN1_PELI->MOD &= ~(u32)CAN_ListenOnlyMode;
if (init_struct->STM == ENABLE)
CAN1_PELI->MOD |= (u32)CAN_SeftTestMode;
else
CAN1_PELI->MOD &= ~(u32)CAN_SeftTestMode;
if (init_struct->SM == ENABLE)
CAN1_PELI->MOD |= (u32)CAN_SleepMode;
else
CAN1_PELI->MOD &= ~(u32)CAN_SleepMode;
CAN1_PELI->EWLR = (u32)init_struct->EWLR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Configures the CAN_Peli reception filter according to the specified
/// parameters in the peli_filter_init_struct.
/// @param peli_filter_init_struct: pointer to a CAN_Peli_FilterInitTypeDef
/// structure that contains the configuration information.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_FilterInit(CAN_Peli_FilterInitTypeDef* peli_filter_init_struct)
{
(peli_filter_init_struct->AFM == CAN_FilterMode_Singal) ? (CAN1_PELI->MOD |= (u32)CAN_FilterMode_Singal)
: (CAN1_PELI->MOD &= (u32)CAN_FilterMode_Double);
CAN1_PELI->FF = peli_filter_init_struct->CAN_FilterId0;
CAN1_PELI->ID0 = peli_filter_init_struct->CAN_FilterId1;
CAN1_PELI->ID1 = peli_filter_init_struct->CAN_FilterId2;
CAN1_PELI->DATA0 = peli_filter_init_struct->CAN_FilterId3;
CAN1_PELI->DATA1 = peli_filter_init_struct->CAN_FilterMaskId0;
CAN1_PELI->DATA2 = peli_filter_init_struct->CAN_FilterMaskId1;
CAN1_PELI->DATA3 = peli_filter_init_struct->CAN_FilterMaskId2;
CAN1_PELI->DATA4 = peli_filter_init_struct->CAN_FilterMaskId3;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Fills each peli_filter_init_struct member with its default value.
/// @param peli_filter_init_struct: pointer to a CAN_InitTypeDef structure
/// which ill be initialized.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_FilterStructInit(CAN_Peli_FilterInitTypeDef* peli_filter_init_struct)
{
peli_filter_init_struct->CAN_FilterId0 = 0;
peli_filter_init_struct->CAN_FilterId1 = 0;
peli_filter_init_struct->CAN_FilterId2 = 0;
peli_filter_init_struct->CAN_FilterId3 = 0;
peli_filter_init_struct->CAN_FilterMaskId0 = 0;
peli_filter_init_struct->CAN_FilterMaskId1 = 0;
peli_filter_init_struct->CAN_FilterMaskId2 = 0;
peli_filter_init_struct->CAN_FilterMaskId3 = 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Initiates and transmits a CAN frame message.
/// @param TxMessage: pointer to a structure which contains CAN Id, CAN DLC and
/// CAN data.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_Transmit(CanPeliTxMsg* peli_transmit_message)
{
CAN1_PELI->FF = (peli_transmit_message->FF << 7) | (peli_transmit_message->RTR << 6) | (peli_transmit_message->DLC);
if (((FunctionalState)peli_transmit_message->FF) != ENABLE) {
CAN1_PELI->ID0 = (peli_transmit_message->IDHH);
CAN1_PELI->ID1 = (peli_transmit_message->IDHL & 0xE0);
if ((FunctionalState)(peli_transmit_message->RTR) != ENABLE) {
CAN1_PELI->DATA0 = peli_transmit_message->Data[0];
CAN1_PELI->DATA1 = peli_transmit_message->Data[1];
CAN1_PELI->DATA2 = peli_transmit_message->Data[2];
CAN1_PELI->DATA3 = peli_transmit_message->Data[3];
CAN1_PELI->DATA4 = peli_transmit_message->Data[4];
CAN1_PELI->DATA5 = peli_transmit_message->Data[5];
CAN1_PELI->DATA6 = peli_transmit_message->Data[6];
CAN1_PELI->DATA7 = peli_transmit_message->Data[7];
}
}
else {
CAN1_PELI->ID0 = peli_transmit_message->IDHH;
CAN1_PELI->ID1 = peli_transmit_message->IDHL;
CAN1_PELI->DATA0 = peli_transmit_message->IDLH;
CAN1_PELI->DATA1 = peli_transmit_message->IDLL;
if ((FunctionalState)(peli_transmit_message->RTR) != ENABLE) {
CAN1_PELI->DATA2 = peli_transmit_message->Data[0];
CAN1_PELI->DATA3 = peli_transmit_message->Data[1];
CAN1_PELI->DATA4 = peli_transmit_message->Data[2];
CAN1_PELI->DATA5 = peli_transmit_message->Data[3];
CAN1_PELI->DATA6 = peli_transmit_message->Data[4];
CAN1_PELI->DATA7 = peli_transmit_message->Data[5];
CAN1_PELI->DATA8 = peli_transmit_message->Data[6];
CAN1_PELI->DATA9 = peli_transmit_message->Data[7];
}
}
(CAN1_PELI->MOD & CAN_MOD_STM) ? (CAN1->CMR = CAN_CMR_GTS | CAN_CMR_AT) : (CAN1->CMR = CAN_CMR_TR | CAN_CMR_AT);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Initiates and transmits a CAN frame message.
/// @param TxMessage: pointer to a structure which contains CAN Id, CAN DLC and
/// CAN data.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_TransmitRepeat(CanPeliTxMsg* peli_transmit_message)
{
CAN1_PELI->FF = (peli_transmit_message->FF << 7) | (peli_transmit_message->RTR << 6) | (peli_transmit_message->DLC);
if (((FunctionalState)peli_transmit_message->FF) != ENABLE) {
CAN1_PELI->ID0 = (peli_transmit_message->IDHH);
CAN1_PELI->ID1 = (peli_transmit_message->IDHL & 0xE0);
if ((FunctionalState)(peli_transmit_message->RTR) != ENABLE) {
CAN1_PELI->DATA0 = peli_transmit_message->Data[0];
CAN1_PELI->DATA1 = peli_transmit_message->Data[1];
CAN1_PELI->DATA2 = peli_transmit_message->Data[2];
CAN1_PELI->DATA3 = peli_transmit_message->Data[3];
CAN1_PELI->DATA4 = peli_transmit_message->Data[4];
CAN1_PELI->DATA5 = peli_transmit_message->Data[5];
CAN1_PELI->DATA6 = peli_transmit_message->Data[6];
CAN1_PELI->DATA7 = peli_transmit_message->Data[7];
}
}
else {
CAN1_PELI->ID0 = peli_transmit_message->IDHH;
CAN1_PELI->ID1 = peli_transmit_message->IDHL;
CAN1_PELI->DATA0 = peli_transmit_message->IDLH;
CAN1_PELI->DATA1 = peli_transmit_message->IDLL;
if ((FunctionalState)(peli_transmit_message->RTR) != ENABLE) {
CAN1_PELI->DATA2 = peli_transmit_message->Data[0];
CAN1_PELI->DATA3 = peli_transmit_message->Data[1];
CAN1_PELI->DATA4 = peli_transmit_message->Data[2];
CAN1_PELI->DATA5 = peli_transmit_message->Data[3];
CAN1_PELI->DATA6 = peli_transmit_message->Data[4];
CAN1_PELI->DATA7 = peli_transmit_message->Data[5];
CAN1_PELI->DATA8 = peli_transmit_message->Data[6];
CAN1_PELI->DATA9 = peli_transmit_message->Data[7];
}
}
(CAN1_PELI->MOD & CAN_MOD_STM) ? (CAN1->CMR = CAN_CMR_GTS | CAN_CMR_AT) : (CAN1->CMR = CAN_CMR_TR);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Receives a correct CAN frame.
/// @param RxMessage: pointer to a structure receive frame which contains CAN
/// Id,CAN DLC, CAN data and FMI number.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_Receive(CanPeliRxMsg* peli_receive_message)
{
u32 tempid;
peli_receive_message->FF = (CAN1_PELI->FF) >> 7;
peli_receive_message->RTR = ((CAN1_PELI->FF) >> 6) & 0x1;
peli_receive_message->DLC = (CAN1_PELI->FF) & 0xf;
if (((FunctionalState)peli_receive_message->FF) != ENABLE) {
tempid = (u32)(CAN1_PELI->ID1 >> 5);
tempid |= (u32)(CAN1_PELI->ID0 << 3);
peli_receive_message->ID = tempid;
peli_receive_message->Data[0] = CAN1_PELI->DATA0;
peli_receive_message->Data[1] = CAN1_PELI->DATA1;
peli_receive_message->Data[2] = CAN1_PELI->DATA2;
peli_receive_message->Data[3] = CAN1_PELI->DATA3;
peli_receive_message->Data[4] = CAN1_PELI->DATA4;
peli_receive_message->Data[5] = CAN1_PELI->DATA5;
peli_receive_message->Data[6] = CAN1_PELI->DATA6;
peli_receive_message->Data[7] = CAN1_PELI->DATA7;
}
else {
tempid = (u32)((CAN1_PELI->DATA1 & 0xf8) >> 3);
tempid |= (u32)(CAN1_PELI->DATA0 << 5);
tempid |= (u32)(CAN1_PELI->ID1 << 13);
tempid |= (u32)(CAN1_PELI->ID0 << 21);
peli_receive_message->ID = tempid;
peli_receive_message->Data[0] = CAN1_PELI->DATA2;
peli_receive_message->Data[1] = CAN1_PELI->DATA3;
peli_receive_message->Data[2] = CAN1_PELI->DATA4;
peli_receive_message->Data[3] = CAN1_PELI->DATA5;
peli_receive_message->Data[4] = CAN1_PELI->DATA6;
peli_receive_message->Data[5] = CAN1_PELI->DATA7;
peli_receive_message->Data[6] = CAN1_PELI->DATA8;
peli_receive_message->Data[7] = CAN1_PELI->DATA9;
}
CAN_FIFORelease(CAN1);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get available current informatoin in receive FIFO only in Peli
/// workmode.
/// @retval The value in reg RMC
////////////////////////////////////////////////////////////////////////////////
u32 CAN_Peli_GetRxFIFOInfo(void)
{
return CAN1_PELI->RMC;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Returns the CAN's last error code (LEC).
/// @retval Error code:
/// - CAN_ERRORCODE_NoErr: No Error
/// - CAN_ERRORCODE_StuffErr: Stuff Error
/// - CAN_ERRORCODE_FormErr: Form Error
/// - CAN_ERRORCODE_ACKErr : Acknowledgment Error
/// - CAN_ERRORCODE_BitRecessiveErr: Bit Recessive Error
/// - CAN_ERRORCODE_BitDominantErr: Bit Dominant Error
/// - CAN_ERRORCODE_CRCErr: CRC Error
/// - CAN_ERRORCODE_SoftwareSetErr: Software Set Error
////////////////////////////////////////////////////////////////////////////////
u8 CAN_Peli_GetLastErrorCode(void)
{
// Return the error code
return (u8)CAN1_PELI->ECC;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Returns the CAN Receive Error Counter (REC).
/// @note In case of an error during reception, this counter is incremented
/// by 1 or by 8 depending on the error condition as defined by the CAN
/// standard. After every successful reception, the counter is
/// decremented by 1 or reset to 120 if its value was higher than 128.
/// When the counter value exceeds 127, the CAN controller enters the
/// error passive state.
/// @retval CAN Receive Error Counter.
////////////////////////////////////////////////////////////////////////////////
u8 CAN_Peli_GetReceiveErrorCounter(void)
{
// Return the Receive Error Counter
return (u8)(CAN1_PELI->RXERR);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Returns the LSB of the 9-bit can Transmit Error Counter(TEC).
/// @retval LSB of the 8-bit CAN Transmit Error Counter.
////////////////////////////////////////////////////////////////////////////////
u8 CAN_Peli_GetLSBTransmitErrorCounter(void)
{
// Return the LSB of the 8-bit CAN Transmit Error Counter(TEC)
return (u8)(CAN1_PELI->TXERR);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Enables or disables the specified CAN interrupts in peli workmode.
/// @param it: specifies the CAN interrupt sources to be enabled or
/// disabled.
/// This parameter can be:
/// @arg CAN_IT_RI: Receive FIFO not empty Interrupt
/// @arg CAN_IT_TI: Transmit Interrupt
/// @arg CAN_IT_EI: ERROR Interrupt
/// @arg CAN_IT_DOI: Data voerflow Interrupt
/// @arg CAN_IT_WUI: Wakeup Interrupt
/// @arg CAN_IT_EPI(only Peli): passive error Interrupt
/// @arg CAN_IT_ALI(only Peli): arbiter lose Interrupt
/// @arg CAN_IT_BEI(only Peli): bus error Interrupt
/// @arg CAN_IT_ALL: use it can enble all Interrupt
/// @param state: new state of the CAN interrupts.
/// This parameter can be: ENABLE or DISABLE.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void CAN_Peli_ITConfig(u32 it, FunctionalState state)
{
(state) ? (CAN1_PELI->IER |= it) : (CAN1_PELI->IER &= ~it);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Checks whether the specified CAN interrupt has occurred or not.
/// @param it: specifies the CAN interrupt source to check.
/// This parameter can be one of the following values:
/// @arg CAN_IT_RI: Receive FIFO not empty Interrupt
/// @arg CAN_IT_TI: Transmit Interrupt
/// @arg CAN_IT_EI: ERROR Interrupt
/// @arg CAN_IT_DOI: Data voerflow Interrupt
/// @arg CAN_IT_WUI: Wakeup Interrupt
/// @arg CAN_IT_EPI(only Peli): passive error Interrupt
/// @arg CAN_IT_ALI(only Peli): arbiter lose Interrupt
/// @arg CAN_IT_BEI(only Peli): bus error Interrupt
/// @arg CAN_IT_ALL: use it can enble all Interrupt
/// @retval The current state of it (SET or RESET).
////////////////////////////////////////////////////////////////////////////////
ITStatus CAN_Peli_GetITStatus(u32 it)
{
return (ITStatus)(((CAN1_PELI->IR & it) != it) ? RESET : SET);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Config CAN_Peli_InitTypeDef baud parameter.
/// @param CAN_Peli_InitTypeDef: CAN struct.
/// @param src_clk: CAN module clock.
/// @param baud: specified baud.
/// @retval The current state of it (SET or RESET).
////////////////////////////////////////////////////////////////////////////////
void CAN_AutoCfg_BaudParam(CAN_Peli_InitTypeDef* init_struct, u32 src_clk, u32 baud)
{
u32 i, value = baud, record = 1;
u32 remain = 0, sumPrescaler = 0;
while ((baud == 0) || (src_clk == 0))
;
sumPrescaler = src_clk / baud;
sumPrescaler = sumPrescaler / 2;
for (i = 25; i > 3; i--) {
remain = sumPrescaler - ((sumPrescaler / i) * i);
if (remain == 0) {
record = i;
break;
}
else {
if (remain < value) {
value = remain;
record = i;
}
}
}
init_struct->SJW = 0;
init_struct->BRP = (sumPrescaler / record) - 1;
init_struct->TESG2 = (record - 3) / 3;
init_struct->TESG1 = (record - 3) - init_struct->TESG2;
}
/// @}
/// @}
/// @}