STM32F405 bxCan不会离开初始模式

STM32F405 bxCan不会离开初始模式,c,arm,embedded,stm32,can-bus,C,Arm,Embedded,Stm32,Can Bus,当我尝试在STM32F405 MCU上初始化bxCan时,在离开请求后,它不会设置CAN\u MSR\u INAK 这是我的密码: rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_CAN2EN); nvic_enable_irq(NVIC_CAN2_RX0_IRQ); can_reset(CAN2); if (can_init(CAN2, // Can false, /

当我尝试在STM32F405 MCU上初始化bxCan时,在离开请求后,它不会设置CAN\u MSR\u INAK

这是我的密码:

rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_CAN2EN);
nvic_enable_irq(NVIC_CAN2_RX0_IRQ);
can_reset(CAN2);
if (can_init(CAN2,          // Can
        false,              // Time triggered communication mode
        true,               // Automatic bus-off management
        true,               // Automatic wakeup mode
        false,              // No automatic retransmission
        false,              // Receive FIFO locked mode
        true,               // Transmit FIFO priority
        CAN_BTR_SJW_1TQ,    // Resynchronization time quanta jump width
        CAN_BTR_TS1_11TQ,   // Time segment 1 time quanta width
        CAN_BTR_TS2_2TQ,    // Time segment 2 time quanta width
        3,                  // Baud rate prescaler (1 mbps)
        false,              // Loopback
        false) != 0)        // Silent mode
    _exit(0);
下面是
can_init
函数:

int can_init(uint32_t canport, bool ttcm, bool abom, bool awum, bool nart,
         bool rflm, bool txfp, uint32_t sjw, uint32_t ts1, uint32_t ts2,
         uint32_t brp, bool loopback, bool silent)
{
    volatile uint32_t wait_ack;
    int ret = 0;

    /* Exit from sleep mode. */
    CAN_MCR(canport) &= ~CAN_MCR_SLEEP;

    /* Request initialization "enter". */
    CAN_MCR(canport) |= CAN_MCR_INRQ;

    /* Wait for acknowledge. */
    wait_ack = CAN_MSR_INAK_TIMEOUT;
    while ((--wait_ack) &&
        ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK));

    /* Check the acknowledge. */
    if ((CAN_MSR(canport) & CAN_MSR_INAK) != CAN_MSR_INAK) {
        return 1;
    }

    /* clear can timing bits */
    CAN_BTR(canport) = 0;

    /* Set the automatic bus-off management. */
    if (ttcm) {
        CAN_MCR(canport) |= CAN_MCR_TTCM;
    } else {
        CAN_MCR(canport) &= ~CAN_MCR_TTCM;
    }

    if (abom) {
        CAN_MCR(canport) |= CAN_MCR_ABOM;
    } else {
        CAN_MCR(canport) &= ~CAN_MCR_ABOM;
    }

    if (awum) {
        CAN_MCR(canport) |= CAN_MCR_AWUM;
    } else {
        CAN_MCR(canport) &= ~CAN_MCR_AWUM;
    }

    if (nart) {
        CAN_MCR(canport) |= CAN_MCR_NART;
    } else {
        CAN_MCR(canport) &= ~CAN_MCR_NART;
    }

    if (rflm) {
        CAN_MCR(canport) |= CAN_MCR_RFLM;
    } else {
        CAN_MCR(canport) &= ~CAN_MCR_RFLM;
    }

    if (txfp) {
        CAN_MCR(canport) |= CAN_MCR_TXFP;
    } else {
        CAN_MCR(canport) &= ~CAN_MCR_TXFP;
    }

    if (silent) {
        CAN_BTR(canport) |= CAN_BTR_SILM;
    } else {
        CAN_BTR(canport) &= ~CAN_BTR_SILM;
    }

    if (loopback) {
        CAN_BTR(canport) |= CAN_BTR_LBKM;
    } else {
        CAN_BTR(canport) &= ~CAN_BTR_LBKM;
    }

    /* Set bit timings. */
    CAN_BTR(canport) |= sjw | ts2 | ts1 |
        ((brp - 1ul) & CAN_BTR_BRP_MASK);

    /* Request initialization "leave". */
    CAN_MCR(canport) &= ~CAN_MCR_INRQ;

    /* Wait for acknowledge. */
    wait_ack = CAN_MSR_INAK_TIMEOUT;
    while ((--wait_ack) &&
           ((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK));

    if ((CAN_MSR(canport) & CAN_MSR_INAK) == CAN_MSR_INAK) {
        ret = 1;
    }

    return ret;
}
因此,这个函数成功地进入了init模式,但不能离开它

我试着做了以下几件事:

  • 初始化CAN1而不是CAN2
  • 设置不同的时钟频率
  • 设置can的不同设置
  • 是否配置can引脚
没有任何效果。它总是在同一点失败

另外(只是为了确保),我尝试禁用bxCan时钟,但甚至无法进入初始化模式(如预期的那样)


同样的代码适用于STM32F103,所以我不知道会出什么问题。

检查以下参数: (i) 检查CAN时钟是否已启用(因为您正在进入初始化模式,这似乎很好。) (ii)检查CAN GPIO端口时钟是否启用(在进入CAN初始化模式之前,您应启用此功能)
(iii)检查是否配置了Can GPIO引脚(在进入Can初始化模式之前,您应该配置此引脚)

使用静默环回模式时,我遇到了相同的问题。解决方案是拉起RX引脚,这样它可以在将模式从“初始化模式”更改为“正常模式”时接收11个隐性位。

您是否正确配置了引脚?我认为F405需要GPIO配置中的替代映射

什么是“等待确认”呢?在硬件有机会设置标志之前,您怎么知道循环不会完成?如果你需要一个超时,你应该用一个硬件定时器来做一个专业的解决方案。在调试过程中,您可能希望“永远”等待。我浏览了一下手册:“软件清除此位以将硬件切换到正常模式。一旦在Rx信号上监测到11个连续的隐性位,CAN硬件将同步并准备好传输和接收。”。因此,根据您的波特率,这可能需要一点时间。如果您的CPU运行在一个快时钟上,那么它可能早在这11位之前就完成了倒计时循环。如果您一直等待设置标志,会发生什么情况?
can_init
是libopencm3库的一部分,所以我没有编写这个函数。通常,它必须在几分钟内完成,而不是65535分钟(CAN_MSR_INAK_超时)。无论如何,不是退出(0),而是退出(0)我试图把
放在while((CAN_MSR(CAN2)&CAN_MSR_INAK)=CAN_MSR_INAK)也没有效果——它只是永远循环。不管是谁写的,它都是草率的、可疑的代码,不会通过任何半体面的代码审查。当然,大多数“从github下载OpenBlabla”都是废话。假设您将波特率设置为10kbps,这是标准CAN波特率。11*1/10kbps=1.1ms。考虑到这么长的时间,您的CPU可能会从65535下降到0一千倍。我同意这段代码的质量值得怀疑,但关键是它不是我问题的根源。好吧,谢谢您的回答(尽管问题已经解决)。原来问题出在硬件上。