280987343 发表于 2011-8-19 18:03:56

STC15F104E eeprom技术求助,高手过来顶下啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

本人参照宏晶的eeprom程序,验证STC15F104E eeprom的功能,但现在编译出来后,功能是实现了,但程序运行到状态5后,关掉电源,再通电,状态能保存,但按键就失灵了,程序就想是跑飞了一样,有没有高手知道是什么原因啊?而且刚上电时要按好几下按键,灯才会亮。真心求解,还望各位大侠帮忙分析下,不胜感激!
#include<stc_new_8051.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
//定义EEPROM的操作命令
#define Idlecommand 0x00       
#define Rdcommand 0x01       
#define Prgcommand 0x02
#define Erasecommand 0x03

sfr IAP_data=0xc2;   //Flash数据寄存器申明
sfr IAP_addrh=0xc3;           //Flash高字节地址寄存器申明
sfr IAP_addrl=0xc4;           //Flash低字节地址寄存器申明
sfr IAP_cmd=0xc5;           //Flash命令模式寄存器申明
sfr IAP_trig=0xc6;           //Flash命令触发寄存器申明
sfr IAP_contr=0xc7;           //ISP/IAP控制寄存器申明

#define Enable_IAP 0x81//晶振<24M

sbit key=P3^5;                   //按键定义
sbit red=P3^2;                   //红灯管脚定义
sbit blue=P3^4;                   //蓝灯管脚定义
uchar temp=0x01;
//************ N*1ms延时程序********
void delay(uint ms)
{
        uchar a;
        while(ms--)
        for(a=110;a>0;a--);
}
//************ 初始化程序************
void init()
{
        blue=1;
        red=1;
}
//************ 关闭ISP,IAP功能************
void ISP_IAP_disable(void)
{
          IAP_contr=0;
          IAP_cmd=0;
          IAP_trig=0;
          IAP_addrh=0x80;
          IAP_addrl=0;
}

//************ 字节读************
uchar byte_read(uint byte_addr)
{
       uchar dat;
       IAP_contr=Enable_IAP;
       IAP_cmd=Rdcommand;
       IAP_addrl=byte_addr;
       IAP_addrh=byte_addr>>8;
       IAP_trig=0x5a;
       IAP_trig=0xa5;
       _nop_();
       dat=IAP_data;
       ISP_IAP_disable();
       return dat;
}
//************ 扇区擦除************
void Setorerase(uint sector_addr)
{
        IAP_contr=Enable_IAP;
        IAP_cmd=Erasecommand;
        IAP_addrl=sector_addr;
        IAP_addrh=sector_addr>>8;
        IAP_trig=0x5a;
        IAP_trig=0xa5;
        _nop_();
        ISP_IAP_disable();
}
//************ 字节写************
void byte_write(uint byte_addr,uchar original_data)
{
        IAP_contr=Enable_IAP;
        IAP_cmd=Prgcommand;
        IAP_addrl=byte_addr;
        IAP_addrh=byte_addr>>8;
        IAP_data=original_data;
        _nop_();
        IAP_trig=0x5a;
        IAP_trig=0xa5;
        _nop_();
        ISP_IAP_disable();
}
//************ 按键程序************
void KEY()
{               
   
        if(key==0)
        {
                delay(10);
                if(key==0)
                {
                        temp++;
                               
                        switch(temp)
                        {
                        case 0x01:                //状态一
                                        red=1;
                                        blue=1;
                                        break;
                        case 0x02:               //状态二
                                        red=0;
                                        blue=1;
                                        break;
                        case 0x03:               //状态三
                                        red=1;
                                        blue=0;
                                        break;
                        case 0x04:               //状态四
                                        red=0;
                                        blue=0;
                                        break;
                        case 0x05:               //状态五
                                        red=1;
                                        blue=1;
                                        break;
                        }
                        Setorerase(0x0000);//擦除扇区
                        byte_write(0x0000,temp);//重新写入数据
                        if(temp==0x05)temp=0x01;       //设定返回值
                        while(!key);
                }                               //判断按键释放
        }
}
//************ 主程序************
void main()
{       
        init();                                               //初始化
        temp=byte_read(0x0000);                //读EEPROM数据
        switch(temp)
                        {
                        case 0x01:                //状态一
                                        red=1;
                                        blue=1;
                                        break;
                        case 0x02:               //状态二
                                        red=0;
                                        blue=1;
                                        break;
                        case 0x03:               //状态三
                                        red=1;
                                        blue=0;
                                        break;
                        case 0x04:               //状态四
                                        red=0;
                                        blue=0;
                                        break;
                        case 0x05:               //状态五
                                        red=1;
                                        blue=1;
                                        break;
                        }
        while(1)
        {
                KEY();
        }                                                                          
}

longwu911 发表于 2011-8-19 22:17:18

你程序有太多缺陷了,KEY函数在哪调用?

280987343 发表于 2011-8-20 17:18:02

回复【1楼】longwu911
你程序有太多缺陷了,key函数在哪调用?
-----------------------------------------------------------------------

