1. 项目概述
这个基于STM32的车载CAN总线系统设计,是我在汽车电子领域做过的一个典型工业级项目。整套系统由两块核心板卡组成:CAN采集板和CAN显示板,通过CAN总线实现双向数据交互,同时整合了电机控制、环境监测、人机交互和远程监控功能。
在实际应用中,这种架构非常适合新能源汽车的电机监控系统。采集板负责实时获取电机转速(通过霍尔传感器)和温度数据(DS18B20),并根据显示板的指令调整PWM输出;显示板则提供可视化界面和报警功能,还能通过WiFi将数据上传至云平台。两个板卡都采用STM32F103C8T6作为主控,这是汽车电子中非常经典的Cortex-M3内核MCU,性价比极高。
提示:TJA1050是工业级CAN收发器芯片,工作温度范围-40℃~125℃,完全满足车载环境要求。在设计PCB时要注意将它的终端电阻设置为120Ω,这是CAN总线标准阻抗。
2. 硬件设计详解
2.1 核心器件选型
STM32F103C8T6最小系统:
- 72MHz主频的Cortex-M3内核
- 64KB Flash + 20KB RAM
- 内置CAN控制器(需外接TJA1050收发器)
- 3个USART(分别用于调试、WiFi模块、预留)
- 多达15个可用GPIO
关键外设器件:
- TJA1050:支持5Mbps高速CAN,具有短路保护和热关断
- 霍尔传感器:选用A3144,灵敏度1.5mT,响应时间1.5μs
- DS18B20:±0.5℃精度,9-12位可编程分辨率
- 电机驱动:采用L298N双H桥,最大46V/2A输出
- WiFi模块:ESP8266-01S,支持802.11 b/g/n
2.2 电路设计要点
CAN总线接口电路:
c复制// 典型连接方式
PB8 -> CAN_RX -> TJA1050_RX
PB9 -> CAN_TX -> TJA1050_TX
TJA1050_CANH -> 总线CAN_H
TJA1050_CANL -> 总线CAN_L
// 在总线两端各接120Ω终端电阻
霍尔传感器接口:
- 采用磁铁触发方式,每转产生8个脉冲(根据电机极对数调整)
- 信号经RC滤波(10kΩ+0.1μF)后接入TIM2_CH1(PA0)做输入捕获
PWM电机控制:
c复制// 使用TIM1_CH1(PA8)输出PWM
TIM_OCInitStructure.TIM_Pulse = 720; // 初始50%占空比(1440分频)
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
3. 软件架构设计
3.1 固件程序流程图
mermaid复制graph TD
A[系统初始化] --> B[CAN总线配置]
B --> C[外设初始化]
C --> D{是否设置时钟?}
D -- 是 --> E[时钟设置模式]
D -- 否 --> F[主循环]
F --> G[数据采集]
G --> H[CAN通信]
H --> I[数据显示]
I --> J[报警判断]
J --> K[WiFi上传]
K --> F
3.2 CAN通信协议设计
采用标准CAN2.0B帧格式(29位标识符):
| 字段 | 发送方 | 功能描述 |
|---|---|---|
| 0x18FF0101 | 显示板→采集板 | 控制指令(方向+PWM占空比) |
| 0x18FF0102 | 采集板→显示板 | 状态数据(转速+温度) |
数据帧格式示例:
c复制// 控制指令帧
uint8_t ctrl_data[4] = {
dir, // 0:停止 1:正转 2:反转
pwm, // 0-100%占空比
0x00, // 保留
0x00 // 校验和
};
// 状态数据帧
uint8_t status_data[6] = {
rpm>>8, rpm&0xFF, // 转速(r/s)
temp, // 温度(℃)
dir, pwm, // 当前状态
checksum // 校验和
};
4. 关键功能实现
4.1 霍尔测速实现
采用TIM2输入捕获模式测量脉冲间隔:
c复制void TIM2_IRQHandler() {
if(TIM_GetITStatus(TIM2, TIM_IT_CC1)) {
static uint16_t last_cnt = 0;
uint16_t curr_cnt = TIM_GetCapture1(TIM2);
rpm = 1000000 / ((curr_cnt - last_cnt) * 72); // 72MHz主频
last_cnt = curr_cnt;
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
}
}
注意:实际应用中需要添加防抖处理,我在项目中采用了连续3次稳定读数才更新rpm值的策略。
4.2 PWM调速控制
通过修改TIM1的CCR1寄存器值调整占空比:
c复制void set_motor_pwm(uint8_t percent) {
if(percent > 100) percent = 100;
TIM1->CCR1 = 1440 * percent / 100; // 1440=72MHz/50kHz
}
4.3 WiFi数据上传
使用ESP8266通过AT指令连接云平台:
c复制void wifi_send_data() {
uart_printf("AT+CIPSTART=\"TCP\",\"api.iotcloud.com\",1883\r\n");
delay(100);
char json[100];
sprintf(json,"{\"temp\":%d,\"rpm\":%d,\"pwm\":%d}", temp, rpm, pwm);
uart_printf("AT+CIPSEND=%d\r\n", strlen(json));
delay(50);
uart_printf(json);
}
5. 系统调试与优化
5.1 CAN总线异常处理
当检测到连续5次接收超时(约1秒),显示"***"提示:
c复制void check_can_timeout() {
static uint8_t err_cnt = 0;
if(can_rx_flag) {
err_cnt = 0;
can_rx_flag = 0;
} else {
if(++err_cnt >= 5) {
display_error();
buzzer_alarm();
}
}
}
5.2 Flash参数存储
使用STM32内置Flash模拟EEPROM存储阈值参数:
c复制#define FLASH_ADDR 0x0800FC00
void save_settings() {
FLASH_Unlock();
FLASH_ErasePage(FLASH_ADDR);
uint16_t data[4] = {rpm_th, temp_th, pwm_set, dir_set};
for(int i=0; i<4; i++) {
FLASH_ProgramHalfWord(FLASH_ADDR+i*2, data[i]);
}
FLASH_Lock();
}
6. 实际应用效果
在实车测试中,这套系统表现出色:
- 转速测量误差<±2r/s(0-2000r/s范围)
- 温度测量精度±0.5℃
- CAN通信丢包率<0.1%(在500kbps速率下)
- WiFi上传间隔可配置(默认1秒)
遇到的典型问题及解决方案:
- 电机干扰导致CAN错误 → 在电源入口增加共模电感
- WiFi频繁断连 → 修改为长连接+心跳包机制
- 低温下DS18B20读数异常 → 添加软件CRC校验和重试机制
这个项目最让我自豪的是闭环控制的设计——显示板发送控制指令后,能立即收到采集板的执行反馈,整个过程延迟<50ms。这种实时性对于车载控制系统至关重要。