查看: 3041|回复: 7

STC官方EEPROM程序运行报错原因分析

[复制链接]
  • TA的每日心情
    奋斗
    2014-11-27 10:41
  • 签到天数: 40 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2014-1-3 17:23:43 | 显示全部楼层 |阅读模式
    分享到:
    如下为STC官方给的EEPROM测试读写程序,写的比较不错的,可以借用,但要遵循STC的要求:
    /*------------------------------------------------------------------*/
    /* --- STC MCU Limited ---------------------------------------------*/
    /* --- STC89-90xx Series MCU ISP/IAP/EEPROM Demo -------------------*/
    /* --- Mobile: (86)13922805190 -------------------------------------*/
    /* --- Fax: 86-755-82905966 ----------------------------------------*/
    /* --- Tel: 86-755-82948412 ----------------------------------------*/
    /* --- Web: www.STCMCU.com -----------------------------------------*/
    /* If you want to use the program or the program referenced in the  */
    /* article, please specify in which data and procedures from STC    */
    /*------------------------------------------------------------------*/

    #include <\STC\STC89C5xRC.H>

    #include <intrins.h>

    typedef unsigned char BYTE;
    typedef unsigned int WORD;

    /*Declare SFR associated with the IAP */
    sfr IAP_DATA    =   0xE2;           //Flash data register
    sfr IAP_ADDRH   =   0xE3;           //Flash address HIGH
    sfr IAP_ADDRL   =   0xE4;           //Flash address LOW
    sfr IAP_CMD     =   0xE5;           //Flash command register
    sfr IAP_TRIG    =   0xE6;           //Flash command trigger
    sfr IAP_CONTR   =   0xE7;           //Flash control register

    /*Define ISP/IAP/EEPROM command*/
    #define CMD_IDLE    0               //Stand-By
    #define CMD_READ    1               //Byte-Read
    #define CMD_PROGRAM 2               //Byte-Program
    #define CMD_ERASE   3               //Sector-Erase

    /*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
    //#define ENABLE_IAP 0x80           //if SYSCLK<40MHz
    #define ENABLE_IAP   0x81           //if SYSCLK<20MHz
    //#define ENABLE_IAP x82            //if SYSCLK<10MHz
    //#define ENABLE_IAP 0x83           //if SYSCLK<5MHz

    //Start address for STC89C58xx EEPROM
    #define IAP_ADDRESS 0x08000

    void 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 System Reset OK
        Delay(10);                      //Delay
        IapEraseSector(IAP_ADDRESS);    //Erase current sector
        for (i=0; i<512; i++)           //Check whether all sector data is FF
        {
            if (IapReadByte(IAP_ADDRESS+i) != 0xff)
                goto Error;             //If error, break
        }
        P1 = 0xfc;                      //1111,1100 Erase successful
        Delay(10);                      //Delay
        for (i=0; i<512; i++)           //Program 512 bytes data into data flash
        {
            IapProgramByte(IAP_ADDRESS+i, (BYTE)i);
        }
        P1 = 0xf8;                      //1111,1000 Program successful
        Delay(10);                      //Delay
        for (i=0; i<512; i++)           //Verify 512 bytes data
        {
            if (IapReadByte(IAP_ADDRESS+i) != (BYTE)i)
                goto Error;             //If error, break
        }
        P1 = 0xf0;                      //1111,0000 Verify successful
        while (1);
    Error:
        P1 &= 0x7f;                     //0xxx,xxxx IAP operation fail
        while (1);
    }

    /*----------------------------
    Software delay function
    ----------------------------*/
    void Delay(BYTE n)
    {
        WORD x;

        while (n--)
        {
            x = 0;
            while (++x);
        }
    }

    /*----------------------------
    Disable ISP/IAP/EEPROM function
    Make MCU in a safe state
    ----------------------------*/
    void IapIdle()
    {
        IAP_CONTR = 0;                  //Close IAP function
        IAP_CMD = 0;                    //Clear command to standby
        IAP_TRIG = 0;                   //Clear trigger register
        IAP_ADDRH = 0x80;               //Data ptr point to non-EEPROM area
        IAP_ADDRL = 0;                  //Clear IAP address to prevent misuse
    }

    /*----------------------------
    Read one byte from ISP/IAP/EEPROM area
    Input: addr (ISP/IAP/EEPROM address)
    Output:Flash data
    ----------------------------*/
    BYTE IapReadByte(WORD addr)
    {
        BYTE dat;                       //Data buffer

        IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
        IAP_CMD = CMD_READ;             //Set ISP/IAP/EEPROM READ command
        IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
        IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
        IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
        IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
        _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
        dat = IAP_DATA;                 //Read ISP/IAP/EEPROM data
        IapIdle();                      //Close ISP/IAP/EEPROM function

        return dat;                     //Return Flash data
    }

    /*----------------------------
    Program one byte to ISP/IAP/EEPROM area
    Input: addr (ISP/IAP/EEPROM address)
           dat (ISP/IAP/EEPROM data)
    Output:-
    ----------------------------*/
    void IapProgramByte(WORD addr, BYTE dat)
    {
        IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
        IAP_CMD = CMD_PROGRAM;          //Set ISP/IAP/EEPROM PROGRAM command
        IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
        IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
        IAP_DATA = dat;                 //Write ISP/IAP/EEPROM data
        IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
        IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
        _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
        IapIdle();
    }

    /*----------------------------
    Erase one sector area
    Input: addr (ISP/IAP/EEPROM address)
    Output:-
    ----------------------------*/
    void IapEraseSector(WORD addr)
    {
        IAP_CONTR = ENABLE_IAP;         //Open IAP function, and set wait time
        IAP_CMD = CMD_ERASE;            //Set ISP/IAP/EEPROM ERASE command
        IAP_ADDRL = addr;               //Set ISP/IAP/EEPROM address low
        IAP_ADDRH = addr >> 8;          //Set ISP/IAP/EEPROM address high
        IAP_TRIG = 0x46;                //Send trigger command1 (0x46)
        IAP_TRIG = 0xb9;                //Send trigger command2 (0xb9)
        _nop_();                        //MCU will hold here until ISP/IAP/EEPROM operation complete
        IapIdle();
    }

            下载后刚开始程序运行正常,但是耐心点等到最后时刻,就会发现当灯按1111,1110>1111,1100>1111,1000>0111,1000的顺序亮,可是出现0111,1000就是说明出错了,这里错误怎么产生的呢?
            原来是因为51MCU内部按一个存储单元 8 位数据进行存储的,而一个扇区512字节,2^8=256,2^9=512,最初定义的WORD型变量 i 为16位,完全可以自增到512来,但是计算机存储器这么的马虎性格,当 i = 255 的时候一个基本存储单元正好全 1 ,当 i = 256 时溢出了,而我们没有做任何处理,于是它还在存储,当然它又从 0 开始存储,而此时 i = 256 与存储单元的值 (就是0)已经不等了,于是当我们最后检验时便会报错出来,至于灯为什么这么亮是报错,请自己看程序吧!




    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2014-11-27 10:41
  • 签到天数: 40 天

    连续签到: 1 天

    [LV.5]常住居民I

     楼主| 发表于 2014-1-3 17:25:27 | 显示全部楼层
    自己先抢楼
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-5-12 10:32
  • 签到天数: 295 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2014-1-3 17:36:48 | 显示全部楼层
    顶一个~~~~~~~~~~~~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    7 小时前
  • 签到天数: 3935 天

    连续签到: 6 天

    [LV.Master]伴坛终老

    发表于 2014-1-3 17:46:11 | 显示全部楼层
    良好的编程习惯很重要
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2016-7-28 09:42
  • 签到天数: 292 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2014-1-4 10:20:32 | 显示全部楼层
    dingyigeg
    顶一个
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2014-11-27 10:41
  • 签到天数: 40 天

    连续签到: 1 天

    [LV.5]常住居民I

     楼主| 发表于 2014-1-4 14:26:39 | 显示全部楼层
    wudianjun2001 发表于 2014-1-3 19:35
    细节决定成败

    ZLG的口号啊
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2014-11-27 10:41
  • 签到天数: 40 天

    连续签到: 1 天

    [LV.5]常住居民I

     楼主| 发表于 2014-1-4 14:27:49 | 显示全部楼层
    a20084666 发表于 2014-1-4 10:20
    dingyigeg
    顶一个

    哇,啥时柳岩也来了?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2020-7-14 11:07
  • 签到天数: 1244 天

    连续签到: 54 天

    [LV.10]以坛为家III

    发表于 2014-1-4 16:37:37 | 显示全部楼层
    顶一顶一~~~~~~~~~
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-11-15 11:31 , Processed in 0.177050 second(s), 28 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.