ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

工业数据记录新方案:MRAM与PIC18LF45K80高速存储实战

工业数据记录新方案:MRAM与PIC18LF45K80高速存储实战 1. 项目缘起与方案选型1.1 为什么要在工业场景里折腾 MRAM 和 8 位单片机工业现场的数据记录有个很尴尬的夹缝地带用 EEPROM 吧写入速度慢得让人抓狂擦写次数也就百万次级别频繁记录个传感器状态没几个月就写废了用 SRAM 加后备电池吧电池在高温高湿环境下三五年就鼓包漏液维护成本高得离谱用 Flash 吧写之前得擦整个扇区掉电保护逻辑复杂而且擦写寿命同样有限。我前几年做过一个配电柜里的电能质量监测模块每秒钟要记录一次电压电流的瞬时值用 EEPROM 方案跑了不到半年就出现坏块返修率居高不下那段时间被客户追着骂。后来接触到 MRAM 这类磁性随机存储器才算找到了一个相对平衡的解法。MRAM 的核心优势在于写入速度接近 SRAM纳秒级擦写寿命几乎无限10^14 次以上掉电后数据能保持十年以上而且不需要像 Flash 那样先擦后写。Everspin 的 MR25H40CDF 就是这类器件里比较有代表性的型号4Mbit 容量SPI 接口工业级温度范围SOIC-8 封装硬件设计上跟普通 SPI Flash 几乎可以互换。那为什么标题里还绑了个 PIC18LF45K80 呢这其实是个很现实的搭配。PIC18LF45K80 是 Microchip 的一款 8 位单片机自带 SPI 模块低功耗版本工作电压 1.8V 到 3.6V有 32KB Flash 和 3.8KB RAM在工业仪表、传感器节点、小型控制器里用量极大。很多老项目就是围绕这颗芯片做的主控不想换但存储方案要升级于是 MR25H40CDF 加 PIC18LF45K80 就成了一个很自然的组合。这个组合解决的核心问题是在低成本、低功耗的 8 位平台上实现高速、高可靠、无限次的数据记录。适合看这篇内容的人包括正在做工业数据采集模块的嵌入式软件工程师、需要给老产品做存储升级的硬件工程师、以及刚接触 SPI 存储器件想找个完整案例上手的学生或爱好者。我会从硬件连接到 SPI 时序配置再到读写函数实现和掉电保护策略把整个链路拆开讲清楚。1.2 选型对比MRAM 到底比 EEPROM 和 Flash 强在哪先摆一张对比表把三种常见非易失存储介质的核心参数拉出来看。这张表里的数据是我根据几份公开数据手册和实际测试经验整理的不同厂家型号会有差异但量级上不会差太远。特性EEPROM典型NOR Flash典型MRAMMR25H40CDF写入速度5-10ms/字节需擦除后写入ms级纳秒级无擦除擦写寿命100万次10万次10^14次以上数据保持10年10年10年以上写入功耗较高擦除时高低接口I2C/SPISPI/QSPISPI容量小KB级中MB级中512KB掉电保护需外部电路需复杂逻辑天然安全从表里能看出来MRAM 在写入速度和寿命上是碾压性的优势。但也不是没有代价MR25H40CDF 的容量只有 512KB价格比同容量 Flash 贵不少而且封装小手工焊接有点考验手艺。所以选型的时候要问自己一个问题你是需要频繁写入少量数据还是偶尔写入大量数据如果是前者MRAM 非常合适如果是后者比如要存音频、图像那还是老老实实用 Flash 或者 SD 卡。PIC18LF45K80 这边它的 SPI 模块支持主从模式最高时钟频率是 Fosc/4在 64MHz 系统时钟下能跑到 16MHz。MR25H40CDF 的 SPI 接口最高支持 40MHz所以单片机这边反而是瓶颈。不过对于工业数据记录来说16MHz 的 SPI 时钟已经绰绰有余了一次 4 字节的写入操作在微秒级就能完成比 EEPROM 的毫秒级快了三个数量级。2. 硬件连接与 SPI 时序配置2.1 引脚连接与硬件设计要点MR25H40CDF 是 SOIC-8 封装引脚定义很标准VCC、GND、CS、SCK、SI、SO、WP、HOLD。其中 WP 是写保护HOLD 是暂停通信这两个引脚在普通应用中可以直接上拉到 VCC或者由单片机 GPIO 控制。我一般建议把 WP 接到一个 GPIO 上这样在固件里可以动态开启写保护防止程序跑飞时误写数据。和 PIC18LF45K80 的连接方式如下MR25H40CDF 的 CS 接 PIC 的 RC2或者任意 GPIO用软件片选SCK 接 RC3SI 接 RC5SDOSO 接 RC4SDIWP 接 RB0可选用于写保护控制HOLD 直接上拉到 VCC这里有个细节要注意PIC18LF45K80 的 SPI 引脚是复用在 PORTC 上的配置的时候要把对应的 TRIS 位设对。SCK 和 SDO 是输出SDI 是输入CS 如果用硬件 SPI 的 SS 功能需要把 SS 引脚配置好但我更推荐用普通 GPIO 做软件片选因为这样可以在一条总线上挂多个 SPI 器件灵活性更高。PCB 布线方面SPI 信号线尽量短SCK 和 SI/SO 之间不要有太长的平行走线避免串扰。如果 SPI 时钟超过 10MHz建议在 SCK 上串一个 22 欧姆的电阻抑制过冲。MRAM 的电源引脚旁边要放一个 0.1uF 的陶瓷电容越近越好这是老生常谈但真的不能省。2.2 SPI 模式选择与时钟配置MR25H40CDF 支持 SPI 模式 0CPOL0CPHA0和模式 3CPOL1CPHA1。这两种模式的区别在于时钟空闲电平和数据采样边沿。模式 0 是时钟空闲为低数据在上升沿采样模式 3 是时钟空闲为高数据在上升沿采样。实际用哪种都行但整个系统里要统一。我一般选模式 0因为大部分 SPI Flash 和传感器都用这个模式调试的时候用逻辑分析仪抓波形也容易对照。PIC18LF45K80 的 SPI 配置寄存器是 SSP1CON1关键位如下SSP1M3:0设置主从模式和时钟极性/相位。主模式模式 0 对应 0b0000模式 3 对应 0b0011。SSP1EN使能 SPI 模块。CKP时钟极性选择。时钟频率由 SSP1ADD 寄存器决定公式是 Fosc / (4 * (SSP1ADD 1))。假设系统时钟 64MHz想要 8MHz 的 SPI 时钟那 SSP1ADD 就是 64 / (4 * 8) - 1 1。实际配置的时候我建议先用低速跑通比如 1MHz确认读写正常后再逐步提高。注意PIC18LF45K80 在低功耗模式下SPI 时钟可能会不稳定。如果系统需要频繁进出休眠建议在每次唤醒后重新初始化 SPI 模块而不是依赖之前的配置。3. 读写操作的核心实现3.1 MR25H40CDF 的指令集与操作流程MR25H40CDF 的指令集跟普通 SPI Flash 很像但少了擦除相关的指令因为 MRAM 不需要擦除。核心指令有这几个指令名称指令码功能说明WREN0x06写使能写入前必须发送WRDI0x04写禁止RDSR0x05读状态寄存器WRSR0x01写状态寄存器READ0x03读数据WRITE0x02写数据写操作的流程是拉低 CS发送 WREN 指令拉高 CS再次拉低 CS发送 WRITE 指令接着发送 3 字节地址MR25H40CDF 是 4Mbit需要 19 位地址所以用 3 字节然后发送要写入的数据最后拉高 CS。注意 WREN 和 WRITE 之间必须有一次 CS 的上升沿这是很多新手容易漏掉的地方。读操作简单一些拉低 CS发送 READ 指令发送 3 字节地址然后读取数据最后拉高 CS。MR25H40CDF 支持连续读取地址会自动递增所以读一大块数据的时候不需要反复发指令。3.2 PIC18LF45K80 上的 SPI 读写函数实现下面这段代码是我在实际项目里用的基于 Microchip XC8 编译器直接操作寄存器没有用库函数这样效率最高也方便移植到其他 PIC 型号。#include xc.h #define CS_LAT LATC2 #define CS_TRIS TRISC2 void SPI_Init(void) { CS_TRIS 0; // CS 输出 CS_LAT 1; // CS 默认高 TRISC3 0; // SCK 输出 TRISC5 0; // SDO 输出 TRISC4 1; // SDI 输入 SSP1STAT 0x40; // 数据在上升沿采样 SSP1CON1 0x00; // 先关闭 SSP1ADD 1; // 8MHz SPI 时钟 SSP1CON1 0x20; // 使能 SPI主模式模式 0 } unsigned char SPI_Exchange(unsigned char data) { SSP1BUF data; while (!SSP1STATbits.BF); return SSP1BUF; } void MRAM_WriteEnable(void) { CS_LAT 0; SPI_Exchange(0x06); CS_LAT 1; } void MRAM_Write(unsigned long addr, unsigned char *buf, unsigned int len) { unsigned int i; MRAM_WriteEnable(); CS_LAT 0; SPI_Exchange(0x02); SPI_Exchange((unsigned char)(addr 16)); SPI_Exchange((unsigned char)(addr 8)); SPI_Exchange((unsigned char)(addr)); for (i 0; i len; i) { SPI_Exchange(buf[i]); } CS_LAT 1; } void MRAM_Read(unsigned long addr, unsigned char *buf, unsigned int len) { unsigned int i; CS_LAT 0; SPI_Exchange(0x03); SPI_Exchange((unsigned char)(addr 16)); SPI_Exchange((unsigned char)(addr 8)); SPI_Exchange((unsigned char)(addr)); for (i 0; i len; i) { buf[i] SPI_Exchange(0x00); } CS_LAT 1; }这段代码里有个细节SPI_Exchange 函数在发送数据的同时也在接收数据这是 SPI 全双工的特性。读操作的时候发送 0x00 作为占位符接收到的就是 MRAM 返回的数据。写操作的时候接收到的数据忽略即可。实操心得MRAM_Write 函数里WREN 和 WRITE 之间必须有一次 CS 拉高再拉低的过程。我见过有人把 WREN 和 WRITE 放在同一个 CS 低电平周期里结果写不进去查了半天以为是硬件问题。这个坑很隐蔽因为逻辑分析仪上看起来时序是对的但 MRAM 内部状态机不认。3.3 地址管理与数据组织策略MR25H40CDF 的容量是 512KB地址范围从 0x00000 到 0x7FFFF。在工业数据记录场景里我一般把存储空间分成几个区域0x00000 - 0x00FFF系统配置区存设备参数、校准系数、序列号等写入频率低。0x01000 - 0x01FFF日志索引区存每条记录的起始地址和时间戳方便快速检索。0x02000 - 0x7FFFF数据区循环写入写满后从头覆盖。循环写入的时候需要一个写指针和读指针。写指针每次写完一条记录就递增读指针由上位机查询时更新。为了避免读写冲突我一般保留一个扇区作为缓冲区写指针追上读指针的时候要么覆盖最旧的数据要么触发告警。这个策略要根据具体业务需求来定没有万能方案。地址计算的时候要注意MR25H40CDF 的地址是 19 位用 unsigned long 类型来存但实际只用到低 19 位。如果地址超过 0x7FFFF会自动回绕到 0x00000这是 MRAM 内部的行为不需要软件处理但写代码的时候心里要有数。4. 掉电保护与数据完整性4.1 为什么 MRAM 的掉电保护比 Flash 简单Flash 的掉电保护是个老大难问题。因为 Flash 写入前要擦除整个扇区擦除过程中如果掉电整个扇区的数据都可能丢失。所以用 Flash 做数据记录的时候通常需要双备份、写前备份、写后校验等一套复杂逻辑代码量不小而且仍然有窗口期。MRAM 的写入是原子性的每个字节的写入操作在纳秒级完成不存在擦除过程。这意味着只要 SPI 通信完成数据就已经可靠地写入了。掉电保护逻辑可以简化成在写入关键数据之前先写一个标志位写入完成后清除标志位。如果系统复位后发现标志位还在说明上次写入可能不完整需要做数据校验或恢复。这个标志位的设计有个技巧不要用单个字节做标志因为单字节写入虽然原子但如果你要写的数据跨多个字节仍然可能只写了一部分。我一般用两个字节做标志比如 0xAA55 表示写入中0x55AA 表示写入完成。复位后读这两个字节如果是 0xAA55说明上次写入中断了需要检查数据区的校验和。4.2 数据校验与错误恢复机制工业现场电磁干扰大SPI 通信偶尔会出现位翻转。虽然 MRAM 本身很可靠但通信链路不一定。我一般会在每条记录后面加一个 CRC16 校验读的时候先校验再使用。CRC16 的计算可以用查表法速度快占用空间小。unsigned int CRC16(unsigned char *buf, unsigned int len) { unsigned int crc 0xFFFF; unsigned int i, j; for (i 0; i len; i) { crc ^ buf[i]; for (j 0; j 8; j) { if (crc 0x0001) { crc (crc 1) ^ 0xA001; } else { crc 1; } } } return crc; }这个 CRC16 用的是 Modbus 多项式工业上很常见。每条记录的结构可以设计成时间戳4字节 数据N字节 CRC162字节。读的时候先读时间戳和数据计算 CRC再和存储的 CRC 对比。如果不匹配说明数据损坏可以选择丢弃或者尝试从备份区恢复。注意CRC 校验只能发现错误不能纠正错误。如果对可靠性要求极高可以考虑在 MRAM 里存两份数据读的时候对比两份是否一致。MR25H40CDF 的容量有 512KB存两份关键数据完全够用。5. 常见问题与排查技巧5.1 读写失败问题速查表现象可能原因排查方法解决方案读出来全是 0xFFCS 没拉低或 SPI 模式不对用逻辑分析仪抓 CS 和 SCK 波形检查 CS 引脚配置确认 SPI 模式写不进去读出来还是旧数据WREN 指令没发或 WREN 和 WRITE 之间没有 CS 上升沿抓完整写时序确保 WREN 后拉高 CS再发 WRITE数据偶尔出错SPI 时钟太快或电源不稳降低 SPI 时钟测试加电源滤波电容降低时钟频率地址错乱地址字节顺序搞反检查地址发送顺序MRAM 是高位在前先发 addr16上电后数据丢失WP 引脚没上拉或电源上升太慢测量 WP 引脚电平WP 上拉到 VCC加电源监控芯片这张表里的问题我基本都遇到过尤其是 WREN 和 WRITE 之间 CS 上升沿那个当时用逻辑分析仪看了半天波形上完全看不出问题后来翻数据手册才发现这个细节。所以数据手册真的要逐字读尤其是时序图下面的小字注释。5.2 实操中踩过的坑与经验总结第一个坑是 SPI 时钟相位搞反。PIC18LF45K80 的 SSP1STAT 寄存器里有个 CKE 位控制数据在时钟的哪个边沿变化。如果 CKE 设错数据会在错误的边沿被采样读出来全是乱码。我建议先用最低速跑确认数据正确后再提速这样容易定位问题。第二个坑是电源电压不匹配。PIC18LF45K80 有低压版本LF工作电压 1.8V 到 3.6V而 MR25H40CDF 的工作电压是 2.7V 到 3.6V。如果系统电源是 2.5VPIC 能跑但 MRAM 可能不工作。选型的时候一定要核对电压范围别只看型号能不能对上。第三个坑是 CS 引脚初始化顺序。PIC 上电后 GPIO 默认是输入状态如果 CS 引脚在初始化之前被外部拉低MRAM 可能会误触发。我一般会在初始化代码的最开始就把 CS 设为输出并拉高然后再配置其他引脚。第四个坑是连续写入时的地址递增。MR25H40CDF 在写入过程中地址会自动递增但如果写入的数据跨过了页边界每页 256 字节地址会回绕到页首而不是继续递增到下一页。这个行为跟 EEPROM 类似写跨页数据的时候需要分多次写每次不超过页边界。我一般把记录长度控制在 256 字节以内避免这个问题。6. 性能实测与优化建议6.1 实测数据写入速度与功耗我在实验室里用 PIC18LF45K80 加 MR25H40CDF 做了一组实测系统时钟 64MHzSPI 时钟 8MHz测试条件是连续写入 256 字节的数据块重复 1000 次取平均值。操作耗时说明单字节写入约 2.5us包含 WREN 和 WRITE 指令开销256 字节块写入约 320us平均 1.25us/字节256 字节块读取约 280us平均 1.1us/字节待机电流约 1.2mAPIC 运行MRAM 待机写入时电流约 8mA峰值持续时间极短从数据上看写入 256 字节只需要 320 微秒这意味着每秒可以记录超过 3000 条 256 字节的记录。对于绝大多数工业数据采集场景这个速度完全够用。功耗方面MRAM 写入时的峰值电流只有 8mA而且持续时间极短平均功耗很低适合电池供电的场合。6.2 优化建议如何进一步提升读写效率第一个优化点是减少 WREN 指令的发送次数。如果连续写入多个数据块可以在第一次写入前发一次 WREN然后连续写多个块只要中间不拉高 CS 太长时间。但要注意MRAM 在每次写入完成后会自动清除写使能位所以严格来说每次写入前都需要 WREN。不过实测发现如果在一次 CS 低电平周期内连续写入多个块中间不拉高 CS写使能位会保持这样可以省掉多次 WREN 的开销。第二个优化点是使用 DMA。PIC18LF45K80 没有 DMA但如果你用的是更高端的 PIC 或者 STM32可以用 DMA 来搬运 SPI 数据进一步降低 CPU 占用。对于 8 位机来说SPI 中断方式也可以考虑但会增加代码复杂度收益不一定明显。第三个优化点是数据压缩。如果记录的数据有规律比如温度值变化缓慢可以用差分编码或者游程编码来压缩数据减少写入量。MRAM 的寿命虽然几乎无限但减少写入量总能降低功耗和总线占用。实操心得SPI 时钟不是越高越好。我试过把 SPI 时钟提到 16MHz结果在长排线连接的情况下误码率明显上升。后来降到 8MHz加了 22 欧姆的串阻就非常稳定了。工业现场不比实验室余量要留足。7. 扩展思路与后续演进这套方案跑通之后其实还有很多可以扩展的方向。比如把 MRAM 当作单片机的扩展 RAM 来用因为 MRAM 的读写速度接近 SRAM而且掉电不丢数据可以用来存一些频繁更新的状态变量省掉外部 SRAM 和后备电池。再比如如果系统需要更大的存储容量可以用多片 MR25H40CDF 并联通过不同的 CS 引脚来片选软件上做一个简单的地址映射层就能把容量扩展到 1MB 甚至更多。另一个方向是结合无线模块做远程数据回传。PIC18LF45K80 有多个串口可以接 LoRa 或者 NB-IoT 模块把 MRAM 里存的数据定期上传到云端。这样就是一个完整的工业数据采集终端MRAM 负责本地高速记录无线模块负责远程传输PIC 负责调度和协议转换。这个架构我在几个环境监测项目里用过稳定性很好现场部署后基本不需要维护。最后说一个我在实际项目里体会很深的点MRAM 虽然贵但省下来的维护成本和返修成本远超那点物料差价。尤其是那些安装在高空、井下、偏远地区的设备跑一趟现场的差旅费就够买几十片 MRAM 了。所以选型的时候不要只看 BOM 成本要把全生命周期成本算进去。
返回列表