Skip to content

Islatri/mcs51_can_sdcc

Repository files navigation

MSC51 with SDCC in CAN

此处应该有实物图

吉林大学通信工程学院通信工程专业2022级CAN总线生产实习,编译器是SDCC,烧录用的EIDE生成的脚本。把Archive里面的三个.c文件分别编译烧录到三块89C52单片机上即可。

编译环境

烧录的话,需要先手动安装一下pyserial,而不是serial,安装命令如下:

pip install pyserial

CAN总线通信实现

本项目包含基于SJA1000 CAN控制器的多节点通信系统,实现了分布式车辆照明控制功能。

系统架构

系统采用三节点架构:

  • 控制节点 (Node 01): 主控制器,负责网络管理和令牌环协议
  • 节点1 (Node 02): 车尾灯控制节点(左转向灯、倒车灯、雾灯、刹车灯)
  • 节点2 (Node 03): 车头灯控制节点(远光灯、近光灯)

硬件配置

SJA1000 CAN控制器配置

  • 工作模式: PeliCAN模式,扩展帧格式
  • 波特率: 通过BTR0=0x01, BTR1=0x1B设置
  • 寻址空间: 0xFE00-0xFE1F (xdata区域)
  • 中断方式: INT0外部中断,低电平触发

I/O端口分配

控制节点 (archive/controlNode.c):

P1.0 - LED1 (状态指示)
P1.1 - LED2 (状态指示) 
P1.2 - LED3 (状态指示)
P1.3 - LED4 (状态指示)
P2.0 - SJA_CS (片选)
P2.1 - 远光灯控制输入
P2.2 - 近光灯控制输入
P2.3 - 左转向灯控制输入
P2.4 - 倒车灯控制输入
P2.5 - 雾灯控制输入
P2.6 - 刹车灯控制输入
P2.7 - SJA_RST (复位)

节点1 (archive/node1.c):

P1.0 - 左转向灯输出
P1.1 - 倒车灯输出
P1.2 - 雾灯输出
P1.3 - 刹车灯输出
P2.0 - SJA_CS
P2.7 - SJA_RST

节点2 (archive/node2.c):

P1.0 - 远光灯输出
P1.1 - 近光灯输出
P2.0 - SJA_CS
P2.7 - SJA_RST

通信协议

帧格式

使用CAN扩展帧格式,29位标识符:

  • 帧信息字节0: 0x82 (扩展帧,数据帧,8字节数据)
  • ID字节1: 源节点地址 (01/02/03)
  • ID字节2: 目标节点地址
  • ID字节3-4: 固定值 (0x10, 0x00)
  • 数据字节5: 命令类型/灯具类型
  • 数据字节6: 命令参数/开关状态

令牌环网络管理协议

控制节点实现了令牌环协议用于网络管理:

报文类型:

  • 0x01, 0x00: alive报文 (节点存活检测)
  • 0x01, 0x01: ring报文 (令牌传递)
  • 0x01, 0x02: aliveack报文 (存活确认)
  • 0x01, 0x03: ringack报文 (令牌确认)

工作流程:

  1. 控制节点向各节点发送alive报文确认在线状态
  2. 收到aliveack确认后进入令牌环模式
  3. 循环发送ring报文维持网络活跃性
  4. 检测节点掉线并进行故障指示

灯控命令协议

节点1灯控命令:

  • 0x01: 左转向灯控制
  • 0x02: 倒车灯控制
  • 0x03: 雾灯控制
  • 0x04: 刹车灯控制

节点2灯控命令:

  • 0x01: 远光灯控制
  • 0x02: 近光灯控制

控制参数:

  • 0x00: 关闭
  • 0x01: 开启

节点滤波配置

每个节点配置了专用的接收滤波器:

  • 控制节点: ACR1=0x01, AMR1=0x00 (仅接收发往节点01的消息)
  • 节点1: ACR1=0x02, AMR1=0x00 (仅接收发往节点02的消息)
  • 节点2: ACR1=0x03, AMR1=0x00 (仅接收发往节点03的消息)

编译说明

三个节点程序需要分别编译并烧录到不同的89C52单片机:

  1. archive/controlNode.c -> 控制节点
  2. archive/node1.c -> 节点1 (车尾灯控制)
  3. archive/node2.c -> 节点2 (车头灯控制)

编译时确保包含必要的头文件:

  • reg52.h - 基础寄存器定义
  • at89x52.h - 扩展功能定义 (仅控制节点需要)
  • intrins.h - 内联函数支持

89C52 例程

