☰
工业控制器分级存储实战:STM32+FPGA架构的EEPROM、NOR Flash与SD卡方案
2026/10/1 20:27:35 网站建设 项目流程

敢说自己做过工业控制器的人,大概率都吃过存储的亏。我见过不少现场事故:设备在产线上跑了三个月,一次断电,校准参数全部归零,客户直接拍桌子;还有的控制器,运行日志一直在写,等售后去现场拷数据,发现SD卡里全是乱码,时间戳错成一团。这些问题的根子不在程序逻辑,而在最容易被忽视的存储方案本身。

这篇文章我想把工业控制器里最常见的一套存储架构一次讲透:STM32做主控、FPGA做实时逻辑,数据分级落到EEPROM、NOR Flash和SD卡上。不是什么高深理论,就是实打实的设计思路、选型依据、电路细节和现场踩坑记录。这一篇是硬件篇的第12篇,前面聊过接口、电源、时钟,这次专门讲数据怎么存。

1. 为什么工业控制器必须用"分级存储"而不是一块芯片走天下

1.1 三类数据特征完全不同,单一介质根本接不住

很多初学者觉得存储嘛,无非就是Flash读读写写。但真把工业控制器的需求列一遍,你会发现完全不是一回事。

第一类数据是系统配置与标定参数。设备序列号、以太网MAC地址、IP配置、PID参数、模拟量校准系数、传感器零点、报警阈值,这些都属于这一类。容量需求很小,通常不到1KB,甚至几百字节就够了,但有两个硬性要求:掉电必须长期保存,而且用户调试时会反复修改。一台设备可能一天被调试人员改几十次参数,每次都要求可靠写入、立即生效。

第二类数据是固件与逻辑镜像。STM32的应用程序、FPGA的配置比特流,大小从几百KB到几十MB不等。这类数据写入频率极低,一年可能就升级一两次,但绝不能在升级时掉链子。一旦烧坏,设备直接变砖,产线停摆,这种风险对工业设备来说完全不能接受。

第三类数据是运行记录与采集数据。运行日志、报警历史、操作记录、过程曲线、故障快照,甚至高速采样波形。这类数据的特点恰好相反:容量需求巨大,几十MB到几十GB都可能;写入几乎是连续的;但单个数据点的可靠性要求相对宽松,丢几秒钟日志不影响大局。可是如果不能持续写入,前面记录的所有数据都白搭。

把这三类数据放在一起看,任何单块存储芯片都无能为力。EEPROM容量做不大,NOR Flash怕频繁擦写,SD卡则要面对可靠性和接口复杂度的问题。最务实的做法就是分级:让每种介质去干自己最擅长的事。

1.2 三种介质的"性格差异"决定了分工

这里要补一个基础知识,很多工程师其实分不清EEPROM和Flash的区别。

EEPROM(电可擦除可编程只读存储器)可以按字节擦写,写寿命通常在100万次以上,写入周期在几毫秒级别,非常适合"小数据+频繁改"的场景。但它的产能密度低、价格贵,做到几Mbit就顶天了。

NOR Flash则是按扇区擦除,典型扇区是4KB或64KB,擦除寿命通常标称10万次,读取速度快,支持XIP(片上执行),适合存固件。但它的擦除操作比EEPROM慢得多,一个4KB扇区擦除要几十到几百毫秒,而且对"频繁改写小数据"这件事很不友好——你改一个字节,也得先把整个扇区的数据搬到RAM、擦掉扇区、再写回去,这个开销在生产频繁参数修改的场景下不可接受。

至于SD卡,本质是一个带主控的小型NAND Flash存储系统,容量可以做到GB级,写速度可以到几十MB/s,内部还有磨损均衡算法。但它作为可移动设备,接口标准复杂,上电时序、卡识别、文件系统都有讲究。在工业环境里,SD卡的可靠性取决于主控芯片的质量和厂家的固件策略,劣质杂牌卡本身就是故障源。

这三兄弟放在一起,正好覆盖了容量、寿命、速度的三个极端。工业控制器的存储设计,本质就是数据特征和介质特性做匹配。

1.3 分级存储的总体架构

先给一张硬核的总览表,后面所有内容都围绕这张表展开:

