optical/NxBase/canctrl.c
2025-09-04 09:45:08 +08:00

371 lines
9.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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