删除以地址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
{
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();
}