存储介质典型容量写寿命典型写入粒度适合数据
EEPROM2Kb ~ 1Mb100万次以上字节/页配置参数、标定值、序列号
NOR Flash1MB ~ 64MB10万次扇区/页FPGA配置、固件镜像、备份
SD卡1GB以上取决于主控块/文件日志、历史数据、采集波形

这张表看起来简单,真正落地的时候,电路、时序、固件策略每一步都是坑。接下来我逐个拆解。

2. 选型逻辑:EEPROM、NOR Flash、SD 卡各自该扛什么活

2.1 EEPROM:小数据、高频改写、必须断电保持

EEPROM是我在早期项目中踩坑最少的介质,但也是被使用最不合理的介质。我见过有人拿一块4Mbit的EEPROM去存大量报文,原因只是"它支持字节写",这是完全用错了场景。

EEPROM的每个存储单元是浮栅晶体管,可以独立擦写,所以才有百万次级别的寿命。但百万次看起来多,如果设计时不做任何磨损保护,调试时频繁写同一个字节,几个月就会到寿命边界。我在实际项目中通常按下面几个原则来用:

  • 只在EEPROM里放"必须断电保持且经常变化"的数据,别拿它当普通RAM用
  • 用页写入而不是逐字节写。AT24C02的页是8字节,AT24C256的页是64字节,一次页写比多次单字节写更快,也减少总线交互
  • 参数区做成循环缓冲区,例如在EEPROM里划分256个参数槽,每次更新写下一个槽,写完一圈再循环,这样写入地址均匀分布,等效寿命可以提高上百倍

另一个容易忽视的点是EEPROM的写周期。I2C写操作发出命令后,从机需要几毫秒完成内部写入,这时候总线上表现为不响应ACK,主机必须正确处理这个时序。高速调试时,如果不等待写周期就发下一条命令,数据全部写飞。

2.2 NOR Flash:固件镜像和 FPGA 配置的家

NOR Flash在我的方案里定位非常明确:存FPGA比特流和固件备份。工业控制器采用FPGA后,通常有两种启动方式:一是FPGA自己主动从NOR Flash加载配置,这叫主动串行模式;二是由主控处理器把配置数据送进去,叫被动模式。我的方案是"主动串行为主+SPI在线升级为辅",既保证上电快速启动,又让STM32可以通过SPI接口升级FPGA。

选NOR Flash芯片时,有几个参数需要重点看:扇区擦除时间、页编程时间、擦写次数、供电电压范围、工作温度范围。工业级产品建议选-40℃到85℃甚至105℃的规格,商业级Flash在高温环境下容易出现擦写失败或者数据保持时间变短的问题。

另外,NOR Flash的读速度很快,很多需要XIP的场合选NOR而不是NAND。FPGA的配置数据从NOR里读,本质是一个顺序流,时序要求不算高,但对供电纹波和信号完整性有要求,这部分放到电路设计里细讲。

2.3 SD 卡:日志记录与数据导出的移动仓库

SD卡在工业控制器里的角色很特殊:技术上它是个可靠的存储介质,但在实际工程里,它更像"外设"而不是"存储器"。原因很简单:可拆卸、有标准文件系统、适合现场取证。

用SD卡做日志存储,需要注意几个点:

  • 板级可以用FATFS或者其他文件系统,日志文件定期轮转,比如按日生成、按大小回卷
  • 写入尽量用比较大的块。SD卡对连续大块写入友好,对随机小块写入很吃力,日志缓冲区至少要512字节以上,更建议4KB到32KB
  • 掉电保护:SD卡最怕写文件系统元数据时掉电,导致整个目录损坏。我通常会设计"日志文件先写到临时区,写完一个数据块后定期同步目录项",或者干脆用"分区循环写"的方式

选卡也是个学问。工业设备不要用消费级杂牌卡,廉价卡在振动、高温、频繁断电环境下,寿命和稳定性都很差。优先选工业级SLC卡,或者至少是大厂MLC的高耐久型号。

2.4 选型参数对照表

把三种介质放在一张表里,更直观:

属性EEPROMNOR FlashSD卡
接口I2C/SPISPI/QSPISDIO/SPI
典型容量2Kb ~ 4Mb4MB ~ 128MB4GB ~ 128GB
擦写单位字节/页扇区块/页
擦写寿命100万次以上10万次主控相关
读取速度慢(I2C)快快
写入速度慢中等快
温度范围通常 -40~85℃通常 -40~85/105℃商业/工业分档
掉电保护字节级原子写需注意扇区管理依赖文件系统
单位成本高(按bit计)中(按bit计)低(按bit计)

