rt-thread/bsp/mm32f103x/Libraries/MM32F103/HAL_lib/src/HAL_can.c

972 lines
31 KiB
C
Raw Normal View History

2021-08-04 14:42:16 +08:00
/**
******************************************************************************
* @file HAL_can.c
* @author AE Team
* @version V1.1.0
* @date 28/08/2019
* @brief This file provides all the CAN firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, MindMotion SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2019 MindMotion</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "HAL_can.h"
#include "HAL_rcc.h"
/**
* @brief: Deinitialinzes the CAN registers to their default reset values
* @retval: None
*/
void CAN_DeInit(CAN_TypeDef* CANx)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
switch (*(uint32_t*)&CANx)
{
case CAN1_BASE:
/* Enable CAN1 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, ENABLE);
/* Release CAN1 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, DISABLE);
break;
default:
break;
}
}
/**
* @brief Initializes the CAN peripheral according to the specified
* parameters in the CAN_InitStruct.
* @param CANx: where x can be 1 to 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.
*/
uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_Basic_InitTypeDef* CAN_Basic_InitStruct)
{
uint8_t InitStatus = CANINITFAILED;
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(CAN_Basic_InitStruct->SJW));
assert_param(IS_FUNCTIONAL_STATE(CAN_Basic_InitStruct->BRP));
assert_param(IS_FUNCTIONAL_STATE(CAN_Basic_InitStruct->SAM));
assert_param(IS_FUNCTIONAL_STATE(CAN_Basic_InitStruct->TESG2));
assert_param(IS_FUNCTIONAL_STATE(CAN_Basic_InitStruct->TESG1));
CANx->BTR0 = ((uint32_t)(CAN_Basic_InitStruct->SJW) << 6) | ((uint32_t)(CAN_Basic_InitStruct->BRP));
CANx->BTR1 = ((uint32_t)(CAN_Basic_InitStruct->SAM) << 7) | ((uint32_t)(CAN_Basic_InitStruct->TESG2) << 4) | \
((uint32_t)(CAN_Basic_InitStruct->TESG1));
if(CAN_Basic_InitStruct->GTS == ENABLE)
{
CANx->CMR |= (uint32_t)CAN_SleepMode;
}
else
{
CANx->CMR &= ~(uint32_t)CAN_SleepMode;
}
CANx->CDR |= ((CAN_Basic_InitStruct->CBP) << 6) | ((CAN_Basic_InitStruct->RXINTEN) << 5) | \
((CAN_Basic_InitStruct->CLOSE_OPEN_CLK) << 3) | (CAN_Basic_InitStruct->CDCLK);
InitStatus = CANINITOK;
return InitStatus;
}
/**
* @brief Configures the CAN_Basic reception filter according to the specified
* parameters in the CAN_Basic_FilterInitStruct.
* @param CAN_Basic_FilterInitStruct: pointer to a CAN_Basic_FilterInitTypeDef structure that
* contains the configuration information.
* @retval None
*/
void CAN_FilterInit(CAN_Basic_FilterInitTypeDef* CAN_Basic_FilterInitStruct)
{
/* Filter Mode */
CAN1->ACR = CAN_Basic_FilterInitStruct->CAN_FilterId;
CAN1->AMR = CAN_Basic_FilterInitStruct->CAN_FilterMaskId;
}
/**
* @brief Fills each CAN_Basic_InitStruct member with its default value.
* @param CAN_Basic_InitStruct : pointer to a CAN_Basic_InitTypeDef structure
* which will be initialized.
* @retval : None
*/
void CAN_StructInit(CAN_Basic_InitTypeDef* CAN_Basic_InitStruct)
{
/*--------------- Reset CAN_Basic init structure parameters values -----------------*/
/* initialize the BRP member(where can be set with (0..63))*/
CAN_Basic_InitStruct->BRP = 0x0;
/* initialize the SJW member(where can be set with (0..3)) */
CAN_Basic_InitStruct->SJW = 0x0;
/* Initialize the TESG1 member(where can be set with (0..15)) */
CAN_Basic_InitStruct->TESG1 = 0x0;
/* Initialize the TESG2 member(where can be set with(0..7)) */
CAN_Basic_InitStruct->TESG2 = 0x0;
/* Initialize the SAM member(where can be set (SET or RESET)) */
CAN_Basic_InitStruct->SAM = RESET;
/* Initialize the GTS member to Sleep Mode(where can be set (ENABLE or DISABLE)) */
CAN_Basic_InitStruct->GTS = DISABLE;
/* Initialize the external pin CLKOUT frequence */
CAN_Basic_InitStruct->CDCLK = 0x0;
/* Initialize the external clk is open or close */
CAN_Basic_InitStruct->CLOSE_OPEN_CLK = 0x0;
/* Initialize the TX1 pin work as rx interrupt output */
CAN_Basic_InitStruct->RXINTEN = 0x0;
/* Initialize the CBP of CDR register */
CAN_Basic_InitStruct->CBP = 0x0;
}
/**
* @brief Enables or disables the specified CAN interrupts.
* @param CANx: where x can be 1 to select the CAN peripheral.
* @param CAN_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 Newstate: new state of the CAN interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval : None.
*/
void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState Newstate)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_ITConfig(CAN_IT));
assert_param(IS_FUNCTIONAL_STATE(Newstate));
if (Newstate != DISABLE)
{
/* Enable the selected CAN interrupt */
CANx->CR |= CAN_IT;
}
else
{
/* Disable the selected CAN interrupt */
CANx->CR &= ~CAN_IT;
}
}
/**
* @brief Initiates and transmits a CAN frame message.
* @param CANx: where x can be 1 to 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
*/
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanBasicTxMsg* BasicTxMessage)
{
/* TXOK and TME bits */
uint8_t state = 0;
/* Check the parameters */
assert_param(IS_CAN_RTR(BasicTxMessage->RTR));
assert_param(IS_CAN_DLC(BasicTxMessage->DLC));
CANx->TXID0 = (BasicTxMessage->IDH);
CANx->TXID1 = (BasicTxMessage->IDL << 5) | (BasicTxMessage->RTR << 4) | (BasicTxMessage->DLC);
if((FunctionalState)(BasicTxMessage->RTR) != ENABLE)
{
CANx->TXDR0 = BasicTxMessage->Data[0];
CANx->TXDR1 = BasicTxMessage->Data[1];
CANx->TXDR2 = BasicTxMessage->Data[2];
CANx->TXDR3 = BasicTxMessage->Data[3];
CANx->TXDR4 = BasicTxMessage->Data[4];
CANx->TXDR5 = BasicTxMessage->Data[5];
CANx->TXDR6 = BasicTxMessage->Data[6];
CANx->TXDR7 = BasicTxMessage->Data[7];
}
CANx->CMR = CAN_CMR_TR;
return state;
}
/**
* @brief Cancels a transmit request.
* @param CANx: where x can be 1 to select the CAN peripheral.
* @retval None
*/
void CAN_CancelTransmit(CAN_TypeDef* CANx)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_TRANSMITMAILBOX(Mailbox));
/* abort transmission */
CANx->CMR = CAN_AT;
}
/**
* @brief Releases the specified receive FIFO.
* @param CANx: where x can be 1 to select the CAN peripheral.
* @retval None
*/
void CAN_FIFORelease(CAN_TypeDef* CANx)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Release FIFO */
CANx->CMR |= (uint32_t)CAN_RRB;
}
/**
* @brief Receives a correct CAN frame.
* @param CANx: where x can be 1 to 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* CANx, CanBasicRxMsg* BasicRxMessage)
{
uint16_t tempid;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_FIFO(FIFONumber));
BasicRxMessage->RTR = (uint8_t)((CANx->RXID1) >> 4) & 0x1;
BasicRxMessage->DLC = (uint8_t)((CANx->RXID1) & 0xf);
tempid = (uint16_t)(((CANx->RXID1) & 0xe0) >> 5);
tempid |= (uint16_t)(CANx->RXID0 << 3);
BasicRxMessage->ID = tempid;
BasicRxMessage->Data[0] = CAN1->RXDR0;
BasicRxMessage->Data[1] = CAN1->RXDR1;
BasicRxMessage->Data[2] = CAN1->RXDR2;
BasicRxMessage->Data[3] = CAN1->RXDR3;
BasicRxMessage->Data[4] = CAN1->RXDR4;
BasicRxMessage->Data[5] = CAN1->RXDR5;
BasicRxMessage->Data[6] = CAN1->RXDR6;
BasicRxMessage->Data[7] = CAN1->RXDR7;
CAN_FIFORelease( CANx);
}
/**
* @brief: Select the Sleep mode or not in Basic workmode
* @param: NewState to go into the Sleep mode or go out
* @retval: None
*/
uint8_t CAN_Sleep(CAN_TypeDef* CANx)
{
uint8_t sleepstatus = CANSLEEPFAILED;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
CANx->CMR |= CAN_SleepMode;
if((CANx->CMR & 0x10) == CAN_SleepMode)
{
sleepstatus = CANSLEEPOK;
}
/* At this step, sleep mode status */
return (uint8_t)sleepstatus;
}
/**
* @brief Wakes the CAN up.
* @param CANx: where x can be 1 to select the CAN peripheral.
* @retval : CANWAKEUPOK if sleep mode left, CANWAKEUPFAILED in an other
* case.
*/
uint8_t CAN_WakeUp(CAN_TypeDef* CANx)
{
uint8_t wakeupstatus = CANWAKEUPFAILED;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Wake up request */
CANx->CMR &= ~CAN_SleepMode;
/* Sleep mode status */
if((CANx->CMR & 0x01) == 0)
{
/* Sleep mode exited */
wakeupstatus = CANWAKEUPOK;
}
/* At this step, sleep mode status */
return (uint8_t)wakeupstatus;
}
/**
* @brief Checks whether the specified CAN flag is set or not.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param CAN_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* CANx, uint32_t CAN_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_GET_FLAG(CAN_FLAG));
if((CANx->SR & CAN_FLAG) == CAN_FLAG)
{
/* CAN_FLAG is set */
bitstatus = SET;
}
else
{
/* CAN_FLAG is reset */
bitstatus = RESET;
}
/* Return the CAN_FLAG status */
return bitstatus;
}
/**
* @brief Checks whether the specified CAN interrupt has occurred or not.
* @param CANx: where x can be 1 to select the CAN peripheral.
* @param CAN_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 CAN_IT (SET or RESET).
*/
ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT)
{
ITStatus itstatus = RESET;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_IT(CAN_IT));
/* check the interrupt enable bit */
if((CANx->IR & CAN_IT) != CAN_IT)
{
itstatus = RESET;
}
else
{
itstatus = SET;
}
return itstatus;
}
/**
* @brief: Select the can work as peli mode or basic mode
* @param CANx: 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* CANx, uint32_t CAN_MODE)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
CANx->CDR |= CAN_MODE;
}
/**
* @brief: Select the Reset mode or not
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param: NewState to go into the Reset mode or go out
* @retval: None
*/
void CAN_ResetMode_Cmd(CAN_TypeDef* CANx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
if(NewState == ENABLE)
{
CANx->CR |= CAN_ResetMode;
}
else
{
CANx->CR &= ~CAN_ResetMode;
}
}
/**
* @brief Clear the data overflow.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @retval None
*/
void CAN_ClearDataOverflow(CAN_TypeDef* CANx)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
CANx->CMR |= (uint32_t)CAN_CDO;
}
/**
* @brief Clears the CAN's IT pending.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @retval None
*/
void CAN_ClearITPendingBit(CAN_TypeDef* CANx)
{
uint32_t temp = 0;
temp = temp;
temp = CANx->IR; //read this register clear all interrupt
}
/**
* @brief: Select the Sleep mode or not in Peli workmode
* @param: NewState to go into the Sleep mode or go out
* @retval: None
*/
void CAN_Peli_SleepMode_Cmd(FunctionalState NewState)
{
if(NewState == ENABLE)
CAN1_PELI->MOD |= CAN_SleepMode;
else
CAN1_PELI->MOD &= ~CAN_SleepMode;
}
/**
* @brief Fills each CAN1_PELI_InitStruct member with its default value.
* @param CAN_Peli_InitStruct : pointer to a CAN_Peli_InitTypeDef structure
* which will be initialized.
* @retval : None
*/
void CAN_Peli_StructInit(CAN_Peli_InitTypeDef* CAN_Peli_InitStruct)
{
/*--------------- Reset CAN_Peli init structure parameters values -----------------*/
/* initialize the BRP member(where can be set with (0..63))*/
CAN_Peli_InitStruct->BRP = 0x0;
/* initialize the SJW member(where can be set with (0..3)) */
CAN_Peli_InitStruct->SJW = 0x0;
/* Initialize the TESG1 member(where can be set with (0..15)) */
CAN_Peli_InitStruct->TESG1 = 0x0;
/* Initialize the TESG2 member(where can be set with(0..7)) */
CAN_Peli_InitStruct->TESG2 = 0x0;
/* Initialize the SAM member(where can be set (SET or RESET)) */
CAN_Peli_InitStruct->SAM = RESET;
/* Initialize the LOM member*/
CAN_Peli_InitStruct->LOM = DISABLE;
/* Initialize the STM member*/
CAN_Peli_InitStruct->STM = DISABLE;
/* Initialize the SM member*/
CAN_Peli_InitStruct->SM = DISABLE;
CAN_Peli_InitStruct->SRR = DISABLE;
CAN_Peli_InitStruct->EWLR = 0x96;
}
/**
* @brief Initializes the CAN_Peli peripheral according to the specified
* parameters in the CAN_Peli_InitStruct.
* @param CAN_Basic_InitStruct: 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* CAN_Peli_InitStruct)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->SJW));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->BRP));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->SAM));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->TESG2));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->TESG1));
CAN1_PELI->BTR0 = ((uint32_t)CAN_Peli_InitStruct->SJW << 6) | ((uint32_t)CAN_Peli_InitStruct->BRP);
CAN1_PELI->BTR1 = ((uint32_t)CAN_Peli_InitStruct->SAM << 7) | ((uint32_t)CAN_Peli_InitStruct->TESG2 << 4) | \
((uint32_t)CAN_Peli_InitStruct->TESG1);
if(CAN_Peli_InitStruct->LOM == ENABLE)
CAN1_PELI->MOD |= (uint32_t)CAN_ListenOnlyMode;
else
CAN1_PELI->MOD &= ~(uint32_t)CAN_ListenOnlyMode;
if(CAN_Peli_InitStruct->STM == ENABLE)
CAN1_PELI->MOD |= (uint32_t)CAN_SeftTestMode;
else
CAN1_PELI->MOD &= ~(uint32_t)CAN_SeftTestMode;
if(CAN_Peli_InitStruct->SM == ENABLE)
CAN1_PELI->MOD |= (uint32_t)CAN_SleepMode;
else
CAN1_PELI->MOD &= ~(uint32_t)CAN_SleepMode;
CAN1_PELI->EWLR = (uint32_t)CAN_Peli_InitStruct->EWLR;
}
/**
* @brief Configures the CAN_Peli reception filter according to the specified
* parameters in the CAN_Peli_FilterInitStruct.
* @param CAN_Peli_FilterInitStruct: pointer to a CAN_Peli_FilterInitTypeDef structure that
* contains the configuration information.
* @retval None
*/
void CAN_Peli_FilterInit(CAN_Peli_FilterInitTypeDef* CAN_Peli_FilterInitStruct)
{
if(CAN_Peli_FilterInitStruct->AFM == CAN_FilterMode_Singal)
CAN1_PELI->MOD |= (uint32_t)CAN_FilterMode_Singal;
else
CAN1_PELI->MOD &= (uint32_t)CAN_FilterMode_Double;
CAN1_PELI->FF = CAN_Peli_FilterInitStruct->CAN_FilterId0;
CAN1_PELI->ID0 = CAN_Peli_FilterInitStruct->CAN_FilterId1;
CAN1_PELI->ID1 = CAN_Peli_FilterInitStruct->CAN_FilterId2;
CAN1_PELI->DATA0 = CAN_Peli_FilterInitStruct->CAN_FilterId3;
CAN1_PELI->DATA1 = CAN_Peli_FilterInitStruct->CAN_FilterMaskId0;
CAN1_PELI->DATA2 = CAN_Peli_FilterInitStruct->CAN_FilterMaskId1;
CAN1_PELI->DATA3 = CAN_Peli_FilterInitStruct->CAN_FilterMaskId2;
CAN1_PELI->DATA4 = CAN_Peli_FilterInitStruct->CAN_FilterMaskId3;
}
/**
* @brief Fills each CAN_Peli_FilterInitStruct member with its default value.
* @param CAN_Peli_FilterInitStruct: pointer to a CAN_InitTypeDef structure which ill be initialized.
* @retval None
*/
void CAN_Peli_FilterStructInit(CAN_Peli_FilterInitTypeDef* CAN_Peli_FilterInitStruct)
{
CAN_Peli_FilterInitStruct->CAN_FilterId0 = 0;
CAN_Peli_FilterInitStruct->CAN_FilterId1 = 0;
CAN_Peli_FilterInitStruct->CAN_FilterId2 = 0;
CAN_Peli_FilterInitStruct->CAN_FilterId3 = 0;
CAN_Peli_FilterInitStruct->CAN_FilterMaskId0 = 0;
CAN_Peli_FilterInitStruct->CAN_FilterMaskId1 = 0;
CAN_Peli_FilterInitStruct->CAN_FilterMaskId2 = 0;
CAN_Peli_FilterInitStruct->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* PeliTxMessage)
{
/* Check the parameters */
assert_param(IS_CAN_RTR(PeliTxMessage->RTR));
assert_param(IS_CAN_DLC(PeliTxMessage->DLC));
CAN1_PELI->FF = (PeliTxMessage->FF << 7) | (PeliTxMessage->RTR << 6) | (PeliTxMessage->DLC);
if(((FunctionalState)PeliTxMessage->FF) != ENABLE)
{
CAN1_PELI->ID0 = (PeliTxMessage->IDHH);
// CAN1_PELI->ID1 = ((PeliTxMessage->IDHL)<<5);
CAN1_PELI->ID1 = (PeliTxMessage->IDHL & 0xE0);
if((FunctionalState)(PeliTxMessage->RTR) != ENABLE)
{
CAN1_PELI->DATA0 = PeliTxMessage->Data[0];
CAN1_PELI->DATA1 = PeliTxMessage->Data[1];
CAN1_PELI->DATA2 = PeliTxMessage->Data[2];
CAN1_PELI->DATA3 = PeliTxMessage->Data[3];
CAN1_PELI->DATA4 = PeliTxMessage->Data[4];
CAN1_PELI->DATA5 = PeliTxMessage->Data[5];
CAN1_PELI->DATA6 = PeliTxMessage->Data[6];
CAN1_PELI->DATA7 = PeliTxMessage->Data[7];
}
}
else
{
CAN1_PELI->ID0 = PeliTxMessage->IDHH;
CAN1_PELI->ID1 = PeliTxMessage->IDHL;
CAN1_PELI->DATA0 = PeliTxMessage->IDLH;
CAN1_PELI->DATA1 = PeliTxMessage->IDLL;
if((FunctionalState)(PeliTxMessage->RTR) != ENABLE)
{
CAN1_PELI->DATA2 = PeliTxMessage->Data[0];
CAN1_PELI->DATA3 = PeliTxMessage->Data[1];
CAN1_PELI->DATA4 = PeliTxMessage->Data[2];
CAN1_PELI->DATA5 = PeliTxMessage->Data[3];
CAN1_PELI->DATA6 = PeliTxMessage->Data[4];
CAN1_PELI->DATA7 = PeliTxMessage->Data[5];
CAN1_PELI->DATA8 = PeliTxMessage->Data[6];
CAN1_PELI->DATA9 = PeliTxMessage->Data[7];
}
}
if(CAN1_PELI->MOD & CAN_MOD_STM)
{
CAN1->CMR = CAN_CMR_GTS | CAN_CMR_AT;
}
else
{
CAN1->CMR = CAN_TR | CAN_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* PeliTxMessage)
{
/* Check the parameters */
assert_param(IS_CAN_RTR(PeliTxMessage->RTR));
assert_param(IS_CAN_DLC(PeliTxMessage->DLC));
CAN1_PELI->FF = (PeliTxMessage->FF << 7) | (PeliTxMessage->RTR << 6) | (PeliTxMessage->DLC);
if(((FunctionalState)PeliTxMessage->FF) != ENABLE)
{
CAN1_PELI->ID0 = (PeliTxMessage->IDHH);
CAN1_PELI->ID1 = ((PeliTxMessage->IDHL) << 5);
if((FunctionalState)(PeliTxMessage->RTR) != ENABLE)
{
CAN1_PELI->DATA0 = PeliTxMessage->Data[0];
CAN1_PELI->DATA1 = PeliTxMessage->Data[1];
CAN1_PELI->DATA2 = PeliTxMessage->Data[2];
CAN1_PELI->DATA3 = PeliTxMessage->Data[3];
CAN1_PELI->DATA4 = PeliTxMessage->Data[4];
CAN1_PELI->DATA5 = PeliTxMessage->Data[5];
CAN1_PELI->DATA6 = PeliTxMessage->Data[6];
CAN1_PELI->DATA7 = PeliTxMessage->Data[7];
}
}
else
{
CAN1_PELI->ID0 = PeliTxMessage->IDHH;
CAN1_PELI->ID1 = PeliTxMessage->IDHL;
CAN1_PELI->DATA0 = PeliTxMessage->IDLH;
CAN1_PELI->DATA1 = PeliTxMessage->IDLL;
if((FunctionalState)(PeliTxMessage->RTR) != ENABLE)
{
CAN1_PELI->DATA2 = PeliTxMessage->Data[0];
CAN1_PELI->DATA3 = PeliTxMessage->Data[1];
CAN1_PELI->DATA4 = PeliTxMessage->Data[2];
CAN1_PELI->DATA5 = PeliTxMessage->Data[3];
CAN1_PELI->DATA6 = PeliTxMessage->Data[4];
CAN1_PELI->DATA7 = PeliTxMessage->Data[5];
CAN1_PELI->DATA8 = PeliTxMessage->Data[6];
CAN1_PELI->DATA9 = PeliTxMessage->Data[7];
}
}
if(CAN1_PELI->MOD & CAN_MOD_STM)
{
CAN1->CMR = CAN_CMR_GTS | CAN_CMR_AT;
}
else
{
CAN1->CMR = CAN_CMR_TR;
}
}
/** @defgroup CAN_Group3 CAN Frames Reception functions
* @brief CAN Frames Reception functions
*
@verbatim
===============================================================================
##### CAN Frames Reception functions #####
===============================================================================
[..] This section provides functions allowing to
(+) Receive a correct CAN frame.
(+) Release a specified receive FIFO
(+) Return the number of the pending received CAN frames.
@endverbatim
* @{
*/
/**
* @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* PeliRxMessage)
{
uint32_t tempid;
PeliRxMessage->FF = (CAN1_PELI->FF) >> 7;
PeliRxMessage->RTR = ((CAN1_PELI->FF) >> 6) & 0x1;
PeliRxMessage->DLC = (CAN1_PELI->FF) & 0xf;
if(((FunctionalState)PeliRxMessage->FF) != ENABLE)
{
tempid = (uint32_t)(CAN1_PELI->ID1 >> 5);
tempid |= (uint32_t)(CAN1_PELI->ID0 << 3);
PeliRxMessage->ID = tempid;
PeliRxMessage->Data[0] = CAN1_PELI->DATA0;
PeliRxMessage->Data[1] = CAN1_PELI->DATA1;
PeliRxMessage->Data[2] = CAN1_PELI->DATA2;
PeliRxMessage->Data[3] = CAN1_PELI->DATA3;
PeliRxMessage->Data[4] = CAN1_PELI->DATA4;
PeliRxMessage->Data[5] = CAN1_PELI->DATA5;
PeliRxMessage->Data[6] = CAN1_PELI->DATA6;
PeliRxMessage->Data[7] = CAN1_PELI->DATA7;
}
else
{
tempid = (uint32_t)((CAN1_PELI->DATA1 & 0xf8) >> 3);
tempid |= (uint32_t)(CAN1_PELI->DATA0 << 5);
tempid |= (uint32_t)(CAN1_PELI->ID1 << 13);
tempid |= (uint32_t)(CAN1_PELI->ID0 << 21);
PeliRxMessage->ID = tempid;
PeliRxMessage->Data[0] = CAN1_PELI->DATA2;
PeliRxMessage->Data[1] = CAN1_PELI->DATA3;
PeliRxMessage->Data[2] = CAN1_PELI->DATA4;
PeliRxMessage->Data[3] = CAN1_PELI->DATA5;
PeliRxMessage->Data[4] = CAN1_PELI->DATA6;
PeliRxMessage->Data[5] = CAN1_PELI->DATA7;
PeliRxMessage->Data[6] = CAN1_PELI->DATA8;
PeliRxMessage->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
*/
uint32_t CAN_Peli_GetRxFIFOInfo(void)
{
return CAN1_PELI->RMC;
}
/** @defgroup CAN_Group5 CAN Bus Error management functions
* @brief CAN Bus Error management functions
*
@verbatim
===============================================================================
##### CAN Bus Error management functions #####
===============================================================================
@endverbatim
* @{
*/
/**
* @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
*/
uint8_t CAN_Peli_GetLastErrorCode(void)
{
uint8_t errorcode = 0;
/* Get the error code*/
errorcode = ((uint8_t)CAN1_PELI->ECC);
/* Return the error code*/
return errorcode;
}
/**
* @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.
*/
uint8_t CAN_Peli_GetReceiveErrorCounter(void)
{
uint8_t counter = 0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Get the Receive Error Counter*/
counter = (uint8_t)(CAN1_PELI->RXERR);
/* Return the Receive Error Counter*/
return counter;
}
/**
* @brief Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC).
* @retval LSB of the 8-bit CAN Transmit Error Counter.
*/
uint8_t CAN_Peli_GetLSBTransmitErrorCounter(void)
{
uint8_t counter = 0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Get the LSB of the 8-bit CAN Transmit Error Counter(TEC) */
counter = (uint8_t)(CAN1_PELI->TXERR);
/* Return the LSB of the 8-bit CAN Transmit Error Counter(TEC) */
return counter;
}
/** @defgroup CAN_Group6 Interrupts and flags management functions
* @brief Interrupts and flags management functions
*
@verbatim
===============================================================================
##### Interrupts and flags management functions #####
===============================================================================
[..] This section provides functions allowing to configure the CAN Interrupts
and to get the status and clear flags and Interrupts pending bits.
[..] The CAN provides 14 Interrupts sources and 15 Flags:
*** Flags ***
=============
*/
/**
* @brief Enables or disables the specified CAN interrupts in peli workmode.
* @param CAN_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 NewState: new state of the CAN interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void CAN_Peli_ITConfig(uint32_t CAN_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_CAN_IT(CAN_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected CAN interrupt */
CAN1_PELI->IER |= CAN_IT;
}
else
{
/* Disable the selected CAN interrupt */
CAN1_PELI->IER &= ~CAN_IT;
}
}
/**
* @brief Checks whether the specified CAN interrupt has occurred or not.
* @param CAN_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 CAN_IT (SET or RESET).
*/
ITStatus CAN_Peli_GetITStatus(uint32_t CAN_IT)
{
ITStatus itstatus = RESET;
/* Check the parameters */
assert_param(IS_CAN_IT(CAN_IT));
/* check the interrupt enable bit */
if((CAN1_PELI->IR & CAN_IT) != CAN_IT)
{
itstatus = RESET;
}
else
{
itstatus = SET;
}
return itstatus;
}
/**
* @brief Config CAN_Peli_InitTypeDef baud parameter.
* @param CAN_Peli_InitTypeDef: CAN struct.
* @param SrcClk: CAN module clock.
* @param baud: specified baud.
* @retval The current state of CAN_IT (SET or RESET).
*/
void CAN_AutoCfg_BaudParam(CAN_Peli_InitTypeDef *CAN_Peli_InitStruct, unsigned int SrcClk, unsigned int baud )
{
unsigned int i, value = baud, record = 1;
unsigned int remain = 0, sumPrescaler = 0;
while(( baud == 0 ) || ( SrcClk == 0 )); //<2F><>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD>ʱ<EFBFBD><CAB1>Ϊ0
sumPrescaler = SrcClk / baud; //<2F>ܷ<EFBFBD>Ƶ
sumPrescaler = sumPrescaler / 2; //
for( i = 25; i > 3; i -- )
{
remain = sumPrescaler - ((sumPrescaler / i) * i);
if( remain == 0 ) //<2F><><EFBFBD><EFBFBD>
{
record = i;
break;
}
else
{
if(remain < value)
{
value = remain;
record = i;
}
}
}
CAN_Peli_InitStruct->SJW = 0;
CAN_Peli_InitStruct->BRP = (sumPrescaler / record) - 1;
CAN_Peli_InitStruct->TESG2 = (record - 3) / 3;
CAN_Peli_InitStruct->TESG1 = (record - 3) - CAN_Peli_InitStruct->TESG2;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/*-------------------------(C) COPYRIGHT 2019 MindMotion ----------------------*/