有很多缺陷?可以说清楚点嘛?key在最后的主函数里啊!
while(1)
{
KEY();
}   
}

280987343 发表于 2011-8-21 17:23:00

高手,大虾们都跑哪去了?我需要你们!!!

280987343 发表于 2011-8-22 12:40:03

没人顶,我自己顶!精诚所至,铁石会开!

280987343 发表于 2011-8-23 13:03:18

继续顶!

280987343 发表于 2011-8-23 18:39:40

自己自顶起来!!!!

tobyliu415 发表于 2011-8-23 19:09:55

首先,风格太差,不出问题是奇迹
temp作为全局变量是极其不好的习惯,其次temp的switch/case语句没有default。
再次,temp=5以后++,变成6就没有人管了

最后
注意这个顺序:

//temp==5
byte_write(0x0000,temp);//重新写入数据
if(temp==0x05)temp=0x01;//设定返回值

//下次启动
temp=byte_read(0x0000); //读EEPROM数据
//temp==5
KEY()
temp++
//temp==6 ????有问题吗?

hnzhy870215 发表于 2011-8-23 19:39:50

给个用的木有问题的你换一下试试,用在STC11F03E的程序,建议你程序换别的型号跑,测试正常后在换回STC15F104E,之前用这颗IC
外部中断是有问题的。所以你还是换别的型号确认程序没问题后在换回来。
/***************************
    STC11F03EEEPROM
***************************
IAP_DATA数据寄存器
IAP_ADDRH 地址寄存器高八位
IAP_ADDRL 地址寄存器低八位
IAP_CMD   命令寄存器
IAP_TRIG命令触发寄存器
          写入5AH,在写入A5H 命令才会生效
IAP_CONTR ISP_IAP命令寄存器
****************************/
#define isp_dataIAP_DATA
#define isp_addrh IAP_ADDRH
#define isp_addrl IAP_ADDRL
#define isp_cmd   IAP_CMD
#define isp_trigIAP_TRIG
#define isp_contr IAP_CONTR
void IAP_Disable()
{
    //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
    //一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
    isp_contr = 0;      //关闭IAP 功能
    isp_cmd   = 0;      //清命令寄存器,使命令寄存器无命令,此句可不用
    isp_trig= 0;      //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
    isp_addrh = 0;
    isp_addrl = 0;
}
void eeprom_eares(unsigned int addres)//扇区擦除。
   {
      isp_addrl=addres;   //低位地址
      isp_addrh=addres>>8; //高位地址
      isp_contr=0x03;//设置等待时间
      isp_contr=isp_contr|0x80; //设时间与ISP操作。
      isp_cmd=0x03;         //扇区命命令
      isp_trig=0x5a;      //触发
      isp_trig=0xa5;      //触发启动。
      delay(1);
      IAP_Disable();//关闭IAP 功能
   }
void eeprom_write(unsigned int addres,unsigned char write_data)//写数据。
   {
      isp_data=write_data;   //要写入的数据。
      isp_addrl=addres;   //低位地址
      isp_addrh=addres>>8; //高位地址
      isp_contr=0x03; //设置等待时间
      isp_contr=isp_contr|0x80; //设时间与ISP操作。
      isp_cmd=0x02;         //写命令
      isp_trig=0x5a;      //触发
      isp_trig=0xa5;      //触发启动。
      delay(1);
      IAP_Disable();//关闭IAP 功能
      }
unsigned char eeprom_read(unsigned int addres)//读数据
   {
      unsigned char z;
      isp_addrl=addres;   //低位地址
      isp_addrh=addres>>8; //高位地址
      isp_contr=0x03; //设置等待时间
      isp_contr=isp_contr|0x80; //设时间与ISP操作。
      isp_cmd=0x01;         //读命令
      isp_trig=0x5a;      //触发
      isp_trig=0xa5;      //触发启动。
      delay(1);
      IAP_Disable();//关闭IAP 功能
      z=isp_data;
      return(z);//返回数据
      }

280987343 发表于 2011-8-25 20:15:05

回复【8楼】hnzhy870215
给个用的木有问题的你换一下试试,用在stc11f03e的程序,建议你程序换别的型号跑,测试正常后在换回stc15f104e,之前用这颗ic
外部中断是有问题的。所以你还是换别的型号确认程序没问题后在换回来。
/***************************
    stc11f03eeeprom
***************************
iap_data数据寄存器
iap_addrh 地址寄存器高八位
iap_addrl 地址寄存器低八位
iap_cmd   命令寄存器
iap_trig命令触发寄存器
          写入5ah,在写入a5h 命令才会生效
iap_contr isp_iap命令寄存器
****************************/
#define isp_dataiap_data
#defi......
-----------------------------------------------------------------------
首先谢谢你的程序与建议,我试下,我现在一直在搞着IC,希望你能多指教指教啊!

BXAK 发表于 2011-8-27 03:36:20

你单片机选用多少M晶振,比如12M时“#define Enable_IAP 0x81//晶振<24M”这项可不符合,
12M应该“#define Enable_IAP 0x83”比较合适
页: [1]
查看完整版本: STC15F104E eeprom技术求助,高手过来顶下啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!