1. 先搞明白:你手里这颗“STM32F103”到底经历了什么
1.1 假芯片不只是“假”,而是几类东西的统称
STM32F103 和 FreeRTOS 这个组合,基本是嵌入式入门到进阶绕不开的一条路。芯片便宜、资料多、生态成熟,从最小系统到跑一个多任务操作系统,按说几小时就能搞定。但我被一个问题卡过整整两天:板子焊好,程序烧进去,芯片一点反应都没有,连仿真器都连不上。换一块芯片,好了。后来仔细检查才发现,买的一批所谓“原装”STM32F103,实际上有几颗是打磨过的翻新片,还有一两颗是用更低容量型号重新打标的。
这里说的“假芯片”,严格讲不是一个东西,而是几类情况的统称:翻新片、散新片、打磨重标片、虚标容量片,甚至还有用兼容型号冒充的。翻新片是从旧板子上拆下来,清洗、整脚、重新打标,外观看着挺新,但内部可能经历过高温、静电或者长期老化,寿命和稳定性毫无保证。散新片是渠道不明、来源说不清楚的管装或盘装货,可能是工厂余料,也可能是不合格品流出来的。打磨重标片最常见,把低容量型号表面打磨掉,重新印上高容量型号的丝印,比如拿 64KB Flash 的型号打磨成 256KB 的,价格能差不少。还有一类是兼容芯片打上 ST 的标,不能说人家芯片本身不能用,但它不是你要的那颗 STM32F103,外设细节有差异,用在 FreeRTOS 项目里就会出现各种莫名其妙的问题。
1.2 为什么偏偏是 STM32F103 中招最多
这个问题其实很简单:出货量太大,生命周期太长。STM32F103 从 2007 年发布到现在,十几年过去依然是很多产品的主力 MCU,大量旧设备报废后,板子上的 F103 被回收,经过处理再流入市场。需求大、供应充足、利润可观,自然有人做这门生意。
还有一个关键因素:STM32F103 的封装和引脚定义太普及了。LQFP48、LQFP64、LQFP100 这些封装,不仅 ST 自己在用,很多国产兼容 Cortex-M3 芯片也做成同样的引脚排布,甚至寄存器地址也有相当高的兼容性。这就给“打磨重标”提供了技术基础,只要把丝印一换,绝大多数人根本看不出来。你拿着万用表量引脚,量不出来;你拿 J-Link 连 SWD,也能连上,因为内核本来就是 Cortex-M3,SWD 接口天然兼容。等你发现不对,往往已经在调试 FreeRTOS 的任务调度了。
1.3 核心风险:从“不能跑”到“跑飞”的各种表现
很多人以为假芯片就是“不能跑”,实际上真正不能跑的反而不是多数。更常见的是以下几种表现:上电后偶尔能跑、偶尔不能跑;跑裸机程序没问题,一上 FreeRTOS 就 HardFault;串口数据忽对忽错;程序运行一段时间后莫名其妙死机。这些现象非常容易误导人,因为你第一反应是怀疑自己的代码或者配置。
我遇到过一颗打磨芯片,裸机点灯、串口回环都正常,但一跑 FreeRTOS 创建第二个任务就死。查了两天代码,最后用调试器读 Flash 容量寄存器,才发现标称 256KB 的芯片实际只有 64KB,程序本身就已经超过硬件容量了。所以如果你也碰到“单任务没事,多任务就挂”的情况,在怀疑调度器配置之前,先给芯片做一次身份验证,成本比排查代码低得多。
2. 软件排查之前,先把硬件底子摸清楚
2.1 供电与上电电流:第一道体检
芯片“没反应”,第一步永远是量供电,这不是废话。很多板子的问题不是假芯片,而是 3.3V 根本就没到芯片引脚上,或者纹波大到芯片直接复位。你拿万用表量 VDD 和 VSS,最好直接在芯片引脚上量,不要量在 LDO 输出端,因为中间可能有断线或虚焊。
除了电压,还要看上电瞬间的电流波形。用示波器电流探头,或者串一个 1 欧姆采样电阻看压降。正常情况下,STM32F103 上电瞬间有一个短暂的充电尖峰,稳定后空跑电流大概在几毫安到十几毫安。如果电流一直很大,比如几十毫安甚至上百毫安,那这颗芯片很可能内部有损伤,常见于翻新片或者被 EOS(过电应力)打过的拆机片。
这里有个实操细节:用可调电源限流上电,先把限流调到 50mA 左右,上电瞬间如果直接触发限流,说明板子或者芯片存在短路或异常大电流。然后把限流慢慢调高,观察电流变化,能帮你快速筛掉一批“坏片”和“假片”。
2.2 NRST、BOOT0/BOOT1 和烧录链路
供电没问题之后,查复位。STM32F103 的 NRST 引脚是低电平复位,内部有上拉,正常工作时应该被拉到高电平。如果外部接了复位按键和电容,要确认电容没有漏电或者装错容值。曾经有个项目,复位电容用了 10uF 而不是推荐的 100nF,导致上电后 NRST 拉低时间过长,芯片一直处于复位状态,表现就是“什么都没反应”。
BOOT0 和 BOOT1 也容易踩坑。BOOT0 拉高时芯片从系统存储器启动,也就是内置 Bootloader;BOOT0 拉低、BOOT1 任意,才从 Flash 启动。如果 BOOT0 悬空或者被外部电路意外拉高,你烧进去的程序根本不会执行。判断方法很粗暴:量 BOOT0 引脚电压,运行状态必须是低电平。BOOT1 在从 Flash 启动时不影响运行,但在某些调试场景会影响。
烧录链路检查是另一个高频坑。ST-Link 连不上芯片,很多人以为是芯片坏了,其实可能是 SWD 引脚被程序复用成了普通 GPIO,或者目标板供电不足拉低了 ST-Link 的电平。一些翻新片因为引脚氧化严重,SWD 连接不稳定,时好时坏,这时候换一颗试一下就能分辨。
2.3 晶振不起振,什么程序都白搭
时钟是 STM32F103 正常运行的命根子。很多“没反应”的板子,问题出在 8MHz 晶振不起振,或者起振条件不好,导致芯片一直在用内部 HSI 时钟源运行。如果程序里配置了 PLL 到 72MHz,而外部晶振根本没有输出,PLL 锁不住,芯片就可能挂死。
检查方法很简单:用示波器量 OSC_IN 和 OSC_OUT 引脚。正常起振时,OSC_OUT 应该能看到 8MHz 的正弦或近似正弦波形,幅度大概在 0 到 3.3V 之间。如果什么都看不到,先检查晶振两端并联的 1MΩ 反馈电阻有没有焊,匹配电容 10pF 到 22pF 是否合适,再检查晶振本身有没有问题。
值得提醒的是,部分假芯片内部的时钟电路并不完全兼容,外部晶振起振条件会变得很苛刻。如果你验证了外部电路完全正常,晶振就是不工作,那这颗芯片的嫌疑就非常大。具体可以用后面要讲的 MCO 输出来进一步验证。
3. 不跑 FreeRTOS,也用裸机把芯片查个底朝天
3.1 点灯和串口回环:先确认“活着”
接到一颗有嫌疑的芯片,我建议先不要急着移植 FreeRTOS,先用最简单的方式确认它是不是真的“活着”。点灯是最基本的操作,随便挑一个 GPIO,配置成推挽输出,拉高拉低,用万用表或示波器观察引脚电平变化。这一步能排除大部分烧录、启动和基础 GPIO 配置问题。
点灯正常之后,测串口。把 PA9(USART1_TX)和 PA10(USART1_RX)短接,配置 USART1 为 115200、8N1,然后程序里自发自收,把收到的数据原样发回去。用 USB 转串口模块连接电脑,打开串口助手,如果发送“hello”能收到“hello”,说明串口外设和引脚都正常。
这里要注意一个细节:如果你用的是假芯片或者兼容芯片,USART 寄存器可能只有部分兼容,尤其是波特率生成逻辑和中断标志位。我在测试中遇到过一颗兼容芯片,USART 能发送但不能接收,查询中断标志位永远不为真,这种问题在不跑操作系统时就能暴露,等移植 FreeRTOS 后更难查。
3.2 用 PA8 的 MCO 输出验证时钟链路
MCO 是 microcontroller clock output 的缩写,STM32F103 上它是 PA8 引脚的复用功能,可以把 SYSCLK、HSI、HSE 或 PLL 时钟分频后输出。这是一个非常实用的裸机验证手段,相当于把芯片内部时钟树“引出”到外部,用示波器一量便知。
用标准库配置 MCO 输出系统时钟的代码很简单,大概这样:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_MCOConfig(RCC_MCO_SYSCLK);程序里先配置好时钟树,外部 8MHz 晶振,PLL 倍频到 72MHz,然后使能 MCO 输出 SYSCLK,用示波器或频率计量 PA8。正常情况下应该看到 72MHz 的方波,如果看到 8MHz 或者 36MHz,说明 PLL 没有正常锁定;如果完全没有波形,说明芯片时钟系统本身就有问题。
有条件的用频率计,没条件的用示波器看频率也可以。我测过一批翻新片,MCO 输出的频率漂移很严重,标称 72MHz 实际测量只有 69MHz 左右,这种芯片在 FreeRTOS 里跑 vTaskDelay 会导致时间基准偏差,串口波特率也会跟着出问题。
3.3 读芯片 ID 和 Flash 容量寄存器:给芯片“验明正身”
如果说 MCO 是检查“身体状态”,那读 ID 就是检查“身份证”。STM32F103 内部有几个寄存器可以直接读出芯片的身份信息,用调试器或者程序都能读,不依赖任何外部设备。
第一个是 Flash 容量寄存器,地址 0x1FFFF7E0,数据类型是 16 位无符号整数,单位是 KB。比如 STM32F103C8T6 标称 64KB Flash,读出来应该是 0x0040,也就是十进制 64;STM32F103RCT6 标称 256KB,读出来应该是 0x0100,十进制 256。如果你买的是 RCT6,读出来只有 64,那这颗芯片就是低容量打磨重标来的。
第二个是芯片唯一 ID 寄存器,地址从 0x1FFFF7E8 开始,一共 96 位,分三个 32 位寄存器。这段数据在每颗芯片出厂时烧录,理论上是全球唯一的。如果你手上的同一批次芯片,读出来的 UID 完全一样,那几乎可以断定是假货或者克隆片。相反,如果 UID 各不相同,也不能完全排除假货,但至少说明不是同一颗芯片翻新的。
第三个是内核 ID 寄存器 CPUID,地址 0xE000ED00。STM32F103 的内核是 Cortex-M3,读取 CPUID 后,其中 PartNo 字段应该是 0xC23,对应 Cortex-M3。如果读出来是 0xC24,那是 Cortex-M4,说明这颗芯片根本不是 F103。这个测试最硬核,任何号称 F103 但内核不对的,直接实锤。
程序里读这些寄存器也很简单:
uint16_t flash_size = *(volatile uint16_t *)0x1FFFF7E0; uint32_t uid[3]; uid[0] = *(volatile uint32_t *)0x1FFFF7E8; uid[1] = *(volatile uint32_t *)0x1FFFF7EC; uid[2] = *(volatile uint32_t *)0x1FFFF7F0; uint32_t cpuid = *(volatile uint32_t *)0xE000ED00;把这几个值通过串口打印出来,或者用调试器直接看内存,芯片的真实身份基本就露馅了。
3.4 Flash 全片擦写测试:揪出低容量冒充高容量的货色
读容量寄存器是看“芯片自己怎么说”,全片擦写测试是看“芯片实际上能做到什么”。如果一个标称 256KB 的芯片实际只有 64KB Flash,程序往高地址写入时会出问题。ST 的标准库在写 Flash 时会检查地址合法性,而不是你去访问非法地址,往往会导致写入失败或者 HardFault。
具体做法很简单:写一个测试程序,从最低地址开始,按页擦除、写入、回读校验,一直做到标称容量对应的最高地址。以 256KB 为例,F103 的 Flash 页大小是 2KB(大容量),一共 128 页。循环 128 次,每页写入特定模式的伪随机数,再读回对比。如果某页写入失败或者回读不一致,说明实际容量不足。
这个测试在 FreeRTOS 环境下也可以做,但建议在裸机下做,避免任务调度打断 Flash 操作,因为 STM32F103 在 Flash 擦写时不能并行执行程序,必须等操作完成才能继续取指令。
我遇到过一批“C8T6”打磨成“RCT6”的芯片,容量寄存器读出来是 256,但实际全片擦写到第 32 页左右(对应 64KB 的位置)就开始出错。这种芯片如果跑简单程序可能永远发现不了问题,因为程序只有几十 KB,根本用不到高地址空间。一旦你上了 FreeRTOS,加了各种任务、队列、信号量,代码变大之后,系统就会在随机时间点崩溃,排查起来极度痛苦。
4. FreeRTOS 环境下的“芯片没反应”,有多少是锅在软件
4.1 任务创建失败:内存不足往往和假芯片容量有关
接下来聊软件层面。FreeRTOS 下最常见的“没反应”,其实不是芯片死了,而是任务压根没创建成功。xTaskCreate 返回 pdPASS 才是创建成功,返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 就说明内存不够。很多人不看返回值,直接继续往下走,后面调度器启动之后,系统看起来就像死了一样。
内存不够有两个原因:一是你给 FreeRTOS 的堆配置太小,这个在 FreeRTOSConfig.h 的 configTOTAL_HEAP_SIZE 里调整;二是芯片实际 SRAM 容量小于标称。比如标称 20KB SRAM 的 C8T6,实际芯片如果是低端型号,可能只有 8KB 或者 10KB,你给 FreeRTOS 堆分配 16KB,一上电就在内存申请阶段静默失败了。
排查方法很简单,在 main 函数里加一个串口打印:
TaskHandle_t xHandle = NULL; BaseType_t xReturn = xTaskCreate(vTaskFunction, "task", 128, NULL, 1, &xHandle); printf("xTaskCreate return: %d\r\n", xReturn);如果返回值不是 1(pdPASS),那就是创建失败。接下来把 configTOTAL_HEAP_SIZE 调小试试,如果能创建成功,说明芯片 SRAM 容量很可疑,应该做芯片验证。
4.2 调度器没启动:vTaskStartScheduler 之前和之后要分开看
FreeRTOS 的启动过程分两个阶段:vTaskStartScheduler 调用之前和之后。很多“芯片没反应”的案例,其实程序卡死在 vTaskStartScheduler 之前的某个环节。比如初始化某个外设时等待一个永远等不到的标志位,或者 GPIO 配置里访问了不存在的寄存器地址。
建议在 main 函数里加入几个标志打印或者 LED 翻转,把代码执行路径可视化出来:
LED_Blink(1); // 进 main Hardware_Init(); LED_Blink(2); // 外设初始化完成 xReturn = xTaskCreate(...); LED_Blink(3); // 任务创建完成 vTaskStartScheduler(); LED_Blink(4); // 正常情况永远走不到这里正常执行会看到 1、2、3,然后 LED 状态停在 3,因为 vTaskStartScheduler 启动调度器后不会返回。如果看不到 2,说明外设初始化卡死;如果连 1 都没有,那问题在更底层的启动代码或硬件。
如果你用的是假芯片或者兼容芯片,启动文件 startup_stm32f10x_hd.s 可能和芯片实际容量不匹配。比如大容量启动文件初始化了中断向量表,但芯片实际是小容量,中断向量偏移和 Flash 布局对不上,程序一进中断就跳飞。这也是裸机简单程序没问题、FreeRTOS 一上就死的原因之一,因为 FreeRTOS 依赖 SysTick 中断,中断一旦触发就崩。
4.3 堆栈溢出、HardFault 和中断优先级
FreeRTOS 环境下的 HardFault 是排查难点,因为它往往不发生在出错现场,而是在任务切换时突然触发。常见原因有三个:任务栈溢出、中断优先级配置错误、非法内存访问。
任务栈溢出排查,前提是开启堆栈溢出检测。在 FreeRTOSConfig.h 里配置:
#define configCHECK_FOR_STACK_OVERFLOW 2同时实现钩子函数:
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) { __disable_irq(); while (1); }溢出触发后程序会卡死在钩子函数里,此时你通过调试器看 pcTaskName 就能知道是哪个任务溢出。建议每个任务的栈从 128 字(512 字节)开始测试,逐步往下降,避免过度浪费内存。
中断优先级这里要特别注意,Cortex-M3 内核要求 FreeRTOS 的临界区正确工作,SysTick 和 PendSV 中断优先级必须合理设置。在 STM32F103 上,如果你用标准库,要确保调用 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4) 设置优先级分组,并且 SysTick、PendSV 的优先级要低于其他外设中断。一个常见错误是把 SysTick 优先级设得比串口中断高,导致串口中断里调用 FreeRTOS API 时,临界区保护失效,系统随机死机。
HardFault 定位技巧:在调试器里打开 Fault 异常,查看 SCB->HFSR(0xE000ED2C)、SCB->CFSR(0xE000ED28)、SCB->BFAR(0xE000ED38)这几个寄存器的值,可以判断是不是总线错误、存储管理错误或者用法错误。比如 BFAR 有效且地址是 0xFFFFFFFF,往往是指针被赋了无效值。
4.4 SysTick、滴答计数和 vTaskDelay 卡死的误区
另一个经典误区是 vTaskDelay 看起来“卡死”了,程序不往前走,但实际情况不是死机,而是时间基准不对。FreeRTOS 依赖 SysTick 产生时基节拍,configTICK_RATE_HZ 定义了每秒节拍数,一般设 1000,也就是 1ms 一个 tick。如果芯片时钟配置错误,SysTick 中断频率不对,vTaskDelay(10) 可能变成 10 秒或者 10 微秒。
我遇到过一个情况:假芯片的 HSI(内部高速时钟)偏差很大,实际频率只有 6MHz 左右,而代码里配置 PLL 时按 8MHz HSI 计算倍频系数。最终 SYSCLK 不是 72MHz,可能只有 54MHz。FreeRTOS 的 tick 周期是按 72MHz 算的,实际频率偏差导致 1ms tick 变成了 1.33ms,任务调度节奏全乱,看起来就像芯片在“抽风”。这种问题通过 PA8 的 MCO 输出一测就能发现时钟频率不对。
使用标准库的 Delay 函数也要小心。如果你在 FreeRTOS 任务里既调用了 vTaskDelay,又使用了基于 SysTick 的 Delay 函数,两者会互相干扰,因为标准库的 Delay 会把 SysTick 重新配置。正确的做法是:任务里的延时统一用 vTaskDelay 或 vTaskDelayUntil,裸机初始化阶段才用标准库 Delay。
5. 怎么拿到实锤:调试器和外设测试说话
5.1 用 STM32CubeProgrammer 和 J-Link 读 ID 与容量
如果你不想写测试代码,直接用调试器工具读芯片信息是最快的。STM32 官方工具 STM32CubeProgrammer 连接芯片后,在主界面可以查看 Device ID、Flash Size、RAM Size、UID 等信息。如果显示的信息和丝印标称不一致,恭喜你,实锤了。
J-Link 用户可以直接用 J-Link Commander 命令行,连接后输入内存读取命令:
mem32 0x1FFFF7E0, 0x2这样会读取 0x1FFFF7E0 开始的 2 个 32 位数据,前 16 位是 Flash 容量(单位 KB),后 96 位是唯一 ID。再读内核 ID:
mem32 0xE000ED00, 0x1对比 CPUID 中 PartNo 字段是否为 0xC23。注意有些芯片用 SWD 时 IDCODE 也能看出端倪,F103 的调试接口 ID 一般是 0x1BA01477,如果读出来是其他值,就要怀疑内核不一样。
这些工具都不用联网,纯粹本地操作,非常安全。批量验证时建议写一个简单的脚本,把读回来的数据导出对比,高效率筛选问题批次。
5.2 外设差异测试:有些“兼容芯片”藏不住
有些兼容芯片在 ID、Flash 容量、内核 ID 上都能伪装得很好,但外设细节做不了完全兼容。STM32F103 的外设种类很丰富,USART、SPI、I2C、ADC、定时器、DAC、PWM 等,逐一测试就能发现差异。
我建议至少做三个测试:定时器 PWM 输出、ADC 采集、低功耗模式。定时器 PWM 测试看频率和占空比是否精确对应配置值,某些兼容芯片的时钟分频逻辑不同,导致 PWM 频率偏差 5% 以上。ADC 测试输入一个已知电压(比如用精密电阻分压得到 1.5V),看采样值是否接近理论值,偏差太大说明参考电压或 ADC 校准有问题。低功耗测试是进入 STOP 模式后量电流,如果电流比手册标称大很多,说明电源管理单元有差异。
这些测试在 FreeRTOS 环境下也能做,只要创建一个测试任务,按顺序跑,把结果通过串口打印出来。需要注意的是,不要让测试任务和实时性要求高的任务抢优先级,否则测试过程中的调度会干扰时间测量,尤其是 PWM 频率测试。
5.3 破坏性检验和低成本土办法
如果你怀疑的是批量货,而不是单颗芯片,可以抽几颗做破坏性检验。用热风枪把芯片从板上拆下来,用砂纸小心打磨表面丝印,然后放到显微镜下看晶圆表面的原厂标记。正规原厂芯片在封装表面或背面通常有激光刻印的批号、产地代码等,打磨重标片在打磨区域会留下明显的砂纸痕迹,边界不自然。这个操作有风险,会毁掉芯片,不适合对单颗珍贵样品使用,但批量采购时抽检是值得的。
还有一个低成本土办法:用手摸芯片温度。STM32F103 正常空载运行,温度接近室温,如果你发现芯片上电十几秒后明显发烫,那大概率有问题。芯片内部损伤、电源短路或者晶圆本身有缺陷,都会导致功耗异常。这个方法不精确,但作为快速筛查很管用。
6. 遇到“没反应”别慌:排查顺序速查表
6.1 一张表理清排查顺序
芯片没反应的时候,最忌讳的是东一榔头西一棒子。我整理了一张排查顺序表,按照从外到内、从硬件到软件的顺序走,能省下大量时间。
| 排查步骤 | 检查内容 | 方法/工具 | 常见的“没反应”原因 |
|---|---|---|---|
| 1 | 供电电压 | 万用表量芯片 VDD 引脚 | 3.3V 没到位、LDO 损坏 |
| 2 | 上电电流 | 可调电源限流观察 | 翻新片内部短路、电流异常 |
| 3 | NRST 电平 | 万用表/示波器量 NRST | 复位电容过大、外部复位电路卡死 |
| 4 | BOOT0/BOOT1 | 量引脚电平 | BOOT0 拉高,程序未从 Flash 启动 |
| 5 | 晶振起振 | 示波器量 OSC_IN/OUT | 晶振虚焊、匹配电容错误 |
| 6 | 烧录链路 | ST-Link/J-Link 连接 | 引脚氧化、SWD 被复用 |
| 7 | 最小程序验证 | 点灯/串口回环 | GPIO/串口初始化错误 |
| 8 | MCO 时钟输出 | 示波器量 PA8 | PLL 未锁定、时钟系统损坏 |
| 9 | 芯片 ID/容量 | 读 0x1FFFF7E0/0xE000ED00 | 假芯片/打磨重标片 |
| 10 | 更换芯片对比 | 换一颗正常芯片 | 确认是否芯片本身问题 |
这个顺序的核心思路:先排除外部电路,再验证芯片基础功能,最后才上升到操作系统层面。很多人在第 6 步之前就怀疑芯片是假的,结果换了芯片照样不行,回头才发现是复位电容的问题,白折腾半天。
6.2 采购与验货:把假芯片堵在产线之外
排查是事后补救,更重要的是一开始就降低买到假芯片的概率。首先是渠道,尽量从原厂授权代理商、知名目录分销商或者有长期合作关系的贸易商采购。价格明显低于市场均价的一定有问题,芯片行业没有那么多“捡漏”机会,低价背后大概率是翻新或散新。
批量到货时要做来料检验,至少抽测一批芯片的 Flash 容量、UID 唯一性和内核 ID。有条件的话做个全片擦写测试,直接刷入一个包含 ID 读取、Flash 回读校验的测试程序,运行通过才能上线贴片。别小看这一步,我见过太多项目因为省了这道流程,几千片芯片贴上产线后才发现问题,损失远比芯片差价大。
另外建议保留样品。每一批采购留几颗,贴好标签,注明采购日期、渠道、批次号。万一后续出现品质纠纷,这些样品是重要的证据。如果你选择渠道时拿不定主意,可以要求供应商提供原厂出货证明或者批次追溯信息,正规供应商一般都能提供。
还有一个经验:如果你的项目对可靠性要求高,尽量不要用 STM32F103 这种年深日久的芯片作为新设计的主选。不是说它不好,而是市场上翻新货太多,供应链风险太高。可以考虑替换为 ST 官方推荐的升级型号,或者经过验证的国产新料,原厂直接供货,假货风险会小很多。
最后再分享一点个人体会
我后来整理这套排查流程时发现,大多数“芯片没反应”的案子,折腾到最后,真正买到假芯片的比例其实没有网上说的那么玄乎。很多只是复位电容焊错、BOOT0 悬空、晶振虚焊这类低级问题。但假芯片也确实存在,而且一旦碰上,成本极高——你会在代码里反复找 bug,找两天发现是芯片的问题,那种感觉非常崩溃。
所以我的习惯是:新到一批芯片,先花十分钟做裸机“体检”,点灯、串口回环、读 ID 和 Flash 容量,全过一遍再拿去跑 FreeRTOS。这十分钟看着是浪费时间,实际上帮你把后面可能耗掉几天的问题拦在门外。芯片是嵌入式项目的地基,地基不牢,上面建什么都是空中楼阁。