选型时先问自己三个问题:数据多大?多久改一次?掉电能不能接受丢一点?这三个问题的答案,基本会自然导向正确的介质。

3. STM32+FPGA 双芯架构下的存储分工与数据通路

3.1 为什么工业控制器爱用 STM32+FPGA 组合

STM32+FPGA不是炫技,而是工业控制器现实需求的结果。STM32这类MCU擅长跑协议栈、管理外设和做复杂逻辑判断,但IO数量、并行处理能力和实时性有限;FPGA擅长并行处理,一个周期内能完成高速计数、多路PWM输出、编码器解码、并行ADC采样这些任务。在电机控制、运动控制、视觉检测前处理这类场景,FPGA几乎是不可或缺的。

存储方案里双芯架构带来一个隐蔽的好处:可以把存储任务按"谁更合适"拆开。STM32管理与协议、参数、日志相关的存储,FPGA只管自己的配置启动。两者通过通用接口交互数据,存储层级天然分开,不用互相拖累。

3.2 存储资源分配方案:谁挂 EEPROM、谁挂 Flash

我给出一个经过验证的具体分配方案,供参考:

  • EEPROM(比如AT24C256,256Kbit=32KB):挂STM32的I2C2,存放设备参数、校准数据、运行状态字、精简版故障记录
  • NOR Flash(比如W25Q128,16MB):挂FPGA配置接口(AS模式)和STM32的SPI(升级时共享),存放FPGA比特流、STM32固件备份、出厂参数备份
  • SD卡(比如工业级32GB):挂STM32的SDIO接口(4bit模式),存放日志、报警、采集数据、配方文件、远程升级镜像

为什么EEPROM不挂在FPGA侧?因为FPGA对参数管理没有意义,FPGA只吃配置流。为什么SD卡不挂FPGA侧?因为文件系统本来就跑在STM32上,FPGA不跑OS,访问SD卡没有优势。

3.3 数据访问路径与总线仲裁

正常运行时的访问路径可以这样理解:

  1. 上电:FPGA主动从NOR Flash加载配置;STM32从内部Flash启动,同时读取EEPROM参数区做校验
  2. 运行:STM32周期性把缓存数据合并写入SD卡;用户修改参数时,STM32先写EEPROM做快速持久化
  3. 升级:STM32通过SPI写NOR Flash,用远程镜像覆盖升级区,然后触发FPGA软复位重新加载

这里最关键的坑是:STM32和FPGA都访问NOR Flash时,必须有仲裁机制。我的做法是:Flash的片选信号经过一个总线开关控制,STM32访问Flash时,先把FPGA侧的配置控制信号隔离或拉低,避免两个主机同时驱动SPI总线。

如果Flash始终挂在FPGA的配置引脚上,而STM32又要在线升级,就得考虑FPGA是否正在读配置。调试时可以在Flash的CS脚上加一个缓冲器,用STM32的GPIO控制使能,这个细节能在现场省很多事。

4. 关键电路设计与实操细节

4.1 EEPROM 的 I2C 电路:上拉、地址和 WP 引脚

EEPROM的电路看起来简单,问题都在细节上。以AT24C256为例,I2C接口需要:

  • I2C总线必须接上拉电阻,典型4.7kΩ。如果总线上挂的器件多或者走线长,可以降到2.2kΩ。我见过有人忘记加上拉,结果总线全是毛刺,通信随机失败
  • 地址引脚A0/A1/A2按需配置,AT24C256的地址是0x50到0x57。设计时最好留出跳线或0欧电阻焊盘,方便多板卡复用或者避开地址冲突
  • WP引脚接GPIO。正常工作时拉高,禁止写入;升级时拉低,允许写入。这能防止程序跑飞时意外改写参数,是工业可靠性的重要一环。

供电方面,如果EEPROM是3.3V供电,MCU也是3.3V,直接连没问题。如果MCU的IO是5V,就要加限流电阻或者做电平转换。工业现场5V的MCU并不少见,这个坑我也踩过。

4.2 NOR Flash 与 FPGA 配置电路:模式选择和在线升级

FPGA配置Flash的接线比较讲究。以SPI接口的NOR Flash为例,FPGA的配置引脚要对应Flash的MISO、MOSI、CS、SCLK。如果采用AS模式,FPGA内部会产生配置时钟,Flash的数据在时钟采样点被读取。

