找回密码
 立即注册
查看: 1097|回复: 7

基于STC32G12K128实验箱V9.62_实验之片内EEPROM读写

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:493
  • 最近打卡:2025-05-01 08:31:58

30

主题

347

回帖

3476

积分

荣誉版主

积分
3476
发表于 2024-5-27 18:42:49 | 显示全部楼层 |阅读模式
本帖最后由 浦江一水 于 2024-5-28 17:02 编辑

基于STC32G12K128实验箱V9.62_实验之片内EEPROM读写

    本实验在《基于STC32G12K128实验箱V9.62_实验之USART2串口通信》实验基础上,参照官方Demo实验18例程,使用串口2与PC机通讯, 实验片内EEPROM的读写。
   
主程序

//********************************************************************************
// 名称: Main.C
// 实验: 通过串口2 读写 STC32G12K128 片内EEPROM (下载时设置EEPROM大小为64K)
// 基于: STC32G12K128 V9.62 实验箱
// 改编: 浦晓明(浦江一水) 2023-12-14
//********************************************************************************
#include "STC32G_SYS.H"
#include "STC32G_UART.H"
#include "STC32G_EEPROM.H"

/**** 本实验程序通讯协议及功能说明

通过串口2(P4.6 P4.7)对STC内部自带的EEPROM(FLASH)进行读写测试。(使用阻塞方式进行串口发送)
对FLASH做扇区擦除、写入、读出的操作,命令指定地址。
默认波特率:  115200,N,8,1.
串口命令设置: (命令字母不区分大小写)
    E 0x0040             --> 对0x000040地址扇区内容进行擦除.
    W 0x0040 1234567890  --> 对0x000040地址写入字符1234567890.
    R 0x0040 10          --> 对0x000040地址读出10个字节数据.
注意:下载时,下载界面"硬件选项"中设置用户EEPROM大小,
并确保串口命令中的地址在EEPROM设置的大小范围之内。
*****************************************************************************************/

/*************  全局变量说明 **************/
u32 E_Addr;                   //指定EEPROM的地址
u8  E_Buf[512];              //读取数据缓存区
extern u8 EE_Buf[512];   //EEPROM的扇区读写缓存
//========================================================================
// 函数: void  delay_ms(unsigned int ms)
// 描述: 毫秒级延时函数。
// 参数: ms,要延时的ms数,自动适应主时钟.
//=====================================================================
void  delay_ms(unsigned int ms)
{ unsigned int i;
  do{ i = MAIN_Fosc / 6000;
      while(--i);
    } while(--ms);
}
/**** 主函数入口 ************************/
void main(void)
{ u8 ch,n,ts=1;
  u16 i,len;
  SYS_Init();              //系统初始化
  UART2_Init(1,1,115200);  //IO切换1,模式1,波特率115200
  //主循环...

  while(1)
  { if(ts)
     { //实验操作提示...
        printf("\r\n** STC32G12K1128单片机内部EEPROM读写测试 **\r\n");
        printf("- 实验箱_USART2(RS232)串口连接PC机串口.波特率115200,8,1,N\r\n");
        printf("- PC机使用串口助手,指令格式如下:(无需回车换行)\r\n");
        printf("  E 0x0040             --> 指定地址删扇区.\r\n");  
        printf("  W 0x0040 ABCDE12345  --> 指定地址写入字符串.\r\n");
        printf("  R 0x0040 10          --> 指定地址与长度,读取字符串.\r\n");
        printf("  (指令包含地址(16进制表达)总长度 >= 8字节)\r\n\r\n");
        printf("请输入指令:\r\n\r\n");
        ts=0;
    }
    delay_ms(100);
    if(RX2_Cnt>=8)          //串口2收到指令信息...
    { for(i=0;i<8;i++)
      { if((RX2_Buf >= 'a') && (RX2_Buf <= 'z'))RX2_Buf -= 0x20; } //小写转大写
      if(((RX2_Buf[0]=='E')||(RX2_Buf[0]=='W')||(RX2_Buf[0]=='R'))&&(RX2_Buf[1]==' '))
      { //解析地址...
        ch=RX2_Buf[4]-0x30; if(ch>9)ch=ch-0x07; E_Addr=(u32)ch;
        ch=RX2_Buf[5]-0x30; if(ch>9)ch=ch-0x07; E_Addr=16*E_Addr+(u32)ch;
        ch=RX2_Buf[6]-0x30; if(ch>9)ch=ch-0x07; E_Addr=16*E_Addr+(u32)ch;
        ch=RX2_Buf[7]-0x30; if(ch>9)ch=ch-0x07; E_Addr=16*E_Addr+(u32)ch;
        //解析指令...
        switch(RX2_Buf[0])
        { case 'E': EEPROM_SectorErase(E_Addr);
                    printf("OK! Sector Erase.\r\n");
                    break;
          case 'W': n=RX2_Cnt-9;   //取指令数据长度
                    EEPROM_Write(E_Addr,RX2_Buf+9,n);
                    printf("OK! Write %2d Byte.\r\n",n);
                    break;
          case 'R': n=RX2_Cnt-9; len=0;  //取指令数据长度
                    for(i=0;i<n;i++){ len=10*len+RX2_Buf[9+i]-'0'; } //取需要读取的数据长度
                    if(len>512)len=512;
                    EEPROM_Read(E_Addr,E_Buf,len);
                    printf("OK! Read out %3d Bytes:\r\n",len);
                    for(i=0;i<len;i++)UART2_SendChar(E_Buf);
                    UART2_SendChar(0x0D); UART2_SendChar(0x0A);
                    break;
        }
      } else { printf("指令无效!!\r\n"); ts=1; }  //提示说明...
      RX2_Cnt=0;RX2_Buf[0]=0;                   //计数清零
    }
  }
}


