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; }
测试建议
- 先开启环回模式测试,通过检查
RXF0R寄存器的FMP位,判断CAN外设是否自收自发成功 - 环回测试正常后,关闭环回模式,连接CAN收发器(如TJA1050),用逻辑分析仪观测总线信号
内容的提问来源于stack exchange,提问作者Jeyeffkay
相关产品推荐
相关产品推荐

