512 lines
12 KiB
C
512 lines
12 KiB
C
|
||
/******************** (C) COPYRIGHT 2011 嵌入式开发工作室 ********************
|
||
* 文件名 :can_app.c
|
||
* 描述 :
|
||
*
|
||
* 版本 :V1.0
|
||
**********************************************************************************/
|
||
#include "Sys.h"
|
||
#include "adc.h"
|
||
#include "can.h"
|
||
#include "CanBusDrv.h"
|
||
#include "candrvctrl.h"
|
||
|
||
static st_cl candrv_if[2];
|
||
|
||
|
||
/*****************************************************************************
|
||
* 记录每一个CAN ID的发送时间
|
||
****************************************************************************/
|
||
static struct
|
||
{
|
||
unsigned int frame_id; /* ID */
|
||
unsigned int period; /* 发送周期 */
|
||
unsigned int send_tick; /* 发送TICK */
|
||
unsigned int sent_tick; /* 发送成功TICK */
|
||
} CAN_ID_SENT_TICK_MAP[] =
|
||
{
|
||
{CANBMS65CINFOID_WULING, 1000, 0, 0},
|
||
{CANBMS38AINFOID_WULING, 100, 0, 0},
|
||
{CANBMS38BINFOID_WULING, 100, 0, 0},
|
||
{CANBMS38CINFOID_WULING, 100, 0, 0},
|
||
{CANBMS38DINFOID_WULING, 100, 0, 0},
|
||
{CANBMS38EINFOID_WULING, 100, 0, 0},
|
||
{CANBMS598INFOID_WULING, 1000, 0, 0},
|
||
{CANBMS599INFOID_WULING, 1000, 0, 0},
|
||
{CANBMS59AINFOID_WULING, 1000, 0, 0},
|
||
};
|
||
void can2_bus_error_cb(e_link_sts err);
|
||
|
||
/****************************************************************************
|
||
* @brief: 检测can ID的实际发送时间是否超过指定时间
|
||
*
|
||
* @param frame_id: 要检测的CAN ID,
|
||
* @param outtime: 超时时间,单位ms
|
||
*
|
||
* @return: bool
|
||
* true: 周期超时
|
||
* false: 未达到超时时间
|
||
*/
|
||
bool can_sent_cycle_timeout(unsigned int frame_id)
|
||
{
|
||
unsigned short i;
|
||
|
||
for (i=0; i < (sizeof(CAN_ID_SENT_TICK_MAP)/sizeof(CAN_ID_SENT_TICK_MAP[0])); i++)
|
||
{
|
||
if (CAN_ID_SENT_TICK_MAP[i].frame_id == frame_id)
|
||
{
|
||
if ( CAN_ID_SENT_TICK_MAP[i].sent_tick == 0)
|
||
{
|
||
return true;
|
||
}
|
||
// if (CAN_ID_SENT_TICK_MAP[i].send_tick == 0 || CAN_ID_SENT_TICK_MAP[i].sent_tick == 0)
|
||
// {
|
||
// return true;
|
||
// }
|
||
#if 0
|
||
else if (abs(CAN_ID_SENT_TICK_MAP[i].sent_tick - CAN_ID_SENT_TICK_MAP[i].send_tick) < 5)
|
||
{
|
||
/* 发送时间和发送成功时间相近,则表示肯定上一次发送成功了,用发送时间进行对比 */
|
||
if (TickOut(&CAN_ID_SENT_TICK_MAP[i].send_tick, CAN_ID_SENT_TICK_MAP[i].period))
|
||
{
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
#endif
|
||
else if (TickOut(&CAN_ID_SENT_TICK_MAP[i].sent_tick, CAN_ID_SENT_TICK_MAP[i].period - 3))
|
||
{
|
||
/* 发送时间和发送成功时间不相近,则表示肯定上一次发送失败了,用上一次发送成功时间进行对比 */
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* @brief: 记录每一个CANid的发送成功的时间
|
||
*
|
||
* @param frame_id: 发送成功CAN ID
|
||
*
|
||
* @return: void
|
||
*/
|
||
static __inline void can_sent_tick_update(unsigned int frame_id)
|
||
{
|
||
unsigned short i;
|
||
|
||
for (i=0; i < (sizeof(CAN_ID_SENT_TICK_MAP)/sizeof(CAN_ID_SENT_TICK_MAP[0])); i++)
|
||
{
|
||
if (CAN_ID_SENT_TICK_MAP[i].frame_id == frame_id)
|
||
{
|
||
TickOut(&CAN_ID_SENT_TICK_MAP[i].sent_tick, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/****************************************************************************
|
||
* @brief: 记录每一个CANid的发送的时间
|
||
*
|
||
* @param frame_id: 发送成功CAN ID
|
||
*
|
||
* @return: void
|
||
*/
|
||
static __inline void can_send_tick_update(unsigned int frame_id)
|
||
{
|
||
unsigned short i;
|
||
|
||
for (i=0; i < (sizeof(CAN_ID_SENT_TICK_MAP)/sizeof(CAN_ID_SENT_TICK_MAP[0])); i++)
|
||
{
|
||
if (CAN_ID_SENT_TICK_MAP[i].frame_id == frame_id)
|
||
{
|
||
TickOut(&CAN_ID_SENT_TICK_MAP[i].send_tick, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*can 包 发送*/
|
||
int8_t can_write( CanTxMsg *TxMessage)
|
||
{
|
||
u16 time_up = 0;
|
||
|
||
if (candrv_if[0].SEND != NULL)
|
||
{
|
||
return candrv_if[0].SEND(0, (TxMessage->IDE == CAN_ID_EXT)?TxMessage->ExtId:TxMessage->StdId, \
|
||
TxMessage->Data, (TxMessage->RTR == CAN_RTR_DATA)?TxMessage->DLC:0, \
|
||
(TxMessage->IDE == CAN_ID_EXT)?TxMessage->ExtId:TxMessage->StdId,NULL);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
int8_t can_write2( CanTxMsg *TxMessage)
|
||
{
|
||
u16 time_up = 0;
|
||
uint8_t TransmitMailbox;
|
||
static u16 sendpoweronflag = 0;
|
||
static u8 sendlowvoltflag = 0;
|
||
static u8 sendhighvoltflag = 0;
|
||
|
||
#if 1
|
||
if(sendpoweronflag++ < 12) //刚上电不判断输入电压
|
||
{
|
||
|
||
}
|
||
else
|
||
{
|
||
if(sendpoweronflag > 100)sendpoweronflag =100;
|
||
if(sendlowvoltflag == 0)
|
||
{
|
||
if (Sample_DataS.VIN_Input_Voltage < 5.90) {
|
||
sendlowvoltflag = 1;
|
||
return 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (Sample_DataS.VIN_Input_Voltage < 6.40) {
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
sendlowvoltflag = 0;
|
||
}
|
||
}
|
||
|
||
if(sendhighvoltflag == 0)
|
||
{
|
||
if (Sample_DataS.VIN_Input_Voltage > 18.1) {
|
||
sendhighvoltflag = 1;
|
||
return 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (Sample_DataS.VIN_Input_Voltage > 17.6) {
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
sendhighvoltflag = 0;
|
||
}
|
||
}
|
||
|
||
}
|
||
#endif
|
||
//UDS禁止发送
|
||
if (!UdsApi_Is_UdsEnableNCMTx()) {
|
||
return 1;
|
||
}
|
||
|
||
if (candrv_if[1].SEND != NULL)
|
||
{
|
||
if (candrv_if[1].SEND(1, (TxMessage->IDE == CAN_ID_EXT)?TxMessage->ExtId:TxMessage->StdId, \
|
||
TxMessage->Data, (TxMessage->RTR == CAN_RTR_DATA)?TxMessage->DLC:0, \
|
||
(TxMessage->IDE == CAN_ID_EXT)?TxMessage->ExtId:TxMessage->StdId, NULL))
|
||
{
|
||
/* 暂时不需要更新 */
|
||
//can_send_tick_update((TxMessage->IDE == CAN_ID_EXT)?TxMessage->ExtId:TxMessage->StdId);
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
/************************************************************************************************************
|
||
* 总线异常BUSSOFF的处理
|
||
***********************************************************************************************************/
|
||
typedef enum
|
||
{
|
||
E_BUS_NORMAL = 0,
|
||
E_BUS_BUSOFF,
|
||
E_BUS_RECOVERY_ACK,
|
||
} bus_recovery_step_e;
|
||
|
||
typedef struct
|
||
{
|
||
unsigned char step; /* 0 - 正常 1 - bus off 延时 2-bus off recovery 确认 */
|
||
unsigned int bus_off_tick; /* 触发bus off的时间 */
|
||
unsigned int recovery_tick; /* recovery的时间 */
|
||
unsigned short recovery_times; /* 连续recovey次数 */
|
||
unsigned char first_frm;
|
||
} bus_off_recovery_t;
|
||
|
||
static const unsigned short BUS_OFF_TIME_MS[] = {30, 198, 198, 198, 198, 198};
|
||
|
||
static bus_off_recovery_t canbus[BSP_CAN_CHANNEL_NUM];
|
||
|
||
/**
|
||
* @brief: 处理bus off的recovery操作
|
||
*
|
||
* @param : void
|
||
*
|
||
* @return: void
|
||
*
|
||
* @remark: 自动恢复总线,可放在定时器或在循环内,其被执行的间隔不能超过10ms。
|
||
*/
|
||
#include "led.h"
|
||
extern void WULING_DCDCSendBms2_force(void);
|
||
extern u8 EntSlpFlag ;
|
||
void can_bus_off_recovery(void)
|
||
{
|
||
unsigned char i;
|
||
unsigned int timeout;
|
||
unsigned char buffer[8]={0};
|
||
|
||
for (i = 0; i < BSP_CAN_CHANNEL_NUM; i++)
|
||
{
|
||
// if ((canbus[i].step == E_BUS_BUSOFF) && (EntSlpFlag==0)/* && 非休眠条件*/)
|
||
if ((canbus[i].step == E_BUS_BUSOFF)/* && 非休眠条件*/)
|
||
{
|
||
if (canbus[i].recovery_times < (sizeof(BUS_OFF_TIME_MS)/sizeof(BUS_OFF_TIME_MS[0])))
|
||
{
|
||
timeout = BUS_OFF_TIME_MS[canbus[i].recovery_times];
|
||
}
|
||
else
|
||
{
|
||
/* reopen 超过指定次数则使用设定的最后一个间隔 */
|
||
timeout = BUS_OFF_TIME_MS[(sizeof(BUS_OFF_TIME_MS)/sizeof(BUS_OFF_TIME_MS[0]))-1];
|
||
}
|
||
if (TickOut(&canbus[i].bus_off_tick, timeout))
|
||
{
|
||
|
||
SYS_ENTER_CRITICAL();
|
||
canbus[i].recovery_times++;
|
||
if (candrv_if[i].ConfigBus != NULL) candrv_if[i].ConfigBus(i, 0,0,0);
|
||
canbus[i].step = E_BUS_RECOVERY_ACK;
|
||
// /* 模拟发送网络管理数据包 */
|
||
// if(ChkPwrManageAccoff()!=0 )
|
||
// {
|
||
buffer[0]=1;
|
||
// }
|
||
if (candrv_if[i].SEND!= NULL) candrv_if[i].SEND(i, CANBMS65CINFOID_WULING, buffer, 8, CANBMS65CINFOID_WULING, NULL);
|
||
|
||
SYS_EXIT_CRITICAL();
|
||
TickOut(&canbus[i].recovery_tick, 0);
|
||
canbus[i].first_frm = 1;
|
||
}
|
||
}
|
||
else if (canbus[i].step == E_BUS_RECOVERY_ACK)
|
||
{
|
||
if (TickOut(&canbus[i].recovery_tick, 103))
|
||
{
|
||
WULING_DCDCSendBms2_force();
|
||
canbus[i].recovery_times = 0;
|
||
canbus[i].step = E_BUS_NORMAL;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: 打印 can 总线状态
|
||
*/
|
||
void can_bus_off_status_printf(void)
|
||
{
|
||
printf("can 1: step(%d), recorvery(%d), last bus off tick(%d), last recovery tick(%d)!\n", \
|
||
canbus[0].step, canbus[0].recovery_times, canbus[0].bus_off_tick, canbus[0].recovery_tick);
|
||
printf("can 2: step(%d), recorvery(%d), last bus off tick(%d) last recovery tick(%d)!\n", \
|
||
canbus[1].step, canbus[1].recovery_times, canbus[1].bus_off_tick, canbus[1].recovery_tick);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/***********************************************************************************************
|
||
* 以下是应用层针对总线底层的接口
|
||
**********************************************************************************************/
|
||
void can2_bus_error_cb(e_link_sts err)
|
||
{
|
||
if (err != e_err_bussoff)
|
||
{
|
||
/* 不是BUSS OFF暂时不处理 */
|
||
return;
|
||
}
|
||
|
||
if (canbus[1].step != E_BUS_BUSOFF)
|
||
{
|
||
|
||
if (candrv_if[1].CloseLink != NULL) candrv_if[1].CloseLink(1);
|
||
canbus[1].step = E_BUS_BUSOFF;
|
||
TickOut(&canbus[1].bus_off_tick, 0);
|
||
}
|
||
}
|
||
|
||
static void can2_comm_sent_cb(unsigned int canid, unsigned int result)
|
||
{
|
||
/* 发送回调 */
|
||
if (result == _SUCCESS)
|
||
{
|
||
/* 发送成功 */
|
||
can_sent_tick_update(canid);
|
||
if (canbus[1].first_frm > 0 && canbus[1].step == E_BUS_RECOVERY_ACK)
|
||
{
|
||
canbus[1].first_frm = 0;
|
||
TickOut(&canbus[1].recovery_tick, 0);
|
||
}
|
||
}
|
||
else if (result == _ABANDON)
|
||
{
|
||
/* 因为异常恢复 */
|
||
}
|
||
else
|
||
{
|
||
/* 发送失败 */
|
||
}
|
||
}
|
||
|
||
static st_pl can2_protocol =
|
||
{
|
||
"整车协议",
|
||
0,
|
||
3,
|
||
10,
|
||
NULL,
|
||
can2_bus_error_cb,
|
||
can2_comm_sent_cb
|
||
};
|
||
|
||
#if 0
|
||
static void can1_bus_error_cb(e_link_sts err)
|
||
{
|
||
|
||
}
|
||
|
||
static void can1_comm_sent_cb(unsigned int canid, unsigned int result)
|
||
{
|
||
/* 发送回调 */
|
||
|
||
}
|
||
#endif
|
||
|
||
static st_pl can1_protocol =
|
||
{
|
||
"整车协议",
|
||
0,
|
||
3,
|
||
10,
|
||
NULL,
|
||
NULL,
|
||
NULL
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
void InitCanDrvCtrlMode(void);
|
||
void InitCanifToCanDrvCtrl(void);
|
||
bool InstallProtocalToIF(unsigned char chan, st_pl* ppl, st_cl * pcl);
|
||
/**
|
||
* @brief: 初始化can 协议的基础功能
|
||
*/
|
||
void can_porting_init(void);
|
||
|
||
/**
|
||
* @brief: 初始化can 协议的基础功能的调度
|
||
*/
|
||
void can_porting_schedule(void);
|
||
|
||
|
||
|
||
|
||
void app_can_handle(void)
|
||
{
|
||
static uint8_t bms_rev_busy_flag = 0;
|
||
static CanRxMsg MutliBMSCAN1Msg;
|
||
CanRxMsg rec_message;
|
||
unsigned int id;
|
||
unsigned char data[8], len;
|
||
|
||
can_porting_schedule();
|
||
|
||
while (candrv_if[0].REC != NULL && candrv_if[0].REC(0,&id, data, &len) == true)
|
||
{
|
||
/* 数据接收 */
|
||
CAN_FRAME_INIT((CanTxMsg *)(&rec_message), id, data, len);
|
||
rec_message.FMI = 0;
|
||
|
||
bms_rev_busy_flag = 1;
|
||
|
||
if(bms_RcvCanSingleDataProc(rec_message) == 1)
|
||
{
|
||
MutliBMSCAN1Msg = rec_message;
|
||
bms_RcvCanMutliData(MutliBMSCAN1Msg,0,&bms_rev_busy_flag);
|
||
}
|
||
|
||
IWDG_Feed();
|
||
}
|
||
|
||
while (candrv_if[1].REC != NULL && candrv_if[1].REC(1,&id, data, &len) == true)
|
||
{
|
||
/* 数据接收 */
|
||
CAN_FRAME_INIT((CanTxMsg *)(&rec_message), id, data, len);
|
||
rec_message.FMI = 0;
|
||
|
||
//UDS允许接收
|
||
if (UdsApi_Is_UdsEnableNCMRx()) {
|
||
bms_RcvCan2DataProc(rec_message);
|
||
}
|
||
UdsApi_MsgQueueIn(rec_message);
|
||
memset(&rec_message,0,sizeof(rec_message));
|
||
|
||
// bms_RcvCan2DataProc(rec_message);
|
||
|
||
IWDG_Feed();
|
||
}
|
||
|
||
can_bus_off_recovery();
|
||
}
|
||
|
||
|
||
void app_can_init(void)
|
||
{
|
||
memset(&canbus[0], 0x00, sizeof(canbus));
|
||
memset(&candrv_if[0], 0x00, sizeof(candrv_if));
|
||
can_porting_init();
|
||
InitCanDrvCtrlMode();
|
||
InitCanifToCanDrvCtrl();
|
||
|
||
if(InstallProtocalToIF(0,&can1_protocol,&candrv_if[0]) == true)
|
||
{
|
||
printf("can1 协议初始化成功\r\n");
|
||
}
|
||
if(InstallProtocalToIF(1,&can2_protocol,&candrv_if[1]) == true)
|
||
{
|
||
printf("can2 协议初始化成功\r\n");
|
||
}
|
||
|
||
if (candrv_if[0].ConfigBus != NULL)
|
||
{
|
||
candrv_if[0].ConfigBus(0, 0, 0, 0);
|
||
}
|
||
if (candrv_if[1].ConfigBus != NULL)
|
||
{
|
||
candrv_if[1].ConfigBus(1, 0, 0, 0);
|
||
}
|
||
}
|
||
|