实验过程与实录截图

实验记录01.jpg

第一次先输入执行指令:
W 0x0040 ABCD012345                                   //对片内存EEPROM地址为0x0040的起始存储区写入10字节长度的字符串;

第二次再输入执行指令:
W 0x004A ...STC32G12K128_Test_EEPROM...   //对片内存EEPROM地址为0x004A的起始存储区写入30字节长度的字符串;

最后输入发送指令:

R 0x0040 40                                                   //从片内存EEPROM地址为0x0040的起始存储区读取40字节长度的数据;
观察到如上图所示, 返回长度为40字节的字符串: 是前两次写入字符串的合成。
ABCD012345...STC32G12K128_Test_EEPROM...


本实验沿用了官方例程的操作对话模式和指令格式, 有所不同的是:
当第二次写入数据到同一扇区时, 并没有把第一次写入的数据擦除掉。
本实验改写了库函数的读写算法。
改写的目的是为了实现:在片内EEPROM的允许地址和长度范围内,可指定任意地址和扇区,可读写任意长度的数据串,提高存储区的利用率,为实战项目奠定基础。
改编的读写算法考虑了EEPROM的只能写1为0和整扇区(512字节)擦除的特性,自动判别是否需要擦除和数据保护,以及跨扇区的读写。

对此算法有兴趣的坛友可从工程文件包中,观看库文件“STC32G_EEPROM.C”。


工程文件包
06-TestEEPROM.rar (316.55 KB, 下载次数: 103)

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:33
  • 最近打卡:2024-07-16 08:38:18

0

主题

24

回帖

296

积分

中级会员

积分
296
发表于 2024-5-28 16:27:11 | 显示全部楼层
坛友这个分享真是及时雨,正准备加入上位机用串口连接STC32单片机模块,感觉参考改一下执行命令就好了
昨天还在弄EEPROM存储参数,只有3个U16数据,正常存储没有问题,断电存储还没有搞好,因为一个扇区存3个U16
用定时器测了一下,擦除扇区再写入要大概21ms,时间有点长,电源部分还得特殊处理。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2024-5-28 16:33:37 | 显示全部楼层
感谢分享,可以尝试下
STC-ISP V6.94E 强大的 【串口助手】
STC-ISP V6.94E 强大的 【字库生成工具】,【图片取模工具】
截图202405281632084217.jpg

截图202405281632484520.jpg

截图202405281633349568.jpg

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:493
  • 最近打卡:2025-05-01 08:31:58

30

主题

347

回帖

3476

积分

荣誉版主

积分
3476
发表于 2024-5-29 09:31:57 | 显示全部楼层
神*** 发表于 2024-5-28 16:33
感谢分享,可以尝试下
STC-ISP V6.94E 强大的 【串口助手】
STC-ISP V6.94E 强大的 【字库生成工具】,【 ...

