This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123 官方CAN例程改为CAN1调试不通

我在TI官方例程CAN0回环调试通过,然后将管脚和初始化配置设置成CAN1后,软件调试不通。CAN无输出

  • 这个。。。就是配置有问题咯

    你确定引脚的辅助功能都配置对了?

  • 上你的初始化代码看看,肯定是有个地方没有改过来。

  • CAN0官方例程运行通过如下:

    void
    CANIntHandler(void)
    {
    uint32_t ui32Status;
    ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
    if(ui32Status == CAN_INT_INTID_STATUS)
    {
    ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
    g_bErrFlag = 1;
    }
    else if(ui32Status == 1)
    {
    CANIntClear(CAN0_BASE, 1);
    g_ui32MsgCount++;
    g_bErrFlag = 0;
    }
    else
    {

    }
    }


    void
    CANInit(uint32_t ui32Base)
    {
    uint32_t ui32Msg;
    ASSERT(_CANBaseValid(ui32Base));
    HWREG(ui32Base + CAN_O_CTL) = CAN_CTL_INIT;
    while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }
    HWREG(ui32Base + CAN_O_IF1CMSK) = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB |
    CAN_IF1CMSK_CONTROL);
    HWREG(ui32Base + CAN_O_IF1ARB2) = 0;
    HWREG(ui32Base + CAN_O_IF1MCTL) = 0;
    for(ui32Msg = 1; ui32Msg <= 32; ui32Msg++)
    {
    while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }
    HWREG(ui32Base + CAN_O_IF1CRQ) = ui32Msg;
    }
    HWREG(ui32Base + CAN_O_IF1CMSK) = (CAN_IF1CMSK_NEWDAT |
    CAN_IF1CMSK_CLRINTPND);

    for(ui32Msg = 1; ui32Msg <= 32; ui32Msg++)
    {
    while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }
    HWREG(ui32Base + CAN_O_IF1CRQ) = ui32Msg;
    }

    HWREG(ui32Base + CAN_O_STS);
    }

    void
    CANMessageSet(uint32_t ui32Base, uint32_t ui32ObjID,
    tCANMsgObject *psMsgObject, tMsgObjType eMsgType)
    {
    uint16_t ui16CmdMaskReg;
    uint16_t ui16MaskReg0, ui16MaskReg1;
    uint16_t ui16ArbReg0, ui16ArbReg1;
    uint16_t ui16MsgCtrl;
    bool bTransferData;
    bool bUseExtendedID;

    bTransferData = 0;

    ASSERT(_CANBaseValid(ui32Base));
    ASSERT((ui32ObjID <= 32) && (ui32ObjID != 0));
    ASSERT((eMsgType == MSG_OBJ_TYPE_TX) ||
    (eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
    (eMsgType == MSG_OBJ_TYPE_RX) ||
    (eMsgType == MSG_OBJ_TYPE_RX_REMOTE) ||
    (eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
    (eMsgType == MSG_OBJ_TYPE_RXTX_REMOTE));

    while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }

    //
    // See if we need to use an extended identifier or not.
    //
    if((psMsgObject->ui32MsgID > CAN_MAX_11BIT_MSG_ID) ||
    (psMsgObject->ui32Flags & MSG_OBJ_EXTENDED_ID))
    {
    bUseExtendedID = 1;
    }
    else
    {
    bUseExtendedID = 0;
    }

    //
    // This is always a write to the Message object as this call is setting a
    // message object. This call always sets all size bits so it sets
    // both data bits. The call uses the CONTROL register to set control
    // bits so this bit needs to be set as well.
    //
    ui16CmdMaskReg = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_DATAA |
    CAN_IF1CMSK_DATAB | CAN_IF1CMSK_CONTROL);

    //
    // Initialize the values to a known state before filling them in based on
    // the type of message object that is being configured.
    //
    ui16ArbReg0 = 0;
    ui16ArbReg1 = 0;
    ui16MsgCtrl = 0;
    ui16MaskReg0 = 0;
    ui16MaskReg1 = 0;

    switch(eMsgType)
    {
    //
    // Transmit message object.
    //
    case MSG_OBJ_TYPE_TX:
    {
    //
    // Set the TXRQST bit and the reset the rest of the register.
    //
    ui16MsgCtrl |= CAN_IF1MCTL_TXRQST;
    ui16ArbReg1 = CAN_IF1ARB2_DIR;
    bTransferData = 1;
    break;
    }

    //
    // Transmit remote request message object
    //
    case MSG_OBJ_TYPE_TX_REMOTE:
    {
    //
    // Set the TXRQST bit and the reset the rest of the register.
    //
    ui16MsgCtrl |= CAN_IF1MCTL_TXRQST;
    ui16ArbReg1 = 0;
    break;
    }

    //
    // Receive message object.
    //
    case MSG_OBJ_TYPE_RX:
    {
    //
    // This clears the DIR bit along with everything else. The TXRQST
    // bit was cleared by defaulting ui16MsgCtrl to 0.
    //
    ui16ArbReg1 = 0;
    break;
    }

    //
    // Receive remote request message object.
    //
    case MSG_OBJ_TYPE_RX_REMOTE:
    {
    //
    // The DIR bit is set to one for remote receivers. The TXRQST bit
    // was cleared by defaulting ui16MsgCtrl to 0.
    //
    ui16ArbReg1 = CAN_IF1ARB2_DIR;

    //
    // Set this object so that it only indicates that a remote frame
    // was received and allow for software to handle it by sending back
    // a data frame.
    //
    ui16MsgCtrl = CAN_IF1MCTL_UMASK;

    //
    // Use the full Identifier by default.
    //
    ui16MaskReg0 = 0xffff;
    ui16MaskReg1 = 0x1fff;

    //
    // Make sure to send the mask to the message object.
    //
    ui16CmdMaskReg |= CAN_IF1CMSK_MASK;
    break;
    }

    //
    // Remote frame receive remote, with auto-transmit message object.
    //
    case MSG_OBJ_TYPE_RXTX_REMOTE:
    {
    //
    // Oddly the DIR bit is set to one for remote receivers.
    //
    ui16ArbReg1 = CAN_IF1ARB2_DIR;

    //
    // Set this object to auto answer if a matching identifier is seen.
    //
    ui16MsgCtrl = CAN_IF1MCTL_RMTEN | CAN_IF1MCTL_UMASK;

    //
    // The data to be returned needs to be filled in.
    //
    bTransferData = 1;
    break;
    }

    //
    // This case never happens due to the ASSERT statement at the
    // beginning of this function.
    //
    default:
    {
    return;
    }
    }

    //
    // Configure the Mask Registers.
    //
    if(psMsgObject->ui32Flags & MSG_OBJ_USE_ID_FILTER)
    {
    if(bUseExtendedID)
    {
    //
    // Set the 29 bits of Identifier mask that were requested.
    //
    ui16MaskReg0 = psMsgObject->ui32MsgIDMask & CAN_IF1MSK1_IDMSK_M;
    ui16MaskReg1 = ((psMsgObject->ui32MsgIDMask >> 16) &
    CAN_IF1MSK2_IDMSK_M);
    }
    else
    {
    //
    // Lower 16 bit are unused so set them to zero.
    //
    ui16MaskReg0 = 0;

    //
    // Put the 11 bit Mask Identifier into the upper bits of the field
    // in the register.
    //
    ui16MaskReg1 = ((psMsgObject->ui32MsgIDMask << 2) &
    CAN_IF1MSK2_IDMSK_M);
    }
    }

    //
    // If the caller wants to filter on the extended ID bit then set it.
    //
    if((psMsgObject->ui32Flags & MSG_OBJ_USE_EXT_FILTER) ==
    MSG_OBJ_USE_EXT_FILTER)
    {
    ui16MaskReg1 |= CAN_IF1MSK2_MXTD;
    }

    //
    // The caller wants to filter on the message direction field.
    //
    if((psMsgObject->ui32Flags & MSG_OBJ_USE_DIR_FILTER) ==
    MSG_OBJ_USE_DIR_FILTER)
    {
    ui16MaskReg1 |= CAN_IF1MSK2_MDIR;
    }

    if(psMsgObject->ui32Flags &
    (MSG_OBJ_USE_ID_FILTER | MSG_OBJ_USE_DIR_FILTER |
    MSG_OBJ_USE_EXT_FILTER))
    {
    //
    // Set the UMASK bit to enable using the mask register.
    //
    ui16MsgCtrl |= CAN_IF1MCTL_UMASK;

    //
    // Set the MASK bit so that this gets transferred to the Message
    // Object.
    //
    ui16CmdMaskReg |= CAN_IF1CMSK_MASK;
    }

    //
    // Set the Arb bit so that this gets transferred to the Message object.
    //
    ui16CmdMaskReg |= CAN_IF1CMSK_ARB;

    //
    // Configure the Arbitration registers.
    //
    if(bUseExtendedID)
    {
    //
    // Set the 29 bit version of the Identifier for this message object.
    //
    ui16ArbReg0 |= psMsgObject->ui32MsgID & CAN_IF1ARB1_ID_M;
    ui16ArbReg1 |= (psMsgObject->ui32MsgID >> 16) & CAN_IF1ARB2_ID_M;

    //
    // Mark the message as valid and set the extended ID bit.
    //
    ui16ArbReg1 |= CAN_IF1ARB2_MSGVAL | CAN_IF1ARB2_XTD;
    }
    else
    {
    //
    // Set the 11 bit version of the Identifier for this message object.
    // The lower 18 bits are set to zero.
    //
    ui16ArbReg1 |= (psMsgObject->ui32MsgID << 2) & CAN_IF1ARB2_ID_M;

    //
    // Mark the message as valid.
    //
    ui16ArbReg1 |= CAN_IF1ARB2_MSGVAL;
    }

    //
    // Set the data length since this is set for all transfers. This is also a
    // single transfer and not a FIFO transfer so set EOB bit.
    //
    ui16MsgCtrl |= (psMsgObject->ui32MsgLen & CAN_IF1MCTL_DLC_M);

    //
    // Mark this as the last entry if this is not the last entry in a FIFO.
    //
    if((psMsgObject->ui32Flags & MSG_OBJ_FIFO) == 0)
    {
    ui16MsgCtrl |= CAN_IF1MCTL_EOB;
    }

    //
    // Enable transmit interrupts if they should be enabled.
    //
    if(psMsgObject->ui32Flags & MSG_OBJ_TX_INT_ENABLE)
    {
    ui16MsgCtrl |= CAN_IF1MCTL_TXIE;
    }

    //
    // Enable receive interrupts if they should be enabled.
    //
    if(psMsgObject->ui32Flags & MSG_OBJ_RX_INT_ENABLE)
    {
    ui16MsgCtrl |= CAN_IF1MCTL_RXIE;
    }

    //
    // Write the data out to the CAN Data registers if needed.
    //
    if(bTransferData)
    {
    _CANDataRegWrite(psMsgObject->pui8MsgData,
    (uint32_t *)(ui32Base + CAN_O_IF1DA1),
    psMsgObject->ui32MsgLen);
    }

    //
    // Write out the registers to program the message object.
    //
    HWREG(ui32Base + CAN_O_IF1CMSK) = ui16CmdMaskReg;
    HWREG(ui32Base + CAN_O_IF1MSK1) = ui16MaskReg0;
    HWREG(ui32Base + CAN_O_IF1MSK2) = ui16MaskReg1;
    HWREG(ui32Base + CAN_O_IF1ARB1) = ui16ArbReg0;
    HWREG(ui32Base + CAN_O_IF1ARB2) = ui16ArbReg1;
    HWREG(ui32Base + CAN_O_IF1MCTL) = ui16MsgCtrl;

    //
    // Transfer the message object to the message object specified by
    // ui32ObjID.
    //
    HWREG(ui32Base + CAN_O_IF1CRQ) = ui32ObjID & CAN_IF1CRQ_MNUM_M;
    }
    int
    main(void)
    {
    tCANMsgObject sCANMessage;
    uint32_t ui32MsgData;
    uint8_t *pui8MsgData;
    pui8MsgData = (uint8_t *)&ui32MsgData;

    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    GPIOPinConfigure(GPIO_PB4_CAN0RX);
    GPIOPinConfigure(GPIO_PB5_CAN0TX);
    GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
    CANInit(CAN0_BASE);
    CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000);
    CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    IntEnable(INT_CAN0);
    CANEnable(CAN0_BASE);

    ui32MsgData = 0;
    sCANMessage.ui32MsgID = 1;
    sCANMessage.ui32MsgIDMask = 0;
    sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    sCANMessage.ui32MsgLen = sizeof(pui8MsgData);
    sCANMessage.pui8MsgData = pui8MsgData;

    while(1)
    {

    CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);

    //
    // Increment the value in the message data.
    //
    ui32MsgData++;
    }

    }

    然后我对上述例程中的CAN0_BASE改为CAN1_BASE,将CANIntClear();CANInit();CANMessageSet();这三个函数里面的CAN_IF1,CAN_O_IF1等等CAN口1的寄存器改为CAN_IF2,CAN_O_IF2,。

    经过测试发现只要CANMessageSet(CAN1_BASE);这条语句在就不行,而且单独跑CAN0可以,CAN0和CAN1一起就都不行了,单独CAN1也不行。所以感觉是初始化配置中某个寄存器藏的比较深没发现,可能没改过来。

    另外既然封装库函数是为了工程师不接触底层寄存器,那现在这种改法还不如直接看寄存器重新编写,所以觉得这库函数封装的有问题,库函数里面只定义了CAN0的寄存器,没有定义其他CAN口的寄存器?我觉得按正常逻辑不应该,可能是我对这个库函数还不理解,调用不对?

  • 你可以在can.c的文件中找找这三个函数的原型看看。任然还是坚信,肯定是你有个地方没有修改过来。你修改后的代码也发上来看看。

  • 你可以看下是不是在startup文件中,你的中断号没有配置好,可以看下,配置一下can1的终端号