基于STC32G12K128实验箱V9.62_实验之片内EEPROM读写
本帖最后由 浦江一水 于 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的地址
u8E_Buf; //读取数据缓存区
extern u8 EE_Buf; //EEPROM的扇区读写缓存
//========================================================================
// 函数: voiddelay_ms(unsigned int ms)
// 描述: 毫秒级延时函数。
// 参数: ms,要延时的ms数,自动适应主时钟.
//=====================================================================
voiddelay_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=='E')||(RX2_Buf=='W')||(RX2_Buf=='R'))&&(RX2_Buf==' '))
{ //解析地址...
ch=RX2_Buf-0x30; if(ch>9)ch=ch-0x07; E_Addr=(u32)ch;
ch=RX2_Buf-0x30; if(ch>9)ch=ch-0x07; E_Addr=16*E_Addr+(u32)ch;
ch=RX2_Buf-0x30; if(ch>9)ch=ch-0x07; E_Addr=16*E_Addr+(u32)ch;
ch=RX2_Buf-0x30; if(ch>9)ch=ch-0x07; E_Addr=16*E_Addr+(u32)ch;
//解析指令...
switch(RX2_Buf)
{ 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-'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; //计数清零
}
}
}
实验过程与实录截图
第一次先输入执行指令:
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”。
工程文件包
坛友这个分享真是及时雨,正准备加入上位机用串口连接STC32单片机模块,感觉参考改一下执行命令就好了{:4_165:}
昨天还在弄EEPROM存储参数,只有3个U16数据,正常存储没有问题,断电存储还没有搞好,因为一个扇区存3个U16
用定时器测了一下,擦除扇区再写入要大概21ms,时间有点长,电源部分还得特殊处理。 感谢分享,可以尝试下
STC-ISP V6.94E 强大的 【串口助手】
STC-ISP V6.94E 强大的 【字库生成工具】,【图片取模工具】
神农鼎 发表于 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 团队一直不断在努力进取,必须赞赏。 浦江一水 发表于 2024-5-29 09:31
感谢神农管理员的浏览、回复和提示。
是的,STC-ISP 很强大很给力。其实我在学习实验箱的编程练习时,用 ...
{:4_196:}
感谢长期对我们的支持和信任
STC-ISP V6.94E【串口助手】可以单独显示,
并且可以单独打开 4个【串口助手】
本帖最后由 浦江一水 于 2024-5-29 12:51 编辑
cadplus 发表于 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引出的“断电存储”话题,聊聊,笑笑,仅供参考。
祝实验学习顺利愉快!
浦江一水 发表于 2024-5-29 12:43
感谢CadPlus的浏览和回复,能让您觉得是“及时雨”,有一点参考价值,本人也觉得很高兴快乐。
看到您的回 ...
非常感谢你的经验分享,配合着你写的上位机软件ISPTXT,DIY小铣床的控制系统已经实现基本设想功能。
我说的掉电存储有正常关机和突然断电关机,本想是精确记录步进电机驱动的三轴位置,重开机时能恢复。
实际上有点难以实现,因为电机断电后再上电的位置不一定是相同了,目前存储坐标只能用作电子安全围栏,
防止撞机或者丝杆脱出,因为丝杆行程不够用到尽了,也没有装限位开关。
cadplus 发表于 2024-6-1 14:30
非常感谢你的经验分享,配合着你写的上位机软件ISPTXT,DIY小铣床的控制系统已经实现基本设想功能。
看到您实践项目有所进展,已实现 基本设想功能, 真为您高兴。小软件能够用上,我也很快乐。
关于说到电机断电后来电再复原定位的控制,确实是有难度的。一般而言,断电保护现场状态数据, 是必不可少的第一步,接下来才是研究复原的策略了。想象中,或许要加入自动校准措施,若要要达到较高精度,就更不容易了。这方面我可能是外行,就不多言了。
在此再祝您实验顺利,生活愉快。
页:
[1]