感谢神农管理员的浏览、回复和提示。

是的,STC-ISP 很强大很给力。其实我在学习实验箱的编程练习时,用的是STC-USB-Link1D工具仿真调试,也一直在使用STC-ISP 包括其中的串口助手,多功能、好用。只是在发写本贴时,为了截图表达通讯对话少量内容, 使用了早期版本的串口助手,只是意在画面简洁些。

STC-ISP 中的【字库生成工具】也做得极好,字体选择方便,字模排列灵活,导出格式多变。相比以前为了做小字库,找各种工具,老废功夫了,现在确实方便多了。

日前已发现,STC-ISP 已经升级到 V6.94E版本,也已更新多日了。真感叹,升级变化之快,功能越来越强大,也充分体现了STC 团队一直不断在努力进取,必须赞赏。

点评

感谢长期对我们的支持和信任 STC-ISP V6.94E【串口助手】可以单独显示, 并且可以单独打开 4个【串口助手】 [attachimg]45629[/attachimg] [attachimg]45630[/attachimg] [attachimg]45631[/attachimg]  详情 回复 发表于 2024-5-29 09:44
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2024-5-29 09:44:16 | 显示全部楼层
浦江*** 发表于 2024-5-29 09:31
感谢神农管理员的浏览、回复和提示。

是的,STC-ISP 很强大很给力。其实我在学习实验箱的编程练习时,用 ...


感谢长期对我们的支持和信任
STC-ISP V6.94E【串口助手】可以单独显示,
并且可以单独打开 4个【串口助手】


截图202405290939471328.jpg
截图202405290940522563.jpg

截图202405290951173968.jpg




截图202405290942405831.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:493
  • 最近打卡:2025-05-01 08:31:58

30

主题

347

回帖

3476

积分

荣誉版主

积分
3476
发表于 2024-5-29 12:43:55 | 显示全部楼层
本帖最后由 浦江一水 于 2024-5-29 12:51 编辑
cadp*** 发表于 2024-5-28 16:27
坛友这个分享真是及时雨,正准备加入上位机用串口连接STC32单片机模块,感觉参考改一下执行命令就好了
昨天 ...

感谢CadPlus的浏览和回复,能让您觉得是“及时雨”,有一点参考价值,本人也觉得很高兴快乐。

看到您的回复中提到“断电存储还没搞好...”, 不知道您要达到如何"断电存储"的目的和指标,顺便也聊几句个人的体会认识...

在本坛, 神农鼎管理员在多种场合、多次提到"EEPROM的使用 配合比较器做掉电检测",提醒要注意检测电压点的选取,即硬件设计首先要注意到的,这是非常需要细细学习和研究的。

在实验箱配套官方例程中,有个“20-使用比较器检测低电压时保存数据到EEPROM”之例程。若按照实验箱的硬件条件和实验方法做一下实验,是完全成功的,其算法理论上也是没有问题的。
可是,当用于现实中实际项目产品的研发, 可能不是这么简单的了。

首先,现实中往往有这样的情况:编程的人所拿到的电路板并非是自己设计的,或者是之前并没有考虑断电保护数据这一要求,而现在又需要增加这项功能。可能是容不得你改动硬件的。即使让你改硬件,那么在量产时,由于分压电阻、滤波电容等元器件的离散性,检测电压的临界点很难保持一致性的,或许还要考虑软件可设临界点,这必然增加调试时间成本和难度。实际效果也往往出现“不太可靠”的现象。
其次,要细细品味理解一下这“掉电”的精确定义。是指检测点外部电压的下降过程?还是指系统整体突然失去供电?

本人在获赠得到STC32G实验箱后,也做过例程20的实验。如果用电位器调节检测点电压下降,EEPROM数据保存,是没有问题的,如果在实验中,突然拔掉电源,这是真正的“掉电”,再试试看结果如何?结果就不是这么回事了。

