对STC15系列单片机EEPROM使用感受

来源:互联网 发布:淘宝九一一正品折扣店 编辑:程序博客网 时间:2024/05/20 03:07

#include "reg51.h"#include "intrins.h"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控制寄存器#define CMD_IDLE    0               //空闲模式#define CMD_READ    1               //IAP字节读命令#define CMD_PROGRAM 2               //IAP字节编程命令#define CMD_ERASE   3               //IAP扇区擦除命令//#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//测试地址#define IAP_ADDRESS 0x0400void Delay(BYTE n);void IapIdle();BYTE IapReadByte(WORD addr);void IapProgramByte(WORD addr, BYTE dat);void IapEraseSector(WORD addr);void main(){    WORD i;    P1 = 0xfe;                      //1111,1110 系统OK    Delay(10);                      //延时    IapEraseSector(IAP_ADDRESS);    //扇区擦除    for (i=0; i<512; i++)           //检测是否擦除成功(全FF检测)    {        if (IapReadByte(IAP_ADDRESS+i) != 0xff)            goto Error;             //如果出错,则退出    }    P1 = 0xfc;                      //1111,1100 擦除成功    Delay(10);                      //延时    for (i=0; i<512; i++)           //编程512字节    {        IapProgramByte(IAP_ADDRESS+i, (BYTE)i);    }    P1 = 0xf8;                      //1111,1000 编程完成    Delay(10);                      //延时    for (i=0; i<512; i++)           //校验512字节    {        if (IapReadByte(IAP_ADDRESS+i) != (BYTE)i)            goto Error;             //如果校验错误,则退出    }    P1 = 0xf0;                      //1111,0000 测试完成    while (1);Error:    P1 &= 0x7f;                     //0xxx,xxxx IAP操作失败    while (1);}/*----------------------------软件延时----------------------------*/void Delay(BYTE n){    WORD x;    while (n--)    {        x = 0;        while (++x);    }}/*----------------------------关闭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();}


这是官方的实例,在测试中总是读不到数据。搞了好长时间也没有找到问题问题,没办法,在官方手册上查找了参数,发现//测试地址#define IAP_ADDRESS 0x0400错了,应该是从//测试地址#define IAP_ADDRESS 0x0000开始,改成就可以了,可以写入数据,关机也可以读取到数据。

但我操作是只写入一个字节,在原程序上改了下,发现还是不能用,从串口反馈过来的数据发现数据不能写入,每次写指令都给定了,但数据就是写不进去,参考别的资料,感觉写入前都发必须先读取出来数据,保存。在擦除一次EEPROM,在把改好的数据写入,把程序写好,测试从串口反馈出来数据都正常了。

这功能很不错,不用外加EEPROM芯片,可以实现功能带记忆,可以存取设定的状态,在下次在开机,执行上次关机的状态。   这次也学会怎样读写EEPROM,平时对EEPROM芯片打交道也很多的,一般都是用编程器来读写的。总感觉很神密的。下回有空自己写个来读取的转机。


0 0