You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F429 Nucleo-144寄存器配置CAN通信异常求助

STM32F429 CAN寄存器配置问题修复(无HAL库)

核心问题分析

TX引脚持续输出显性信号,本质是CAN外设未完成正确初始化流程,或引脚配置、波特率参数存在错误,导致发送请求无法触发正常报文传输。

关键修复点

1. GPIO引脚配置错误

原代码中PD0(RX)的复用功能未正确配置,STM32F429的PD0/PD1需映射到AF9(CAN1)才能正常工作。修正后的pins()函数:

int pins()
{
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;

    // RX (PD0) - 复用功能AF9
    GPIOD->MODER &= ~GPIO_MODER_MODER0_Msk; // 先清零模式位
    GPIOD->MODER |= GPIO_MODER_MODER0_1;    // 设置为复用功能(10)
    GPIOD->AFR[0] |= (9 << GPIO_AFRL_AFRL0_Pos); // 配置AF9映射
    GPIOD->OTYPER &= ~(GPIO_OTYPER_OT0);
    GPIOD->PUPDR &= ~(GPIO_PUPDR_PUPDR0);
    GPIOD->OSPEEDR |= GPIO_OSPEEDR_OSPEED0_Msk; // 高速模式

    // TX (PD1) - 复用功能AF9
    GPIOD->MODER &= ~GPIO_MODER_MODER1_Msk;
    GPIOD->MODER |= GPIO_MODER_MODER1_1;
    GPIOD->AFR[0] |= (9 << GPIO_AFRL_AFRL1_Pos); // 配置AF9映射
    GPIOD->OTYPER &= ~(GPIO_OTYPER_OT1);
    GPIOD->PUPDR &= ~(GPIO_PUPDR_PUPDR1);
    GPIOD->OSPEEDR |= GPIO_OSPEEDR_OSPEED1_Msk; // 高速模式
    return 0;
}

2. CAN初始化流程修正

  • 进入/退出初始化模式时,必须等待硬件确认状态,避免配置不生效
  • 波特率参数中TS1的最大值为15(对应16个时间量子),原代码设置16超出位域范围
  • 先清零寄存器再配置,避免原有位干扰

修正后的intCAN()函数:

int intCAN()
{
    RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;

    CAN1->MCR &= ~CAN_MCR_SLEEP;
    CAN1->MCR |= CAN_MCR_INRQ; // 请求进入初始化模式
    while(!(CAN1->MSR & CAN_MSR_INAK)); // 等待硬件确认进入初始化状态

    // 清零BTR寄存器后重新配置
    CAN1->BTR = 0;
    CAN1->BTR |= CAN_BTR_LBKM; // 环回模式(测试用)
    CAN1->BTR |= (7 << CAN_BTR_BRP_Pos); // BRP=7,分频系数8
    CAN1->BTR |= (7 << CAN_BTR_TS2_Pos); // TS2=7,8个时间量子
    CAN1->BTR |= (15 << CAN_BTR_TS1_Pos); // TS1=15,16个时间量子
    CAN1->BTR |= (1 << CAN_BTR_SJW_Pos); // SJW=1,2个时间量子

    CAN1->MCR &= ~CAN_MCR_INRQ; // 退出初始化模式
    while(CAN1->MSR & CAN_MSR_INAK); // 等待硬件进入正常模式

    // 配置发送邮箱0
    CAN1->sTxMailBox[0].TIR = 0;
    CAN1->sTxMailBox[0].TIR &= ~CAN_TI0R_RTR; // 数据帧
    CAN1->sTxMailBox[0].TIR &= ~CAN_TI0R_IDE; // 标准ID
    CAN1->sTxMailBox[0].TIR |= (0x1 << CAN_TI0R_STID_Pos); // STID=1

    CAN1->sTxMailBox[0].TDTR = 0;
    CAN1->sTxMailBox[0].TDTR |= (0x1 << CAN_TDT0R_DLC_Pos); // DLC=1

    CAN1->sTxMailBox[0].TDLR = 0x8; // DATA0=0x8
    CAN1->sTxMailBox[0].TDHR = 0;

    return 0;
}

3. 发送流程优化

发送前需确保邮箱空闲,避免发送冲突,修正后的main()函数:

int main(void)
{
    pins();
    intCAN();
    intFilter();

    // 等待邮箱0空闲
    while(CAN1->sTxMailBox[0].TIR & CAN_TI0R_TXRQ);

    // 触发发送
    CAN1->sTxMailBox[0].TIR |= CAN_TI0R_TXRQ;

    // 可选:等待发送完成
    while(!(CAN1->sTxMailBox[0].TIR & CAN_TI0R_TXOK));

    while(1); // 防止程序跑飞
}

4. 过滤器配置简化(测试阶段可选)

若仅测试发送功能,可暂时禁用过滤器,避免干扰:

int intFilter()
{
    CAN1->FMR |= CAN_FMR_FINIT; // 进入过滤器初始化模式
    CAN1->FA1R &= ~CAN_FA1R_FACT0; // 禁用过滤器0
    CAN1->FMR &= ~CAN_FMR_FINIT; // 退出过滤器初始化模式
    return 0;
}

测试建议

  1. 先开启环回模式测试,通过检查RXF0R寄存器的FMP位,判断CAN外设是否自收自发成功
  2. 环回测试正常后,关闭环回模式,连接CAN收发器(如TJA1050),用逻辑分析仪观测总线信号

内容的提问来源于stack exchange,提问作者Jeyeffkay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 07:15:45