- 打卡等级:以坛为家II
- 打卡总天数:493
- 最近打卡:2025-05-01 08:31:58
荣誉版主
- 积分
- 3476
|
本帖最后由 浦江一水 于 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; //计数清零
}
}
}
实验过程与实录截图
第一次先输入执行指令:
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)
|
|