本人在职业生涯中做过一些单片机项目,有过这方面的经历体会:
举例项目是一个“在线测试分析仪”,有可能连续测试,昼夜不停的。用户要求具有“来电”“掉电”时刻的记录功能,也就是能查看某段时间(比如三个月)内,开机(来电)、关机(掉电)的时刻,就是年月日时分秒。以便可确认测试分析记录数据的有效性,并且“掉电”后“来电”了,测试仪要自动恢复到“掉电”之前的运行状态。这些要求是完全合理的,是必须要做到的。于是乎,这就涉及到“掉电保护数据”的问题了。
稍加分析可知, 这“来电”,好办,上电后单片机初始化时记录时刻。而“掉电”,就难办了,开定时比较器?找检测电压点?改电路元器件配置?来实现“在掉电过程中及时保存用户数据到EEPROM中”? 正当同事们等待下一步如何改硬件的时候,我在没有改动任何硬件的基础上,完全靠软件编程,就实现了用户的要求。同事们认为不可思议,很好奇,这是如何做到的?
其实,说出来是很简单的。说穿了,是一点儿也不稀奇的,同事们笑了。
思路是这样的:
存储器可以是内部EEPROM,也可以是外部EEPROM,原理相同。
存储区分三块,一是运行数据参数区,二是来电掉电时刻记录区,三是测试分析结果数据区。
开机(来电)记录时刻(时刻记录区的存储地址递增循环),就不必说了。
重点是如何记录“掉电”时刻。
测试仪是每秒钟测一个周期的,在测试分析期间,将所有测试数据、运行状态参数等,打一个包,结构数据包,每秒保存一次到运行参数区,以便“来电”时恢复现场。
同时将正在运行的时刻,记录到“掉电”记录中(这次时刻记录区的存储地址不变)。
正常测试期间,周期性地将测试分析数据(比如分钟均值)记录到数据区,编号递增,供用户查询处理。
如果测试期间突然掉电,就让它停止工作, 不必考虑检测电压下降时赶快保存等动作。
这样,如果查询运行日志,会查询到所有来电掉电的时刻,最后“掉电”的时刻,就是最后正常运行的时刻。
这样的算法,可能存在两点疑问:
一是“误差”,误差一秒钟。认为“掉电”时刻被提前了一秒钟。其实未必,可能记录最后运行时刻时0.1秒,掉电时刻是0.9秒。误差总是存在的,掉电是随机的,提前或恰好的概率各占50%。
二是“寿命”,频繁地擦写EEPROM,是否缩短使用寿命。那么EEPROM可擦写10万次,而且不是总在某一个单元扇区擦除。那么仪器准备使用多少年呢?
结果是这样的解释用户就没有疑问了。

以上关于读写EEPROM引出的“断电存储”话题,聊聊,笑笑,仅供参考。

祝实验学习顺利愉快!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:33
  • 最近打卡:2024-07-16 08:38:18

0

主题

24

回帖

296

积分

中级会员

积分
296
发表于 2024-6-1 14:30:10 | 显示全部楼层
浦江*** 发表于 2024-5-29 12:43
感谢CadPlus的浏览和回复,能让您觉得是“及时雨”,有一点参考价值,本人也觉得很高兴快乐。

看到您的回 ...

非常感谢你的经验分享,配合着你写的上位机软件ISPTXT,DIY小铣床的控制系统已经实现基本设想功能。

屏幕截图 2024-05-30 200403.jpg


我说的掉电存储有正常关机和突然断电关机,本想是精确记录步进电机驱动的三轴位置,重开机时能恢复。
实际上有点难以实现,因为电机断电后再上电的位置不一定是相同了,目前存储坐标只能用作电子安全围栏,
防止撞机或者丝杆脱出,因为丝杆行程不够用到尽了,也没有装限位开关。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:493
  • 最近打卡:2025-05-01 08:31:58

30

主题

347

回帖

3476

积分

荣誉版主

积分
3476
发表于 2024-6-1 19:14:09 | 显示全部楼层
cadp*** 发表于 2024-6-1 14:30
非常感谢你的经验分享,配合着你写的上位机软件ISPTXT,DIY小铣床的控制系统已经实现基本设想功能。

看到您实践项目有所进展,已实现 基本设想功能, 真为您高兴。小软件能够用上,我也很快乐。
关于说到电机断电后来电再复原定位的控制,确实是有难度的。一般而言,断电保护现场状态数据, 是必不可少的第一步,接下来才是研究复原的策略了。想象中,或许要加入自动校准措施,若要要达到较高精度,就更不容易了。这方面我可能是外行,就不多言了。
在此再祝您实验顺利,生活愉快。
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:16 , Processed in 0.150298 second(s), 99 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表