如果你的工位上有一块 Blue Pill(STM32F103C8T6 最小系统板),大概率它的宿命是“吃灰”或者“流水灯”。但真正让这块十几块钱的板子值回票价的,往往不是裸机 GPIO 翻转,而是把它当成理解工业通信和系统可靠性的实验台。
我做嵌入式项目时发现一个很普遍的现象:很多开发者用 Blue Pill 做 CAN、RS485、传感器采集都能跑通,但一接到真正的工业现场,就出现随机复位、通信乱码、甚至板子烧毁。排查到最后,原因高度集中在同一个词上:隔离。
这篇文章就用“在 Blue Pill 上做隔离实验”这条线,讲清楚隔离到底隔离什么、为什么必须隔离、以及怎么用低成本方案把三种最常见的隔离做出来。读完你可以获得:一套完整的光耦隔离输入实验、一套隔离 CAN 通信实验、一套隔离 RS485 通信实验,以及对应的 STM32 CubeMX 配置和 HAL 库代码,还有一套不依赖高端仪器的隔离效果验证方法。
1. 隔离到底隔离什么
1.1 三种常见隔离类型
在嵌入式系统里,“隔离”不是单一概念,它至少包含三个层面:电源隔离、信号隔离、地隔离。这三者经常同时出现,但解决的问题不同。
电源隔离解决的是供电域之间的干扰问题。比如你用一个隔离 DC-DC 模块,把 5V 输入变成另一路 5V 输出,输入和输出之间没有导线直连,能量通过变压器磁场传递,两边的地也是分开的。这能解决输入侧电网噪声、浪涌窜入后端电路的问题。
信号隔离解决的是数据通路上的干扰问题。典型器件是光耦、数字隔离器、隔离收发器。它们让信号跨过一道“屏障”,屏障两侧只传递逻辑电平或差分信号,不传递电气连接。
地隔离解决的是地电位差问题。这是很多通信异常和烧板子的根源。两个节点相距几十米时,两边的地电位可能相差几伏甚至几十伏。如果直接用导线把两地连在一起,地环路电流就会产生,轻则通信误码,重则烧毁收发器。隔离的本质,就是把两个地切开,让信号自己“跨越”过去。
1.2 为什么 MCU 系统需要隔离
我在实际项目中见过最典型的案例:一块 Blue Pill 通过 CAN 总线连接一台带变频器的设备,变频器启动瞬间,总线报错率飙升,没过多久,板子上的 CAN 收发器就挂了。
原因并不复杂。变频器是大功率开关设备,它的地线/机壳电位在启动瞬间会发生剧烈变化。节点之间的地电位差通过 CAN 总线屏蔽层或地线形成回路,产生共模电流。这个电流流经收发器,超过其共模电压范围,就会导致总线错误,严重时直接击穿芯片。
解决办法就是隔离。把 MCU 侧地和总线侧地用隔离收发器切开,让共模电流只能局限在总线侧,无法进入 MCU 逻辑侧。
1.3 关于隔离的常见误解
最容易产生的误解有三个。
第一个误解是“只要加了光耦,隔离就完成了”。实际上光耦只隔离了信号,如果两侧的电源仍然共用同一个电源,那地环路并没有被真正切断。正确做法是信号隔离、电源隔离、地隔离三者配合,缺一不可。
第二个误解是“高速信号也能用 PC817 隔离”。PC817 这种普通光耦的上升沿、下降沿都在微秒级,做开关量检测没问题,但用来跑 115200 波特率的 UART,波形会严重劣化,通信基本不稳定。高速信号要用高速光耦或者数字隔离器。
第三个误解是“Blue Pill 上没有隔离相关外设,做不了这个实验”。实际上隔离实验的关键不在 MCU 本身,而在外部隔离器件和正确的接线。Blue Pill 自带的 CAN 控制器、USART、GPIO 完全可以配合外部隔离电路完成实验。
如果你熟悉 Windows 安全里 Credential Guard 和 VBS Key Isolation 的思路,会发现隔离思维高度一致:把不可信环境与可信环境分开,收窄信任边界,限制故障传播半径。在工业现场,物理隔离仍是可靠性最高的手段。
2. Blue Pill 能做哪些隔离实验
2.1 Blue Pill 硬件资源盘点
Blue Pill 的核心芯片是 STM32F103C8T6,属于 Cortex-M3 内核,主频最高 72MHz,官方标称 64KB Flash、20KB SRAM。
它在这个隔离实验里最值得关注的资源有三个:
- 1 路 bxCAN 控制器,引脚为 PA11(CAN_RX)和 PA12(CAN_TX)
- 3 路 USART,常用 USART1 的 PA9(TX)和 PA10(RX)
- 多路 GPIO,可以配置为输入、输出、外部中断
板载资源方面,常见 Blue Pill 带一个 AMS1117 稳压芯片提供 3.3V、一个 USB 接口、一个 8MHz 晶振、两个 LED(PC13 通常接 LED,部分板子也引出其他引脚)。没有板载按键,所以实验中如果需要按键,需要用杜邦线外接一个。
2.2 硬件隔离与软件隔离
在 STM32F103 上,你还要理解“硬件隔离”和“软件隔离”的边界。
STM32F103 属于 Cortex-M3,不像 Cortex-M7 等内核自带 MPU(内存保护单元)。这意味着在软件层面,你无法通过 MPU 将某段内存区域严格标记为“某个任务独享”,让其他任务访问时触发硬件异常。
所以在这块板子上,软件隔离只能做到逻辑层隔离:通过 FreeRTOS 任务划分、互斥量、队列、看门狗等方式,把不同功能模块的错误影响范围控制住。它不能防止一个任务因为指针越界而去破坏另一个任务的内存。
而硬件隔离是物理层面的,光耦、隔离收发器是真正把电气通路切断。对于工业环境下的可靠性,硬件隔离是基础,软件隔离是补充。两者并不冲突。
2.3 实验规划
本文规划三个实验,按难度递增:
| 实验 | 隔离对象 | 核心器件 | 涉及外设 |
|---|---|---|---|
| 实验一 | 开关量输入 | PC817 光耦 | GPIO、USART1 |
| 实验二 | CAN 总线 | ISO1050 或 CTM1050 | bxCAN、USART1 |
| 实验三 | RS485 总线 | ADM2483 | USART1、GPIO |
这三个实验覆盖了嵌入式领域最常见的隔离场景。实验一帮你建立“隔离是需要回路完整设计”的基本概念,实验二和实验三把隔离放到工业总线通信的真实场景中,是价值最高的部分。
3. 实验一:光耦隔离输入
3.1 原理与器件选型
光耦隔离输入是成本最低、最容易理解的隔离实验。原理并不复杂:输入端是一颗发光二极管(LED),输出端是一个光敏三极管。输入侧的电信号让 LED 发光,光照射到输出侧的光敏三极管上使其导通,输出侧产生对应的电平变化。输入侧和输出侧之间只有光耦合,没有电气连接。
实验中推荐使用 PC817。这是一颗极其常见、几毛钱一颗的四脚光耦,引脚排布为:1 脚为阳极、2 脚为阴极、3 脚为发射极、4 脚为集电极。
PC817 适合 10kHz 以下的低速开关量信号,用来检测继电器触点、工业传感器、按钮等完全够用。如果想隔离更高频率的转速脉冲、PWM 波形,则要考虑 6N137、HCPL-0611 等高速光耦,或者数字隔离器。这个区别非常重要,很多新手把所有信号都往 PC817 上接,结果辛辛苦苦焊完板子,测试时发现波形变形严重。
3.2 硬件接线
以“外部 24V 传感器信号接入 MCU”为场景,接线如下:
- 外部信号正极 -> 限流电阻 -> PC817 的 1 脚(阳极)
- PC817 的 2 脚(阴极)-> 外部信号地(GND_IN)
- PC817 的 4 脚(集电极)-> MCU 的 PB0
- PC817 的 4 脚(集电极)同时通过 10kΩ 电阻上拉到 MCU 3.3V
- PC817 的 3 脚(发射极)-> MCU 地(GND_MCU)
关键点在于:
- 外部信号地和 MCU 地必须完全分开。如果把 GND_IN 和 GND_MCU 接在一起,那么隔离等于没有做。
- 限流电阻的取值由输入信号电压决定。PC817 的发光二极管正向压降 VF 约为 1.2V,工作电流 IF 建议选 5~10mA。计算方法是 R = (Vin - VF) / IF。24V 输入时可选 2.2~4.7kΩ,12V 输入时可选 1~2kΩ,5V 输入时可选 470Ω~1kΩ。
- 输出侧上拉电阻是必须的。因为光耦导通时,集电极被拉到低电平;光耦截止时,集电极需要上拉到高电平,否则输出状态不确定。
另外提醒一点:PC817 的输出侧 VCC(即上拉的电源)使用 MCU 的 3.3V 即可,因为这个信号最终要被 MCU 读取。输入侧的电流回路则不经过 MCU 电源,这正是“信号通路隔离”的直观体现。
3.3 STM32CubeIDE / CubeMX 配置
打开 STM32CubeMX,新建工程,芯片选择 STM32F103C8Tx。
主要配置如下:
- RCC -> HSE 选择 Crystal/Ceramic Resonator
- SYS -> Debug 选择 Serial Wire,方便用 ST-Link 调试
- PB0 配置为 GPIO_Input,引脚上下拉选择 Pull-up(也可以靠外部 10kΩ 上拉,内部上拉作为双保险)
- USART1 配置为 Asynchronous,波特率 115200,8N1
- 时钟树配置为系统时钟 72MHz,让 APB1 和 APB2 外设时钟保持默认合理值
配置完成后,Project Manager 里选择工具链 MDK-ARM 或 STM32CubeIDE,生成代码。
3.4 核心代码实现
在生成的main.c中,在 USER CODE 区域编写轮询读取逻辑。这里用简单的电平变化检测 + UART 打印:
/* USER CODE BEGIN Includes */ #include <stdio.h> #include <string.h> /* USER CODE END Includes */ /* USER CODE BEGIN PV */ uint8_t last_level = 0; uint8_t current_level = 0; /* USER CODE END PV */ /* USER CODE BEGIN 2 */ printf("Optocoupler isolation test started.\r\n"); /* USER CODE END 2 */ /* USER CODE BEGIN 3 */ while (1) { current_level = HAL_GPIO_ReadPin(PB0_GPIO_Port, PB0_Pin); if (current_level != last_level) { char buf[64]; snprintf(buf, sizeof(buf), "Input level: %s\r\n", current_level == GPIO_PIN_SET ? "HIGH" : "LOW"); HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), 100); last_level = current_level; } HAL_Delay(20); } /* USER CODE END 3 */另外,在usart.c或main.c中需要重定向printf。比较简单的做法是重写fputc:
/* USER CODE BEGIN 0 */ int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100); return ch; } /* USER CODE END 0 */需要包含<stdio.h>。这样 UART 连接 USB-TTL 后,可以用串口助手直接看到状态变化。
3.5 运行验证
给 MCU 上电,用 USB-TTL 连接 USART1 的 PA9(TX)和 PA10(RX),注意共地。串口助手波特率设为 115200。
然后用一个外部电源模拟传感器信号:外部电源正极串入限流电阻接到 PC817 的 1 脚,2 脚接外部电源负极。当外部电源打开时,串口应当输出:
Input level: LOW当外部电源关闭时,串口应当输出:
Input level: HIGH这里输出 HIGH 还是 LOW 取决于光耦输出端的接法。上述接法中,光耦导通时 PB0 被拉到地,所以为 LOW;光耦截止时上拉使 PB0 为 HIGH。
验证隔离有效性:用万用表电阻挡测量“外部输入地”和“MCU 地”之间的电阻,正常情况下应为开路或兆欧级以上。如果测量得到接近 0Ω,说明两地被错误连通,需要检查接线。
4. 实验二:隔离 CAN 总线通信
4.1 为什么 CAN 需要隔离
CAN 总线是差分总线,设计初衷是抗干扰,但这不代表节点之间可以直接互相连接地线。CAN 主要用于汽车和工业控制,总线上各个节点分散在不同位置,供电回路也不同,节点之间很可能存在地电位差。
如果每个节点都把本地地和总线的参比地直接相连,地环路电流就会在节点间流动,导致共模电压超出收发器的允许范围。总线两侧地电位差过大时,即使没有通信,也可能有电流持续流过收发器,最终损坏器件。
所以 CAN 的隔离,核心是把“控制器侧 MCU 地”和“总线侧收发器地”切开。控制器通过隔离栅把 TX/RX 信号传输到总线侧,总线侧的收发器使用独立于 MCU 的隔离电源供电。
4.2 两套隔离 CAN 方案对比
实际项目中有两种主流方案:
| 方案 | 组成 | 优点 | 缺点 |
|---|---|---|---|
| 集成隔离收发器 | ISO1050、CTM1050 | 外围简单,可靠性高 | 成本略高,选型余地小 |
| 数字隔离器 + 普通收发器 | ADuM1201 + TJA1050 | 选型灵活,可以组合不同总线 | 外围更多,占板面积大 |
本文以 ISO1050 为例。ISO1050 是 TI 的隔离式 CAN 收发器,内部集成信号隔离栅,数字侧供电 VCC1 支持 3.3V/5V,总线侧供电 VCC2 需要 5V,并需要为总线侧单独准备隔离电源。
如果使用周立功的 CTM1050 等集成模块,模块内部已经包含了隔离电源,外围更简单,但原理和接线思想一致。
4.3 硬件接线
以 ISO1050 为例,接线如下:
- ISO1050 的 TXD 接 STM32 的 PA12(CAN_TX)
- ISO1050 的 RXD 接 STM32 的 PA11(CAN_RX)
- ISO1050 的 VCC1 接 3.3V,GND1 接 MCU 地
- ISO1050 的 VCC2 接 5V 隔离电源正极,GND2 接总线侧地
- ISO1050 的 CANH、CANL 分别接总线 CANH、CANL
- 总线两端各接一个 120Ω 终端电阻
这里最容易踩的坑是:如果把 VCC2 直接接到 MCU 板上的 5V,那么 GND1 和 GND2 实际上还是通过电源模块内部连在一起,隔离效果就打折了。总线侧 5V 必须来自隔离电源模块,比如 B0505S,它输入 5V,输出隔离的 5V,输入输出地相互独立。
4.4 STM32CubeMX 配置
在 CubeMX 中完成以下配置:
- 启用 CAN1,Mode 选择 Normal
- 参数设置里,波特率配置为 500kbps。对于 72MHz 系统时钟、APB1 36MHz 的典型配置,可以选择 Prescaler=4,BS1=13,BS2=4,SJW=1,得到约 500kbps
- 使能 CAN1 中断,NVIC Settings 里勾选 CAN1 RX0 interrupt
- USART1 配置为 115200,用于调试日志输出
CubeMX 会自动把 PA11 配置为 CAN_RX,PA12 配置为 CAN_TX。
4.5 核心代码实现
这一节设计一个简单实用的程序:同一份代码烧录到两块 Blue Pill,一块作为发送节点,一块作为接收节点。发送节点通过外部按键触发发送 CAN 帧;接收节点收到后翻转板载 LED,并通过串口打印数据。
在main.c的 USER CODE 区添加全局变量:
/* USER CODE BEGIN PV */ CAN_TxHeaderTypeDef txHeader; CAN_RxHeaderTypeDef rxHeader; uint8_t txData[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; uint8_t rxData[8]; uint32_t txMailbox; uint8_t btnPressed = 0; /* USER CODE END PV */在初始化部分,配置发送帧头并启动 CAN:
/* USER CODE BEGIN 2 */ txHeader.StdId = 0x123; txHeader.IDE = CAN_ID_STD; txHeader.RTR = CAN_RTR_DATA; txHeader.DLC = 8; txHeader.TransmitGlobalTime = DISABLE; HAL_CAN_Start(&hcan); HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING); printf("CAN isolation test started.\r\n"); /* USER CODE END 2 */主循环中,检测 PA0 按键。我在这里假设 PA0 外接一个按键,另一端接 GND,按下时读到低电平:
/* USER CODE BEGIN 3 */ while (1) { if (HAL_GPIO_ReadPin(PA0_GPIO_Port, PA0_Pin) == GPIO_PIN_RESET) { if (!btnPressed) { btnPressed = 1; if (HAL_CAN_AddTxMessage(&hcan, &txHeader, txData, &txMailbox) == HAL_OK) { printf("CAN message sent, ID=0x%03lX\r\n", txHeader.StdId); } } } else { btnPressed = 0; } HAL_Delay(10); } /* USER CODE END 3 */接收中断回调函数,在main.c或单独文件中实现。收到 ID 为 0x123 的帧后翻转 LED,并把接收到的数据通过串口打印:
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { if (hcan->Instance == CAN1) { HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxHeader, rxData); if (rxHeader.StdId == 0x123) { HAL_GPIO_TogglePin(PC13_GPIO_Port, PC13_Pin); printf("CAN received: "); for (int i = 0; i < rxHeader.DLC; i++) { printf("%02X ", rxData[i]); } printf("\r\n"); } } }LED 引脚是 Blue Pill 板载的 PC13,CubeMX 中把 PC13 配置为 GPIO_Output 即可。
4.6 运行验证
两块板子都烧录上述代码后,接线:
- 发送节点 CANH 接接收节点 CANH
- 发送节点 CANL 接接收节点 CANL
- 总线两端各并联一个 120Ω 终端电阻
- 两个节点各自保持独立的隔离电源
在发送节点按一下 PA0 按键,接收节点的串口应该打印:
CAN received: 01 02 03 04 05 06 07 08同时接收节点的板载 LED 翻转一次。如果发送后没有反应,优先检查三件事:终端电阻是否接好、CANH/CANL 是否接反、两边的波特率是否一致。用示波器观察 CANH 与 CANL 之间的差分波形,正常显性位时差分电压约 2V,隐性位时约 0V。
5. 实验三:隔离 RS485 通信
5.1 RS485 隔离的必要性
RS485 是工业控制中应用最广的串行总线之一,采用差分信号,抗共模干扰能力强,支持多节点、长距离传输。但它的可靠性依然受地电位差影响。
RS485 通常要求收发器 A、B 引脚之间的共模输入电压在一定范围内,典型为 -7V 到 +12V。如果两个节点相距较远,地电位差超过这个范围,通信就会出现误码,甚至损坏收发器。在雷击、电机启停、大功率设备切换等场景下,这个问题更严重。
所以 RS485 也需要隔离。本文使用 ADM2483,它是一款集成信号隔离的 RS485 收发器,内部包含数字隔离栅,方向控制由 DE 和 RE 引脚决定,非常适合 STM32 这类半双工 RS485 应用。
5.2 硬件接线
ADM2483 的关键引脚接线如下:
- ADM2483 的 DI 接 STM32 的 PA9(USART1_TX)
- ADM2483 的 RO 接 STM32 的 PA10(USART1_RX)
- ADM2483 的 DE 和 RE 并联,共同接 STM32 的 PA8
- ADM2483 的 VCC1 接 3.3V,GND1 接 MCU 地
- ADM2483 的 VCC2 接 5V 隔离电源,GND2 接总线侧地
- ADM2483 的 A、B 接 RS485 总线 A、B
- 总线两端各接一个 120Ω 终端电阻
DE 和 RE 并联的接法很常见。DE 是高电平使能发送,RE 是低电平使能接收,两者并联后,PA8 输出高电平进入发送模式,输出低电平进入接收模式。这正好符合 RS485 半双工的工作方式:要么发,要么收,不能同时进行。
这里还要强调:VCC2 同样必须来自隔离电源,不能直接复用 MCU 的 5V。否则 GND2 和 GND1 会通过电源内部连接,隔离就会失效。
5.3 STM32CubeMX 配置
CubeMX 中完成以下配置:
- USART1 配置为 Asynchronous,波特率 115200,8N1
- PA8 配置为 GPIO_Output,初始电平为低(接收模式)
- PC13 配置为 GPIO_Output(LED)
- NVIC 中使能 USART1 全局中断(如果使用接收中断)
5.4 核心代码实现
先写一个 RS485 发送函数。发送前把 DE/RE 拉高,发送完成后拉低,回到接收模式:
/* USER CODE BEGIN 0 */ void RS485_Send(uint8_t *data, uint16_t len) { HAL_GPIO_WritePin(PA8_GPIO_Port, PA8_Pin, GPIO_PIN_SET); HAL_UART_Transmit(&huart1, data, len, 100); HAL_GPIO_WritePin(PA8_GPIO_Port, PA8_Pin, GPIO_PIN_RESET); } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART1) { HAL_GPIO_TogglePin(PC13_GPIO_Port, PC13_Pin); printf("RS485 received: 0x%02X\r\n", rxByte); HAL_UART_Receive_IT(&huart1, &rxByte, 1); } } /* USER CODE END 0 */在全局变量区域定义rxByte:
/* USER CODE BEGIN PV */ uint8_t rxByte = 0; uint8_t sendBuf[8] = {0xAA, 0x55, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; /* USER CODE END PV */在初始化后,启动接收中断:
/* USER CODE BEGIN 2 */ printf("RS485 isolation test started.\r\n"); HAL_UART_Receive_IT(&huart1, &rxByte, 1); /* USER CODE END 2 */主循环里做一个简单的定时发送演示:
/* USER CODE BEGIN 3 */ while (1) { RS485_Send(sendBuf, sizeof(sendBuf)); printf("RS485 sent: "); for (int i = 0; i < sizeof(sendBuf); i++) { printf("%02X ", sendBuf[i]); } printf("\r\n"); HAL_Delay(1000); } /* USER CODE END 3 */如果要测试接收节点,只需要把最后一段 while 循环内容去掉,保留HAL_UART_Receive_IT即可。或者用同一份代码,两块板子互发,观察串口打印和 LED 翻转。
5.5 运行验证
两块板子分别接好 ADM2483,然后把两块板的隔离侧分别接到同一根 RS485 总线上:
- A 接 A
- B 接 B
- 总线两端各接一个 120Ω 终端电阻
- 两个节点的隔离电源各自独立
上电后,每块板子每秒发送一次数据,同时接收对方发来的数据。串口助手应该看到类似输出:
RS485 sent: AA 55 01 02 03 04 05 06 RS485 received: AA 55 01 02 03 04 05 06如果出现乱码,最常见的原因是波特率不一致或者 DE/RE 切换时序不对。发送期间 DE 必须保持高电平,如果发送函数返回后立刻拉低 DE,但 UART 移位寄存器还没发完最后一位,就会把尾巴截断,导致接收方第一个字节丢失。
6. 软件层面的隔离设计
硬件隔离解决的是电气通路问题,但一个可靠系统还需要软件层面的隔离。Blue Pill 没有 MPU,无法做严格的内存隔离,但我们仍然可以用 RTOS 和合理的软件架构来控制故障影响范围。
6.1 FreeRTOS 任务隔离
CubeMX 集成 FreeRTOS 后,可以把系统拆成几个独立任务:
- 采集任务:负责读取光耦输入、传感器数据
- 通信任务:负责 CAN、RS485 报文的收发
- 心跳任务:负责 LED 闪烁或系统状态输出
任务之间通过队列或信号量传递数据,尽量避免多个任务直接读写同一个全局变量。这样即使通信任务卡死,也不会立刻拖垮采集任务,还可以由看门狗或监控任务去复位通信任务。
6.2 外设访问互斥
CAN、USART 这类外设被多个任务同时使用时,必须加互斥量。比如一个任务要发送 CAN 帧,另一个任务也在发送,如果不加保护,两条报文的数据可能交错,或者邮箱被覆盖。
正确做法是在发送函数外包裹互斥量:
osMutexAcquire(canMutexHandle, osWaitForever); HAL_CAN_AddTxMessage(&hcan, &txHeader, txData, &txMailbox); osMutexRelease(canMutexHandle);6.3 看门狗与故障恢复
STM32F103 有独立看门狗 IWDG 和窗口看门狗 WWDG。在通信类项目中,看门狗的作用不只是防死机,更是“故障容忍”的一部分。
例如,上位机可能长时间不发指令,如果看门狗超时时间太短,系统会不断复位。更合理的设计是:把看门狗喂狗放在主循环或监控任务里,监控任务同时检查通信状态,如果发现通信异常,先尝试重新初始化外设,再决定是否复位整个系统。
6.4 隔离思维与更高层系统
隔离不仅是硬件问题,也是系统设计思想。
在 PC 安全领域,Windows 的 Credential Guard 和 VBS Key Isolation 通过虚拟化安全模式把密钥保护在独立隔离环境中,即使系统内核被攻破,攻击者也难以直接窃取密钥。在机器学习领域,Isolation Forest 通过随机切分特征空间来度量数据点“是否容易被孤立”,从而检测离群点。这些技术各不相关,但底层逻辑一致:把风险的传播半径限制住。
在 STM32 上做硬件隔离实验,本质是在最小成本上实践这种“限制故障传播半径”的工程思维方式。
7. 隔离效果的测试与验证方法
很多读者做完隔离实验后会问:我怎么证明隔离真的有效?没有高端测试设备,也可以用常见仪器完成基本验证。
7.1 万用表测量隔离电阻
用万用表电阻挡测量:
- MCU 地(GND1)与总线侧地(GND2)之间的电阻,应为无穷大或兆欧级以上
- MCU 3.3V 与总线侧 5V 之间的电阻,应同样为无穷大或兆欧级
如果测量到几欧姆或者几十欧姆,说明两侧地可能通过接线、电源或 PCB 布线意外连在一起。
需要注意,测量前必须断电。并且在电路刚断电时,电容上可能还有残留电压,最好等几秒再测。
7.2 示波器观察波形
示波器是验证隔离通信质量的有效工具。观察 CANH 与 CANL 的差分波形,正常时显性位差分电压约 2V,隐性位约 0V。RS485 的 A、B 差分波形类似,只是电平定义不同。
这里有一个容易犯的错误:把示波器探头的接地夹接到隔离两侧的其中一个地,然后再去测量另一侧的信号。如果示波器设备本身通过电源地连接到了其他地,可能会把隔离两侧短路。正确做法是:示波器探头地夹只接到当前测量侧的地,保持测量参考点一致。
7.3 共模干扰模拟测试
在安全范围内,可以给总线侧地人为叠加一个直流偏置,模拟地电位差。
例如在 ISO1050 或 ADM2483 的允许