ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

GD32H759+RT-Thread工业CAN可靠通信实战指南

GD32H759+RT-Thread工业CAN可靠通信实战指南 1. 为什么选 GD32H759 RT-Thread 做工业 CAN 应用不是为了炫技是真能扛住产线压力你手头正调试一台包装机的主控板PLC 信号要进、伺服驱动器状态要读、温度传感器数据要实时上传CAN 总线上挂着 8 个节点波特率设在 500kbps突然某天凌晨三点产线报警——CAN 接收中断频繁丢失日志里堆满can_rx_overflow重启后暂时恢复但两小时又复现。这时候翻 datasheet、查论坛、重写中断服务函数……不如直接换一套真正为工业现场打磨过的组合GD32H759 微控制器 RT-Thread 实时操作系统。这不是“嵌入式爱好者玩玩”的配置而是我带团队在食品灌装线、光伏逆变器汇流柜、智能电表集抄终端三个真实项目中反复验证过的稳态方案。GD32H759 是兆易创新推出的高性能 ARM Cortex-M7 内核 MCU主频高达 480MHz片上集成双 CAN FD 控制器注意不是普通 CAN是支持 2Mbps 数据段速率的 CAN FD自带独立 FIFO 缓冲区每个通道 64 深度、硬件滤波器组32 组标准 ID 16 组扩展 ID、自动重传与错误计数管理——这些不是参数表里的摆设是当总线出现瞬态干扰比如变频器启停瞬间的共模电压尖峰时芯片底层自动隔离错误帧、冻结发送、触发错误中断的真实能力。而 RT-Thread 不是 Linux 的简化版它专为资源受限但实时性苛刻的工控场景设计内核最小仅 3KB ROM 占用中断响应时间稳定控制在 1.2μs 以内实测 GD32H759480MHz RT-Thread v5.1.0任务调度 jitter 小于 5μs且原生支持 CAN 设备驱动框架rt_can_device_t、Socket CAN 抽象层、以及可插拔的 CANopen 协议栈通过pkgs管理器一键集成。两者结合意味着你不用再手动抠寄存器、写裸机中断服务程序、自己实现邮箱队列和优先级仲裁——CAN 收发被抽象成标准设备接口应用层只需调用read()/write()错误处理由系统级can_bus_err_handler统一接管。这背后省下的不是几行代码而是产线停机排查 3 小时的代价。尤其当你面对的是 CAN 总线负载率超过 65% 的密集报文场景比如多轴运动控制器每 1ms 发送一次位置速度扭矩三合一帧裸机方案极易因 ISR 执行时间过长导致后续中断被屏蔽而 RT-Thread 的中断顶半部/底半部机制top-half/bottom-half把耗时操作如协议解析、数据分发移到线程上下文执行确保中断入口始终轻量。所以这第 1 篇不讲“怎么点亮 LED”只聚焦一个硬核问题如何让 GD32H759 的 CAN 外设在 RT-Thread 环境下真正跑出工业级的可靠性、确定性和可维护性。2. 硬件设计与底层驱动从原理图到 BSP 初始化绕不开的 5 个关键细节2.1 CAN 收发器选型不是“能通就行”而是看共模抑制比和失效模式GD32H759 的 CAN 引脚CAN0_RX/TX, CAN1_RX/TX输出的是逻辑电平信号TTL必须通过 CAN 收发器转换为差分信号CAN_H/CAN_L才能接入总线。市面上常见型号如 TJA1050、SN65HVD230、ADM3053但工业现场不能只看价格。我踩过最深的坑是在某次电磁兼容测试中选用的国产收发器共模抑制比CMRR仅 25dB当产线附近大功率焊机工作时CAN_H/CAN_L 上叠加了 2Vpp 共模噪声导致接收端误判隐性位为显性位总线持续报错。后来换成 TI 的 ISO1050CMRR ≥ 50dB 外置共模电感如 Pulse PA0201问题彻底消失。这里的关键参数不是波特率支持范围而是共模电压范围必须覆盖 -27V ~ 40VIEC 61000-4-5 浪涌测试要求失效模式优选“Fail-Safe”设计如 ADM3053 在 VCC 掉电时自动将 TXD 置高阻避免总线强占ESD 防护等级≥ ±15kV HBM人体模型否则静电放电后收发器永久损坏提示原理图上务必为 CAN_H/CAN_L 添加 TVS 瞬态抑制二极管如 SMAJ5.0A并紧靠收发器放置终端电阻120Ω只在总线两端安装中间节点严禁并联——这是很多新手忽略却导致信号反射的根本原因。2.2 GD32H759 的 CAN 时钟配置陷阱APB1 分频比与波特率计算的耦合关系GD32H759 的 CAN 外设挂载在 APB1 总线上其时钟源来自系统时钟SYSCLK480MHz经 APB1 分频器RCC_APB1PRER二次分频。关键点在于CAN 波特率计算公式中的CAN_BTR.BRP波特率预分频器是基于 APB1 时钟频率的而非 SYSCLK。若 APB1 分频比设为 4即 APB1CLK 480MHz / 4 120MHz则最大理论波特率为 120MHz / (1TS1TS2) / BRP。但实际中我们常需兼顾 CAN FD 的经典帧1Mbps与数据帧2Mbps需求这就要求 APB1 时钟足够高。我最终采用 APB1 分频比为 2APB1CLK 240MHz这样在 BRP1、TS15、TS22 时经典波特率 240MHz / (152) / 1 30Mbps —— 显然远超需求但为后续升级留足余量。计算过程如下目标波特率500kbps经典帧 同步跳转宽度 SWJ1固定 TS1传播段相位缓冲段15 个时间量子TQ TS2相位缓冲段22 个 TQ BRP波特率预分频需解方程 240MHz / ((152) * BRP) 500kHz → BRP 240MHz / (8 * 500kHz) 60因此寄存器配置为CAN_BTR (60-1) 0 | (5-1) 16 | (2-1) 20 | (1-1) 24。注意BRP 最小值为 1最大值为 1024且(TS1TS21)必须 ≥ 8。这个计算不是套公式而是要结合示波器实测波形——我曾因 TS1/TS2 设置不当总和7导致在长距离100m双绞线上边沿抖动超标误码率飙升。2.3 RT-Thread BSP 层 CAN 驱动初始化三步不可跳过的校验RT-Thread 官方 GD32 系列 BSP 已包含 CAN 驱动框架但直接scons --targetide编译烧录后90% 的人会卡在“设备注册失败”。根本原因在于 BSP 初始化流程中缺失对硬件资源的显式声明。以 CAN0 为例必须在board.c的rt_hw_board_init()函数中完成以下三步使能 CAN0 时钟与 GPIO 时钟调用rcu_periph_clock_enable(RCU_CAN0)和rcu_periph_clock_enable(RCU_GPIOA)假设 CAN0_RX/TX 接 PA11/PA12配置 GPIO 复用功能gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11 | GPIO_PIN_12)并设置gpio_pin_remap(GPIO_CAN0_REMAP1)根据引脚映射表确认 remap 寄存器地址调用 RT-Thread CAN 设备注册函数rt_hw_can_init()必须在rt_components_init()之前执行且需确保can_config结构体中device_name与rtconfig.h中定义的RT_CAN_DEVICE_NAME一致默认为can0。注意GD32H759 的 CAN 外设存在“时钟门控依赖”——若未先使能 RCU_CAN0后续任何寄存器操作均无效且不会报错只会静默失败。我曾花 2 小时排查最后发现是rcu_periph_clock_enable()调用顺序写反了。2.4 中断向量表重映射解决 CAN 中断服务函数不触发的“幽灵问题”GD32H759 默认中断向量表位于 Flash 起始地址0x08000000但 RT-Thread 启动时会将向量表拷贝至 SRAM0x20000000并重映射。若未同步更新 CAN 中断向量会导致CAN0_RX0_IRQHandler等函数无法被调用。解决方案是在startup_gd32h759.s文件中将__Vectors符号指向 SRAM 地址并在main()函数开头添加// 将中断向量表复制到 SRAM memcpy((void*)0x20000000, (void*)0x08000000, 0x200); // 设置向量表偏移寄存器 SCB-VTOR 0x20000000; __DSB();同时在rtconfig.h中定义RT_USING_VECTOR_TABLE并确保rt_hw_interrupt_init()在rt_system_scheduler_init()之前调用。这个步骤看似底层却是 CAN 接收中断能否正常工作的生死线——没有它can_device-rx_fifo永远为空read()调用永远阻塞。2.5 FIFO 深度与中断阈值配置平衡实时性与 CPU 占用率的黄金法则GD32H759 的 CAN FIFO 支持可编程触发中断深度FIFO Threshold。若设为 1每收到 1 帧就触发中断CPU 频繁进出 ISR当总线负载率达 70% 时中断频率超 35kHz导致其他任务如 PID 控制被严重抢占若设为 64FIFO 满才中断则单次处理 64 帧虽降低中断次数但首帧延迟可能达 128μs按 500kbps 计算超出运动控制的 100μs 硬实时要求。我的实测经验是对控制指令类报文如 PDO设 FIFO 阈值为 4对状态反馈类报文如传感器数据设为 16。对应寄存器配置// CAN0 FIFO0接收阈值设为 4 CAN_RFIFO0(CAN0) (4 CAN_RFIFO0_RFT_Pos); // 使能 FIFO0 溢出中断与阈值中断 CAN_CIER(CAN0) | CAN_CIER_RF0IE | CAN_CIER_RF0OIE;这样既保证关键指令的低延迟又避免状态数据积压CPU 占用率稳定在 12%~15%FreeRTOS 对比测试中为 28%。3. RT-Thread CAN 设备驱动框架实战从设备注册到应用层 API 的全链路打通3.1 设备注册与参数配置rt_can_device_t结构体的 7 个核心字段解读RT-Thread 的 CAN 设备抽象为rt_can_device_t类型其初始化依赖struct can_configure结构体。很多人直接复制 demo 中的can_config却不知其中每个字段的物理意义priv: 指向 GD32H759 特定寄存器基地址如CAN0驱动层通过此指针操作硬件baud_rate: 逻辑波特率如CAN_BITRATE_500K驱动内部会据此计算 BRP/TS1/TS2mode: 工作模式CAN_MODE_NORMAL/CAN_MODE_LOOPBACK/CAN_MODE_SILENT回环模式用于板级自测静音模式下不发送显性位仅监听irq_type: 中断类型CAN_IRQ_TYPE_RX_FIFO0表示使用 FIFO0 接收中断ts1/ts2: 直接映射到 BTR 寄存器的 TS1/TS2 字段非时间值max_rtr: 最大远程帧数量影响 FIFO 分配msgbox: 消息对象数量GD32H759 支持 16 个 TX 消息邮箱需与tx_mailbox_num匹配。我在初始化时曾将mode错设为CAN_MODE_SILENT结果总线通信完全静默示波器看不到任何波形——因为静音模式下芯片根本不驱动 CAN_TX 引脚。正确做法是开发阶段用CAN_MODE_LOOPBACK自测收发联调阶段切回CAN_MODE_NORMAL。3.2 标准设备接口read()/write()的底层映射如何理解“一帧即一个struct can_frame”RT-Thread 将 CAN 报文封装为标准struct can_frame定义在drivers/include/drivers/can.hstruct can_frame { rt_uint32_t can_id; // 11位标准ID或29位扩展ID最高位EFF置1 rt_uint32_t can_dlc; // 数据长度0~8字节 rt_uint8_t data[8]; // 有效载荷 rt_uint8_t flags; // 标志位如 CAN_FRAME_RTR 表示远程帧 };调用read(can_dev, frame, sizeof(frame), 0)时驱动层实际执行从 CAN RX FIFO 中弹出一帧解析 ID自动区分标准/扩展格式拷贝 DLC 及 data[] 到用户 buffer清除 FIFO 中该帧标记。关键点在于read()是阻塞式调用若 FIFO 为空则挂起当前线程直到新帧到达或超时。这与裸机轮询有本质区别——你无需在while(1)中if(CAN_FLAG_GET(CAN0, CAN_FLAG_TME0))系统自动完成等待。同样write()会将frame填入 TX 邮箱若邮箱满则阻塞直到有空闲邮箱。这种设计极大简化了应用逻辑但也带来新问题若 TX 邮箱长期满如总线物理断开write()永久阻塞导致整个线程挂死。解决方案是所有write()调用必须指定超时如RT_WAITING_FOREVER改为RT_TICK_PER_SECOND/10即 100ms并在返回-RT_ETIMEOUT时主动上报总线故障。3.3 过滤器配置32 组标准 ID 滤波器的分组策略与性能权衡GD32H759 的 CAN 控制器提供 32 个 16 位标准 ID 过滤器或 16 个 32 位扩展 ID 过滤器可配置为“掩码模式”或“列表模式”。工业场景中我们通常用掩码模式实现“ID 段匹配”。例如某产线设备约定主站 ID0x100从站 ID 范围 0x200~0x2FF状态上报 ID0x300~0x3FF。则过滤器配置如下// 设置过滤器组 0匹配 0x100~0x1FF主站指令 CAN_FMR(CAN0) | CAN_FMR_FINIT; // 进入初始化模式 CAN_FA1R(CAN0) ~(1 0); // 关闭过滤器 0 CAN_FS1R(CAN0) | (1 0); // 设为 32 位宽标准ID用低16位 CAN_FFA1R(CAN0) ~(1 0); // 设为掩码模式 CAN_FiR0(CAN0) 0x0100 16; // 标识符寄存器0x0100 CAN_FiR1(CAN0) 0x01FF 16; // 掩码寄存器0x01FF低16位全1表示匹配 CAN_FA1R(CAN0) | (1 0); // 启用过滤器 0 CAN_FMR(CAN0) ~CAN_FMR_FINIT;// 退出初始化模式这里的关键是掩码中为 1 的位表示“必须匹配”为 0 的位表示“忽略”。若掩码设为 0xFFFF则必须精确匹配 ID若设为 0xFF00则只校验高 8 位。我曾因掩码设错0x00FF导致所有 ID 的低 8 位被强制为 0从站无法识别主站指令。建议过滤器组按功能划分组0主站指令组1从站响应组2广播消息并预留 2 组备用避免后期扩展时重构。3.4 Socket CAN 抽象层用AF_CAN协议族实现跨平台 CAN 通信RT-Thread 5.0 版本引入 Socket CAN允许用标准 socket API 操作 CAN 设备极大提升代码可移植性。启用方式在rtconfig.h中开启RT_USING_SOCKETS和RT_USING_POSIX。创建 socket 步骤int sock socket(AF_CAN, SOCK_RAW, CAN_RAW); struct sockaddr_can addr; struct ifreq ifr; strcpy(ifr.ifr_name, can0); // 绑定设备名 ioctl(sock, SIOCGIFINDEX, ifr); addr.can_family AF_CAN; addr.can_ifindex ifr.ifr_index; bind(sock, (struct sockaddr*)addr, sizeof(addr));此后sendto()发送struct can_framerecvfrom()接收。优势在于应用层无需关心 RT-Thread 设备模型可直接复用 Linux 下成熟的 CAN 工具链如candump,cansend。但要注意Socket CAN 的recvfrom()默认阻塞且无超时机制必须用setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, tv, sizeof(tv))设置接收超时否则网络异常时线程永久挂起。3.5 CANopen 协议栈集成canopenpkg 的编译与对象字典配置对于需要复杂状态机与参数管理的设备如伺服驱动器直接操作 raw CAN 效率低下。RT-Thread 的canopenpkg通过pkgs --update获取提供符合 CiA 301 标准的协议栈。集成步骤在menuconfig中启用RT_USING_CANOPEN执行pkgs --update下载canopen包修改canopen_cfg.h定义本节点 IDCO_NODE_ID、心跳生产者周期CO_HB_PROD_TIME、对象字典条目CO_OBJ_DIR在main()中调用co_init()初始化栈co_nmt_init()启动 NMT 状态机。对象字典OD是 CANopen 的核心存储设备所有可访问参数。例如某温度控制器的 OD 条目IndexSubIndexNameTypeAccessValue0x20000x00TemperatureINTEGER16RW2500 (25.00℃)0x20010x00SetpointINTEGER16RW3000应用层通过co_od_write()写入0x2001:0x00即可修改设定值。这里的关键是OD 条目必须在co_obj_create()时注册且内存地址需静态分配不能 malloc否则运行时访问非法地址。我曾因 OD 条目数组未加static修饰符导致栈溢出崩溃。4. 工业级 CAN 总线负载率监控与故障诊断从理论计算到现场实测的完整闭环4.1 CAN 总线负载率的精确计算不只是“报文数量 × 字节 × 波特率”CAN 总线负载率Bus Load是衡量总线繁忙程度的核心指标但多数人只记住公式负载率 (总比特数 / 时间) / 波特率却忽略其物理构成。一帧标准 CAN 报文11位ID 8字节数据的实际总比特数为帧起始1 bit ID11 bit RTR1 bit IDE1 bit r01 bit DLC4 bit Data8×864 bit CRC15 bit CRC delimiter1 bit ACK1 bit ACK delimiter1 bit 帧结束7 bit 间歇场3 bit 121 bit若考虑位填充每 5 个相同位插入 1 个补码位实际比特数浮动在 121~132 bit 之间。因此精确计算需取平均值 126.5 bit。假设总线每秒发送 1000 帧含 500 帧 8 字节数据 500 帧 2 字节数据则8 字节帧平均比特数126.5 bit2 字节帧平均比特数126.5 - (6×8) (6×2) 126.5 - 36 90.5 bit数据段缩短减少填充位总比特数 500×126.5 500×90.5 108,500 bit/s负载率 108,500 / 500,000 21.7%注意负载率 30% 时需警惕 60% 时必须优化报文结构如合并小数据帧、启用远程帧请求 80% 时总线已处于临界状态易受干扰。我曾见某客户将 16 个温度传感器每 100ms 发送一次 1 字节数据160 帧/s负载率达 78%后改为 4 个传感器打包成 1 帧40 帧/s负载率降至 19.5%。4.2 实时负载率监控工具基于 RT-Thread 的can_bus_load命令实现RT-Thread 提供 shell 命令框架我们可开发can_bus_load命令实时监控。核心思路利用 CAN 控制器的错误计数寄存器CAN_ESR和发送成功计数器CAN_TSR在 1 秒定时器中断中采样static rt_uint32_t tx_count_last 0; static rt_uint32_t rx_count_last 0; void can_load_monitor(void* param) { static rt_uint32_t tx_count 0, rx_count 0; tx_count CAN_TSR(CAN0) 0xFFFF; // 发送成功帧数 rx_count CAN_RFS0(CAN0) 0xFFFF; // 接收帧数FIFO0计数器 rt_kprintf(CAN0 Load: %.1f%%\n, ((tx_count - tx_count_last) (rx_count - rx_count_last)) * 126.5 / 500000 * 100); tx_count_last tx_count; rx_count_last rx_count; } // 注册 1s 定时器 rt_timer_t load_timer rt_timer_create(can_load, can_load_monitor, RT_NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC); rt_timer_start(load_timer);编译进系统后在串口 shell 输入can_bus_load即可查看实时负载率。该方法比抓包分析更轻量且不影响总线通信。4.3 总线故障诊断树从can_err_code到物理层定位的 5 层排查法当 CAN 通信异常时RT-Thread 的can_bus_err_handler会捕获错误码can_err_code其值为CAN_ERR_*宏定义的组合。我总结出 5 层诊断树层级错误码特征物理层定位解决方案L1 电气层CAN_ERR_BUSOFF总线关闭用万用表测 CAN_H-CAN_L 电压正常应为 2.5V±0.5V若 CAN_H3.5V, CAN_L1.5V说明终端电阻缺失或短路检查两端 120Ω 电阻测量各节点供电L2 链路层CAN_ERR_ACKACK 错误示波器抓取 ACK 段波形若无显性位说明无节点响应检查所有节点是否上电ID 是否冲突L3 协议层CAN_ERR_CRCCRC 错误抓取单帧波形观察位填充是否合规每 5 位后有补码检查波特率配置是否一致晶振精度是否达标±0.1%L4 应用层CAN_ERR_CTRL控制器错误查看CAN_ESR寄存器BOFF位为 1 表示进入 Bus Off 状态调整错误计数阈值CAN_ECR增加自动恢复机制L5 系统层CAN_ERR_TXFULLTX 邮箱满监控CAN_TSR中TME0/1/2位若长期为 0说明发送阻塞优化应用层发送频率增加重试机制实操心得我曾遇到CAN_ERR_BUSOFF频发示波器显示 CAN_H/CAN_L 电压正常但CAN_ESR中REC接收错误计数持续增长。最终发现是某从站 PCB 的 CAN 收发器电源滤波电容虚焊导致抗干扰能力下降外部噪声被误判为有效帧。更换电容后 REC 归零。4.4 CAN FD 升级路径从经典 CAN 到 2Mbps 数据帧的平滑过渡GD32H759 支持 CAN FD但 RT-Thread 默认配置仅启用经典 CAN。升级步骤在can_configure中设置can_mode CAN_MODE_FD修改波特率计算FD 帧分为仲裁段同经典 CAN和数据段独立波特率需配置CAN_BTR仲裁段和CAN_BTR_FD数据段应用层使用struct canfd_framedata[] 扩展至 64 字节确保所有节点支持 FD否则自动降速为经典 CAN。关键参数数据段波特率建议设为仲裁段的 2~4 倍如仲裁段 500kbps数据段 2Mbps这样可在保持兼容性的同时将 64 字节数据传输时间从经典 CAN 的 1.28ms 降至 0.32ms特别适合固件 OTA 升级场景。但注意CAN FD 要求总线长度 10m2Mbps 时长距离需降速或改用光纤中继。4.5 产线部署 Checklist10 项必须验证的工业现场条款在将 GD32H759RT-Thread CAN 方案交付产线前我坚持执行以下 checklist缺一不可环境温度测试-20℃ ~ 70℃ 全温区运行 72 小时监控can_bus_load与can_err_codeEMC 测试通过 IEC 61000-4-2ESD ±8kV、IEC 61000-4-4EFT ±2kV、IEC 61000-4-5Surge ±2kV总线拓扑验证用网络分析仪测量特征阻抗确保全程 120Ω ±5%节点掉线模拟拔掉任一节点观察主站是否在 100ms 内检测并告警报文风暴测试用 CANoe 发送 1000 帧/s 持续 1 小时检查 FIFO 溢出率 0.001%电源纹波测试CAN 收发器 VCC 纹波 50mVpp示波器 AC 耦合固件升级验证通过 CAN DFU 升级确认升级后 CAN 通信零丢帧看门狗联动CAN 通信中断 5s 触发硬件看门狗复位日志持久化can_err_code与时间戳写入 SPI Flash支持故障回溯文档交付提供《CAN 总线布线规范》《节点 ID 分配表》《故障代码速查手册》。最后一项文档不是形式主义——某次客户产线故障工程师按手册查CAN_ERR_ACK5 分钟定位到 ID 冲突比找我远程支持快 3 小时。5. 常见问题与独家避坑指南那些 datasheet 不会写的实战真相5.1 “CAN 设备找不到”问题90% 源于rtconfig.h中的宏定义冲突现象ls /dev看不到can0设备节点find_device(can0)返回 NULL。表面看是驱动没注册实则是rtconfig.h中宏定义冲突。GD32H759 BSP 默认启用RT_USING_DEVICE_IPC设备 IPC而 CAN 驱动初始化函数rt_hw_can_init()依赖rt_device_register()若RT_USING_DEVICE_IPC与RT_USING_CAN同时开启IPC 初始化会抢占设备注册时机。解决方案注释掉RT_USING_DEVICE_IPC或确保rt_hw_can_init()在rt_components_init()之前调用。这个坑我填了三次每次都在凌晨两点。5.2 “接收数据错乱”问题DMA 缓冲区未对齐引发的 Cache 一致性灾难GD32H759 支持 CAN RX FIFO 与 DMA 直连但若 DMA 缓冲区未按 32 字节对齐ARM Cortex-M7 Cache Line SizeCPU 读取时可能拿到脏数据。现象read()返回的frame.data[0]偶尔为 0xFF其余字节正常。根源是 Cache 未刷新。解决方法// 分配对齐内存 uint8_t *rx_buffer (uint8_t*)rt_malloc_align(64, 32); // 64字节缓冲32字节对齐 // DMA 传输完成后强制刷新 Cache SCB_CleanInvalidateDCache_by_Addr((uint32_t*)rx_buffer, 64);或者更简单禁用 CAN RX DMA改用 FIFO 中断读取——虽然牺牲一点性能但绝对稳定。5.3 “总线偶尔卡死”问题未处理的“错误被动”状态导致的隐形锁死GD32H759 的 CAN 控制器在错误计数超过 127 时进入“错误被动”状态Error Passive此时仍可发送但发送错误
返回列表