371 lines
9.0 KiB
C
371 lines
9.0 KiB
C
|
||
#include "canctrl.h"
|
||
|
||
#if (COMM_CAN != 0)
|
||
|
||
#include "trigger.h"
|
||
#include "cpuid.h"
|
||
|
||
//-------------------------------------------------------------------------------
|
||
|
||
CanRxCtrl g_canRxCtrl;
|
||
CanTxCtrl g_canTxCtrl;
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
void InitCanMsgList(void);
|
||
void InitCanFilter(void);
|
||
|
||
//------------------------------------------------------------------------
|
||
// 默认过滤器,接收所有数据包
|
||
void DefaultCanFilter(u8 fifo)
|
||
{
|
||
HAL_StatusTypeDef halsta;
|
||
|
||
CAN_FilterTypeDef hFilterConfig;
|
||
hFilterConfig.FilterBank = 0; // 待初始化的过滤器为主0--13 , 从14--27
|
||
hFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // 工作在标识符屏蔽位模式
|
||
hFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // 过滤器位宽为1个32位。
|
||
hFilterConfig.FilterIdHigh = 0x0000; // 设定过滤器标识符(32位位宽时为其高段位,16位位宽时为第一个)
|
||
hFilterConfig.FilterIdLow = 0x0000; // 设定过滤器标识符(32位位宽时为其低段位,16位位宽时为第二个)
|
||
hFilterConfig.FilterMaskIdHigh = 0x0000; // 设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其高段位,16位位宽时为第一个)
|
||
hFilterConfig.FilterMaskIdLow = 0x0000; // 设定过滤器屏蔽标识符或者过滤器标识符(32位位宽时为其低段位,16位位宽时为第二个)
|
||
hFilterConfig.FilterFIFOAssignment = fifo; // 过滤器被关联到FIFO
|
||
hFilterConfig.SlaveStartFilterBank = 14; // 从节点CAN过滤器(对于主CAN无意义)。双CAN的系统必须设置
|
||
hFilterConfig.FilterActivation = CAN_FILTER_ENABLE; // 使能过滤器
|
||
|
||
halsta = HAL_CAN_ConfigFilter(&HCAN, &hFilterConfig);
|
||
|
||
printf("DefaultCanFilter at fifo%d, halsta=%d\r\n", fifo, halsta);
|
||
}
|
||
|
||
|
||
void (*SetCanFilter)(u8) = DefaultCanFilter;
|
||
|
||
void RegistFilter(void*func)
|
||
{
|
||
SetCanFilter = (void (*)(u8))func;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
void InitCanCtrl(void)
|
||
{
|
||
HAL_StatusTypeDef halsta; // 状态
|
||
|
||
InitCanMsgList(); // 控制数据结构初始化
|
||
|
||
if (SetCanFilter != NULL) // 过滤器初始化
|
||
{
|
||
SetCanFilter(CAN_FILTER_FIFO0);
|
||
}
|
||
|
||
halsta = HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_MSG_PENDING); // 打开CAN接收中断
|
||
if (halsta != HAL_OK)
|
||
{
|
||
printf("HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_MSG_PENDING) failed\r\n");
|
||
}
|
||
|
||
halsta = HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_FULL); // 打开CAN邮箱满中断
|
||
if (halsta != HAL_OK)
|
||
{
|
||
printf("HAL_CAN_ActivateNotification(&HCAN, CAN_IT_RX_FIFO0_FULL) failed\r\n");
|
||
}
|
||
|
||
halsta = HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY); // 关闭发送中断
|
||
if (halsta != HAL_OK)
|
||
{
|
||
printf("HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY) failed\r\n");
|
||
}
|
||
|
||
halsta = HAL_CAN_Start(&HCAN); // 启动CAN模块
|
||
if (halsta != HAL_OK)
|
||
{
|
||
printf("HAL_CAN_Start failed\r\n");
|
||
}
|
||
}
|
||
|
||
// 初始化控制结构
|
||
void InitCanMsgList(void)
|
||
{
|
||
memset(&g_canTxCtrl, 0, sizeof(CanTxCtrl));
|
||
memset(&g_canRxCtrl, 0, sizeof(CanRxCtrl));
|
||
|
||
g_canTxCtrl.pktTxListHead = g_canTxCtrl.pktTxList; // 头指针
|
||
g_canTxCtrl.pktTxListTail = g_canTxCtrl.pktTxList; // 尾指针
|
||
g_canTxCtrl.pktTxNumber = 0; // 有效个数
|
||
g_canTxCtrl.sendingFlag = 0;
|
||
|
||
g_canRxCtrl.pktRxListHead = g_canRxCtrl.pktRxList; // 头指针
|
||
g_canRxCtrl.pktRxListTail = g_canRxCtrl.pktRxList; // 尾指针
|
||
g_canRxCtrl.pktRxNumber = 0; // 有效个数
|
||
}
|
||
|
||
//---------------------------------------------------------
|
||
/*
|
||
HAL_OK = 0x00U,
|
||
HAL_ERROR = 0x01U,
|
||
HAL_BUSY = 0x02U,
|
||
HAL_TIMEOUT = 0x03U,
|
||
*/
|
||
// 发送数据到总线
|
||
int TransCanDataToBus(void)
|
||
{
|
||
HAL_StatusTypeDef halsta; // 发送状态
|
||
u32 tsmBox; // 发送邮箱
|
||
|
||
// printf("TransCanDataToBus\r\n");
|
||
|
||
// 从队列取一个数据包发送
|
||
if (g_canTxCtrl.pktTxNumber <= 0)
|
||
{
|
||
//printf("pktTxNumber=%d\r\n", g_canTxCtrl.pktTxNumber);
|
||
return 1;
|
||
}
|
||
|
||
halsta = HAL_CAN_AddTxMessage(&HCAN, &(g_canTxCtrl.pktTxListTail->canTxhead) , g_canTxCtrl.pktTxListTail->data, &tsmBox);
|
||
//printf("exid=0x%x,tsmBox=%d,halsta=%d\r\n", g_canTxCtrl.pktTxListTail->canTxhead.ExtId, tsmBox,halsta);
|
||
if (halsta == HAL_OK)
|
||
{
|
||
EnterCritical();
|
||
g_canTxCtrl.pktTxNumber--;
|
||
g_canTxCtrl.pktTxListTail++;
|
||
if (g_canTxCtrl.pktTxListTail > &(g_canTxCtrl.pktTxList[TRANS_PKT_LIST_NUM-1]))
|
||
{
|
||
g_canTxCtrl.pktTxListTail = &(g_canTxCtrl.pktTxList[0]);
|
||
}
|
||
ExitCritical();
|
||
|
||
// printf("HAL_OK, g_canTxCtrl.pktTxNumber=%d\r\n", num);
|
||
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
printf("TransCanDataToBus:other sta, halsta=%d\r\n", halsta);
|
||
return 2;
|
||
}
|
||
}
|
||
|
||
// 从总线上接收数据
|
||
int ResvCanDataFromBus(void)
|
||
{
|
||
HAL_StatusTypeDef halsta;
|
||
CanRxMsg rxMsg;
|
||
|
||
halsta = HAL_CAN_GetRxMessage(&HCAN, CAN_RX_FIFO0, &(rxMsg.canRxhead), rxMsg.data); // 读取数据
|
||
if (halsta == HAL_OK)
|
||
{
|
||
//printf("get a can packet:\r\n");
|
||
//printf("exid=0x%x\r\n", rxMsg.canRxhead.ExtId);
|
||
if (g_canRxCtrl.pktRxNumber < RESV_PKT_LIST_NUM-1) // 添加到队列中
|
||
{
|
||
// printf("add to rxlist, add=0x%x\r\n", g_canRxCtrl.pktRxListHead);
|
||
memcpy(g_canRxCtrl.pktRxListHead, &rxMsg, sizeof(CanRxMsg));
|
||
|
||
g_canRxCtrl.pktRxNumber++;
|
||
g_canRxCtrl.pktRxListHead++;
|
||
if (g_canRxCtrl.pktRxListHead > &(g_canRxCtrl.pktRxList[RESV_PKT_LIST_NUM-1]))
|
||
{
|
||
g_canRxCtrl.pktRxListHead = &(g_canRxCtrl.pktRxList[0]);
|
||
}
|
||
//printf("resv RxNum=%d\r\n", g_canRxCtrl.pktRxNumber);
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
printf("can receive buff is full\r\n");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
printf("ResvCanDataFromBus:other sta, halsta=%d\r\n", halsta);
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
//---------------------------------------------------------
|
||
|
||
// 添加发送数据到队列
|
||
int SendACANDataPacket(CanTxMsg * pMsg)
|
||
{
|
||
int rslt;
|
||
if (pMsg == NULL)
|
||
{
|
||
printf("SendACANDataPacket:para error\r\n");
|
||
return -1;
|
||
}
|
||
|
||
if (g_canTxCtrl.pktTxNumber < TRANS_PKT_LIST_NUM)
|
||
{
|
||
// 添加一个数据包到发送队列
|
||
memcpy(g_canTxCtrl.pktTxListHead, pMsg, sizeof(CanTxMsg)); // 拷贝数据
|
||
|
||
EnterCritical();
|
||
g_canTxCtrl.pktTxNumber++;
|
||
g_canTxCtrl.pktTxListHead++;
|
||
if (g_canTxCtrl.pktTxListHead > &(g_canTxCtrl.pktTxList[TRANS_PKT_LIST_NUM-1]))
|
||
{
|
||
g_canTxCtrl.pktTxListHead = &(g_canTxCtrl.pktTxList[0]);
|
||
}
|
||
ExitCritical();
|
||
|
||
if (g_canTxCtrl.sendingFlag == 0) // 没有发送
|
||
{
|
||
rslt = TransCanDataToBus(); // 启动发送队列中数据到总线
|
||
|
||
if (rslt == 0) // 添加到队列成功,队列中有数据
|
||
{
|
||
//printf("send a can packet in app\r\n");
|
||
g_canTxCtrl.sendingFlag = 1; // 设置标志
|
||
HAL_CAN_ActivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY); // 打开邮箱空中断
|
||
}
|
||
else if (rslt == 1) // 队列中没有数据要发送
|
||
{
|
||
//printf("send list empty in app\r\n");
|
||
g_canTxCtrl.sendingFlag = 0;
|
||
HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY); // 没有数据发送,关闭中断
|
||
}
|
||
else // 没有合适的邮箱
|
||
{
|
||
printf("no mail box in app, start later\r\n");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//printf("sendingFlag=1\r\n");
|
||
HAL_CAN_ActivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY); // 打开邮箱空中断
|
||
}
|
||
rslt = 0;
|
||
}
|
||
else
|
||
{
|
||
printf("can send buff is full\r\n");
|
||
rslt = 1;
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
|
||
// 从队列中读取数据
|
||
int GetACanDataPacket(CanRxMsg * pMsg)
|
||
{
|
||
int rslt;
|
||
if (pMsg == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
if (g_canRxCtrl.pktRxNumber > 0)
|
||
{
|
||
memcpy(pMsg, g_canRxCtrl.pktRxListTail, sizeof(CanRxMsg));
|
||
|
||
EnterCritical();
|
||
g_canRxCtrl.pktRxNumber--;
|
||
//printf("2.RxNum=%d\r\n", g_canRxCtrl.pktRxNumber);
|
||
g_canRxCtrl.pktRxListTail++;
|
||
if (g_canRxCtrl.pktRxListTail > &(g_canRxCtrl.pktRxList[RESV_PKT_LIST_NUM-1]))
|
||
{
|
||
g_canRxCtrl.pktRxListTail = &(g_canRxCtrl.pktRxList[0]);
|
||
}
|
||
ExitCritical();
|
||
|
||
rslt = 0;
|
||
}
|
||
else
|
||
{
|
||
rslt = 1;
|
||
}
|
||
|
||
return rslt;
|
||
}
|
||
|
||
//---------------------------------------------------------
|
||
|
||
void CanTransIntProc(void)
|
||
{
|
||
int rslt;
|
||
|
||
rslt = TransCanDataToBus();
|
||
|
||
if (rslt == 0) // 队列中有数据且发送成功
|
||
{
|
||
//printf("send a can packet in int\r\n");
|
||
}
|
||
else if (rslt == 1) // 队列中没有数据要发送
|
||
{
|
||
// printf("send list empty in int, close int\r\n");
|
||
g_canTxCtrl.sendingFlag = 0;
|
||
HAL_CAN_DeactivateNotification(&HCAN, CAN_IT_TX_MAILBOX_EMPTY); // 没有数据发送,关闭中断
|
||
}
|
||
else // 没有邮箱
|
||
{
|
||
printf("no mail box in int\r\n");
|
||
}
|
||
}
|
||
|
||
void CanResvIntProc(void)
|
||
{
|
||
u32 len;
|
||
len = HAL_CAN_GetRxFifoFillLevel(&HCAN, CAN_RX_FIFO0); // 个数
|
||
while(len != 0)
|
||
{
|
||
//printf("get a can packet:\r\n");
|
||
ResvCanDataFromBus(); // 读取数据,添加到队列
|
||
len--;
|
||
}
|
||
}
|
||
|
||
//---------------------------------------------------------
|
||
|
||
// CAN邮箱0发送完成中断的回调函数
|
||
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *pcan)
|
||
{
|
||
// if (pcan->Instance == CAN1)
|
||
{
|
||
CanTransIntProc();
|
||
}
|
||
}
|
||
|
||
// CAN邮箱1发送完成中断的回调函数
|
||
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *pcan)
|
||
{
|
||
// if (pcan->Instance == CAN1)
|
||
{
|
||
CanTransIntProc();
|
||
}
|
||
}
|
||
|
||
// CAN邮箱2发送完成中断的回调函数
|
||
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *pcan)
|
||
{
|
||
// if (pcan->Instance == CAN1)
|
||
{
|
||
CanTransIntProc();
|
||
}
|
||
}
|
||
|
||
// CAN邮箱0接收中断回调函数
|
||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *pcan)
|
||
{
|
||
// if (pcan->Instance == CAN1)
|
||
{
|
||
//printf("rx fifo 0\r\n");
|
||
CanResvIntProc();
|
||
}
|
||
}
|
||
|
||
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *pcan)
|
||
{
|
||
printf("can rx fifo0 full\r\n");
|
||
}
|
||
|
||
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
|
||
{
|
||
printf("can error\r\n");
|
||
}
|
||
//---------------------------------------------------------
|
||
#endif
|
||
|