CAN总线(Controller Area Network)作为一种高可靠性的串行通信协议,最初由Bosch公司为汽车电子系统设计,现已广泛应用于工业自动化、医疗设备等领域。其采用差分信号传输(ISO 11898标准)和基于优先级的非破坏性仲裁机制,在复杂电磁环境中展现出卓越的抗干扰能力。Atmel T89C51CC01微控制器集成了符合CAN 2.0B规范的控制器,支持11位标准帧和29位扩展帧格式,最高通信速率可达1Mbps。
提示:选择T89C51CC01进行CAN开发时,需特别注意其内部CAN控制器与外部收发器(如TJA1050)的电气特性匹配,建议在CANH/CANL线路间并联120Ω终端电阻以消除信号反射。
典型T89C51CC01 CAN节点硬件组成包括:
c复制// 典型硬件连接示意
sbit CAN_EN = P1^0; // 收发器使能控制
void Hardware_Init() {
CAN_EN = 1; // 使能CAN收发器
// 其他外设初始化...
}
商业开发板如PHYTEC PhyCORE-T89C51CC01提供完整外设:
c复制#define IO_PORT XBYTE[0xFFA0] // 内存映射IO定义
#define LED1 0x01
#define LED2 0x02
#define SW1 0x04
#define SW2 0x08
makefile复制// 典型工程配置片段
BL51_LOCATE = CODE(0x0000-0x3FFF)
BL51_MISC = PRINT(.\Objects\memory.map) IXREF
利用调试脚本实现硬件行为模拟:
ini复制// DEBUGGER.INI示例片段
define button "模拟按键S1", "PressSwitch(1)"
SIGNAL void PressSwitch(unsigned char v) {
_WBYTE(0xFFA0, _RBYTE(0xFFA0) | v);
swatch(0.1); // 保持按下状态100ms
_WBYTE(0xFFA0, _RBYTE(0xFFA0) & ~v);
}
完整CAN初始化步骤:
c复制void CAN_Init(uint16_t baudrate) {
CANGCON |= 0x01; // 进入初始化模式
while(!(CANGSTA & 0x01));
// 设置250kbps波特率(22.1184MHz时钟)
CANBT1 = 0x34; // 同步跳转宽度=1Tq, TSEG1=5Tq
CANBT2 = 0x1C; // TSEG2=2Tq, 采样点=87.5%
CANBT3 = 0x37; // 分频因子=6
// 配置验收滤波器(接收所有标准帧)
CANIDAC = 0x08; // 32位验收码模式
CANIDAR0 = 0x00; // 验收码全0
CANIDMR0 = 0xFF; // 屏蔽码全1(不屏蔽)
CANGCON &= ~0x01; // 退出初始化模式
while(CANGSTA & 0x01);
}
c复制// 轮询发送函数
uint8_t CAN_PollSend(uint32_t id, uint8_t* data, uint8_t len) {
if(CANSTAT & 0x80) return 0; // 检查发送缓冲区状态
CANTID = id << 21; // 标准ID左移21位
CANTFC = len; // 设置数据长度
for(uint8_t i=0; i<len; i++)
CANTDH = data[i];
CANCMR = 0x01; // 触发发送
return 1;
}
c复制// 中断服务例程
void CAN_ISR() interrupt 19 {
uint8_t status = CANSTAT;
if(status & 0x01) { // 接收中断
uint8_t len = CANRFS & 0x0F;
for(uint8_t i=0; i<len; i++)
rx_buf[i] = CANRDH;
CANCMR = 0x04; // 释放接收缓冲区
}
if(status & 0x80) { // 发送中断
tx_complete = 1;
CANCMR = 0x08; // 清除发送中断
}
}
c复制void HandleRemoteFrame(uint32_t id) {
if((id & 0x1FFFF800) == 0x10400) { // 检查远程帧ID
uint8_t data[8];
data[0] = ADCON0 >> 4; // 读取ADC值
CAN_Send(id, data, 1); // 发送响应数据
}
}
物理层检查:
寄存器状态分析:
c复制void CAN_Diagnose() {
printf("CANSTAT: %02X\n", CANSTAT);
printf("CANERR: %02X\n", CANERR);
printf("CANBT: %04X\n", (CANBT1<<8)|CANBT2);
}
常见错误代码处理:
定时器同步采样:
c复制// 配置定时器2用于同步采样
T2CON = 0x30; // 16位自动重装
RCAP2H = 0xFC; // 1ms间隔@22.1184MHz
RCAP2L = 0x66;
TR2 = 1; // 启动定时器
双缓冲接收策略:
c复制#pragma space xdata
uint8_t CAN_RxBuf[2][8]; // 双接收缓冲区
#pragma space default
总线负载计算:
code复制总线利用率 = (帧数 × (130 + 8×数据字节)) × 100% / (波特率 × 时间)
硬件抽象层设计:
c复制// hal_can.h
typedef struct {
void (*Init)(uint32_t baud);
uint8_t (*Send)(CAN_Frame* frame);
uint8_t (*Receive)(CAN_Frame* frame);
} CAN_Driver;
时钟配置差异处理:
CANopen协议栈集成:
c复制void ProcessPDO(CAN_Frame* frame) {
if(frame->id >= 0x180 && frame->id <= 0x57F) {
// 处理过程数据对象
}
}
安全机制实现:
在完成基础CAN通信功能后,建议通过逻辑分析仪捕获实际总线波形(如图1所示),验证信号完整性和时序参数是否符合ISO 11898-2标准。对于工业现场应用,可考虑增加CAN总线隔离模块(如ADM3053)以增强系统抗干扰能力。