ARTICLE DETAIL

资讯详情

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

MRAM与PIC18F96J65工业嵌入式存储方案:SPI驱动、掉电保护与性能优化

MRAM与PIC18F96J65工业嵌入式存储方案:SPI驱动、掉电保护与性能优化 1. 为什么MRAM加PIC18的组合值得单独拿出来讲做工业嵌入式的人大概都有过这种体验设备装在现场断电重启之后关键参数丢了或者日志写到一半掉电整条记录变成乱码。用EEPROM吧写入速度慢得让人着急擦写寿命也就百万次级别高频采集场景下没几个月就写废了用SRAM加后备电池吧电池本身就是个隐患高温环境下两三年就得换维护成本高得离谱用Flash吧写之前还得擦整个扇区掉电保护逻辑写起来头大。MR25H40CDF这颗器件就是冲着这些痛点来的。它是Everspin出品的一款4Mbit512K×8串行MRAM走SPI接口和传统的SPI Flash、SPI EEPROM在引脚上高度兼容但底层存储机理完全不同——磁阻式存储写入不需要擦除字节级随机写写入速度可以跑到几十纳秒量级理论擦写次数是无限的官方给的 endurance 是 10^14 次以上实际上你根本写不到那个量级。工作温度覆盖工业级-40到85℃部分批次能到105℃这对工业现场来说非常关键。PIC18F96J65则是Microchip PIC18家族里比较能打的一颗8位MCU96KB Flash、3.8KB RAM、带以太网MAC、带SPI/I2C/USART一应俱全100脚TQFP封装在工业控制、数据采集、通信网关这类场景里出镜率很高。它内置的MSSP模块支持SPI主从模式配合MR25H40CDF做数据存储是一个非常典型的低成本、高可靠、掉电安全的嵌入式存储方案。这套组合适合谁看如果你正在做工业仪表、数据记录仪、PLC扩展模块、电力监测终端、医疗设备参数存储这类项目需要在没有文件系统、没有操作系统、甚至没有RTOS的裸机环境下可靠地保存配置参数、校准系数、运行日志、故障记录那这套方案基本可以直接抄作业。如果你用的是STM32、GD32、ESP32底层逻辑也是通的SPI时序和命令集是通用的换个HAL库照样跑。我下面会从方案选型、硬件连接、SPI时序、驱动实现、掉电保护、常见坑这几个维度把整套东西拆开讲清楚。所有代码基于PIC18F96J65的XC8编译器环境但思路对任何MCU都适用。2. 方案整体设计与选型思路拆解2.1 为什么是MRAM而不是EEPROM或FRAM先把这个为什么讲透不然选型就是拍脑袋。工业嵌入式存储的需求可以归纳成四条掉电不丢、写入要快、寿命要长、接口要简单。EEPROM掉电不丢、接口简单但写入慢典型5ms一个字节的页写周期、寿命有限100万次FRAM掉电不丢、写入快、寿命高但容量普遍偏小、价格偏高而且很多FRAM对时序要求比较刁钻NOR Flash容量大、便宜但写入前必须擦除、擦写寿命只有10万次左右、写入速度也一般。MR25H40CDF的定位正好卡在中间4Mbit容量对参数存储和中等规模日志足够用SPI接口和Flash完全兼容写入不需要擦除、字节级可写、写入周期没有延迟不像EEPROM写完要等内部编程完成寿命几乎无限。代价是单价确实比同容量Flash贵但对于工业设备来说这颗料省下来的掉电保护逻辑开发时间和现场故障率远比那点BOM成本值钱。我个人的经验是如果单台设备的存储写入频率超过每天1000次或者对掉电瞬间的数据完整性有硬要求MRAM就是比EEPROM更省心的选择。如果只是存个设备序列号、出厂日期这种一年写不了几次的东西那EEPROM足够了没必要上MRAM。2.2 PIC18F96J65的MSSP模块能力评估PIC18F96J65内部有两个MSSPMaster Synchronous Serial Port模块都可以配置成SPI模式。SPI模式支持主机和从机主机模式下时钟由MCU产生支持四种SPI模式CPOL/CPHA组合波特率通过SSPADD寄存器分频得到。这里有个关键点PIC18的SPI主机时钟计算公式是 Fosc / (4 × (SSPADD 1))注意是4倍分频起步不是2倍。比如你系统时钟跑40MHzPIC18F96J65用外部晶振加PLL可以到40MHz想要10MHz的SPI时钟SSPADD要设成0得到40/(4×1)10MHz。想要5MHzSSPADD设成1得到40/(4×2)5MHz。这个公式很多人第一次用会算错以为和STM32一样是2分频起步。MR25H40CDF的SPI时钟最高支持40MHz读操作写操作最高也是40MHz所以PIC18在40MHz系统时钟下能跑到的10MHz SPI时钟完全够用甚至还有余量。如果你对速度要求不高跑2.5MHz或5MHz更稳PCB走线不好的时候能减少误码。2.3 硬件连接方案与片选策略MR25H40CDF是8脚SOIC封装引脚定义很标准CS、SO、SI、SCK、VDD、VSS、WP、HOLD。其中WP是写保护HOLD是通信暂停这两个脚如果不用可以直接拉高VDD但工业环境建议WP接一个GPIO或者直接接VDD并通过软件命令做写保护HOLD一般直接拉高就行。和PIC18F96J65的连接方式MR25H40CDF引脚PIC18F96J65引脚说明CS任意GPIO如RC2片选低有效SOSDI如RC4主机输入从机输出SISDO如RC5主机输出从机输入SCKSCK如RC3时钟WPVDD或GPIO写保护HOLDVDD暂停控制不用就拉高VDD3.3V电源VSSGND地关于片选这里要展开讲一下。SPI协议里片选分硬件片选和软件片选两种。硬件片选是MCU的SPI外设自动控制CS引脚软件片选是用普通GPIO手动拉低拉高。PIC18的MSSP模块在主机模式下不自动控制CS所以必须用软件片选——也就是把CS配成一个普通输出GPIO在每次SPI事务开始前拉低结束后拉高。注意软件片选虽然灵活但必须保证CS拉低到第一个SCK边沿之间有足够的建立时间。MR25H40CDF要求CS建立时间最小5nsPIC18在40MHz下一条指令周期是100ns所以只要在拉低CS之后至少执行一条NOP或者一条无关指令再操作SSPBUF时序就绰绰有余。我见过有人在CS拉低后立即写SSPBUF结果在某些编译优化等级下指令重排导致CS还没稳定时钟就出来了读回来全是0xFF。加一条NOP最保险。另外如果总线上挂多个SPI从设备每个设备一个独立CS不用的设备CS必须拉高否则会干扰总线。这一点在工业多从机场景里特别容易翻车。3. MR25H40CDF的核心命令集与时序细节3.1 命令集速查与操作码解析MR25H40CDF的命令集和标准SPI Flash非常像但少了擦除相关的命令多了MRAM特有的东西。核心命令如下命令名称操作码功能说明WREN0x06写使能写操作前必须发WRDI0x04写禁止RDSR0x05读状态寄存器WRSR0x01写状态寄存器READ0x03读数据WRITE0x02写数据RDID0x9F读器件ID状态寄存器里最关键的是WEL位bit1和BP0/BP1位bit2/bit3。WEL是写使能锁存每次写操作前发WREN会把它置1写操作完成后自动清零。BP0/BP1是块保护位可以保护部分地址区域不被写入工业场景里可以用它来保护固件区或标定区。RDID命令返回的器件IDMR25H40CDF应该是0x18开头厂商代码后面跟容量代码。具体值建议实测确认因为不同批次可能有细微差异不要死记硬背网上的值。3.2 读时序从CS拉低到数据输出的完整过程读操作是这套方案里最基础也最频繁的动作。完整时序是这样的CS拉低发送READ命令0x03发送24位地址MR25H40CDF是4Mbit需要19位地址但协议上按24位发高5位忽略从SO引脚逐位读回数据每个SCK上升沿或下降沿取决于SPI模式输出一位数据可以连续读地址自动递增直到CS拉高MR25H40CDF支持的最高读时钟是40MHz但实际能跑多快取决于你的PCB走线质量和MCU的SPI能力。PIC18在40MHz系统时钟下SPI最高10MHz这个速度下读512字节大概需要400多微秒完全够用。实操心得连续读的时候地址会自动回卷到0x00000。也就是说如果你从0x7FFFF开始读读完最后一个字节后会自动回到0x00000继续。这个特性在做环形日志缓冲的时候特别好用不需要软件判断边界硬件自动帮你回卷。但要注意如果你不想回卷就得自己控制读取长度。3.3 写时序为什么MRAM不需要等待写操作的时序和读类似但有几个关键差异CS拉低发送WREN命令0x06然后CS拉高WREN是一个独立事务CS再次拉低发送WRITE命令0x02发送24位地址发送要写入的数据字节CS拉高写入完成注意WREN必须作为一个独立的事务完成也就是CS拉低-发WREN-CS拉高然后再开始写事务。我见过有人把WREN和WRITE连在一起发中间不拉高CS结果写不进去。虽然有些Flash允许这样但MR25H40CDF的数据手册明确要求WREN是独立事务不要图省事。MRAM最大的优势在这里体现写完最后一个字节CS拉高之后数据就已经真正写进存储单元了不需要像EEPROM那样等待内部编程周期典型5ms也不需要像Flash那样等待擦除和编程。你可以立即发起下一次读操作读回来的就是新数据。这个特性对高频数据记录场景来说是质变——EEPROM每写一个字节要等5ms一秒最多写200个字节MRAM可以连续写SPI时钟多快就能写多快10MHz下每秒能写超过100万字节。3.4 SPI模式选择与CPOL/CPHA配置MR25H40CDF支持SPI模式0CPOL0CPHA0和模式3CPOL1CPHA1。这两种模式的区别在于时钟空闲电平和采样边沿。模式0SCK空闲为低数据在SCK上升沿采样下降沿输出。 模式3SCK空闲为高数据在SCK下降沿采样上升沿输出。PIC18的SSPCON寄存器里CKP位控制时钟极性CKE位控制采样边沿。配置成模式0就是CKP0、CKE0或者根据具体数据手册的位定义调整。我一般用模式0因为这是最通用的大部分SPI从设备都支持。注意SPI模式配错是最常见的读回来全是0xFF或0x00的原因。如果你发现读ID都不对第一件事就是检查CPOL/CPHA配置。用逻辑分析仪抓一下SCK和SI/SO的波形对照数据手册的时序图一眼就能看出来。4. 基于PIC18F96J65的驱动实现与实操步骤4.1 底层SPI字节收发函数一切从最基础的字节收发开始。PIC18的MSSP模块在主机模式下写SSPBUF就启动一次发送同时接收到的数据会放进SSPBUF。所以收发是同一个动作。#include xc.h // 假设系统时钟40MHzSPI时钟10MHz // SSPADD 0 时Fosc/(4*(01)) 10MHz void SPI_Init(void) { // 配置SCK(RC3)、SDO(RC5)为输出SDI(RC4)为输入 TRISCbits.TRISC3 0; // SCK output TRISCbits.TRISC4 1; // SDI input TRISCbits.TRISC5 0; // SDO output TRISCbits.TRISC2 0; // CS output CS_MRAM 1; // 片选拉高空闲状态 SSPCON1 0x20; // SSPEN1, CKP0, SPI Master mode Fosc/4 SSPCON2 0x00; // 无特殊配置 SSPSTAT 0x00; // CKE0, 模式0 SSPADD 0; // 10MHz 40MHz Fosc } unsigned char SPI_ExchangeByte(unsigned char data) { SSPBUF data; while(!SSPIF); // 等待传输完成 SSPIF 0; // 清标志 return SSPBUF; // 返回接收到的数据 }这段代码里有个细节SSPIF标志必须在每次传输后手动清零否则下一次while会直接跳过。另外SSPBUF在写入后如果上一次的数据还没被读走会导致写冲突WCOL位被置1所以每次传输完必须把SSPBUF读走。上面的代码通过return SSPBUF保证了这一点。4.2 MRAM读写驱动封装有了字节收发函数就可以封装MRAM的读写操作了。#define CMD_WREN 0x06 #define CMD_WRDI 0x04 #define CMD_RDSR 0x05 #define CMD_WRSR 0x01 #define CMD_READ 0x03 #define CMD_WRITE 0x02 #define CMD_RDID 0x9F void MRAM_WriteEnable(void) { CS_MRAM 0; __delay_us(1); // 保证CS建立时间 SPI_ExchangeByte(CMD_WREN); CS_MRAM 1; } unsigned char MRAM_ReadStatus(void) { unsigned char status; CS_MRAM 0; __delay_us(1); SPI_ExchangeByte(CMD_RDSR); status SPI_ExchangeByte(0xFF); CS_MRAM 1; return status; } void MRAM_WriteByte(unsigned long addr, unsigned char data) { MRAM_WriteEnable(); CS_MRAM 0; __delay_us(1); SPI_ExchangeByte(CMD_WRITE); SPI_ExchangeByte((addr 16) 0xFF); SPI_ExchangeByte((addr 8) 0xFF); SPI_ExchangeByte(addr 0xFF); SPI_ExchangeByte(data); CS_MRAM 1; } unsigned char MRAM_ReadByte(unsigned long addr) { unsigned char data; CS_MRAM 0; __delay_us(1); SPI_ExchangeByte(CMD_READ); SPI_ExchangeByte((addr 16) 0xFF); SPI_ExchangeByte((addr 8) 0xFF); SPI_ExchangeByte(addr 0xFF); data SPI_ExchangeByte(0xFF); CS_MRAM 1; return data; } void MRAM_WriteBuffer(unsigned long addr, unsigned char *buf, unsigned int len) { unsigned int i; MRAM_WriteEnable(); CS_MRAM 0; __delay_us(1); SPI_ExchangeByte(CMD_WRITE); SPI_ExchangeByte((addr 16) 0xFF); SPI_ExchangeByte((addr 8) 0xFF); SPI_ExchangeByte(addr 0xFF); for(i 0; i len; i) { SPI_ExchangeByte(buf[i]); } CS_MRAM 1; } void MRAM_ReadBuffer(unsigned long addr, unsigned char *buf, unsigned int len) { unsigned int i; CS_MRAM 0; __delay_us(1); SPI_ExchangeByte(CMD_READ); SPI_ExchangeByte((addr 16) 0xFF); SPI_ExchangeByte((addr 8) 0xFF); SPI_ExchangeByte(addr 0xFF); for(i 0; i len; i) { buf[i] SPI_ExchangeByte(0xFF); } CS_MRAM 1; }这套代码可以直接用但有几个地方值得优化。第一__delay_us(1)在每次事务里都加会累积成可观的延迟。如果SPI时钟是10MHz一个字节传输0.8微秒加1微秒延迟相当于速度减半。实际测试下来PIC18在40MHz下CS拉低后直接操作SSPBUF时序也是够的因为写SSPBUF到SCK真正输出之间至少有一个指令周期的延迟。所以这个delay可以去掉或者改成一条NOP。我保留它是因为在低优化等级下更保险你可以根据实际情况调整。第二批量写的时候WREN只需要发一次后面连续写多个字节都在同一个WRITE事务里完成地址自动递增。上面的MRAM_WriteBuffer就是这么做的效率比逐字节写高得多。4.3 器件ID读取与自检流程上电之后第一件事应该是读器件ID确认MRAM在线且通信正常。unsigned char MRAM_ReadID(void) { unsigned char id; CS_MRAM 0; __delay_us(1); SPI_ExchangeByte(CMD_RDID); id SPI_ExchangeByte(0xFF); CS_MRAM 1; return id; } // 自检 void MRAM_SelfTest(void) { unsigned char id MRAM_ReadID(); if(id ! 0x18) // 预期厂商代码 { // 通信异常点亮故障灯或记录错误 ERROR_LED 1; } // 写读回环测试 unsigned long testAddr 0x7FFF0; // 用最后一个扇区做测试 unsigned char testData 0xA5; MRAM_WriteByte(testAddr, testData); unsigned char readBack MRAM_ReadByte(testAddr); if(readBack ! testData) { ERROR_LED 1; } }自检地址选在存储区末尾避免覆盖实际数据。写读回环测试是验证SPI通信和MRAM读写功能的最直接方法。如果ID读不对先查硬件如果ID对但回环失败查时序和写使能逻辑。4.4 参数存储区的地址规划4Mbit等于512KB地址范围0x00000到0x7FFFF。实际项目里不会全部用完需要做地址规划。我一般这样分地址范围用途大小0x00000 - 0x00FFF设备信息区序列号、型号、出厂日期4KB0x01000 - 0x01FFF配置参数区校准系数、通信参数4KB0x02000 - 0x02FFF配置参数备份区4KB0x03000 - 0x7EFFF运行日志环形缓冲区约500KB0x7F000 - 0x7FFFF保留/自检区4KB配置参数做双备份是工业设备的基本操作。写入的时候先写主区读回校验再写备份区。读取的时候先读主区校验失败读备份区。这样即使写入过程中掉电导致主区损坏备份区还能救回来。日志区用环形缓冲写指针存在MRAM的固定位置比如0x00FF0每次写日志前先读指针写完更新指针。因为MRAM写入不需要等待这个流程可以做得很快不会阻塞主循环。5. 掉电保护与数据完整性设计5.1 为什么MRAM的掉电保护逻辑比EEPROM简单EEPROM写一个字节需要5ms的内部编程时间这5ms内如果掉电这个字节可能写了一半数据就坏了。所以用EEPROM做掉电保护必须加储能电容保证掉电后MCU还能撑够5ms完成写入或者用双备份加校验的方式。MRAM没有这个问题。写入是纳秒级的CS拉高那一刻数据就已经在存储单元里了。只要你的SPI事务在掉电前完成数据就是完整的。掉电保护的重点从保证写完变成了保证事务原子性——也就是一个多字节的数据结构要么全写进去要么全不写。实现事务原子性的常用方法是影子页提交标志先把新数据写到影子区写完后在提交标志位置写一个魔数然后更新主区数据最后清除提交标志。上电时检查提交标志如果标志存在说明上次写入中断了需要用影子区数据恢复主区。5.2 电源监测与写入时机控制PIC18F96J65内部有HLVD高/低电压检测模块可以设置一个电压阈值当VDD低于阈值时产生中断。这个功能配合MRAM可以做很精细的掉电保护。思路是这样的正常工作时VDD是3.3VHLVD阈值设成2.9V。当电源开始下降VDD跌到2.9V时触发HLVD中断在中断里立即停止所有非关键任务把当前需要保存的关键数据通过SPI写入MRAM。因为MRAM写入极快只要电源从2.9V跌到MCU最低工作电压PIC18F96J65是2.0V的时间足够完成几次SPI事务就行。假设电源下降斜率是1V/ms从2.9V到2.0V有0.9ms10MHz SPI下能传上千字节足够保存关键参数了。实操心得HLVD中断里不要做复杂运算只做最必要的SPI写入。中断服务程序越短越好。我一般会在主循环里维护一个待保存数据的副本HLVD中断触发时直接把这个副本写进MRAM不做任何格式转换。5.3 数据校验与坏块管理MRAM虽然寿命近乎无限但工业环境的电磁干扰、电源波动、极端温度都可能导致位翻转。所以关键数据必须加校验。最简单的是CRC16或CRC32每个数据块后面跟4字节CRC。读取时先算CRC再比对不匹配就用备份区数据。MRAM不需要像Flash那样做坏块管理因为不存在擦除磨损。但如果检测到某个地址反复读写失败可以在软件层标记该区域为不可用把数据迁移到保留区。这种情况极少发生但工业设备讲究的是万一。5.4 写保护机制的软硬件配合MR25H40CDF的WP引脚是硬件写保护低电平有效。正常工作时WP拉高允许写入。如果系统检测到异常比如电压不稳、温度超标可以把WP拉低禁止所有写入操作防止数据被破坏。软件层面状态寄存器的BP0/BP1位可以保护地址空间的上半部分或全部。我一般把固件参数区设成受保护日志区不保护。这样即使程序跑飞误写也不会破坏关键参数。注意修改BP位本身也需要先发WREN而且修改后需要一定时间生效。不要在中断里频繁改BP位容易出问题。6. 常见问题排查与避坑经验实录6.1 读回来全是0xFF或0x00这是最高频的问题没有之一。排查顺序如下现象可能原因排查方法读ID返回0xFFMISO没接、CS没拉低、SPI模式错万用表测通断逻辑分析仪抓波形读ID返回0x00时钟没输出、MOSI没接、从机没供电测SCK有无波形测VDD读ID对但读数据错地址发送错误、时序临界降低SPI时钟试试写进去读出来不对WREN没发或不是独立事务检查WREN和WRITE之间CS是否拉高我踩过最坑的一次是CS引脚配置成了输入结果软件拉低拉高根本没效果CS一直悬空读回来全是0xFF。查了半天代码最后用万用表一测才发现TRIS配错了。所以硬件排查永远先于软件排查。6.2 写入成功但重启后数据丢失这种情况通常是写入了但没写对地方或者读的时候地址算错了。检查地址计算有没有溢出——MR25H40CDF是19位地址如果你用16位变量存地址超过0xFFFF的部分就丢了。我建议地址变量统一用unsigned long32位虽然浪费一点但不会出错。还有一种可能是写保护没解除。检查状态寄存器的BP位和WEL位。WEL在每次写操作后自动清零所以每次写之前都要重新发WREN。如果你连续写多个数据块每个块之前都要发WREN不能只发一次。6.3 SPI时钟太快导致偶发误码10MHz SPI在洞洞板或飞线上跑很容易出问题。如果你发现大部分时候正常偶尔读回一个字节不对大概率是信号完整性问题。解决方法降低SPI时钟到5MHz或2.5MHz缩短SPI走线在SCK和MOSI上串22欧姆电阻确保地平面完整。工业现场还有电磁干扰的问题。如果设备附近有大功率变频器、继电器、接触器SPI通信可能被干扰。除了降低时钟和加电阻还可以在CS、SCK、MOSI上加大到100nF的对地电容注意电容太大会影响时序要实测。MRAM本身对干扰不敏感因为存储单元是磁性的但SPI接口是电信号该做的防护不能省。6.4 多从机场景下的片选冲突如果SPI总线上挂了多个从机每个从机的CS必须独立控制不通信的从机CS必须拉高。我见过有人把两个从机的CS接在一起结果两个从机同时响应数据总线打架读回来全是乱码。另外如果从机支持HOLD功能不用的HOLD脚一定要拉高悬空会导致从机进入不确定状态。MR25H40CDF的HOLD脚内部有弱上拉但工业环境建议外部再加一个10K上拉到VDD。6.5 上电初始化顺序的坑MR25H40CDF上电后需要一定时间稳定数据手册给的是VDD达到最低工作电压后100微秒左右。如果你上电后立即发命令可能器件还没准备好读回来是错的。稳妥的做法是上电后延时1毫秒再初始化SPI和MRAM。PIC18F96J65这边MSSP模块的初始化要在配置好TRIS和系统时钟之后。如果系统时钟用了PLL要等PLL锁定OSCCON的IOFS或OSTS位再初始化SPI否则SPI时钟频率不对通信也会失败。6.6 常见问题速查表问题排查方向快速验证通信完全不通供电、CS、SCK、SPI模式读ID写不进去WREN、WP引脚、BP位读状态寄存器数据偶发错误SPI时钟、走线、干扰降时钟测试重启丢数据地址计算、写保护、电源写读回环多从机冲突CS独立性、HOLD引脚逐个从机单独测试7. 性能实测与优化建议7.1 实测数据参考我在40MHz系统时钟、10MHz SPI时钟下做过实测操作耗时说明单字节读约4微秒含CS开销和命令地址单字节写约5微秒含WREN独立事务256字节连续读约220微秒地址自动递增256字节连续写约230微秒含WREN1KB连续写约850微秒批量写效率更高对比同容量SPI EEPROM单字节写通常需要5-10毫秒含内部编程等待MRAM快了三个数量级。这意味着原来需要加储能电容才能完成的掉电保存现在直接在掉电瞬间写就行硬件成本也省了。7.2 批量写优化技巧批量写的时候WREN只需要发一次WRITE命令发一次地址发一次然后连续发数据字节地址自动递增。这样均摊下来每个字节的开销就是SPI传输时间本身没有额外命令开销。但要注意WRITE事务不能跨页边界吗MR25H40CDF没有页的概念整个存储区是线性地址空间可以连续写任意长度只要不超过0x7FFFF。这一点比Flash方便太多Flash跨页写会回卷到页首MRAM不会。7.3 读取速度优化读操作没有WREN开销效率更高。如果需要频繁读取同一区域的数据可以在RAM里做缓存减少SPI访问次数。PIC18F96J65有3.8KB RAM缓存配置参数和常用数据足够了。如果SPI时钟想再提高可以超频到12.5MHz试试SSPADD设成-1不行最小是0所以10MHz是PIC18在40MHz下的极限。想要更快只能换MCU比如用带高速SPI的32位MCU。但对于大多数工业参数存储场景10MHz已经远远够用了。7.4 功耗考量MR25H40CDF的待机电流典型值只有几微安读写电流在10mA左右。对于电池供电的工业设备可以在不访问MRAM时把CS拉高器件自动进入低功耗待机。PIC18F96J65本身也有多种低功耗模式配合起来可以做到很低的系统功耗。如果设备是电池供电且需要长期记录数据建议用定时唤醒的方式MCU定时醒来采集数据写入MRAM然后继续休眠。MRAM写入快醒来的时间可以很短平均功耗就降下来了。8. 这套方案的扩展思路MR25H40CDF加PIC18F96J65的组合除了做参数存储和日志记录还能玩出一些别的花样。比如做数据黑匣子设备运行时的关键状态每秒钟写一次MRAM因为写入快且寿命无限可以连续记录几个月甚至几年的数据。出故障时把MRAM里的数据读出来就是完整的运行轨迹。这在工业设备故障诊断里价值很大。比如做配置版本管理每次修改配置参数时不覆盖旧数据而是追加写入新版本MRAM里保留最近N个版本的配置。需要回滚时直接读旧版本。4Mbit容量可以存很多个版本而且写入快用户点保存按钮时几乎无感。比如做掉电瞬间的数据快照利用HLVD中断在电源跌落到MCU最低工作电压之前的几百微秒内把RAM里的关键变量全部写入MRAM。下次上电时从MRAM恢复实现断电续跑。这个在自动化产线上特别有用设备突然断电后重新上电能从断点继续执行不用人工干预。我在实际项目里用这套方案做过一个电力监测终端每秒采集32个通道的数据每个通道4字节也就是每秒128字节。连续记录72小时就是33MB超过了4Mbit容量。所以做了环形缓冲只保留最近24小时的数据写满后覆盖最旧的。MRAM的地址自动回卷特性在这里帮了大忙写指针到末尾自动回到开头软件只需要维护一个写指针变量存在MRAM固定位置上电时读出来接着写。踩过几次坑之后我总结出一条经验MRAM的地址空间规划一定要留余量不要算得刚刚好。因为后期需求变更、数据格式调整、增加新参数都需要额外空间。我一般只用到总容量的70%左右剩下的留作扩展和坏块替换。另外写指针、版本号、校验和这些元数据一定要放在独立的区域不要和数据混在一起否则数据区扩容时会很麻烦。最后分享一个小技巧MR25H40CDF的状态寄存器里有一个SRWD位状态寄存器写保护配合WP引脚可以实现硬件级的写保护。把WP引脚接到一个GPIO上正常工作时拉高允许写设备进入锁定模式时拉低同时把SRWD置1这样连状态寄存器都改不了彻底防止误写。这个功能在设备出厂标定完成后特别有用标定参数写进去然后硬件锁定现场人员怎么折腾都不会丢。
返回列表