1. CAN控制器初始化与位定时配置
任务目标
完成CAN控制器的基础初始化配置,包括:使能CAN外设时钟、配置位时序(波特率)、设置工作模式(正常模式/环回模式),并通过读取寄存器验证配置是否生效。本案例以STM32F407的bxCAN外设为例,使用标准外设库(SPL)实现。
环境依赖
- 硬件:STM32F407开发板(板载CAN收发器TJA1050)
- 软件:Keil MDK-ARM 5.x + STM32F4xx标准外设库
- 连接:CAN_H/CAN_L接入CAN分析仪或双板互联
关键完整代码
#include "stm32f4xx.h"
#include "stm32f4xx_can.h"
// 引脚配置:PB8=RX, PB9=TX(复用功能AF9)
static void CAN_GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_CAN1);
}
// CAN初始化:波特率500kbps,正常模式
void CAN_Init_Config(void) {
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
// 1. 使能CAN1时钟(APB1总线,时钟42MHz)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
CAN_GPIO_Config();
// 2. CAN寄存器初始化
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
// 3. 位时序配置:APB1=42MHz,500kbps
// BS1=9tq, BS2=6tq, Prescaler=3 → 42MHz/(3*(1+9+6))=500kHz
CAN_InitStructure.CAN_TTCM = DISABLE; // 时间触发关闭
CAN_InitStructure.CAN_ABOM = ENABLE; // 自动离线管理
CAN_InitStructure.CAN_AWUM = ENABLE; // 自动唤醒
CAN_InitStructure.CAN_NART = DISABLE; // 非自动重传
CAN_InitStructure.CAN_RFLM = DISABLE; // 接收FIFO非锁定
CAN_InitStructure.CAN_TXFP = DISABLE; // 发送优先级由标识符决定
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; // 正常模式
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; // 同步跳转1tq
CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq; // 时间段1 = 9tq
CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq; // 时间段2 = 6tq
CAN_InitStructure.CAN_Prescaler = 3; // 预分频3
CAN_Init(CAN1, &CAN_InitStructure);
// 4. 滤波器配置:接收所有ID(屏蔽模式)
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
// 验证函数:读取寄存器并返回配置状态
uint8_t CAN_Verify_Config(void) {
uint8_t status = 0;
// 检查CAN1是否已退出初始化模式(进入正常模式)
if ((CAN1->MCR & CAN_MCR_INRQ) == 0) {
status |= 0x01; // Bit0: 初始化模式已退出
}
// 验证波特率寄存器:BS1=9, BS2=6, Prescaler=3
uint32_t btr = CAN1->BTR;
if (((btr & CAN_BTR_TS1) >> 16) == 8) { // TS1[3:0]+1=9
status |= 0x02; // Bit1: BS1配置正确
}
if (((btr & CAN_BTR_TS2) >> 20) == 5) { // TS2[2:0]+1=6
status |= 0x04; // Bit2: BS2配置正确
}
if ((btr & CAN_BTR_BRP) == 2) { // BRP[9:0]+1=3
status |= 0x08; // Bit3: 预分频配置正确
}
// 验证工作模式(正常模式:SILM=0, LBKM=0)
if ((CAN1->BTR & (CAN_BTR_SILM | CAN_BTR_LBKM)) == 0) {
status |= 0x10; // Bit4: 正常模式
}
return status;
}
// 主函数调用示例
int main(void) {
uint8_t verify_result;
CAN_Init_Config();
verify_result = CAN_Verify_Config();
// 若verify_result == 0x1F,则所有配置项均正确
while (1) {
// 主循环(可在此添加发送/接收测试)
}
}
运行与验证
- 将代码编译下载至STM32F407开发板,确保PB8/PB9已连接CAN收发器。
- 在
main()中调用CAN_Init_Config()完成初始化。 - 调用
CAN_Verify_Config(),通过调试器观察返回值:
| 返回值 | 含义 |
|---|---|
| 0x1F | 所有配置项正确(初始化模式退出、BS1=9、BS2=6、预分频=3、正常模式) |
| 其他值 | 对应位为0表示该项配置失败,需检查时钟或寄存器写入 |
通过条件:verify_result == 0x1F,且CAN1的MCR寄存器INRQ位为0(已退出初始化模式)。若使用CAN分析仪连接总线,可观察到总线空闲电平(隐性位2.5V)。
常见问题
- 初始化失败(INRQ始终为1):检查CAN1时钟是否已使能,以及GPIO复用配置是否正确。
- 波特率偏差:确认APB1时钟频率为42MHz(若系统时钟不同需重新计算预分频值)。
- 无法退出初始化模式:在设置
CAN_MCR_INRQ=0后需等待硬件确认,标准外设库的CAN_Init()已包含等待机制。