STC12C5A60S2系列单片机内部EEPROM

本文介绍了STC89系列单片机中的EEPROM特性,包括STC89C51和STC89C52自带的2KdEEPROM,并详细阐述了ISP(在系统编程)和IAP(在应用编程)技术,特别是如何利用IAP实现在应用中修改Flash数据。示例代码展示了如何擦除、读写EEPROM扇区,并提供了错误处理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单片机内部EEPROM介绍

记得我在学习STC89系列单片机的时候,曾经学到一个内容是EEPROM的读写,当时使用的是AT2402芯片。
EEPROM(Electrically Erasable Programmable read only memory)是指带电可擦可编程只读存储器
是一种掉电后数据不丢失的存储芯片

其实,STC89C51,STC89C52内部都自带有2Kd EEPROM。STC单片机是利用IAP技术实现EEPROM,内部Flash擦写次数可达100 000次以上。

ISP(In System Programable)是指在系统编程,通俗地讲,就是片子已经焊在板子上,不用取下,就可以简单而方便的对其进行编程,比如,我们通过计算器给STC单片机下载程序,这就是利用ISP技术
IAP(In Application Programable)是指在应用编程,就是片子提供一系列的机制(硬件/软件上的),当片子在运行程序时可以提供一种改变Flash数据的方法,通俗点讲,也就是说,程序自己可以往程序存储器里写数据数据或修改程序,这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一小段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。大家要注意,千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。
——参考郭天祥51单片机C语言教程

我们查看STC12的芯片手册,知道了STC12C5A60S2这款单片机有1K的EEPROM字节数,两个扇区,如下截图:
请添加图片描述
每一个扇区512字节,同时STC公司建议同一次修改的数据放在同一个扇区,不是同一次修改的数据放在不同三期,不必用满,当然可全用。

查看芯片手册我们查到STC12C5A60S2内部EEPROM地址表:
第一扇区:0000H–1FFH
第二扇区:200H–3FFH

要想了解更多内部EEPROM,可以查看官方发芯片手册。

例程参考

例程参考了STC的资料及程序

#include <STC12C5A60S2.h>
#include "intrins.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

/*Define ISP/IAP/EEPROM command*/
//定义ISP / IAP / eepm命令
#define CMD_IDLE    0               //Stand-By
#define CMD_READ    1               //Byte-Read
#define CMD_PROGRAM 2               //Byte-Program
#define CMD_ERASE   3               //Sector-Erase

/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//为IAP_CONTR定义ISP/IAP/EEPROM操作常量  
//#define ENABLE_IAP 0x80           //if SYSCLK<30MHz
//#define ENABLE_IAP 0x81           //if SYSCLK<24MHz
#define ENABLE_IAP  0x82            //if SYSCLK<20MHz
//#define ENABLE_IAP 0x83           //if SYSCLK<12MHz
//#define ENABLE_IAP 0x84           //if SYSCLK<6MHz
//#define ENABLE_IAP 0x85           //if SYSCLK<3MHz
//#define ENABLE_IAP 0x86           //if SYSCLK<2MHz
//#define ENABLE_IAP 0x87           //if SYSCLK<1MHz

//Start address for STC12C5A60S2 EEPROM
#define IAP_ADDRESS 0x0000

void Delay(BYTE n);
void UartInit(void);
void putchar(char ch);
void prints(char *s);
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);

void main()
{
    WORD i;
	UartInit();						//串口初始化

    P1 = 0xfe;                      //1111,1110 System Reset OK 		系统复位成功
    Delay(10);                      //Delay
    IapEraseSector(IAP_ADDRESS);    //Erase current sector 				删除当前扇区
	
	
    for (i=0; i<512; i++)           //Check whether all sector data is FF
    {
        if (IapReadByte(IAP_ADDRESS+i) != 0xff)
            goto Error;             //If error, break
    }
    P1 = 0xfc;                      //1111,1100 Erase successful
    Delay(10);                      //Delay
	
	
    for (i=0; i<9; i++)           //Program 512 bytes data into data flash
    {
        IapProgramByte(IAP_ADDRESS+i, (BYTE)i);
    }
    P1 = 0xf8;                      //1111,1000 Program successful
    Delay(10);                      //Delay
	
	
    for (i=0; i<9; i++)           //Verify 512 bytes data
    {
		prints("当前地址:");
		putchar(i + '0');
		putchar('\n');
		
		prints("当前地址储存内容为:");
		putchar(IapReadByte(IAP_ADDRESS+i) + '0');
		putchar('\n');
		
		if (IapReadByte(IAP_ADDRESS+i) != (BYTE)i)
            goto Error;             //If error, break
    }
    P1 = 0xf0;                      //1111,0000 Verify successful
    while (1);
Error:
    P1 &= 0x7f;                     //0xxx,xxxx IAP operation fail
    while (1);
}