实际设计中有几个细节需要关注:

  • 配置时钟频率不要超过Flash的最高工作频率,FPGA配置时序的要求要查数据手册确认
  • Flash的WP#和HOLD#引脚要处理干净,上拉到VCC或者加RC,防止悬空导致误触发写保护或暂停
  • 如果STM32需要在线升级FPGA配置,Flash的CS就不能直接连FPGA的固定引脚,得用IO切换或者总线开关来控制

在线升级"烧到一半掉电"的问题是工业现场的噩梦。推荐做双镜像区:A区和B区各存一份合法比特流,升级时写B区并校验CRC,校验通过后切换启动标志,下次启动FPGA从B区加载。这样即使升级中途掉电,A区依然可用,设备不会变砖。

4.3 SD 卡接口设计:电平、走线和供电

SD卡的接口设计有几个容易翻车的地方:

  • 电平:标准SD卡接口是3.3V,主控IO也是3.3V时直接连接。如果主控是5V,必须电平转换
  • SDIO走线:4bit数据线加DCLK加CMD,数据线要求尽量等长,注意阻抗和驱动强度,过长的走线会导致高速模式初始化失败
  • 上拉电阻:CMD和数据线需要弱上拉,有些MCU内部带了,外部可以加10kΩ到47kΩ,保证卡在初始化阶段稳定
  • CD(卡检测)引脚和写保护开关:用GPIO读取,检测SD卡是否插入,避免在无卡时执行文件系统操作导致死机

还有一个很意外的坑:SD卡在大容量写入时,供电电流可以达到100mA以上。如果板子上用LDO直接给SD卡供电,瞬间压降可能拉低整个3.3V电压,需要加足够的滤波电容(10μF钽电容加100nF陶瓷),或者用独立电源单独给卡供电。

4.4 电源与掉电保护:掉电检测和储能电容

工业控制器掉电是常态,存储设计必须正视这件事。我的做法是在电源入口放置掉电检测电路:用电阻分压加比较器或者ADC监控24V母线,当电压低于某个阈值(比如18V)时触发一个PVD/EXTI中断。

掉电中断触发后,MCU的紧急任务只有一件:把RAM里的关键参数写入EEPROM,然后把日志缓存的尾部数据追加到SD卡,如果时间和电源还够。时间窗口大概只有几十到几百毫秒,取决于板子上储能电容的容量。

设计时可以用超级电容(0.5F到1F)在掉电后维持3.3V输出几百毫秒。EEPROM掉电写入的场景下,I2C速度400kHz,写128字节加等待写周期大约8到15ms,完全来得及。关键是初始化时就要规划好"紧急存储区",而不是掉电时再遍历RAM找数据。

5. 固件层的支撑策略:写入、校验和掉电恢复

5.1 写入策略与磨损均衡

硬件只是载体,固件策略才是可靠性的灵魂。EEPROM的磨损均衡,核心做法是"循环缓冲加版本号"。

具体实现思路:把EEPROM某个区域划分为N个槽位,每个槽位存一份参数副本加序列号加CRC。写入时找序列号最大的槽位的下一个槽位写,N个槽位循环使用。读取时遍历所有槽位,取序列号最大且CRC校验通过的那份。这样寿命可以扩大到N倍,而且天然支持回滚——如果最新槽位CRC出错,自动读取前一个。

可以用下面的结构体来组织参数槽:

