找回密码
 立即注册
查看: 375|回复: 11

EEPROM的范例错误,建议尽快修改范例。并检查其他的范例有误类似的错误。

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2026-02-27 12:42:32
已绑定手机

1

主题

6

回帖

27

积分

新手上路

积分
27
发表于 2026-1-2 22:52:06 | 显示全部楼层 |阅读模式
stc的ISP软件给出的代码有bug,再数据定义上不严谨,是正负数,不是无符号的字节或整数,导致大于0x7f时出错。

原代码与修改的代码如下:
强烈建议stc尽快改掉,以免误导更多的使用者。
一个小小的错误可能会导致使用者花费大量的时间查找错误。

1、是源代码,2、是修改的代码
其实就是将范例中的数据类型前面加上unsigned 即可。

1、源代码:

#include "reg51.h"
#include "intrins.h"

sfr     P0M1    =   0x93;
sfr     P0M0    =   0x94;
sfr     P1M1    =   0x91;
sfr     P1M0    =   0x92;
sfr     P2M1    =   0x95;
sfr     P2M0    =   0x96;
sfr     P3M1    =   0xb1;
sfr     P3M0    =   0xb2;
sfr     P4M1    =   0xb3;
sfr     P4M0    =   0xb4;
sfr     P5M1    =   0xc9;
sfr     P5M0    =   0xca;

sfr     IAP_DATA    =   0xC2;
sfr     IAP_ADDRH   =   0xC3;
sfr     IAP_ADDRL   =   0xC4;
sfr     IAP_CMD     =   0xC5;
sfr     IAP_TRIG    =   0xC6;
sfr     IAP_CONTR   =   0xC7;
sfr     IAP_TPS     =   0xF5;

void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

char IapRead(int addr)
{
    char dat;

    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    IapErase(0x0400);
    P0 = IapRead(0x0400);                       //P0=0xff
    IapProgram(0x0400, 0x12);
    P1 = IapRead(0x0400);                       //P1=0x12

    while (1);
}


2、修改后的代码:

#include "reg51.h"
#include "intrins.h"

sfr     P0M1    =   0x93;
sfr     P0M0    =   0x94;
sfr     P1M1    =   0x91;
sfr     P1M0    =   0x92;
sfr     P2M1    =   0x95;
sfr     P2M0    =   0x96;
sfr     P3M1    =   0xb1;
sfr     P3M0    =   0xb2;
sfr     P4M1    =   0xb3;
sfr     P4M0    =   0xb4;
sfr     P5M1    =   0xc9;
sfr     P5M0    =   0xca;

sfr     IAP_DATA    =   0xC2;
sfr     IAP_ADDRH   =   0xC3;
sfr     IAP_ADDRL   =   0xC4;
sfr     IAP_CMD     =   0xC5;
sfr     IAP_TRIG    =   0xC6;
sfr     IAP_CONTR   =   0xC7;
sfr     IAP_TPS     =   0xF5;

void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

unsigned char IapRead(unsigned int addr)
{
    unsigned char dat;

    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(unsigned int addr, unsigned char dat)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(unsigned int addr)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    IapErase(0x0400);
    P0 = IapRead(0x0400);                       //P0=0xff
    IapProgram(0x0400, 0x12);
    P1 = IapRead(0x0400);                       //P1=0x12

    while (1);
}




回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2026-02-27 12:42:32
已绑定手机

1

主题

6

回帖

27

积分

新手上路

积分
27
发表于 2026-1-3 15:57:09 | 显示全部楼层
用原来的范例程序,下面的语句就会出错,编译后运行永远是 i=2,即使EEPROM单元0x100的数值=0xaa
unsigned char data i;
i = 0;
IapProgram(0x0100, 0xaa);
if (IapRead(0x100) == 0xaa)  //读取0x100地址的内容是否为0xaa
{
  i =1;
}
else
{
  i = 2;
}
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2026-02-27 12:42:32
已绑定手机

1

主题

6

回帖

27

积分

新手上路

积分
27
发表于 2026-1-3 16:11:59 | 显示全部楼层
原来的范例程序,下面的语句就会出错,编译后运行永远是 i=2,即使EEPROM单元0x100的数值=0xaa
unsigned char data i;
i = 0;
IapProgram(0x0100, 0xaa);
if (IapRead(0x100) == 0xaa)  //读取0x100地址的内容是否为0xaa
{
  i =1;
}
else
{
  i = 2;
}
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:724
  • 最近打卡:2026-03-18 07:56:47
已绑定手机

97

主题

7244

回帖

1万

积分

超级版主

积分
13791
发表于 2026-1-3 10:39:18 | 显示全部楼层
是的,严谨的不参与负数计算的一律unsigned
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:252
  • 最近打卡:2026-03-19 10:28:30
已绑定手机

22

主题

627

回帖

2322

积分

金牌会员

积分
2322
发表于 2026-1-3 12:27:27 | 显示全部楼层
负数也没问题的
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:178
  • 最近打卡:2026-03-22 02:05:49

25

主题

231

回帖

2059

积分

金牌会员

积分
2059
发表于 2026-1-3 13:39:52 来自手机 | 显示全部楼层
无符号数右移,高位补零。
有符号数右移,高位补符号位。如果是负数,移入的是1。
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2026-02-27 12:42:32
已绑定手机

1

主题

6

回帖

27

积分

新手上路

积分
27
发表于 2026-1-3 15:59:35 | 显示全部楼层
如果把范例中的程序改为:
unsigned char IapRead(unsigned int addr)
{
    unsigned char dat;
   …………
  return dat;
}

运行后就符合预期。
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2026-02-27 12:42:32
已绑定手机

1

主题

6

回帖

27

积分

新手上路

积分
27
发表于 2026-1-3 16:01:11 | 显示全部楼层
如果把范例中的程序改为:
unsigned char IapRead(unsigned int addr)
{
    unsigned char dat;
   …………
  return dat;
}

运行后就符合预期。
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:6
  • 最近打卡:2026-02-27 12:42:32
已绑定手机

1

主题

6

回帖

27

积分

新手上路

积分
27
发表于 2026-1-3 16:06:49 | 显示全部楼层
如果这样做也可以避坑:

usigned char i;

i = IapRead(0x100);
if (i == 0xaa)
{

}

但是还是建议将原来中的char改为unsigned char,地址int改为unsigned int
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2026-03-20 16:42:01

7

主题

13

回帖

413

积分

中级会员

积分
413
发表于 2026-1-3 17:17:54 | 显示全部楼层
原来的例程没错。
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-22 06:24 , Processed in 0.113711 second(s), 92 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表