972 lines
31 KiB
C
972 lines
31 KiB
C
/**
|
||
******************************************************************************
|
||
* @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>© 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 ----------------------*/
|
||
|