⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zlg_can.c

📁 LPC11C14 CAN 代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    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 + -