• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

STC15系列内部EEPROM怎样应用

最近想用STC单片机做一个LED调光台灯,采用PWM调光,用内部EEPROM做掉电记忆。参考了STC官网上的EEPROM测试程序,测试了一下,一切正常,可是加到自己的程序里,编译没问题,就是存储不正常表现是不论关机前调到任何亮度,关机后再开都是最大亮度。已经调试2天了,就是无法存储求各位大侠指点一二,不胜感激
全部回复(21)
正序查看
倒序查看
2017-01-06 22:19
下面把程序贴上来
/**************************************************/
#include
#include
#define uchar unsigned char  
#define uint 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
#define IAP_ADDRESS  0x00
sbit led0=P3^4;
sbit led1=P3^5;
sbit add=P3^3;
sbit wsw=P3^2;
sbit doc=P3^1;
sbit footsw=P3^0;
uchar bright;
uchar flag=0;
uint i=0;
/****************关闭IAP********************************/
void  IAPIdle()
{
IAP_CONTR   =0;  //关闭IAP功能
IAP_CMD     =0;  //清除命令寄存器
IAP_TRIG    =0;  //清除触发寄存器
IAP_ADDRH   =0x80;  //将地址设置到非IAP区域
IAP_ADDRL   =0;  //
/****************从EEPROM读一字节**************************/
uchar IAPReadByte(uchar addr)
{
uchar 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_();  //等待EEPROM操作完成
dat=IAP_DATA;  //读EEPROM数据
IAPIdle();  //关闭IAP
return dat;  //返回数据
}
/***************写一字节到EEPROM**************************/
void  IAPProgramByte(uchar addr,uchar dat)
{
IAP_CONTR   =ENABLE_IAP;  //使能IAP
IAP_CMD     =CMD_PROGRAM; //设置IAP命令
IAP_ADDRL   =addr;  //设置IAP底地址
IAP_ADDRH   =addr>>8;  //设置IAP高地址
IAP_DATA=dat;  //写EEPROM数据
IAP_TRIG    =0x5a;  //写触发命令0x5a
IAP_TRIG    =0xa5;  //写触发命令0xa5
_nop_();  //等待EEPROM操作完成
IAPIdle();  //关闭IAP
}
/**************扇区擦除**********************************/
void IAPEraseSector(uint 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_();  //等待EEPROM操作完成
IAPIdle();  //关闭IAP
}
/*******************延时程序1ms********************
void delay1ms(uint a){
uchar i;
while(--a !=0){
for(i=0;i<600;i++);
}
}
/*************************************************/
void delay(uchar z)
{
        TMOD=0x02; //定时器0工作方式2,8位自动重装
        TH0=256-60;
    AUXR |= (1<<7); //T0设为1T 
        EA=1;
        ET0=1;
        TR0=1;
        while(i
        i = 0;
}
/*******************驱动程序**********************/
void drive (void){
uchar a;
if(footsw==0){
a=0x10;
}
else{
a=bright;
}
   switch(flag){
    case 0:
led0=led1=0;
delay(a);
a=~a;
led0=led1=1;
delay(a);
a=~a;
break;
         case 1:
led0=1;
led1=0;
delay(a);
a=~a;
led0=led1=1;
delay(a);
a=~a;
break;
  case 2:
led0=0;
led1=1;
delay(a);
a=~a;
led0=led1=1;
delay(a);
a=~a;
break;
 }
}
/*******************亮度加程序********************/
void Add (void){
if(add==0){
bright++;
if(bright>0xfe){
bright=0xfe;
}
IAPProgramByte(IAP_ADDRESS,bright); //掉电保存标志
}
}
/*******************亮度减程序*********************/
void Doc (void){
if(doc==0){
bright--;
if(bright<0x05){
bright=0x05;
}
IAPProgramByte(IAP_ADDRESS,bright); //掉电保存标志
}
}
/*******************主程序**************************/
void main (void){
PCON = PCON & ~(1<<5); //低压检测标志清0
ELVD = 1; //低压监测中断允许
PLVD = 1; //低压中断 优先级高
EA  = 1;
IE=0x81;
IT0=1;
bright= IAPReadByte(IAP_ADDRESS);
IAPEraseSector(IAP_ADDRESS);
add=1;
while(1){
drive();
Add();
Doc();
// IAPProgramByte(IAP_ADDRESS,bright); //掉电保存值
}
}
/****************************************************/
void timer0() interrupt 1
{
      i++;
}
/***************************************************/
void INT0() interrupt 0
{
EX0=0;
flag++;   
if(flag>=3){
flag=0 ;
}
EX0=1;
}
/****************掉电检测服务程序*******************/
void LVD_Routine(void) interrupt 6
{
IAPProgramByte(IAP_ADDRESS,bright); //掉电保存值
  while(PCON & (1<<5))                        //检测是否仍然低电压
        {
                PCON = PCON & ~(1<<5);                //低压检测标志清0
                for(i=0; i<100; i++)        ;        //延时一下
        }
}

/*************************************************/

请大侠指点,程序哪里有问题,小菜感激不尽。。。。。。

0
回复
2017-01-06 22:55
@流淌的歌声1104
下面把程序贴上来/**************************************************/#include#include#defineucharunsignedchar #defineuintunsigned int #defineCMD_IDLE  0//空闲模式#defineCMD_READ  1//IAP字节读命令#defineCMD_PROGRAM 2//IAP字节编程命令#defineCMD_ERASE  3//IAP扇区擦除命令#defineENABLE_IAP 0x82#defineIAP_ADDRESS 0x00sbitled0=P3^4;sbitled1=P3^5;sbitadd=P3^3;sbitwsw=P3^2;sbitdoc=P3^1;sbitfootsw=P3^0;ucharbright;ucharflag=0;uinti=0;/****************关闭IAP********************************/void IAPIdle(){IAP_CONTR =0; //关闭IAP功能IAP_CMD  =0; //清除命令寄存器IAP_TRIG  =0; //清除触发寄存器IAP_ADDRH =0x80; //将地址设置到非IAP区域IAP_ADDRL =0; //} /****************从EEPROM读一字节**************************/ucharIAPReadByte(ucharaddr){uchardat; //数据缓冲区IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_READ; //设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成dat=IAP_DATA; //读EEPROM数据IAPIdle(); //关闭IAPreturndat; //返回数据}/***************写一字节到EEPROM**************************/void IAPProgramByte(ucharaddr,uchardat){IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_PROGRAM;//设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_DATA=dat; //写EEPROM数据IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成IAPIdle(); //关闭IAP}/**************扇区擦除**********************************/voidIAPEraseSector(uintaddr){IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_ERASE; //设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成IAPIdle(); //关闭IAP}/*******************延时程序1ms********************voiddelay1ms(uinta){uchari;while(--a!=0){for(i=0;i
单片机型号是STC15F104E或15W104,6个IO全部用完

0
回复
2017-01-08 16:53
@流淌的歌声1104
单片机型号是STC15F104E或15W104,6个IO全部用完[图片][图片]

下面是掉电存储测试程序

/*******************************************************
  STC15W104 掉电保存EEPROM测试
  测试芯片工作频率为11.0592MHz
/********************************************************/
#include
#include
#define uchar unsigned char  
#define uint unsigned  int
#define ENABLE_IAP  0x82
#define IAP_ADDRESS  0x0000
#define CMD_IDLE    0   //空闲模式
#define CMD_READ    1   //IAP字节读命令
#define CMD_PROGRAM 2   //IAP字节编程命令
#define CMD_ERASE 3   //IAP扇区擦除命令
uchar bright;
sbit P30 = P3^0;
/***************延时程序*********************************/
void  Delay(uchar n)
{
uint 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;  //
/****************从EEPROM读一字节**************************/
uchar IAPReadByte(uint addr)
{
uchar 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_();  //等待EEPROM操作完成
dat=IAP_DATA;  //读EEPROM数据
IAPIdle();  //关闭IAP
return dat;  //返回数据
}
/***************写一字节到EEPROM**************************/
void  IAPProgramByte(uint addr,uchar dat)
{
IAP_CONTR   =ENABLE_IAP;  //使能IAP
IAP_CMD     =CMD_PROGRAM; //设置IAP命令
IAP_ADDRL   =addr;  //设置IAP底地址
IAP_ADDRH   =addr>>8;  //设置IAP高地址
IAP_DATA=dat;  //写EEPROM数据
IAP_TRIG    =0x5a;  //写触发命令0x5a
IAP_TRIG    =0xa5;  //写触发命令0xa5
_nop_();  //等待EEPROM操作完成
IAPIdle();  //关闭IAP
}
/**************扇区擦除**********************************/
void IAPEraseSector(uint 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_();  //等待EEPROM操作完成
IAPIdle();  //关闭IAP
}
/**************主函数***********************************/
void main()
{
//   Delay(10);
PCON = PCON & ~(1<<5); //低压检测标志清0
ELVD = 1; //低压监测中断允许
PLVD = 1; //低压中断 优先级高
EA  = 1;
bright=IAPReadByte(IAP_ADDRESS);
if(bright != 0xf2) bright = 0x00;
IAPEraseSector(IAP_ADDRESS); //扇区擦除
P3=bright; //1111,1110系统OK
Delay(10); //延时
while(1);
/**********************************************/
void LVD_Routine(void) interrupt 6
{
bright = 0xf2;
IAPProgramByte(IAP_ADDRESS,bright ); //掉电保存值
}
/*************************************************/

0
回复
2017-01-08 22:08
@流淌的歌声1104
下面是掉电存储测试程序/******************************************************* STC15W104掉电保存EEPROM测试 测试芯片工作频率为11.0592MHz/********************************************************/#include#include#defineucharunsignedchar #defineuintunsigned int#defineENABLE_IAP 0x82#defineIAP_ADDRESS 0x0000#defineCMD_IDLE  0 //空闲模式#defineCMD_READ  1 //IAP字节读命令#defineCMD_PROGRAM2 //IAP字节编程命令#defineCMD_ERASE3 //IAP扇区擦除命令ucharbright;sbitP30=P3^0;/***************延时程序*********************************/void Delay(ucharn){uintx;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; //} /****************从EEPROM读一字节**************************/ucharIAPReadByte(uintaddr){uchardat; //数据缓冲区IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_READ; //设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成dat=IAP_DATA; //读EEPROM数据IAPIdle(); //关闭IAPreturndat; //返回数据}/***************写一字节到EEPROM**************************/void IAPProgramByte(uintaddr,uchardat){IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_PROGRAM;//设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_DATA=dat; //写EEPROM数据IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成IAPIdle(); //关闭IAP}/**************扇区擦除**********************************/voidIAPEraseSector(uintaddr){IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_ERASE; //设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成IAPIdle(); //关闭IAP}/**************主函数***********************************/voidmain(){// Delay(10);PCON=PCON&~(1
你用的是掉电时低压检测再保存数据
0
回复
2017-01-09 11:10
已经被添加到社区经典图库喽
http://www.dianyuan.com/bbs/classic/
0
回复
曾兵
LV.2
7
2017-01-10 11:21
@流淌的歌声1104
单片机型号是STC15F104E或15W104,6个IO全部用完[图片][图片]
你好,我个人认为是你的设计思路出问题了,你采用掉点检测存储,EEPROM在电压下是不建议对其进行读写操作的,如果要采用掉点再存储,应该留一个端口对电源电压进行检测,把单片两端的电容加大是电源电压掉电后单片机要维持工作一段时间来对数据进行处理。或者每次调光的数据都要优先保存在EEPROM里面,然后再读出操作然后再保存。
0
回复
2017-01-12 16:34
@曾兵
你好,我个人认为是你的设计思路出问题了,你采用掉点检测存储,EEPROM在电压下是不建议对其进行读写操作的,如果要采用掉点再存储,应该留一个端口对电源电压进行检测,把单片两端的电容加大是电源电压掉电后单片机要维持工作一段时间来对数据进行处理。或者每次调光的数据都要优先保存在EEPROM里面,然后再读出操作然后再保存。

你好,曾老师,我仔细研究了STC15系列的官方资料,它内部有一个低压中断,检测到VCC下降到某一电压,比如3.82V时会产生中断。另外,EEPROM官方资料只是不建议低压时操作,并不是不能操作。官方下载软件上有低压时禁止操作EEPROM选项,不勾选就可以了。这样我就可以利用低压中断来存储数据了。我的测试程序就是就是掉电存储。EEPROM可以操作10000次以上,也许我的灯用坏了,EEPROM也不会坏,可是现在是不用掉电中断,每次调光都存储也不行

0
回复
2017-01-12 16:37
@lihui710884923
你用的是掉电时低压检测再保存数据
是的,旅长
0
回复
2017-01-12 16:40
@电源网-fqd
已经被添加到社区经典图库喽http://www.dianyuan.com/bbs/classic/
谢谢!
0
回复
曾兵
LV.2
11
2017-01-13 10:34
@流淌的歌声1104
你好,曾老师,我仔细研究了STC15系列的官方资料,它内部有一个低压中断,检测到VCC下降到某一电压,比如3.82V时会产生中断。另外,EEPROM官方资料只是不建议低压时操作,并不是不能操作。官方下载软件上有低压时禁止操作EEPROM选项,不勾选就可以了。这样我就可以利用低压中断来存储数据了。我的测试程序就是就是掉电存储。EEPROM可以操作10000次以上,也许我的灯用坏了,EEPROM也不会坏[图片],可是现在是不用掉电中断,每次调光都存储也不行[图片]
曾老师这个称呼我可受不起啊,我也是懂点皮毛而已,要学习的东西还很多,只看你的程序有一点需要修改一下void Add (void){
if(add==0){
bright++; 按键程序后面应该加防抖延时void Add (void){
if(add==0){ delay();if(add==0){
bright++;

}

#define IAP_ADDRESS  0x00这个地址是不是应该为0X0000;

0
回复
2017-01-13 17:25
@曾兵
曾老师这个称呼我可受不起啊,我也是懂点皮毛而已,要学习的东西还很多,只看你的程序有一点需要修改一下voidAdd(void){if(add==0){bright++; 按键程序后面应该加防抖延时voidAdd(void){if(add==0){ delay();if(add==0){bright++;}#defineIAP_ADDRESS 0x00这个地址是不是应该为0X0000;
0
回复
yorkhu
LV.1
13
2017-01-16 18:03

用掉电侦测来保存EEPROM 是非常不科学的,不知道你测量过从掉电开始到MCU停止大概要多长时间,而EERPOM的写又需要多长时间,即便时间够我也是不推荐这种写法的

如果一定要这样做可以如下:

1.你可以在供电上加个外部电源检测电路比如分压,来检测外部是否断电,这个比MCU的低压中断来得早得多

2.MCU供电用二极管与外部电源隔开,并加大电容,当外部掉电之后,确保MCU还有足够的电执行EEPROM操作

3.每次EEPROM操作前都是需要先擦除,再写入

0
回复
2017-01-16 22:30
@曾兵
曾老师这个称呼我可受不起啊,我也是懂点皮毛而已,要学习的东西还很多,只看你的程序有一点需要修改一下voidAdd(void){if(add==0){bright++; 按键程序后面应该加防抖延时voidAdd(void){if(add==0){ delay();if(add==0){bright++;}#defineIAP_ADDRESS 0x00这个地址是不是应该为0X0000;
三人行,必有我师!何况您确实比我懂得多。感谢老师与我一菜鸟讨论。您说的Add==0后面需不需要延时,我是这么想的:后面的变量bright是自加1,后面去掉了while(Add==0),不需要等待Add弹起,这样的效果是按键按下后接着抬手,变量bright可能加1,也可能加2或更多,这对brightL来说不重要,因为我就想要他连加。如果按下Add不放,bright就会连加,直到放手。如果嫌他加的速度过快,可以加一点延时。如果想让他乖乖的每按一次只加1,那延时是必须的,而且后面必须加上等按键弹起的语句while(Add==0)。
0
回复
2017-01-16 22:32
@yorkhu
用掉电侦测来保存EEPROM是非常不科学的,不知道你测量过从掉电开始到MCU停止大概要多长时间,而EERPOM的写又需要多长时间,即便时间够我也是不推荐这种写法的如果一定要这样做可以如下:1.你可以在供电上加个外部电源检测电路比如分压,来检测外部是否断电,这个比MCU的低压中断来得早得多2.MCU供电用二极管与外部电源隔开,并加大电容,当外部掉电之后,确保MCU还有足够的电执行EEPROM操作3.每次EEPROM操作前都是需要先擦除,再写入
说的对,我只是想试验一下
0
回复
曾兵
LV.2
16
2017-01-17 10:12
@流淌的歌声1104
三人行,必有我师!何况您确实比我懂得多。感谢老师与我一菜鸟讨论。您说的Add==0后面需不需要延时,我是这么想的:后面的变量bright是自加1,后面去掉了while(Add==0),不需要等待Add弹起,这样的效果是按键按下后接着抬手,变量bright可能加1,也可能加2或更多,这对brightL来说不重要,因为我就想要他连加。如果按下Add不放,bright就会连加,直到放手。如果嫌他加的速度过快,可以加一点延时。如果想让他乖乖的每按一次只加1,那延时是必须的,而且后面必须加上等按键弹起的语句while(Add==0)。
大家都是相互学习,共同进步,
0
回复
lanming77
LV.1
17
2017-01-17 16:50
为什么要掉电储存呢? 可以在按键按下加或减就存储一次bright 值 ,开机先读取EEPROM内bright值就可以复原了。
0
回复
cxflbh
LV.3
18
2017-01-18 09:42
@lanming77
为什么要掉电储存呢?可以在按键按下加或减就存储一次bright值,开机先读取EEPROM内bright值就可以复原了。

根本就没必要掉电存储,我都是先把存储的值和设定值做比较,不相等再存。比如:

if(power_set!=IapReadByte(POWER_IAP_ADDRESS))  //功率保存       

 {

POWER_write(); //保存功率设定值

 jizun_voltage(power_set);  //输出基准电压

}

0
回复
2017-01-18 21:55
@cxflbh
根本就没必要掉电存储,我都是先把存储的值和设定值做比较,不相等再存。比如:if(power_set!=IapReadByte(POWER_IAP_ADDRESS)) //功率保存     {POWER_write();//保存功率设定值 jizun_voltage(power_set); //输出基准电压}
数据改变一次就写一次eeprom,
0
回复
2017-01-19 22:38
@lihui710884923
数据改变一次就写一次eeprom,

感谢大家的热心帮助,我的程序终于调试成功了!不成功的原因是每次开机或复位后要加一定的延时,比如100ms,甚至10ms有时都可以,比如上面的掉电测试程序。今天闲来无事翻看一本杂志,看到一篇关于EEPROM应用的文章,其中有一句话说上电后一定要延时几百毫秒待电源稳定后再进行EEPROM操作,否则极易操作失败。我赶紧打开电脑,在main函数最前面加上了100ms延时后,编译,下载到单片机,哈哈,操作成功!心中不免有些感慨,想起杜洋老师在他著的《爱上单片机》一书中的一句话:我和单片机一起玩耍,我玩它时,它总能给我带来幸福和成就感。它玩我的时候,我总会烦躁,不知所措,可是耐心研究之后发现过错总是出在我的马虎大意。我早应该发现我的测试程序里有一个10ms的延时程序有需要的亲们可以在楼上程序里加上100ms延时后直接用!

通过实验,掉电存储是可行的,因为EEPROM操作需要较长时间,影响其他程序运行,另外存储次数也是有限的,如果变量操作频繁,一天几百上千次,那就用不了多长时间了,所以,这个实验还是有意义的

0
回复
2017-01-19 22:48
@流淌的歌声1104
下面把程序贴上来/**************************************************/#include#include#defineucharunsignedchar #defineuintunsigned int #defineCMD_IDLE  0//空闲模式#defineCMD_READ  1//IAP字节读命令#defineCMD_PROGRAM 2//IAP字节编程命令#defineCMD_ERASE  3//IAP扇区擦除命令#defineENABLE_IAP 0x82#defineIAP_ADDRESS 0x00sbitled0=P3^4;sbitled1=P3^5;sbitadd=P3^3;sbitwsw=P3^2;sbitdoc=P3^1;sbitfootsw=P3^0;ucharbright;ucharflag=0;uinti=0;/****************关闭IAP********************************/void IAPIdle(){IAP_CONTR =0; //关闭IAP功能IAP_CMD  =0; //清除命令寄存器IAP_TRIG  =0; //清除触发寄存器IAP_ADDRH =0x80; //将地址设置到非IAP区域IAP_ADDRL =0; //} /****************从EEPROM读一字节**************************/ucharIAPReadByte(ucharaddr){uchardat; //数据缓冲区IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_READ; //设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成dat=IAP_DATA; //读EEPROM数据IAPIdle(); //关闭IAPreturndat; //返回数据}/***************写一字节到EEPROM**************************/void IAPProgramByte(ucharaddr,uchardat){IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_PROGRAM;//设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_DATA=dat; //写EEPROM数据IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成IAPIdle(); //关闭IAP}/**************扇区擦除**********************************/voidIAPEraseSector(uintaddr){IAP_CONTR =ENABLE_IAP; //使能IAPIAP_CMD  =CMD_ERASE; //设置IAP命令IAP_ADDRL =addr; //设置IAP底地址IAP_ADDRH =addr>>8; //设置IAP高地址IAP_TRIG  =0x5a; //写触发命令0x5aIAP_TRIG  =0xa5; //写触发命令0xa5_nop_(); //等待EEPROM操作完成IAPIdle(); //关闭IAP}/*******************延时程序1ms********************voiddelay1ms(uinta){uchari;while(--a!=0){for(i=0;i

void main (void){

    DELAY_MS(100);//在此处加入100ms延时就OK!

    以下省略

0
回复
2017-02-14 08:55
之前我用的STC11F01看了数据手册很简单,eeprom是死的,先调试出来可以调光的,然后在调光的后边加保存到rom的语句,这样每调一次保存一次。烧进去。在把程序开始读取改为读取之前的地址,再烧进去就可以了。
0
回复