LPC1752 CAN总线学习#

CAN 工作模式#

../../_images/CAN%E6%A8%A1%E5%BC%8F.svg
正常模式:

CAN 寄存器 MODRM,LOM,STM 位全为0

正常模式下的自发自收(全局测试):

在正常模式下,发送时同时置位 CMD 寄存器的 SRR

只听模式:

置位 MOD 寄存器的 LOM 位,该模式下禁一切发送,收到 CAN 总线的数据也不做应答

测试模式下的自发自收(局部测试):
  • 置位 MOD 寄存器的 STM

  • 发送时同时置位 CMD 寄存器的 SRR

同样的测试环境不同板子结果可能不同:

  • 测试条件: CAN 总线不接任何设备,且本设备 CAN 终端电阻不接

  • 测试结果: 有板子能成功收发,有板子不能(必须把终端电阻接上才能通过)

ARM提供的 CAN 驱动需修改的地下#
static int32_t CANx_SetMode(ARM_CAN_MODE mode, uint8_t x)
{
    LPC_CAN_TypeDef *ptr_CAN;
    uint32_t         event;

    if (x >= CAN_CTRL_NUM)           {
        return ARM_DRIVER_ERROR;
    }
    if (can_driver_powered[x] == 0U) {
        return ARM_DRIVER_ERROR;
    }

    ptr_CAN = ptr_CANx[x];

    event = 0U;
    switch (mode) {
        case ARM_CAN_MODE_INITIALIZATION:
            ptr_CAN->MOD    =  CAN_MOD_RM;            // Enter reset mode
            // Disable filter and allow table RAM access
            LPC_CANAF->AFMR =  CANAF_AFMR_AccBP | CANAF_AFMR_AccOff;
            if (can_unit_state[x] != ARM_CAN_UNIT_STATE_INACTIVE) {
                can_unit_state[x]    = ARM_CAN_UNIT_STATE_INACTIVE;
                event                = ARM_CAN_EVENT_UNIT_BUS_OFF;
            }
            break;
        case ARM_CAN_MODE_NORMAL:
            LPC_CANAF->AFMR =  0U;                    // Enable filter
            ptr_CAN->MOD   &= ~(CAN_MOD_STM |         // Deactivate Self Test Mode
                                CAN_MOD_LOM |          // Deactivate Listen Only Mode
                                CAN_MOD_RM) ;          // Enter operating mode
            can_loopback[x] =  0U;                    // Loopback not active
            if (can_unit_state[x] != ARM_CAN_UNIT_STATE_ACTIVE) {
                can_unit_state[x]    = ARM_CAN_UNIT_STATE_ACTIVE;
                event                = ARM_CAN_EVENT_UNIT_ACTIVE;
            }
            break;
        case ARM_CAN_MODE_RESTRICTED:
            return ARM_DRIVER_ERROR_UNSUPPORTED;
        case ARM_CAN_MODE_MONITOR:
            LPC_CANAF->AFMR =  0U;                    // Enable filter
            ptr_CAN->MOD   |=  CAN_MOD_LOM;           // Activate Listen Only Mode
            ptr_CAN->MOD   &= ~(CAN_MOD_STM |         // Deactivate Self Test Mode
                                CAN_MOD_RM) ;          // Enter operating mode
            can_loopback[x] =  0U;                    // Loopback not active
            if (can_unit_state[x] == ARM_CAN_UNIT_STATE_ACTIVE) {
                can_unit_state[x]    = ARM_CAN_UNIT_STATE_PASSIVE;
                event                = ARM_CAN_EVENT_UNIT_PASSIVE;
            }
            break;
        case ARM_CAN_MODE_LOOPBACK_INTERNAL:
            LPC_CANAF->AFMR =  0U;                    // Enable filter
            //ptr_CAN->MOD   |=  CAN_MOD_STM |          // Activate Self Test Mode
            //                   CAN_MOD_LOM ;          // Activate Listen Only Mode
            // 内部测试(局部测试)是自测模式下,自发自收来完成的
            ptr_CAN->MOD |= CAN_MOD_STM;              // Activate Self Test Mode
            ptr_CAN->MOD   &= ~(CAN_MOD_LOM |
                                CAN_MOD_RM) ;           // Enter operating mode
            can_loopback[x] =  1U;                    // Loopback active
            if (can_unit_state[x] == ARM_CAN_UNIT_STATE_ACTIVE) {
                can_unit_state[x]    = ARM_CAN_UNIT_STATE_PASSIVE;
                event                = ARM_CAN_EVENT_UNIT_PASSIVE;
            }
            break;
        case ARM_CAN_MODE_LOOPBACK_EXTERNAL:
            LPC_CANAF->AFMR =  0U;                    // Enable filter
            //ptr_CAN->MOD   |=  CAN_MOD_STM;           // Activate Self Test Mode
            //ptr_CAN->MOD   &=~(CAN_MOD_LOM |          // Deactivate Listen Only Mode
            //                   CAN_MOD_RM) ;          // Enter operating mode
            // 外部测试(全局测试)是正常模式下,自发自收来完成
            ptr_CAN->MOD   &= ~(CAN_MOD_STM |         // Deactivate Self Test Mode
                                CAN_MOD_LOM |          // Deactivate Listen Only Mode
                                CAN_MOD_RM) ;          // Enter operating mode
            can_loopback[x] =  1U;                    // Loopback active
            if (can_unit_state[x] == ARM_CAN_UNIT_STATE_PASSIVE) {
                can_unit_state[x]    = ARM_CAN_UNIT_STATE_ACTIVE;
                event                = ARM_CAN_EVENT_UNIT_ACTIVE;
            }
            break;
    }
    if ((CAN_SignalUnitEvent[x] != NULL) && (event != 0U)) {
        CAN_SignalUnitEvent[x](event);
    }

    return ARM_DRIVER_OK;
}