给初学者发一个自己用的STC专用EEPROM操作模块代码,简单改一下适合大多数STC芯片。
/*******************************************************************************/
/************ STC15W408AS单片机 EEPROM 操作模块头文件 "STC_EEPROM.H" ************/
/*******************************************************************************/
/********************** 注意事项: 内部时钟频率12.000MHZ ************************/
/*******************************************************************************/
#ifndef __STC_EEPROM_H__
#define __STC_EEPROM_H__
/*-----------------------------------------------------------------------------*/
/* 加载用到的头文件 */
/*-----------------------------------------------------------------------------*/
#ifndef __INTRINS_H__
#include <INTRINS.H> //加载系统应用头文件INTRINS.H
#endif
#ifndef __STC15W408AS_H__
#include "STC15W408AS.H" //加载STC单片机STC15W408AS专用头文件
#endif
/*-----------------------------------------------------------------------------*/
/* 数据类型缩写定义 */
/*-----------------------------------------------------------------------------*/
#ifndef _DATA_TYPE_ABBREVIATIONS_ //如果没有宏定义“数据类型缩写”标示将进行“_DATA_TYPE_ABBREVIATIONS_”标示宏定义
#define _DATA_TYPE_ABBREVIATIONS_ //宏定义“_DATA_TYPE_ABBREVIATIONS_”标示
#define int8 signed char //重定义8位字符型数据类型为:int8(-128~127)
#define int16 signed short int //重定义16位短整数型数据类型为:int16(-32768~32767)
#define int32 signed long int //重定义32位长整数型数据类型为:int32(-2147483648~2147483647)
#define int64 signed long long int //重定义64位超级整数型数据类型为:int64(-xxx~xxx)
#define uint8 unsigned char //重定义8位正字符型数据类型为:uint8(0~255)
#define uint16 unsigned short int //重定义16位正短整数型数据类型为:uint16(0~65535)
#define uint32 unsigned long int //重定义32位正长整型数据类型为:uint32(0~4294967295)
#define uint64 unsigned long long int //重定义64位正超级整数型数据类型为:uint64(0~xxxx)
#define float32 float //重定义浮点小数数据类型为:float32(3.4e-38~3.4e38)
#define float64 double //重定义双精度浮点小数数据类型为:float64(1.7e-308~1.7e308)
#define TRUE 1 //宏定义真常量
#define FALSE 0 //宏定义假常量
#endif
/*-----------------------------------------------------------------------------*/
/* 声明SFR类型寄存器地址与IAP的关系 */
/*-----------------------------------------------------------------------------*/
//sfr IAP_DATA = 0xC2; //Flash数据寄存器
//sfr IAP_ADDRH = 0xC3; //Flash寄存器高八位地址
//sfr IAP_ADDRL = 0xC4; //Flash寄存器低八位地址
//sfr IAP_CMD = 0xC5; //Flash读写操作控制命令寄存器
//sfr IAP_TRIG = 0xC6; //Flash触发命令寄存器
//sfr IAP_CONTR = 0xC7; //Flash控制寄存器
/*-----------------------------------------------------------------------------*/
/* 定义可全局调用的常量 */
/*-----------------------------------------------------------------------------*/
//声明 ISP/IAP/EEPROM 读写操作寄存器IAP_CMD常量值
#define CMD_IDLE 0 //待机模式无操作
#define CMD_READ 1 //从用户的应用程序区对"Data Flash/EEPROM"区进行字节读操作
#define CMD_PROGRAM 2 //从用户的应用程序区对"Data Flash/EEPROM"区进行字节编程操作
#define CMD_ERASE 3 //从用户的应用程序区对"Data Flash/EEPROM"区进行扇区擦除操作
//声明 ISP/IAP/EEPROM 各扇区起始地址常量
#define IAP_ADDRESS_A 0x0000 //声明STC89C58xx EEPROM 第一扇区起始地址常量
#define IAP_ADDRESS_B 0x0200 //声明STC89C58xx EEPROM 第二扇区起始地址常量
//声明 ISP/IAP/EEPROM CPU实际运行的系统时钟频率常量值标示
#ifndef _SYSclk_
#define _SYSclk_ 12000000 //宏定义CPU实际运行的系统时钟频率(单位:Hz,根据时钟频率修改,EEPROM模块使用)
#endif
//声明 ISP/IAP/EEPROM 控制寄存器IAP_CONTR常量值
#if (24000000 <= _SYSclk_)
#define ENABLE_IAP 0x80 //如果 24MHz <= SYSCLK < 30MHz
#elif (20000000 <= _SYSclk_)
#define ENABLE_IAP 0x81 //如果 20MHz <= SYSCLK < 24MHz
#elif (12000000 <= _SYSclk_)
#define ENABLE_IAP 0x82 //如果 12MHz <= SYSCLK < 20MHz
#elif ( 6000000 <= _SYSclk_)
#define ENABLE_IAP 0x83 //如果 6 MHz <= SYSCLK < 12MHz
#elif ( 3000000 <= _SYSclk_)
#define ENABLE_IAP 0x84 //如果 3 MHz <= SYSCLK < 6 MHz
#elif ( 2000000 <= _SYSclk_)
#define ENABLE_IAP 0x85 //如果 2 MHz <= SYSCLK < 3 MHz
#elif ( 1000000 <= _SYSclk_)
#define ENABLE_IAP 0x86 //如果 1 MHz <= SYSCLK < 2 MHz
#else
#define ENABLE_IAP 0x87 //如果 1 KHz <= SYSCLK < 1 MHz
#endif
/*-----------------------------------------------------------------------------*/
/* 声明可全局调用的变量 */
/*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/
/* 声明可全局调用的函数 */
/*-----------------------------------------------------------------------------*/
/*******************************************************************************
* 函数名称: Iap_Idle(void)
* 函数功能: 置寄存器状态为闲置函数
* 函数输入: 无
* 函数输出: 无
* 函数说明:
*******************************************************************************/
extern void Iap_Idle(void)
{
IAP_CONTR = 0; //Flash控制寄存器清空,禁止ISP/IAP操作
IAP_CMD = 0; //Flash读写操作控制命令寄存器,去除ISP/IAP命令
IAP_TRIG = 0; //Flash触发命令寄存器,防止ISP/IAP命令误触发
IAP_ADDRH = 0xFF; //Flash地址寄存器高八位,指向非EEPROM区,防止误操作
IAP_ADDRL = 0xFF; //Flash地址寄存器低八位,指向非EEPROM区,防止误操作
}
/*******************************************************************************
* 函数名称: uint8 Iap_Read_Byte(uint16 addr)
* 函数功能: 读取相应地址处字节函数
* 函数输入: 有 addr = 字节位置
* 函数输出: 有 返回字节内容
* 函数说明:
*******************************************************************************/
extern uint8 Iap_Read_Byte(uint16 addr)
{
uint8 dat;
IAP_CONTR = ENABLE_IAP; //设置等待时间
IAP_CMD = CMD_READ; //设置操作控制为读取命令
IAP_ADDRL = addr; //设置要读操作的高位地址
IAP_ADDRH = addr >> 8; //设置要读操作的低位地址
IAP_TRIG = 0x5A; //
IAP_TRIG = 0xA5; //
_nop_(); //
dat = IAP_DATA; //读出地址处的数据
Iap_Idle(); //置寄存器状态为闲置
return dat; //返回值
}
/*******************************************************************************
* 函数名称: Iap_Program_Byte(uint16 addr,uint8 dat)
* 函数功能: 写入程序字节函数
* 函数输入: 有 addr = 要写入数据的位置 dat = 要写入的数据内容
* 函数输出: 无
* 函数说明:
*******************************************************************************/
extern void Iap_Program_Byte(uint16 addr,uint8 dat)
{
IAP_CONTR = ENABLE_IAP; //设置允许操作FLASH等待时间
IAP_CMD = CMD_PROGRAM; //设置操作控制为写入命令
IAP_ADDRL = addr; //设置要写入操作的高位地址
IAP_ADDRH = addr >> 8; //设置要写入操作的低位地址
IAP_DATA = dat; //写入数据
IAP_TRIG = 0x5A; //
IAP_TRIG = 0xA5; //
_nop_(); //
Iap_Idle(); //置寄存器状态为闲置函数
}
/*******************************************************************************
* 函数名称: Eeprom_Delete_Sector(uint16 addr)
* 函数功能: 擦除EEPROM扇区函数
* 函数输入: 有 addr = 要删除扇区的初始地址
* 函数输出: 无
* 函数说明:
*******************************************************************************/
extern void Eeprom_Delete_Sector(uint16 addr)
{
IAP_CONTR = ENABLE_IAP; //设置等待时间
IAP_CMD = CMD_ERASE; //设置操作控制为擦除扇区命令
IAP_ADDRL = addr; //设置要写入操作的高位地址
IAP_ADDRH = addr >> 8; //设置要写入操作的低位地址
IAP_TRIG = 0x5A; //
IAP_TRIG = 0xA5; //
_nop_(); //
Iap_Idle(); //置寄存器状态为闲置函数
}
/*******************************************************************************
* 函数名称: Eeprom_Read_All(bit s,uint8 *dat,uint16 z)
* 函数功能: 读取EEPROM扇区内全部数据的函数
* 函数输入: 有 s = 扇区号(0为一扇区;1为二扇区) *dat = 数据数组指针 z = 数组长度
* 函数输出: 无
* 函数说明:
*******************************************************************************/
extern void Eeprom_Read_All(bit s,uint8 *dat,uint16 z)
{
uint8 i,y;
uint16 x;
if (s == 0)
{
for (i=0;i<z;i++)
{
x = IAP_ADDRESS_A + i;
y = Iap_Read_Byte(x);
if (y == 0xFF) dat[i] = 0x00;
dat[i] = y;
}
}
else
{
for (i=0;i<z;i++)
{
x = IAP_ADDRESS_B + i;
y = Iap_Read_Byte(x);
if (y == 0xFF) dat[i] = 0x00;
dat[i] = y;
}
}
}
/*******************************************************************************
* 函数名称: Save_All_Data(bit s,uint8 *dat,uint16 n)
* 函数功能: 存储全部参数函数
* 函数输入: 有 s = 扇区号(0为一扇区;1为二扇区) *dat = 数据数组指针 n = 数组长度
* 函数输出: 有 0->失败 1->成功
* 函数说明:
*******************************************************************************/
extern bit Save_All_Data(bit s,uint8 *dat,uint16 n)
{
uint16 i,x;
if (s == 0)
{
EA = 0; //禁止中断
Eeprom_Delete_Sector(IAP_ADDRESS_A); //擦除第一扇区全部数据
for (i=0;i<512;i++)
{
if (Iap_Read_Byte(IAP_ADDRESS_A + i) != 0xFF) //检测扇区中每个地址位的数据是否被擦除
{
EA = 1; //重新允许中断
return FALSE; //如果第一扇区数据未真正擦除返回错误信息
}
}
for (i=0;i<n;i++)
{
x = IAP_ADDRESS_A + i;
Iap_Program_Byte(x,dat[i]);
}
EA = 1; //重新允许中断
return TRUE; //正确存储数据后返回1
}
else
{
EA = 0; //禁止中断
Eeprom_Delete_Sector(IAP_ADDRESS_B); //擦除第二扇区全部数据
for (i=0;i<512;i++)
{
if (Iap_Read_Byte(IAP_ADDRESS_B + i) != 0xFF)
{
EA = 1; //重新允许中断
return FALSE; //如果第二扇区数据未真正擦除返回错误信息
}
}
for (i=0;i<n;i++)
{
x = IAP_ADDRESS_B + i;
Iap_Program_Byte(x,dat[i]);
}
EA = 1; //重新允许中断
return TRUE;
}
}
/*******************************************************************************/
#endif
/*******************************************************************************/
|