/*----------------------------
Software delay function
----------------------------*/
void Delay(BYTE n)
{
    WORD x;

    while (n--)
    {
        x = 0;
        while (++x);
    }
}

//串口初始化,晶振11.0592,波特率9600
void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x04;		//独立波特率发生器时钟为Fosc,即1T
	BRT = 0xDC;		//设定独立波特率发生器重装值
	AUXR |= 0x01;		//串口1选择独立波特率发生器为波特率发生器
	AUXR |= 0x10;		//启动独立波特率发生器
	
//	EA = 1;//开总中断
//	ES = 1;//开串口中断
}


//向串口发送一个字符
void putchar(char ch)
{
	SBUF = ch;
	while(!TI);TI = 0;
}

//向串口发送一段字符串
void prints(char *s)
{
	while(*s != '\0')//发送字符串,直到遇到0才结束
	{
		SBUF = *s++;
		while(!TI);
		TI = 0;
	}
}

/*----------------------------
Disable ISP/IAP/EEPROM function
Make MCU in a safe state

禁用ISP / IAP / eepm函数  
使MCU处于安全状态
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //Close IAP function
    IAP_CMD = 0;                    //Clear command to standby
    IAP_TRIG = 0;                   //Clear trigger register
    IAP_ADDRH = 0x80;               //Data ptr point to non-EEPROM area
    IAP_ADDRL = 0;                  //Clear IAP address to prevent misuse
}

/*----------------------------
Read one byte from ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
Output:Flash data

从ISP/IAP/EEPROM区读取一个字节  
输入:addr (ISP/IAP/EEPROM地址)  
输出:闪存数据  
----------------------------*/
BYTE IapReadByte(WORD addr)
{
    BYTE dat;                       //Data buffer

    IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
    IAP_CMD = CMD_READ;             //Set ISP/IAP/EEPROM READ command
    IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
    IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
    IAP_TRIG = 0x5a;                //Send trigger command1 (0x5a)
    IAP_TRIG = 0xa5;                //Send trigger command2 (0xa5)
    _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
    dat = IAP_DATA;                 //Read ISP/IAP/EEPROM data
    IapIdle();                      //Close ISP/IAP/EEPROM function

    return dat;                     //Return Flash data
}

/*----------------------------
Program one byte to ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
       dat (ISP/IAP/EEPROM data)
Output:-

编程一个字节到ISP/IAP/EEPROM区域  
输入:addr (ISP/IAP/EEPROM地址)  
dat (ISP / IAP / eepm数据)  
输出:  
----------------------------*/
void IapProgramByte(WORD addr, BYTE dat)
{
    IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
    IAP_CMD = CMD_PROGRAM;          //Set ISP/IAP/EEPROM PROGRAM command
    IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
    IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
    IAP_DATA = dat;                 //Write ISP/IAP/EEPROM data
    IAP_TRIG = 0x5a;                //Send trigger command1 (0x5a)
    IAP_TRIG = 0xa5;                //Send trigger command2 (0xa5)
    _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
    IapIdle();
}

/*----------------------------
Erase one sector area 
Input: addr (ISP/IAP/EEPROM address)
Output:-

删除一个扇区  
输入:addr (ISP/IAP/EEPROM地址)  
输出:  
----------------------------*/
void IapEraseSector(WORD addr)
{
    IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
    IAP_CMD = CMD_ERASE;            //Set ISP/IAP/EEPROM ERASE command
    IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
    IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
    IAP_TRIG = 0x5a;                //Send trigger command1 (0x5a)
    IAP_TRIG = 0xa5;                //Send trigger command2 (0xa5)
    _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
    IapIdle();
}


请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小明n.n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值