#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