📄 zlg_can.c
字号:
canAcceptFilterSet(ptCanNode, ulFrameID, ulFrameIDMsk, ucFramType);
/* 验收滤波设置 */
// 中断使能
canIntEnable(ptCanNode); /* 注册中断服务函数并使能CAN中断*/
return CAN_OK;
}
/*********************************************************************************************************
** Function name: canCirBufSend
** Descriptions: 触发指定循环队列中的帧数据的发送工作
** input parameters: ptBuf 指向循环队列的指针
** global variable: GptCanCirBuf:待发送的缓冲区入口地址
** GbCanCirBufSend:标志是否将缓冲区数据发送出去
** Returned value: EMPTY 缓存为空
** NOT_EMPTY 缓存不空
** CAN_ERROR 循环队列错误,操作失败
**
** Created By: 张展威
** Created date: 2008.09.10
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
INT8U canCirBufSend(CANNODEINFO *ptCanNode, CANCIRBUF *ptCanCirBuf)
{
CANFRAME tCanFrame;
unsigned char ucEnable = 0;
if (ptCanNode == 0) { /* 检查节点的有效性 */
return CAN_ERROR;
}
if (ptCanNode->ptCanTxCirBuf != (CANCIRBUF *)0) { /* 已有"缓存区"在发送队列 */
return BUSY;
}
/* 给需要发送的CAN节点 */
if (canCirBufRead(ptCanCirBuf, &tCanFrame) != CAN_OK) { /* 缓存区不为空,继续发送 */
return CAN_ERROR;
}
ucEnable = __ENTER_CIRTICAL(); /* 进入临界区 */
ptCanNode->ptCanTxCirBuf = ptCanCirBuf; /* 将要发送的缓冲区首地址传递 */
ptCanNode->ucNodeState &= ~CAN_FRAM_SEND; /* 状态更新为“发送未完成” */
canFrameSend(ptCanNode, &tCanFrame); /* 发送一帧数据,其余数据将 */
/* 在中断中继续发送 */
__EXIT_CIRTICAL(ucEnable); /* 退出临界区 */
return CAN_OK; /* 返回操作结果 */
}
/*********************************************************************************************************
** Function name: canHandler
** Descriptions: 实现中断接收一帧或多帧CAN报文,以及发送成功的标志设置
** input parameters: ptCanNode:指向CAN软件节点的指针
** output parameters: 无
** Returned value: 无
** Modified by: 张展威
** Modified date: 2008.09.20
** Descriptions: CAN中断处理函数
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void canHandler(CANNODEINFO *ptCanNode)
{
CANFRAME *ptCanFrame;
CANFRAME tCanFrame;
CAN_MSG_OBJ tMsgObjBuf;
unsigned long ulMsgObjID;
unsigned long ulNewData;
unsigned long ulTxObjMask = 1UL << (ptCanNode->ulTxMsgObjNr - 1);
INT32U ulStatus = 0;
INT32U ulTxReq = 0;
INT32U ulBit = 0;
INT8U i = 0;
unsigned long ulCallBackMsg = CAN_NO_ERROR;
ulMsgObjID = CANIntStatus(ptCanNode->ulBaseAddr,CAN_INT_STS_OBJECT);
/* 读取中断标志,用于分析状态中断*/
ulStatus = CANStatusGet(ptCanNode->ulBaseAddr, CAN_STS_CONTROL);
ulNewData = CANStatusGet(ptCanNode->ulBaseAddr, CAN_STS_NEWDAT);
ulTxReq = CANStatusGet(ptCanNode->ulBaseAddr, CAN_STS_TXREQUEST);
ulNewData &= ~ulTxObjMask; /* 忽略发送报文对象的NewDat */
if (ulStatus & CAN_STATUS_LEC_MSK ) {
ptCanNode->ucNodeState |= CAN_SEND_FAIL; /* 发送失败,传输产生了错误 */
} else {
ptCanNode->ucNodeState &= ~CAN_SEND_FAIL; /* 通信成功,清除错误标志 */
}
if (ulStatus & CAN_STATUS_BUS_OFF) {
CANIntDisable(ptCanNode->ulBaseAddr, CAN_INT_MASTER | CAN_INT_ERROR);
/* 关闭CAN中断 */
ptCanNode->ucNodeState |= CAN_BUS_OFF; /* 脱离总线 */
ptCanNode->ulBofTimer = 0;
ulCallBackMsg |= CAN_BUS_OFF; /* 脱离总线 */
}
ulStatus = ulNewData;
if (ulMsgObjID != 0) { /* 存在挂起中断 */
for (i = 0; i < 32; i++) {
ulBit = 1UL << i;
if ((ptCanNode->ulDaReObjMsk & ulNewData & ulBit) != 0){ /* 收到数据帧 */
ptCanFrame = canCirBufMalloc(ptCanNode->ptCanReCirBuf); /* 取得缓存地址 */
if (ptCanFrame == (CANFRAME *)0) { /* 缓存申请失败,说明缓冲区已满 */
ptCanFrame = &tCanFrame; /* 用局部变量进行缓存,将被丢弃 */
}
tMsgObjBuf.pucMsgData = ptCanFrame->ucDatBuf; /* 传递帧数据缓存地址 */
CANMessageGet(ptCanNode->ulBaseAddr, (i + 1), &tMsgObjBuf, 0);
/* 读出接收数据 */
ptCanFrame->ucDLC = tMsgObjBuf.ulMsgLen; /* 记录数据场长度 */
if (tMsgObjBuf.ulFlags & MSG_OBJ_EXTENDED_ID) { /* 扩展帧 29 位标志字符 */
ptCanFrame->ulID = (tMsgObjBuf.ulMsgID & 0x1FFFFFFF);
/* 记录CAN报文ID */
ptCanFrame->ucTtypeFormat = XTD_DATA; /* 记录为扩展数据帧 */
} else { /* 标准帧 11 位标志字符 */
ptCanFrame->ulID = (tMsgObjBuf.ulMsgID & 0x000007FF);
/* 记录CAN报文ID */
ptCanFrame->ucTtypeFormat = STD_DATA; /* 记录为标准数据帧 */
}
} else if ((ptCanNode->ulRmReObjMsk & ulNewData & ulBit) != 0) {
/* 收到远程帧 */
ptCanFrame = canCirBufMalloc(ptCanNode->ptCanReCirBuf); /* 取得缓存地址 */
if (ptCanFrame == (CANFRAME *)0) { /* 缓存申请失败,说明缓冲区已满 */
ptCanFrame = &tCanFrame; /* 用局部变量进行缓存,将被丢弃 */
}
tMsgObjBuf.pucMsgData = ptCanFrame->ucDatBuf; /* 传递帧数据缓存地址 */
CANMessageGet(ptCanNode->ulBaseAddr, (i + 1), &tMsgObjBuf, 0);
ptCanFrame->ucDLC = tMsgObjBuf.ulMsgLen; /* 记录数据场长度 */
if (tMsgObjBuf.ulFlags & MSG_OBJ_EXTENDED_ID) { /* 扩展帧 29 位标志字符 */
ptCanFrame->ulID = (tMsgObjBuf.ulMsgID & 0x1FFFFFFF);
ptCanFrame->ucTtypeFormat = XTD_RMRQS; /* 记录为扩展远程帧 */
} else { /* 标准帧 11 位标志字符 */
ptCanFrame->ulID = (tMsgObjBuf.ulMsgID & 0x000007FF);
ptCanFrame->ucTtypeFormat = STD_RMRQS; /* 记录为标准远程帧 */
}
}
ulStatus &= ~ulBit;
if (ulStatus == 0) { /* 剩余报文对象已经没有新数据了 */
break;
}
}
ulStatus = ulMsgObjID;
for (i = 0; i < 32; i++) { /* 清除中断标志 */
ulBit = 1UL << i;
if (ulMsgObjID & ulBit) {
CANIntClear(ptCanNode->ulBaseAddr, i + 1);
}
ulStatus &= ~ulBit;
if (ulStatus == 0) { /* 剩余报文对象已经没有新数据了 */
break;
}
}
if (ulNewData & ((ptCanNode->ulRmReObjMsk) |(ptCanNode->ulDaReObjMsk))) {
/* 收到数据帧或远程帧 */
ptCanNode->ucNodeState |= CAN_FRAM_RECV; /* 收到数据 */
ulCallBackMsg |= CAN_FRAM_RECV;
}
if ((ulTxObjMask & ulMsgObjID) != 0) { /* 成功发送数据 */
ptCanNode->ucNodeState |= CAN_FRAM_SEND; /* 发送完成 */
ulCallBackMsg |= CAN_FRAM_SEND;
}
}
// 检查是否有数据等待发送
ulTxReq = CANStatusGet(ptCanNode->ulBaseAddr, CAN_STS_TXREQUEST);
if ((ulTxReq & ulTxObjMask) == 0) { /* 检查CAN控制器是否可以发送收据*/
if (ptCanNode->ptCanTxCirBuf != 0) { /* 检查是否有数据等待发送 */
if (canCirBufRead(ptCanNode->ptCanTxCirBuf, &tCanFrame) == CAN_OK) {
ptCanNode->ucNodeState &= ~CAN_FRAM_SEND; /* 缓存区不为空,继续发送 */
canFrameSend(ptCanNode, &tCanFrame); /* 触发下一帧的发送工作 */
} else {
ptCanNode->ptCanTxCirBuf = 0; /* 发送队列空闲 */
}
}
}
if (ulCallBackMsg) { /* 回调函数的消息类型不为0 */
if (ptCanNode->pfCanHandlerCallBack) { /* 存在回调函数 */
ptCanNode->pfCanHandlerCallBack(ulCallBackMsg, ulNewData, ulMsgObjID);
}
}
CANIntClear(ptCanNode->ulBaseAddr, CAN_INT_INTID_STATUS); /* 清除状态中断标志 */
}
/*********************************************************************************************************
** Function name: canNodeBusOn
** Descriptions: CAN控制器重新接入总线(清零初始化位,使能相应的中断)
** input parameters: ptCanNode:指向CAN软件节点的指针
** output parameters: 无
** Returned value: 无
** Modified by: 张展威
** Modified date: 2008.09.20
** Descriptions:
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void canNodeBusOn(CANNODEINFO *ptCanNode)
{
if (ptCanNode == 0) { /* 检查节点的有效性 */
return;
}
CANEnable(ptCanNode->ulBaseAddr); /* 退出初始化模式,启动CAN节点 */
CANIntClear(ptCanNode->ulBaseAddr, CAN_INT_INTID_STATUS); /* 清除状态中断标志 */
CANIntEnable(ptCanNode->ulBaseAddr, CAN_INT_MASTER | CAN_INT_ERROR);/* 设置中断源 */
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -