STC内部EEPROM表








删除以地址400开始的512字节空间。

写入测试的20个以0开始连续加一的数据。

然后读出发送到串口,电脑读出接收的数据显示。





/*-----EEPROM 读写测试通过 2014 4 18 06:12---L271 CODE 474--------------*/

//芯片的工作频率修改为11.0592MHz波特率9600 程序修改向串口发送完成状态数据
#include "reg51.h"
#include "intrins.h"
#define uint unsigned int
#define uchar unsigned char
typedef unsigned char BYTE;
typedef unsigned int WORD;
//-----------------------------------------------
sfr IAP_DATA = 0xC2; //IAP 数据寄存器
sfr IAP_ADDRH = 0xC3; //IAP 地址寄存器高字节
sfr IAP_ADDRL = 0xC4; //IAP 地址寄存器低字节
sfr IAP_CMD = 0xC5; //IAP 命令寄存器
sfr IAP_TRIG = 0xC6; //IAP 命令触发寄存器
sfr IAP_CONTR = 0xC7; //IAP 控制寄存器
sfr AUXR=0x8e; //辅助寄存器
sfr SADDR=0xA9; //从机地址寄存器
sfr SADEN=0xB9; //从机地址屏蔽寄存器
char count;
sfr P4=0xc0;
sfr P5=0xc8;
sbit out=P1^5; //
sbit out1=P4^5; //
sbit out2=P1^6; //
sbit out3=P1^7; //
sbit key1=P0^0; //
sbit key2=P0^1; //
int Buff;
#define SLAVE 1 //定义从机编号,0 为从机 1, 1 为从机 2
#if SLAVE==0
#define SAMASK 0x33 //从机 1 地址屏蔽位
#define SERADR 0x55 //从机 1 的地址为 xx01,xx01
#define ACKTST 0x78 //从机 1 应答测试数据
#else
#define SAMASK 0x3C //从机 2 地址屏蔽位
#define SERADR 0x5A //从机 2 的地址为 xx01,10xx
#define ACKTST 0x49 //从机 2 应答测试数据
#endif
#define URMD 2 //0:使用定时器 2 作为波特率发生器
#define CMD_IDLE 0 //空闲模式
#define CMD_READ 1 //IAP 字节读命令
#define CMD_PROGRAM 2 //IAP 字节编程命令
#define CMD_ERASE 3 //IAP 扇区擦除命令
#define ENABLE_IAP 0x82 //if SYSCLK<20MHz
#define IAP_ADDRESS 0x0400
void send(unsigned temp);
/*******************************************/
void delay(uint t)
{
uint i,j;
for(i=0;i<t;i++)
{
for(j=0;j<121;j++);
}
}
/******************软件延时*****************/
void Delay1(BYTE n)
{
WORD x;
while (n--)
{
x = 0;
while (++x);
}
}
/*--------UART 中断服务程序-------------------*/
void Uart() interrupt 4 using 1
{
if(RI)
{
Buff=SBUF;
RI=0;
}
}
/*------------初始化串口---------------------*/
void InitUart()
{
SADDR=SERADR;
SADEN=SAMASK;
SCON=0x50; //8位数据,可变波特率允许接收
#if URMD==0
T2L=0xDF; //设置波特率重装值
T2H=0xFE; //9600bps(65536-11059200/4/9600)
AUXR &=0x40; //定时器1时钟为Fosc/12,即12T
AUXR&=0xFE; //串口1选择定时器1为波特率发生器
#elif URMD==1
AUXR=0x40; //定时器 1 为 1T 模式
TMOD=0x20; //设定定时器1为16位自动重装方式
TL1=0xDF; //设定定时初值
TH1=0xFE; //设定定时初值
ET1=0; //禁止定时器1中断
TR1=1; //启动定时器1
#else
TMOD=0x20; //设置定时器 1 为 8 位自动重装载模式
AUXR=0x40; //定时器 1 为 1T 模式
TL1=TH1=0xDB; // 9600 bps(256 - 11059200/32/9600)
TR1=1;
#endif
}
/*******************************************/
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
void main()
{
WORD i;
int j=0;
unsigned t;
InitUart(); //初始化串口
ES = 1;
EA = 1;
P0=0XFF;
out1=0;
out2=1;
out3=1;
delay(2000);
out1=1;
out2=0;
out3=1;
delay(2000);
out1=1;
out2=1;
out3=0;
delay(2000);
out1=1;
out2=1;
out3=1;
while (1)
{
if(!key1)
{
out1=0;
out2=0;
out3=0;
delay(2000);
out1=1;
out2=1;
out3=1;
send(0X01); //**************** 系统OK
Delay1(10); //延时
IapEraseSector(IAP_ADDRESS); //扇区擦除
for (i=0; i<512; i++) //检测是否擦除成功(全FF 检测)
{
if (IapReadByte(IAP_ADDRESS+i)!=0xff)
goto Error; //如果出错,则退出
}
send(0X0f); //P1 = 0xfc; //1111,1100 擦除成功
Delay1(10); //延时 (BYTE)
for (i=0;i<20;i++) //编程512 字节
{
IapProgramByte(IAP_ADDRESS+i,j+=1);//
out2=0;
send(j); //P1 = 0xf8; //1111,1000 编程完成
delay(200);
out2=1;
delay(200);
}
Delay1(10); //延时
for (i=0; i<20; i++) //校验512 字节i=WORD i
{
t=IapReadByte(IAP_ADDRESS+i);
send(t);
out=0;
delay(200);
out=1;
delay(200);
}
goto Error; //如果校验错误,则退出
send(0X10); //P1 = 0xf0; //1111,0000 测试完成
while (1)
{
P0=0XFF; //测试完成 无限循环
out1=0;
out2=1;
out3=1;
delay(20);
out1=1;
out2=0;
out3=1;
delay(20);
out1=1;
out2=1;
out3=0;
delay(20);
out1=1;
out2=1;
out3=1;
}
Error:
send(0X00); //P1 &= 0x7f; //0xxx,xxxx IAP 操作失败
delay(2000);
}
}
}

/***串口发送数据***********************/
void send(unsigned temp)
{
unsigned serial;
serial=temp;
SBUF=(unsigned char)temp;
while(TI!=1);
TI=0;
}
/*----------------------------
关闭IAP
----------------------------*/
void IapIdle()
{
IAP_CONTR = 0; //关闭IAP 功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP 区域
IAP_ADDRL = 0;
}
/*----------------------------
从ISP/IAP/EEPROM 区域读取一字节
----------------------------*/
BYTE IapReadByte(WORD addr)
{
BYTE dat; //数据缓冲区
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //设置IAP 命令
IAP_ADDRL = addr; //设置IAP 低地址
IAP_ADDRH = addr >> 8; //设置IAP 高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM 操作完成
dat = IAP_DATA; //读ISP/IAP/EEPROM 数据
IapIdle(); //关闭IAP 功能
return dat; //返回
}
/*----------------------------
写一字节数据到ISP/IAP/EEPROM 区域
----------------------------*/
void IapProgramByte(WORD addr, BYTE dat)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //设置IAP 命令
IAP_ADDRL = addr; //设置IAP 低地址
IAP_ADDRH = addr >> 8; //设置IAP 高地址
IAP_DATA = dat; //写ISP/IAP/EEPROM 数据
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM 操作完成
IapIdle();
}
/*----------------------------
扇区擦除
----------------------------*/
void IapEraseSector(WORD addr)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_ERASE; //设置IAP 命令
IAP_ADDRL = addr; //设置IAP 低地址
IAP_ADDRH = addr >> 8; //设置IAP 高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a)
IAP_TRIG = 0xa5; //写触发命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM 操作完成
IapIdle();
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STC8单片机读写内部EEPROM KEIL工程文件源码: /* STC8 内部EEPROM测试 从手册717页上可以看出 STC8的 EEPROM空间为1k 地址在0000h-03ffh 地址也是1024的大小 次程序结合手册 编写 大同小异 程序的主要目的是 先清楚地址0 到512 (一个扇区)的数据 然后读取 清楚扇区的数据 如果清楚成功 则读到的数据都为0xff 然后在向里写入 1-ff 1-ff 512个这样的字节 然后在读里面的字节 判断是否和写入的一样 整个过程都是通过串口在不停的上传给电脑 重点强调 更新数据一定是要先擦除整个扇区 才能更新 这是和外部E2的比较大的区别 但是和flash的写法差不多 要求 下载时 STC8 内部晶振为11.0592 电脑打开串口的波特率为9600 */ #include "stc8.h" #define u8 unsigned char #define u16 unsigned int #define CMD_IDLE 0 //空闲模式 #define CMD_READ 1 //IAP字节读命令 #define CMD_PROGRAM 2 //IAP字节编程命令 #define CMD_ERASE 3 //IAP字节擦除命令 #define ENABLE_IAP 0X82 //if SYSCLK<20MHz //测试地址 #define IAP_ADDRESS 0X0000 //从手册上可以看出 STC15F2K60S2的EEPROM地址是0x0000- 0x03ff 正好是1k的地址空间 sbit led=P5^5; //P3.5口LED灯定义 //延时函数 void delay(u8 n) { while(n--); } //关闭IAP void IapIdle() { IAP_CONTR=0; //关闭IAP功能 IAP_CMD =0; //清除命令寄存器 IAP_TRIG =0; //清楚触发寄存器 IAP_ADDRH=0X80; //将地址设置到非IAP区域 IAP_ADDRL=0; } //从ISP/IAP/EEPROM区域读取一个字节 u8 IapReadByte(u16 addr) { u8 dat; //数据缓冲区 IAP_CONTR=ENABLE_IAP; //使能IAP 同时设置等待时间 IAP_CMD=CMD_READ; //设置IAP命令 IAP_ADDRL=addr; //设置IAP低地址 IAP_ADDRH=addr>>8; //设置IAP高地址 IAP_TRIG=0X5a; //写触发命令(0x5a) 写触摸命令以后 命令才会生效 手册713页 IAP_TRIG=0Xa5; //写触发命令(0xa5) delay(10); //等待ISP/IAP/EEPROM操作完成 dat=IAP_DATA; //读ISP/IAP/EEPROM数据 IapIdle(); //关闭IAP功能 return dat; //返回 } //写一个字节数据到ISP/IAP/EEPROM区域 void IapProgramByte(u16 addr,u8 dat) { IAP_CONTR=ENABLE_IAP; //使能IAP 同时设置等待时间 IAP_CMD=CMD_PROGRAM; //设置IAP命令 IAP_ADDRL=addr; //设置IAP低地址 IAP_ADDRH=addr>>8; //设置IAP高地址 IAP_DATA=dat; //写ISP/IAP/EEPROM数据 IAP_TRIG=0X5a; //写触发命令(0x5a) 写触摸命令以后 命令才会生效 手册713页 IAP_TRIG=0Xa5; //写触发命令(0xa5) delay(10); //等待ISP/IAP/EEPROM操作完成 IapIdle(); //关闭IAP功能 } //扇区擦除 void IapEraseSector(u16 addr) { IAP_CONTR=ENABLE_IAP; //使能IAP 同时设置等待时间 IAP_CMD=CMD_ERASE; //设置IAP命令 IAP_ADDRL=addr; //设置IAP低地址 IAP_ADDR
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值