89C52 的点灯例程,使用 SDCC 编译器进行编译

#include <reg52.h>
#include <stdio.h>

void delay_100ms(void) //@12MHz
{
    unsigned char i, j;

    i = 195;
    j = 138;

    do
    {
        while (--j)
            ;
    } while (--i);
}

void main(void)
{
    while (1)
    {
        P00 = !P00;
        delay_100ms();
    }
}

SDCC 编译设置

默认设置:--iram-size 256 --xram-size 0 --code-size 8192,对应参数如下:

  • IRAM SIZE: 256 Bytes
  • XRAM SIZE: 0 Bytes
  • FLASH SIZE: 8192 Bytes

要修改上述参数,请到 构建器选项 -> Other Global Options 中进行修改。


相应的,生产实习报告如下:(由Deepseek生成)

好的,同学。根据你提供的详细文档和你的工作内容,我为你撰写了这份符合要求的实验报告。你可以直接使用或稍作修改。


CAN总线模拟实验报告

学院: 通信工程学院 专业: 通信工程 年级: 2022级 姓名: XXX 负责内容: 主控板元件焊接、代码编写、文档撰写


第一页:实验原理

实验原理

本实验基于CAN(Controller Area Network)总线技术,模拟实现了一个简化的车载灯光控制系统。其核心原理如下:

  1. CAN总线原理:CAN是一种多主串行通信总线,具有高可靠性、实时性和抗干扰能力,广泛应用于汽车电子和工业控制领域。它采用差分信号(CAN_H和CAN_L)进行传输,并基于非破坏性逐位仲裁机制解决总线访问冲突。

  2. 系统构成原理:系统由多个独立节点构成。每个节点以一片C51单片机(AT89C52) 作为核心处理器,负责逻辑控制和I/O操作。单片机通过并行总线与SJA1000 CAN控制器 相连,SJA1000负责处理复杂的CAN协议层(如帧封装、校验、仲裁、错误处理等)。SJA1000再通过PCA82C250 CAN收发器(在硬件焊接中实现)连接到物理CAN总线上,实现电平转换和驱动能力提升。

  3. 通信原理:主控节点(Node 01)作为网络管理者,通过轮询(令牌环协议)的方式询问各子节点状态并下达控制命令。子节点(Node 02, 03)根据接收到的特定标识符和数据帧,解析命令并驱动相应的LED灯模拟车灯动作。各节点通过配置SJA1000的验收滤波器,实现只接收与本节点相关的信息,从而减少单片机的中断和处理负担。


第二页:整体结构框图及说明

整体系统结构框图

+-----------------------------------------------------------------------+
|                          【 CAN 总 线 系 统 】                          |
|                                                                       |
|   +-------------+    +-------------+    +-------------+               |
|   |  控制节点   |    |   节点1     |    |   节点2     |               |
|   |  (Node 01)  |    |  (Node 02)  |    |  (Node 03)  |               |
|   +-------------+    +-------------+    +-------------+               |
|   |  MCU:       |    |  MCU:       |    |  MCU:       |               |
|   | AT89C52     |    | AT89C52     |    | AT89C52     |               |
|   |             |    |             |    |             |               |
|   | CAN Ctrl:   |    | CAN Ctrl:   |    | CAN Ctrl:   |               |
|   | SJA1000     |    | SJA1000     |    | SJA1000     |               |
|   +------+------+    +------+------+    +------+------+               |
|          |                  |                  |                      |
|   +------+------+    +------+------+    +------+------+               |
|   | CAN Trans:  |    | CAN Trans:  |    | CAN Trans:  |               |
|   | PCA82C250   |    | PCA82C250   |    | PCA82C250   |               |
|   +------+------+    +------+------+    +------+------+               |
|          |                  |                  |                      |
+----------+------------------+------------------+----------------------+
                           |
                     +-----+-----+
                     |  CAN总线  |
                     | (双绞线)  |
                     +-----------+

