使用STC单片机的老司机,都喜欢把原来的程序直接应用的新的系列CPU中。今天我也把STC15W EEPROM程序直接拷贝到STC8G2K64S4下应用,出现数据读写存储异常,写入的数据,和读出的数据不一致,仿真、串口打印读出数据为0xFFFF;
后查阅资料发现STC15系列单片机与STC8G关于EEPROM的寄存器的定义绝大部分相同,但STC8G单片机增加了IAP_TPS;如下图所示:
sfr IAP_DATA = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD = 0xC5;
sfr IAP_TRIG = 0xC6;
sfr IAP_CONTR = 0xC7;
sfr IAP_TPS = 0xF5; //STC8G2K64S4系列特有的EEPROM寄存器,如果没有操作这个寄存器,则EEPROM数据存储、读取异常
//定义Flash 操作等待时间及允许IAP/ISP/EEPROM 操作的常数
#define ENABLE_ISP 0x80 //系统工作时钟<30MHz 时,对IAP_CONTR 寄存器设置此值
union union_temp16
{
INT16U un_temp16;
INT8U un_temp8[2];
}my_unTemp16;
//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
unsigned char EEPROM_Byte_Read(unsigned short int add)
{
IAP_DATA = 0x00;
IAP_TPS=12; *//STC8G需要操作寄存器单元
IAP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间
IAP_CMD = 0x01; //IAP/ISP/EEPROM 字节读命令
IAP_ADDRL=add;
IAP_ADDRH=add>>8;
IAP_TRIG = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
nop();
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
return (IAP_DATA);
}
//从EEPROM连续读数据
void EEPROM_Read(unsigned short int add,unsigned char *outdat,unsigned char num)
{
unsigned char i;
for(i=0;i<num;i++)
{
*outdat++=EEPROM_Byte_Read(add+i);
}
}
//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void EEPROM_Byte_Program(unsigned short int add, unsigned char ch)
{
IAP_CONTR = ENABLE_ISP; //打开 IAP 功能, 设置Flash 操作等待时间
IAP_TPS=12; *//STC8G需要操作寄存器单元
IAP_CMD = 0x02; //IAP/ISP/EEPROM 字节编程命令
IAP_ADDRL = add;
IAP_ADDRH = add>>8;
IAP_DATA = ch; //要编程的数据先送进IAP_DATA 寄存器
IAP_TRIG = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
nop();
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
//从EEPROM连续写数据
void EEPROM_Write(unsigned short int add,unsigned char *indat,unsigned char num)
{
unsigned char i;
for(i=0;i<num;i++)
{
EEPROM_Byte_Program(add+i,*indat++);
}
}
//擦除扇区, 入口:DPTR = 扇区地址
void EEPROM_Sector_Erase(INT16U add)
{
IAP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间
IAP_TPS=12; //STC8G需要操作寄存器单元
IAP_CMD = 0x03; //IAP/ISP/EEPROM 扇区擦除命令
IAP_ADDRL = add;
IAP_ADDRH = add>>8;
IAP_TRIG = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
nop();
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
void IAP_Disable()
{
//关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
IAP_CONTR = 0; //关闭IAP 功能
IAP_CMD = 0; //清命令寄存器,使命令寄存器无命令,此句可不用
IAP_TRIG = 0; //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
IAP_ADDRH = 0x80;
IAP_ADDRL = 0;
}
2020.6.12 记。