typedef struct { uint8_t slot_id; // 槽位编号 uint32_t seq; // 写入序列号 uint16_t crc16; // 整槽校验 uint8_t param[64]; // 实际参数数据 } ParamSlot;

NOR Flash侧,双镜像方案也算是一种磨损均衡,因为升级率不高,寿命压力不大,但可靠性要求极高。

SD卡侧的磨损主要是文件策略问题:日志按日期分文件、限制单文件大小、定期清理旧数据。FATFS在嵌入式环境里最常见,如果日志量很大,也可以考虑底层的扇区级日志设计,但这个实现复杂度会上一个台阶。

5.2 数据完整性与双备份机制

存储的可靠性有一条铁律:单体数据不能作为唯一真值。参数区必须是双份甚至三份冗余,掉电保护的第一原则是"即使写坏了也不会丢旧数据"。

具体做法:

  • 参数区:双份冗余加CRC16校验,启动时对比两份,CRC不一致时以另一份为准,并自动修复损坏的那份
  • FPGA配置Flash:双镜像,启动标志区记录当前有效镜像号
  • SD卡日志:周期性fsync,确保关键记录落盘,对掉电丢失窗口设置一个容忍上限

我的经验是:校验一定要用CRC32而不是简单的求和。纯校验和在单字节翻转时可能漏检,工业现场电磁干扰很容易造成多位翻转。CRC32虽然计算量大一点,对MCU来说也就几毫秒的事,完全值得。

5.3 标准的掉电保护流程

一个标准掉电存储流程应该是这样的:

  1. 检测到电源跌落中断
  2. 关闭非必要外设中断,进入紧急存储模式
  3. 把参数缓存区的"脏数据"写入EEPROM紧急区
  4. 把日志缓冲区的尾部数据追加写入SD卡
  5. 电源完全断开前,所有外设进入低功耗或复位状态

这个过程里还要注意一个细节:掉电检测必须加迟滞,否则电源抖动会造成反复进入中断。比较器可以加迟滞电阻,MCU内部的PVD本身有滞回特性,这个要活用。

6. 现场问题排查:三块存储的常见故障实录

6.1 EEPROM 数据丢失和 I2C 卡死

故障一:参数写进去,重启后全丢。 排查思路:先查写入是否真的成功,读回验证;再查WP引脚是不是被拉高;最后查上拉电阻和总线时序。我遇到最多的情况其实是初始化顺序问题——写EEPROM时I2C外设还没完全就绪,代码把时序带错了。

故障二:写EEPROM死等。 典型原因是硬件上没有正确处理NACK响应,或者I2C总线被某个设备卡死。解决办法是给I2C访问加超时,并允许总线错误恢复,这让现场排查轻松很多。

6.2 NOR Flash 加载失败和升级变砖

故障一:FPGA上电后无法加载。 先量Flash供电和CS信号,看FPGA的状态引脚。再检查配置模式跳线是否和固件一致。用示波器抓配置时钟,确认FPGA确实在发起读取。

故障二:在线升级后FPGA加载失败。 多半是双镜像标志写错或者擦写中断。恢复手段是用独立烧录器重写,或者从备用区恢复到主区。我还遇到过Flash型号差异导致配置时序不匹配的情况,换回原型号就好了。

6.3 SD 卡挂载失败和日志损坏

故障一:初始化失败,提示"SD card not mount"。 先换一张卡测试,排除卡本身问题;再查供电电压和CD引脚检测;然后检查SDIO时钟频率是否过高,有些卡不支持高速模式,降低时钟频率往往能解决。

故障二:写入日志一段时间后文件损坏。 通常是文件系统在掉电时没有同步。可以增加掉电检测后主动同步的流程,或者每次写日志时小批量地同步目录项。如果还不能解决,就考虑预留冗余分区。

故障三:写入速度越来越慢。 可能原因包括用了SPI模式而不是SDIO模式、日志缓冲太小、或者卡本身写速不行。先用速度测试程序测一下卡的裸写速度,再做针对性优化。

6.4 常见故障速查表

最后整理一份速查表,方便现场排查:

现象可能原因排查动作
EEPROM数据重启丢失WP脚被拉高、上拉缺失检查WP控制、读回验证
I2C总线卡死从机无ACK、总线冲突加超时、查上拉电阻
FPGA无法配置Flash接线错误、模式引脚错误查配置引脚电平与时钟
升级后FPGA变砖双镜像标志错误、镜像CRC失败用烧录器重写、检查CRC
SD卡挂载失败供电不足、接触不良、时序不对换卡、量电压波形、降时钟
日志频繁损坏掉电未同步文件元数据增加fsync、加超级电容

做控制器这些年,我最大的体会是:存储方案的选择不是"哪个好"的问题,而是"哪个在你的可靠性预算内"的问题。EEPROM虽然寿命久,但你不做磨损均衡照样会挂;NOR Flash虽然稳定,但升级方案不做镜像一样会跪;SD卡容量大,但不管理文件系统掉电照样坏。硬件给了可能性,固件和策略兜底。

最后一个建议:如果你在设计初期就把存储分区做出来,调试阶段能省一半时间。别等样机出来了再补存储逻辑,那样你会像我当年一样,蹲在产线边上改代码改到怀疑人生。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询