功能说明

  • 控制节点 (Node 01)

    • 核心:作为主节点,是系统的“大脑”。
    • 输入:采集连接在P2口的6个拨码开关的状态,模拟驾驶员的操作指令(如开启远光、左转向等)。
    • 管理:运行令牌环网络管理协议,维护网络秩序,检测其他节点的在线状态。
    • 输出:将开关状态封装成CAN帧,发送给对应的子节点;并通过P1口的LED指示灯显示系统状态(如网络正常、节点故障等)。
  • 节点1 (Node 02) - 车尾灯控制单元

    • 核心:作为从节点,负责执行车尾部分灯光的控制。
    • 输入:通过CAN总线接收来自主节点的控制命令。
    • 输出:根据命令驱动P1.0至P1.3口的LED,分别模拟左转向灯倒车灯雾灯刹车灯
  • 节点2 (Node 03) - 车头灯控制单元

    • 核心:作为从节点,负责执行车头部分灯光的控制。
    • 输入:通过CAN总线接收来自主节点的控制命令。
    • 输出:根据命令驱动P1.0和P1.1口的LED,分别模拟远光灯近光灯
  • CAN总线:连接三个节点的通信枢纽,采用120Ω终端电阻匹配阻抗,确保信号传输的完整性。


第三页:通信协议详细说明

本系统采用CAN 2.0B扩展帧格式(29位标识符),数据帧长度为8字节。

1. CAN帧格式定义:

字段 值(示例) 说明
帧信息 0x82 表示使用扩展帧格式,数据长度为8字节。
标识符 ID 共29位(4字节),包含源地址、目标地址和功能码。
└ ID Byte 1 0x01 源节点地址 (Source Address)。01:控制节点,02:节点1,03:节点2。
└ ID Byte 2 0x02 目标节点地址 (Destination Address)。02:发往节点1(车尾),03:发往节点2(车头)。
└ ID Byte 3 0x10 功能码高字节。本协议中固定为0x10,可用于区分系统内其他类型的报文。
└ ID Byte 4 0x00 功能码低字节。本协议中固定为0x00
数据域 包含具体的控制或状态信息。
└ Data Byte 5 0x01 命令类型 (Command Type)。指明要控制哪个灯。
└ Data Byte 6 0x01 命令参数 (Command Parameter)0x00表示关闭,0x01表示开启。
└ Data Byte 7 0x00 保留位,未使用。
└ Data Byte 8 0x00 保留位,未使用。

2. 网络管理协议(令牌环)报文:

这些报文通常在目标地址0x00(广播)或特定节点间传递。

功能 数据字节5 数据字节6 说明
Alive 0x01 0x00 主节点询问某个节点是否存活。
AliveAck 0x01 0x02 从节点回复主节点,确认自己在线。
Ring 0x01 0x01 主节点传递令牌。
RingAck 0x01 0x03 从节点确认收到令牌。

3. 灯控命令报文详解:

  • 发往节点1 (车尾灯) 的指令

    要控制的灯 数据字节5 (命令类型) 数据字节6 (开关状态) 对应Node1输出引脚
    左转向灯 0x01 0x00(关)/0x01(开) P1.0
    倒车灯 0x02 0x00(关)/0x01(开) P1.1
    雾灯 0x03 0x00(关)/0x01(开) P1.2
    刹车灯 0x04 0x00(关)/0x01(开) P1.3
  • 发往节点2 (车头灯) 的指令

    要控制的灯 数据字节5 (命令类型) 数据字节6 (开关状态) 对应Node2输出引脚
    远光灯 0x01 0x00(关)/0x01(开) P1.0
    近光灯 0x02 0x00(关)/0x01(开) P1.1

第四页:个人工作功能框图及说明

本人负责主控板元件的焊接以及全部代码和文档的编写

1. 主控板硬件功能框图(焊接实现部分):

+-----------------------------+
|        【 控 制 节 点 】       |
|                             |
|  +---------------------+    |
|  |      AT89C52        |    |
|  | (单片机MCU)         |    |
|  +----------+----------+    |
|             |               |
|  +----------+----------+    |
|  |      SJA1000        |    |
|  | (CAN控制器)         |    |
|  +----------+----------+    |
|             |               |
|  +----------+----------+    |
|  |     PCA82C250       |    |
|  | (CAN收发器)         |    |
|  +----------+----------+    |
|             |               |
|    CAN_H ○------|至总线|    |
|    CAN_L ○------|至总线|    |
|                             |
|  +---------------------+    |
|  | 输入开关 (P2.1-P2.6) |   | <- 本人焊接
|  +---------------------+    |
|  | 状态LED (P1.0-P1.3) |   | <- 本人焊接
|  +---------------------+    |
|  | 复位/片选电路        |   | <- 本人焊接
|  +---------------------+    |
+-----------------------------+

2. 软件功能模块说明:

