Files
LFP_48V_mBMS_FW/mBMS_APP_V3117/HARDWARE/can.c

211 lines
6.8 KiB
C

#include "sys.h"
#include "delay.h"
#include "can.h"
#include "includes.h" //ucos Use
//////////////////////////////////////////////////////////////////////////////////
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
//ALIENTEK STM32F4 Explorer Board
//Initialize serial port 2
//Hot Atomic @ALIENTEK
//Forum: www.openedv.com
//Date modified: 2015/9/12
//Version: V1.0
//All rights reserved pirated reserved.
//Copyright(C) Guangzhou wing electronic technology limited company 2009-2019
//All rights reserved
//********************************************************************************
//////////////////////////////////////////////////////////////////////////////////
/* Defines -------------------------------------------------------------------*/
#define RX_BUFFER_SIZE 320
/* Type declarations ---------------------------------------------------------*/
typedef struct
{
CAN_TypeDef *can;
volatile u16 RxInPos, RxOutPos;
volatile uint32_t RxOverflowCount;
u16 TxInPos, TxOutPos;
CanRxMsg RxBuf[RX_BUFFER_SIZE];
} CAN_Info;
/* Exported macro ------------------------------------------------------------*/
CAN_Info Can;
//Initializes CAN Port
//Bound: baud rate
void can1_init(u32 buadrate)
{
//GPIO port settings
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
Can.can = CAN1;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC , ENABLE); //Enable GPIOC clock
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD , ENABLE); //Enable GPIOD clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //Enable CAN1 clock
//CAN1 pins reuse maps
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1); //GPIOD 0 multiplex CAN1 RX
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1); //GPIOD 1 multiplex CAN1 TX
//CAN1 port configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //GPIOD 2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //Multiplexing function
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Speed 100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //Non Pull-up
GPIO_Init(GPIOD, &GPIO_InitStructure); //Initialize PD 0, 1 for CAN1 RX, TX
//CAN1 port configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //GPIOC 12
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //Multiplexing function
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Speed 100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //Non Pull-up
GPIO_Init(GPIOC, &GPIO_InitStructure); //Initialize PD 0, 1 for CAN1 RX, TX
//CAN1 port configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; //GPIOD 0, 1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //Multiplexing function
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Speed 50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //Push-pull multiplexed output
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //Pull-up
GPIO_Init(GPIOD, &GPIO_InitStructure); //Initialize PD 0, 1 for CAN1 RX, TX
//CAN1 Initialization settings
CAN_DeInit(Can.can);
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
switch (buadrate)
{
case 125000:
CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
CAN_InitStructure.CAN_Prescaler = 42;
break;
case 250000:
CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
CAN_InitStructure.CAN_Prescaler = 21;
break;
case 500000:
CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;
CAN_InitStructure.CAN_Prescaler = 7;
break;
case 1000000:
/* CAN Baudrate = 1MBps*/
CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
CAN_InitStructure.CAN_Prescaler = 4;
break;
}
CAN_InitStructure.CAN_TTCM = DISABLE; //
CAN_InitStructure.CAN_ABOM = DISABLE; //
CAN_InitStructure.CAN_AWUM = DISABLE; //
CAN_InitStructure.CAN_NART = DISABLE; //
CAN_InitStructure.CAN_RFLM = DISABLE; //
CAN_InitStructure.CAN_TXFP = ENABLE; //
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_Init(Can.can, &CAN_InitStructure); //Initialize CAN1 port
CAN_ITConfig(Can.can, CAN_IT_FMP0, ENABLE);
}
void CAN1_RX0_IRQHandler(void) //CAN 1 interrupt service routine
{
CanRxMsg RxMessage;
CAN_ClearITPendingBit(Can.can, CAN_IT_FMP0);
CAN_Receive(Can.can, CAN_FIFO0, &RxMessage);
uint16_t next = (uint16_t)((Can.RxInPos + 1U) % RX_BUFFER_SIZE);
if (next == Can.RxOutPos) {
Can.RxOverflowCount++;
} else {
memcpy(&Can.RxBuf[Can.RxInPos], &RxMessage, sizeof(CanRxMsg));
__DMB();
Can.RxInPos = next;
}
}
/*******************************************************************************
* Function Name : u8 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)
*******************************************************************************/
u8 CAN_GetPacket(CanRxMsg *packet)
{
if (Can.RxInPos != Can.RxOutPos)
{
memcpy(packet, &Can.RxBuf[Can.RxOutPos], sizeof(CanRxMsg));
__DMB();
Can.RxOutPos = (uint16_t)((Can.RxOutPos + 1U) % RX_BUFFER_SIZE);
return SUCCESS;
}
else
return ERROR;
}
void CAN_SendPacket(CanTxMsg *packet)
{
u8 retMsgBox;
uint8_t result;
int i;
uint32_t wait_box = 10000;
do {
retMsgBox = CAN_Transmit(Can.can, packet);
} while ((retMsgBox == CAN_TxStatus_NoMailBox) && (--wait_box > 0));
i = 0;
if (retMsgBox != CAN_TxStatus_NoMailBox)
{
result = CAN_TransmitStatus(CAN1, retMsgBox);
// while (((result == CAN_TxStatus_Failed) || (result == CAN_TxStatus_Pending))&&(i < 0xFFF))
while (((result == CAN_TxStatus_Failed) )&&(i < 0xFF))
{
result = CAN_TransmitStatus(CAN1, retMsgBox);
i++;
}
if(i >= 0xFF)
{
// if (result == CAN_TxStatus_Pending)
// CAN_CancelTransmit(CAN1, retMsgBox);
// delay_os_ms(100);
//
// if (screenmode == DIAG_MODE)
// printf("\r\n Tx Error (%d)", retMsgBox);
}
}
else
{
can1_init(250000);
delay_os_ms(10);
retMsgBox = CAN_Transmit(CAN1, packet);
}
}