Files
LFP_48V_mBMS_FW/APP_R3323/App/Hardware/can.c

240 lines
7.8 KiB
C

/**
******************************************************************************
* @file can.c
* @author AMG Energy Solution Team
* @version V1.0.0
* @date 07-Feb-2022
* @brief This file provides all the codes of CAN communication 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, STMICROELECTRONICS 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 2022 AMG</center></h2>
******************************************************************************
*/
/** @addtogroup mBMS2
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "can.h"
#include "string.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* CAN channel definition */
/* CAN baudrate definition */
#define CAN_BAUDRATE (250000ul)
/* CAN RX Port/Pin definition */
#define CAN_RX_PORT (PortE)
#define CAN_RX_PIN (Pin01)
#define CAN_RX_FUNC (Func_Can1_Rx)
/* CAN TX Port/Pin definition */
#define CAN_TX_PORT (PortE)
#define CAN_TX_PIN (Pin00)
#define CAN_TX_FUNC (Func_Can1_Tx)
#define TX_BUFFER_SIZE 10
#define RX_BUFFER_SIZE 320
/* Private macro -------------------------------------------------------------*/
typedef struct {
volatile uint16_t RxInPos, RxOutPos;
volatile uint32_t RxOverflowCount;
uint16_t TxInPos, TxOutPos;
stc_can_rxframe_t RxBuf[RX_BUFFER_SIZE];
stc_can_txframe_t TxBuf[TX_BUFFER_SIZE];
} CAN_Info;
/* Private variables ---------------------------------------------------------*/
CAN_Info Can;
/* Private function prototypes -----------------------------------------------*/
void CAN_RxIrqCallBack(void);
/* Private functions ---------------------------------------------------------*/
// Initializes CAN Port
void can_init(uint32_t CAN_Baud_Rate)
{
stc_can_init_config_t stcCanInitCfg;
stc_can_filter_t stcFilter;
stc_irq_regi_conf_t stcIrqRegiConf;
stc_port_init_t stcPortInit;
MEM_ZERO_STRUCT(stcCanInitCfg);
MEM_ZERO_STRUCT(stcFilter);
MEM_ZERO_STRUCT(stcIrqRegiConf);
MEM_ZERO_STRUCT(stcPortInit);
MEM_ZERO_STRUCT(Can);
stcPortInit.enPinMode = Pin_Mode_Out;
stcPortInit.enExInt = Disable;
stcPortInit.enPullUp = Enable;
/* SPI Port/Pin initialization */
PORT_Init(CAN_TX_PORT, CAN_TX_PIN, &stcPortInit);
stcPortInit.enPinMode = Pin_Mode_In;
PORT_Init(CAN_RX_PORT, CAN_RX_PIN, &stcPortInit);
// PORT_Init(PortB, Pin03, &stcPortInit);
PORT_Init(PortB, Pin04, &stcPortInit);
//<<Enable can peripheral clock and buffer(ram)
PWC_RamOpMdConfig(HighSpeedMd);
PWC_RamPwrdownCmd(PWC_RAMPWRDOWN_CAN, Enable);
PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_CAN, Enable);
//<<CAN GPIO config
PORT_SetFunc(CAN_RX_PORT, CAN_RX_PIN, CAN_RX_FUNC, Disable);
PORT_SetFunc(CAN_TX_PORT, CAN_TX_PIN, CAN_TX_FUNC, Disable);
//<<Can bit time config
// stcCanInitCfg.stcCanBt.PRESC = 4u-1u;//???,??????????
switch(CAN_Baud_Rate) {
case 1000: // 1000K
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
break;
case 500: // 500K
stcCanInitCfg.stcCanBt.PRESC = 4u-1u;
break;
case 250: // 125K
stcCanInitCfg.stcCanBt.PRESC = 8u-1u;
break;
case 125: // 100K
stcCanInitCfg.stcCanBt.PRESC = 16u-1u;
break;
default:
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
break;
}
// stcCanInitCfg.stcCanBt.PRESC = 1u-1u;
stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u;
stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u;
stcCanInitCfg.stcCanBt.SJW = 3u-1u;
stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u;
stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u;
stcCanInitCfg.enCanRxBufAll = CanRxNormal;
stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
stcCanInitCfg.enCanSAck = CanSelfAckDisable; //CanSelfAckEnable;
stcCanInitCfg.enCanSTBMode = CanSTBFifoMode;
CAN_Init(&stcCanInitCfg);
//<<Can filter config
stcFilter.enAcfFormat = CanAllFrames;
stcFilter.enFilterSel = CanFilterSel1;
stcFilter.u32CODE = 0x00000000u;
stcFilter.u32MASK = 0x1FFFFFFFu;
CAN_FilterConfig(&stcFilter, Enable);
//<<Can Irq Enable
CAN_IrqCmd(CanRxIrqEn, Enable);
CAN_IrqCmd(CanTxPrimaryIrqEn, Enable);
stcIrqRegiConf.enIRQn = Int005_IRQn;
stcIrqRegiConf.enIntSrc = INT_CAN_INT;
stcIrqRegiConf.pfnCallback = &CAN_RxIrqCallBack;
enIrqRegistration(&stcIrqRegiConf);
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
}
void CAN_RxIrqCallBack(void)
{
if (true == CAN_IrqFlgGet(CanRxIrqFlg)) {
CAN_IrqFlgClr(CanRxIrqFlg);
stc_can_rxframe_t received;
uint16_t next = (uint16_t)((Can.RxInPos + 1U) % RX_BUFFER_SIZE);
/* Always drain the hardware receive slot, even when the software queue is full. */
CAN_Receive(&received);
if (next == Can.RxOutPos) {
Can.RxOverflowCount++;
} else {
memcpy(&Can.RxBuf[Can.RxInPos], &received, sizeof(received));
__DMB();
Can.RxInPos = next;
}
// CAN_IrqCmd(CanRxIrqEn, Disable);
}
if (true == CAN_IrqFlgGet(CanTxPrimaryIrqFlg)) {
CAN_IrqFlgClr(CanTxPrimaryIrqFlg);
// CAN_IrqCmd(CanRxIrqEn, Enable);
}
if (true == CAN_IrqFlgGet(CanBusErrorIrqFlg)) {
CAN_IrqFlgClr(CanBusErrorIrqFlg);
}
if (true == CAN_IrqFlgGet(CanArbiLostIrqFlg)) {
CAN_IrqFlgClr(CanArbiLostIrqFlg);
}
NVIC_ClearPendingIRQ(Int005_IRQn);
}
/*******************************************************************************
* Function Name : uint8_t CAN_GetPacket(CanRxMsg *packet)
* Description : Send 1 packet data to CAN Port transmit buffer
* Parameters : none
* Return : Transmission result (0: buffer empty, 1: buffer has data)
*******************************************************************************/
uint8_t CAN_GetPacket(stc_can_rxframe_t *packet)
{
if (Can.RxInPos != Can.RxOutPos) {
memcpy(packet, &Can.RxBuf[Can.RxOutPos], sizeof(stc_can_rxframe_t));
__DMB();
Can.RxOutPos = (uint16_t)((Can.RxOutPos + 1U) % RX_BUFFER_SIZE);
return 1;
}
else
return 0;
}
void CAN_SendPacket(stc_can_txframe_t *packet)
{
uint32_t timeout = 50000;
while ((M4_CAN->TCMD_f.TPE != 0) && (--timeout > 0)) {
__NOP();
}
if (timeout == 0) {
M4_CAN->TCMD |= CanPTBTxAbortCmd;
}
CAN_SetFrame(packet);
en_can_tx_buf_status_t txSts = CAN_TransmitCmd(CanPTBTxCmd);
switch (txSts) {
case CanTxBufEmpty: // = 0, ///< TTEN=0 or TTTBM=0: STB is empty
// printf("CanTxBufEmpty \r\n");
break; ///< TTEN=1 and TTTBM=1: PTB and STB are empty
case CanTxBufnotHalfFull: // = 1, ///< TTEN=0 or TTTBM=0: STB is less than or equal to half full
// printf("CanTxBufnotHalfFull \r\n");
break; ///< TTEN=1 and TTTBM=1: PTB and STB are not empty and not full
case CanTxBufHalfFull: // = 2, ///< TTEN=0 or TTTBM=0: STB is more than half full
// printf("CanTxBufHalfFull \r\n");
break; ///< TTEN=1 and TTTBM=1: None
case CanTxBufFull: // = 3, ///< TTEN=0 or TTTBM=0: STB is full
// printf("CanTxBufFull \r\n");
break;
}
// CAN_IrqCmd(CanRxIrqEn, Enable);
}
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/