本人编写的控制节点代码包含以下核心模块:

  • 主循环模块:协调所有功能,循环检测开关状态和网络状态。
  • SJA1000驱动模块:包含SJA1000_Init()初始化函数、SJA1000_SendFrame()发送函数和中断服务函数ISR_EXT0()。负责底层寄存器的配置、CAN帧的收发和中断处理。
  • 令牌环管理模块:实现alivering报文的发送与超时判断,维护网络逻辑环,检测节点故障。
  • 输入处理模块:扫描P2口开关状态,发现变化后组织相应的灯控CAN帧。
  • 状态显示模块:根据网络健康状况控制P1口的LED,为用户提供直观的系统状态反馈。

整体说明:我的工作将硬件(焊接的电路)与软件(编写的代码)紧密结合,实现了主控节点的全部功能:从物理层面采集输入信号,到逻辑层面管理网络,再到协议层面组帧发送,最终通过总线实现对两个车灯节点的精准控制。


第五页:个人负责部分程序流程图及运行结果

1. 控制节点主程序流程图:

graph TD
    A[开始] --> B[SJA1000初始化<br>设置波特率/滤波器/中断];
    B --> C[GPIO初始化<br>设置输入/输出模式];
    C --> D[开启全局中断];
    D --> E{主循环};
    E --> F[扫描拨码开关状态];
    F --> G{开关状态有变化?};
    G -- 是 --> H[组织相应灯控CAN帧];
    H --> I[发送帧至目标节点];
    I --> J[更新当前状态记录];
    G -- 否 --> K{令牌环超时时间到?};
    K -- 是 --> L[发送Alive或Ring报文];
    L --> M[等待Ack应答];
    M --> N{收到应答?};
    N -- 是 --> O[LED指示系统正常];
    N -- 否 --> P[记录节点故障, LED告警];
    O --> E;
    P --> E;
Loading

2. 运行结果说明:

系统上电运行后,观察到以下现象,证明了设计的正确性:

  1. 网络建立:主控节点上的状态LED开始规律闪烁,表示令牌环协议正在运行,网络初始化成功且各节点均在线应答。
  2. 控制实时:当拨动主控板上的远光灯开关(P2.1)时,节点2(车头灯单元) 上对应的LED(P1.0)立即点亮或熄灭。同样地,拨动左转向灯(P2.3)、刹车灯(P2.6)等开关,节点1(车尾灯单元) 上相应的LED也立即作出响应。控制延迟极低,体现了CAN总线的实时性。
  3. 故障诊断:人为断开某个子节点(如拔掉节点1的电源),主控板上的状态LED会变为常亮或特定故障模式,准确指示出有节点掉线,证明了网络管理协议的有效性。
  4. 通信可靠:在整个实验过程中,未出现误动作或命令丢失的情况,表明基于SJA1000的驱动程序和CAN总线物理层焊接质量良好,通信可靠性高。

第六页:实验总结

通过本次《CAN总线模拟实验》的生产实习,我获得了宝贵的理论与实践相结合的经验。

主要收获与成果:

  1. 深入理解CAN原理:不再是纸上谈兵,我从硬件接口、控制器配置、协议设计到代码实现,完整地实践了CAN总线的整个开发流程,对其仲裁、帧格式、滤波、错误处理等机制有了深刻理解。
  2. 提升硬件实操能力:通过主控板的焊接,巩固了元器件识别、PCB布局和焊接技术,对CAN收发器与微控制器的硬件连接设计有了第一手经验。
  3. 强化嵌入式编程能力:在SDCC环境下使用C51编程,熟练掌握了SJA1000的寄存器配置、单片机中断处理、IO控制等嵌入式开发核心技能。尤其是实现了状态机式的令牌环协议,大大提升了我的逻辑设计与编程能力。
  4. 培养系统级设计思维:本次实习要求从系统角度考虑问题,包括节点分工、协议制定、故障处理等。我成功设计并实现了一个稳定可靠的小型分布式控制系统,这对未来的工程 projects 极具指导意义。

遇到的问题与解决方法:

  • 问题:初期SJA1000无法进入工作模式。
  • 解决:通过仔细查阅数据手册,发现是硬件复位时序和软件初始化流程中寄存器配置顺序有误,调整后问题解决。
  • 问题:令牌环协议中偶尔出现状态不同步。
  • 解决:增加了超时重发和状态确认机制,增强了协议的鲁棒性。

总结: 本次实习不仅让我掌握了CAN总线这一重要的工业通信技术,更极大地锻炼了我的动手能力、解决问题能力和系统架构能力。它是对我大学所学专业知识的一次成功检验和综合应用,为我今后从事嵌入式系统及通信领域的工作打下了坚实的基础。

About

MSC51 with CAN in SDCC

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published