phrol 发表于 2012-11-17 21:11:50

求助stc90c52里面的eeprom,救命。

本帖最后由 phrol 于 2012-11-17 22:57 编辑

最近在做课程设计,做一个校园打铃系统,要求存24组时间,掉电保存,我就想采用eeprom来做。我想的是先把24组时间存到一个数组里,然后再把数组一次性写到eeprom里面。可是遇到问题了。具体问题请参考下面程序void main(),scan_key(),set_time()
#include <REG52.H>
#include "ds1302.h"                        //包含DS1302头文件
#include "eeprom.h"
#define leddata P0                        //定义LED数据口
#define sec 0x80                        //1302秒寄存器地址
#define min 0x82                        //1302分寄存器地址
#define hou 0x84                        //1302时寄存器地址
#define read 0x01                        //读操作,因为读的时候地址要加1,使最低位为1
sbit MODE=P3^5;                                //按键定义,下同
sbit SET=P3^2;
sbit UP=P3^3;
sbit DOWN=P3^4;
sbit led0=P2^3;                                //LED位选,因为布线不是按顺序布的,程序定义一下就可以了,下同
sbit led1=P2^4;
sbit led2=P2^5;
sbit led3=P2^6;
sbit led4=P2^1;
sbit led5=P2^2;
sbit buzz=P1^3;
//**************函数声明*****************
void delays(unsigned char);
void display(void);
void choosedis(void);
void Scan_Key(void);
void id_case1_key();
void id_case2_key();
void Set_id(unsigned char sel,unsigned char sel_1);
void eeprom_Write(uint ucAddr,uchar ucData);            
unsigned char eeprom_Read(uint ucAddr);
void eeprom_Erase(uint ucAddr);
void eeprom_IspClose();
void Set_Time(void);
void Checkring(void);
void Runbeep(void);
unsigned char JUDGE(unsigned char pro,unsigned char pro_1);
//*************变量定义******************
unsigned char id=0,timecount,re_disp=0,rd=0,project=0,run_beep=0;                //定义用到的变量,id为调整模式用,不为0时表示调整模式,调整哪个量由id值确定,rd用来选择存放24数据,值为0——1,project值1——24
                                                                                        //timecount用于500ms定时记数,时间到取反flag标志位,re_disp记数200次共10s,调整状态下按键无操作10s自动返回正常显示状态
bit hour,minute,second,flag=1;                                //定义位变量,hour,minute,second分别为调整时闪烁标志位,flag 500ms取反一次,调整位闪烁及冒号闪烁用
unsigned char code tab[]={0xfc, 0x60, 0xda, 0xf2,
                                   0x66, 0xb6, 0xbe, 0xe0,
                   0xfe, 0xf6,};        //LED码表,根据硬件修改
unsigned char inittime={0x00,0x29,0x16,0x16,0x11,0x06,0x04};                                                //初始化1302时用到的初始化数据
unsigned char stringhou={'\0'}, stringmin={'\0'};
//                        秒分钟 小时日   月   年星期
unsigned inthouchek=0x2000, minchek=0x2001;
void t0(void) interrupt 1 using 0                        //中断处理程序,主要用于取反标志位,返回正常显示状态,方式1                  
{
        TH0=(65535-50000)/256; //50ms定时
        TL0=(65535-50000)%256;
        timecount++;re_disp++;run_beep++;
        if(timecount>10)
                   {
                        timecount=0;
                    flag=~flag;
                   }
        if(re_disp>200)
                {
                        re_disp=0;
                        if(id)id=0;               
                }
}
void delays(unsigned char k)                                //延时函数
{
        unsigned char i,j;
        for(i=0;i<k;i++)
                for(j=0;j<50;j++);
}
void display(void)                                                        //显示函数
{
        if(!rd)
        {
                if(flag&hour)                                                        //如hour为1表示调整时,flag为1时不显示
                        {
                                led0=0;leddata=0x00;delays(10);led0=1;
                                led1=0;leddata=0x00;delays(10);led1=1;        //&~((unsigned char)~flag<<6)该句根据flag的值决定来显示小数点,为1时显示,4个小数点组成两对冒号,下同
                        }
                else                                                                        //flag为0时显示,产生闪烁效果,下同
                        {
                                leddata=tab;led0=0;delays(10);led0=1;
                                leddata=tab;led1=0;delays(10);led1=1;
                        }
                if(flag&minute)
                        {
                                led2=0;leddata=0x00;delays(10);led2=1;
                                led3=0;leddata=0x00;delays(10);led3=1;
                        }
                else
                        {
                                leddata=tab;led2=0;delays(10);led2=1;
                                leddata=tab;led3=0;delays(10);led3=1;
                        }
        }
        else
        {
                if(flag&hour)                                                        //如hour为1表示调整时,flag为1时不显示
                        {
                                led0=0;leddata=0x00;delays(10);led0=1;
                                led1=0;leddata=0x00;delays(10);led1=1;        //&~((unsigned char)~flag<<6)该句根据flag的值决定来显示小数点,为1时显示,4个小数点组成两对冒号,下同
                        }
                else                                                                        //flag为0时显示,产生闪烁效果,下同
                        {
                                leddata=tab/10];led0=0;delays(10);led0=1;
                                leddata=tab%10];led1=0;delays(10);led1=1;
                        }
                if(flag&minute)
                        {
                                led2=0;leddata=0x00;delays(10);led2=1;
                                led3=0;leddata=0x00;delays(10);led3=1;
                        }
                else
                        {
                                leddata=tab/10];led2=0;delays(10);led2=1;
                                leddata=tab%10];led3=0;delays(10);led3=1;
                        }
        }

}
//void choosedis(void)
//{
//        if(flag)
//                {
//                        led0=0;leddata=0x00;delays(10);led0=1;
//                        led1=0;leddata=0x00;delays(10);led1=1;                               
//                        led2=0;leddata=0x00;delays(10);led2=1;
//                        led3=0;leddata=0x00;delays(10);led3=1;
//                }
//        else
//                {
//                        led0=0;leddata=0x00;delays(10);led0=1;
//                        led1=0;leddata=0x00;delays(10);led1=1;                               
//                        leddata=tab;led2=0;delays(10);led2=1;
//                        leddata=tab;led3=0;delays(10);led3=1;
//                }
//}
void Scan_Key(void)                                //键盘检测函数
{
        signed char checkhou, checkmin, checksec, counthou, countmin;       
        display();                                        //程序开头调用显示函数
        if(!MODE)
                {
                        rd++;if(rd>1)rd=0;
                        while(!MODE)display();
                        re_disp=0;
                }
        if(!SET)                                       
                {
                        while(!SET)display();        //等待按键释放,如一直按下一直调用显示函数,防止显示中断
                        re_disp=0;                                //清除记数,重新开始10s定时
                        id++;if(id>2)id=0;                //id加1,后面根据id值对应调整项目
                }
        if(id==0){hour=0;minute=0;}        //根据id值跳到相应处理函数
        if(id==1){hour=1;id_case1_key();}                //id为1,选择调整小时位,闪烁标志位置1,然后跳到键盘处理函数,下同
        if(id==2){hour=0;minute=1;id_case1_key();}
        if(rd==1){if(id==0)id_case2_key();}

//        counthou=eeprom_Read(0x2002);
//        countmin=eeprom_Read(0x2001);
        checkhou=Read1302(hou|read)/16*10+Read1302(hou|read)%16;
        checkmin=Read1302(min|read)/16*10+Read1302(min|read)%16;
        checksec=Read1302(sec|read)/16*10+Read1302(sec|read)%16;
//        counthou=eeprom_Read(houchek);
//        countmin=eeprom_Read(minchek);
//        eeprom_IspClose();
        if((checkhou==eeprom_Read(houchek))&&(checksec==0))Runbeep();
//        Checkring();
}
void id_case2_key(void)
{
        display();                                                               
        if (!DOWN) //减少
              {
                       while(!DOWN)display();                        //等待按键释放,如一直按下一直调用显示函数,防止显示中断
                        re_disp=0;                                                //清除记数,重新开始10s定时
                        project=JUDGE(project,0);        //

              }
           if (!UP)//增加
              {
                       while(!UP)display();
                        re_disp=0;
                        project=JUDGE(project,1);
              }       
}
unsigned char JUDGE(unsigned char pro,unsigned char pro_1)
{
        if(pro_1==0)pro--; else pro++;
        if(pro<0)pro=23;
        if(pro>23)pro=0;
        return pro;               
}

void id_case1_key(void)                                                //键盘处理函数,只有按下set键时才会进入,
{
        display();                                                               
        if (!DOWN) //减少
              {
                       while(!DOWN)display();                        //等待按键释放,如一直按下一直调用显示函数,防止显示中断
                        re_disp=0;                                                //清除记数,重新开始10s定时
                        Set_id(id,0);                                        //,
              }
           if (!UP)//增加
              {
                       while(!UP)display();
                        re_disp=0;
                           Set_id(id,1);   
              }
}

//根据选择调整相应项目并写入DS1302
void Set_id(unsigned char sel,unsigned char sel_1)                //执行调整项目的函数
{
        signed char max,mini,address,item;                                       
        if(sel==1){address=hou; max=23;mini=0;}    //小时        //根据id值确定要调整的项,并确定调整上下限,下同
        if(sel==2){address=min; max=59;mini=0;}    //分钟
//if(sel==3){address=sec; max=0;mini=0;}   //秒
        if(!rd)
        {
                item=Read1302(address|read)/16*10+Read1302(address|read)%16;        //从相应的地址读取当前数据并转换为十进制
        }
        else
        {
                if(sel==1)item=stringhou;
                if(sel==2)item=stringmin;
        }
        if (sel_1==0) item--;else item++;                                                                //确定是对项目加还是减,并对越限处理
        if(item>max) item=mini;   
        if(item<mini) item=max;
        if(!rd)
        {
                Write1302(0x8e,0x00);//允许写操作       
                Write1302(address,item/10*16+item%10);                                                        //将调整结果转换成压缩BCD码重新写入1302
                Write1302(0x8e,0x80);//写保护,禁止写操作
        }
        else
        {
                if(sel==1){stringhou=item;}//Set_Time();}                //优化意识
                if(sel==2){stringmin=item;Set_Time();}
        }
       
}
void Set_Time(void)
{
        unsigned char i, houadd=0x2000, minadd=0x2001;
        eeprom_Erase(0x2000);
        eeprom_Write(0x2000,17);       
//        eeprom_Write(0x2001,35);
//        for(i=0;i<24;i++,houadd+=2, minadd+=2)
//        {       
//                eeprom_Write(houadd,stringhou[);
//                eeprom_Write(minadd,stringmin[);
//        }
}       


void Runbeep(void)
{          
    run_beep=0;
        while(run_beep<100)//判断flag1是否到100
   {
   buzz=1;//没有,则,继续驱动蜂鸣器响,时间约为:10s=50ms*200
   display();
   }
   buzz=0;//关闭蜂鸣器
}       
void main()                                                        //主函数        {
{               
                TMOD=0x01;                                        //初始化定时器
                TH0=(65535-50000)/256;
                TL0=(65535-50000)%256;
                EA=1;
                ET0=1;
                TR0=1;
                Write1302(0x90,0xa0);//关闭充电二级管,不能对后备电池进行充电,防止发胀,原来的程序是打开的请关闭
                Write1302(0x8e,0x80);//写保护,禁止写操作
                Set1302(inittime);
                buzz=0;//防止上电复位高电平蜂鸣器一直工作
                if(!UP&!DOWN)Set1302(inittime);                        //如果同时按下UP和DOWN键则初始化1302,该语句在while(1)前,只执行一次,需要复位,防止误操作
                while(1)
                        {
                                Scan_Key();                                                //主程序一直调用键盘检测函数即可
                                houchek+=2;
                                minchek+=2;
                                if(houchek>0x2047)houchek=0x2000;
                                if(minchek>0x2048)minchek=0x2001;
                        }
}
问题1.set_time()函数里,我现在只想设置一个17:35,小时存在0x2000,分钟存在0x2001,(并且我是想偶数地址位存小时,奇数位存分钟)看他能不能响,可是scan_key函数里面我现在只能比较小时相同,或者分钟相同,而且比较小时相同,还只能仅限于单独把小时写入0x2000才能实现,分钟也是一样,只能是当仅有分钟写入0x2001时才行。不知道我表没表达清楚。。也就是我只能读一个地址,写一个地址,不能使写两个地址,读两个地址。求求各位大神帮帮吗啊。我还有仿真图,需要的话我可以发给你。我所剩时日不多。救命。(我把i删掉了,免得又斜体)
下面是我用的eeprom的驱动函数不知道对不对。———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————       
   #ifndef _EEPROM_H
    #define _EEPROM_H


    #include <REG52.h>
    #include <intrins.h>


    #define uint unsigned int
    #define uchar unsigned char


    /**      定义ISP_DATA特殊寄存器      **/
    sfr ISP_DATA= 0xE2;
    sfr ISP_ADDRH = 0xE3;
    sfr ISP_ADDRL = 0xE4;
    sfr ISP_CMD   = 0xE5;
    sfr ISP_TRIG= 0xE6;
    sfr ISP_CONTRL = 0xE7;


    /**      定义ISP/IAP命令及等待时间    **/
    #define ISP_READ 1    // 字节读 //
    #define ISP_WRITE 2    // 字节写,前提是该字节是空,0FFH//
    #define ISP_ERASE 3 // 扇区擦除,要某字节为空,要擦一扇区。//
    #define WITE_TIME 1 // 设置等待时间,40MHz以下为0,20MHz以下为1,10MHz以下为2,5MHz以下为3。//


    /**   声明接口函数    **/
    /****************************************************************************************
      函数名称:eeprom_Write()
      函数功能:将数据写入eeprom存储区
      入口参数:ucAddr 扇区起始地址;ucData 要写入的数据
      出口参数:无
      备注:
    ***************************************************************************************/
    extern void eeprom_Write(uint ucAddr,uchar ucData);


    /****************************************************************************************
      函数名称:eeprom_Read()
      函数功能:读取eeprom存储区数据
      入口参数:ucAddr 读取数据的地址
      出口参数:ucData 返回读取的数据
      备注:
    ***************************************************************************************/
    extern uchar eeprom_Read(uint ucAddr);


    /****************************************************************************************
    函数名称:eeprom_Erase()
    函数功能:擦除一个扇区数据
    入口参数:ucAddr 扇区起始地址
    出口参数:无
    备注:
    ****************************************************************************************/
    extern void eeprom_Erase(uint ucAddr);


#endif

/*****************************************************************************************
    文件名:eeprom.c
    作者:oydl82
    版本:V1.0
    说明:STC89C51系列单片机内置EEPROM读写模块源文件
    修改:
*****************************************************************************************/

/****************************************************************************************
    函数名称:eeprom_IspClose()
    函数功能:关闭ISP操作
    入口参数:无
    出口参数:无
    备注:
***************************************************************************************/
void eeprom_IspClose()
{
    ISP_CONTRL = 0x00; // 禁ISP/IAP操作 //
    ISP_CMD = 0x00; // 去除ISP/IAP命令 //
    ISP_TRIG = 0x00; // 防止ISP/IAP命令 //
    ISP_ADDRH = 0xff;
    ISP_ADDRL = 0xff; // 送地址高、低字节单元为00,指向非ERRPROM区,防止误操作。//
    EA = 1; // 开中断 //
}

/****************************************************************************************
    函数名称:eeprom_Write()
    函数功能:将数据写入eeprom存储区
    入口参数:ucAddr 扇区起始地址;ucData 要写入的数据
    出口参数:无
    备注:
***************************************************************************************/
void eeprom_Write(uint ucAddr,uchar ucData)
{
    ISP_DATA = ucData; // ISP要写入的数据 //
    ISP_ADDRL = ucAddr;    // ISP/IAP操作时的地址寄存器低八位    //
    ISP_ADDRH = ucAddr >> 8; // ISP/IAP操作时的地址寄存器高八位 //
    ISP_CONTRL = 0x81; // 设置ISPEN为1,等待时间为2。//
    ISP_CMD = ISP_WRITE; // 送字节编程命令。 //
    EA = 0; // 关中断。//
    ISP_TRIG = 0x46;
    ISP_TRIG = 0xB9; // 先送0x46,再送0xB9,使ISP/IAP命令生效。//
    _nop_();
    eeprom_IspClose(); // 关闭ISP操作。//
}


/****************************************************************************************
    函数名称:eeprom_Read()
    函数功能:读取eeprom存储区数据
    入口参数:ucAddr 读取数据的地址
    出口参数:ucData 返回读取的数据
    备注:
***************************************************************************************/
uchar eeprom_Read(uint ucAddr)
{
    uchar ucData;
    ISP_ADDRL = ucAddr; // ISP/IAP操作时的地址寄存器低八位    //
    ISP_ADDRH = ucAddr >> 8; // ISP/IAP操作时的地址寄存器高八位    //
    ISP_CONTRL = 0x81; // 设置ISPEN为1,等待时间为2。//
    ISP_CMD = ISP_READ; // 送字节读命令。 //
    EA = 0;    // 关中断。//
    ISP_TRIG = 0x46;
    ISP_TRIG = 0xB9; // 先送0x46,再送0xB9,使ISP/IAP命令生效。//
    ucData = ISP_DATA; // 读取ISP_DATA的内容。//
    _nop_();
    eeprom_IspClose(); // 关闭ISP操作。//
    return (ucData);
}


/****************************************************************************************
    函数名称:eeprom_Erase()
    函数功能:擦除一个扇区数据
    入口参数:ucAddr 扇区起始地址
    出口参数:无
    备注:
***************************************************************************************/
void eeprom_Erase(uint ucAddr)
{
    ISP_ADDRL = ucAddr;    // ISP/IAP操作时的地址寄存器低八位    //
    ISP_ADDRH = ucAddr >> 8; // ISP/IAP操作时的地址寄存器高八位    //
    ISP_CONTRL = 0x81; // 设置ISPEN为1,等待时间为2。//
    ISP_CMD = ISP_ERASE; // 送扇区命令。 //
    EA = 0; // 关中断。//
    ISP_TRIG = 0x46;
    ISP_TRIG = 0xB9; // 先送0x46,再送0xB9,使ISP/IAP命令生效。//
    _nop_();
    eeprom_IspClose(); // 关闭ISP操作。//
}

phrol 发表于 2012-11-17 21:51:27

有没有人救救我啊。{:cry:}

876192514 发表于 2012-11-17 22:34:34

void Set_Time(void)
{
      unsigned char i, houadd=0x2000, minadd=0x2001;
      eeprom_Erase(0x2000);
      eeprom_Write(0x2000,17);      
//      eeprom_Write(0x2001,35);
//      for(i=0;i<24;i++,houadd+=2, minadd+=2)
//      {      
//                eeprom_Write(houadd,stringhou);
//                eeprom_Write(minadd,stringmin);
//      }
}      


修改为
void Set_Time(void)
{
      unsigned int i, houadd=0x2000, minadd=0x2001;
      eeprom_Erase(0x2000);
      eeprom_Write(0x2000,17);      
//      eeprom_Write(0x2001,35);
//      for(i=0;i<24;i++,houadd+=2, minadd+=2)
//      {      
//                eeprom_Write(houadd,stringhou);
//                eeprom_Write(minadd,stringmin);
//      }
}      


phrol 发表于 2012-11-17 22:38:27

不知道怎么变成斜体了。。。好像是我的【i】这个东西不见了的原因

876192514 发表于 2012-11-17 22:46:41

//                        秒分钟 小时日   月   年星期
unsigned charhouchek=0x2000, minchek=0x2001;
改成
//                        秒分钟 小时日   月   年星期
unsigned inthouchek=0x2000, minchek=0x2001;

phrol 发表于 2012-11-17 22:48:06

876192514 发表于 2012-11-17 22:34 static/image/common/back.gif
void Set_Time(void)
{
      unsigned char i, houadd=0x2000, minadd=0x2001;


我改了还是不行啊,我觉得不是数据类型的问题吧,因为我直接        eeprom_Write(0x2000,17);        //        eeprom_Write(0x2001,35); 我是直接写的地址啊

876192514 发表于 2012-11-17 22:49:36

下面那个总是数据类型不对了吧

phrol 发表于 2012-11-17 22:53:40

876192514 发表于 2012-11-17 22:49 static/image/common/back.gif
下面那个总是数据类型不对了吧

我改了的还是不行。还是老毛病。只能传一个17的时候才会响,传了35就不响了

phrol 发表于 2012-11-17 22:55:59

为什么改来改去还是斜体啊。。悲剧

phrol 发表于 2012-11-17 22:58:36

本帖最后由 phrol 于 2012-11-17 23:00 编辑

876192514 发表于 2012-11-17 22:49 static/image/common/back.gif
下面那个总是数据类型不对了吧

辛苦了。{:loveliness:} 虽然问题没有解决,还是谢谢

876192514 发表于 2012-11-17 23:08:49

表示程序这么长只能分析出这些问题了 几个建议 显示如果使用数码管动态扫描的话的话 还是丢到定时器里面去比较好 还有操作EEPROM没必要关中断 再有按键不要做成死循环判断松开按键(此处给你两个思路 一个是判断按键数值两次相同则将按键置为无效的数值(反正程序只用到一次) 或者做成再有标位置的 只能当按键电平有效 并且标志位有效(进入后置位标志这样下次就不会在进入了 按键松开后清除标志)然后置位某个变量 程序检测到这个变量用完后清除(或者用来判断按键时长也行))

876192514 发表于 2012-11-17 23:16:14

本帖最后由 876192514 于 2012-11-17 23:24 编辑

phrol 发表于 2012-11-17 22:58 static/image/common/back.gif
辛苦了。 虽然问题没有解决,还是谢谢

反正只会玩STC 所以来看看
你可以把数据写入到时钟芯片的RAM中 反正提供了很多空间

phrol 发表于 2012-11-18 12:42:10

876192514 发表于 2012-11-17 23:16 static/image/common/back.gif
反正只会玩STC 所以来看看
你可以把数据写入到时钟芯片的RAM中 反正提供了很多空间 ...

谢谢了,我自己再查查资料。昨晚因为用户组的限制不能回复你实在抱歉了

phrol 发表于 2012-11-18 14:45:43

有大神吗?顶一个,我现在去图书馆复习电磁波了。苦逼

phrol 发表于 2012-11-18 21:17:58

再顶个{:lol:}

phrol 发表于 2012-11-18 23:14:11

顶一个,这周三就要交了,郁闷了

phrol 发表于 2012-11-19 12:50:21

顶起来。。

phrol 发表于 2012-11-19 21:03:04

我自己SB了,没烧到单片机里去,结果仿真不行,实物就行了。我编辑下我现在的函数。唉。实践出真知啊。

phrol 发表于 2012-11-19 21:03:42

#include <REG52.H>
#include "ds1302.h"                        //包含DS1302头文件
#include "eeprom.h"
#define leddata P0                        //定义LED数据口
#define sec 0x80                        //1302秒寄存器地址
#define min 0x82                        //1302分寄存器地址
#define hou 0x84                        //1302时寄存器地址
#define read 0x01                        //读操作,因为读的时候地址要加1,使最低位为1
sbit MODE=P3^5;                                //按键定义,下同
sbit SET=P3^2;
sbit UP=P3^3;
sbit DOWN=P3^4;
sbit led0=P2^3;                                //LED位选,因为布线不是按顺序布的,程序定义一下就可以了,下同
sbit led1=P2^4;
sbit led2=P2^5;
sbit led3=P2^6;
sbit led4=P2^1;
sbit led5=P2^2;
sbit buzz=P1^3;
//**************函数声明*****************
void delays(unsigned char);
void display(void);
void choosedis(void);
void Scan_Key(void);
void id_case1_key();
void id_case2_key();
void Set_id(unsigned char sel,unsigned char sel_1);
void eeprom_Write(uint ucAddr,uchar ucData);            
unsigned char eeprom_Read(uint ucAddr);
void eeprom_Erase(uint ucAddr);
void eeprom_IspClose();
void Set_Time(void);
void Checkring(void);
void Runbeep(void);
unsigned char JUDGE(unsigned char pro,unsigned char pro_1);
void Init();
//*************变量定义******************
unsigned char id=0,timecount,re_disp=0,rd=0,project=0,run_beep=0;                //定义用到的变量,id为调整模式用,不为0时表示调整模式,调整哪个量由id值确定,rd用来选择存放24数据,值为0——1,project值1——24
                                                                                        //timecount用于500ms定时记数,时间到取反flag标志位,re_disp记数200次共10s,调整状态下按键无操作10s自动返回正常显示状态
bit hour,minute,second,flag=1;                                //定义位变量,hour,minute,second分别为调整时闪烁标志位,flag 500ms取反一次,调整位闪烁及冒号闪烁用
unsigned char code tab[]={0xfc, 0x60, 0xda, 0xf2,
                                   0x66, 0xb6, 0xbe, 0xe0,
                   0xfe, 0xf6,};        //LED码表,根据硬件修改
unsigned char inittime={0x58,0x34,0x17,0x16,0x11,0x06,0x04};                                                //初始化1302时用到的初始化数据
unsigned char stringhou={'\0'}, stringmin={'\0'};
//                        秒分钟 小时日   月   年星期
unsigned inthouchek=0x2000, minchek=0x2001;

void t0(void) interrupt 1 using 0                        //中断处理程序,主要用于取反标志位,返回正常显示状态,方式1                  
{
        TH0=(65535-50000)/256; //50ms定时
        TL0=(65535-50000)%256;
        timecount++;re_disp++;run_beep++;
        if(timecount>10)
                   {
                        timecount=0;
                    flag=~flag;
                   }
        if(re_disp>200)
                {
                        re_disp=0;
                        if(id)id=0;               
                }
}
void delays(unsigned char k)                                //延时函数
{
        unsigned char i,j;
        for(i=0;i<k;i++)
                for(j=0;j<50;j++);
}
void display(void)                                                        //显示函数
{
        if(!rd)
        {
                if(flag&hour)                                                        //如hour为1表示调整时,flag为1时不显示
                        {
                                led0=0;leddata=0x00;delays(10);led0=1;
                                led1=0;leddata=0x00;delays(10);led1=1;        //&~((unsigned char)~flag<<6)该句根据flag的值决定来显示小数点,为1时显示,4个小数点组成两对冒号,下同
                        }
                else                                                                        //flag为0时显示,产生闪烁效果,下同
                        {
                                leddata=tab;led0=0;delays(10);led0=1;
                                leddata=tab;led1=0;delays(10);led1=1;
                        }
                if(flag&minute)
                        {
                                led2=0;leddata=0x00;delays(10);led2=1;
                                led3=0;leddata=0x00;delays(10);led3=1;
                        }
                else
                        {
                                leddata=tab;led2=0;delays(10);led2=1;
                                leddata=tab;led3=0;delays(10);led3=1;
                        }
        }
        else
        {
                if(flag&hour)                                                        //如hour为1表示调整时,flag为1时不显示
                        {
                                led0=0;leddata=0x00;delays(10);led0=1;
                                led1=0;leddata=0x00;delays(10);led1=1;        //&~((unsigned char)~flag<<6)该句根据flag的值决定来显示小数点,为1时显示,4个小数点组成两对冒号,下同
                        }
                else                                                                        //flag为0时显示,产生闪烁效果,下同
                        {
                                leddata=tab/10];led0=0;delays(10);led0=1;
                                leddata=tab%10];led1=0;delays(10);led1=1;
                        }
                if(flag&minute)
                        {
                                led2=0;leddata=0x00;delays(10);led2=1;
                                led3=0;leddata=0x00;delays(10);led3=1;
                        }
                else
                        {
                                leddata=tab/10];led2=0;delays(10);led2=1;
                                leddata=tab%10];led3=0;delays(10);led3=1;
                        }
        }

}

void Scan_Key(void)                                //键盘检测函数
{
        signed char checkhou, checkmin, checksec, counthou, countmin;       
        display();                                        //程序开头调用显示函数
        if(!MODE)
                {
                        rd++;if(rd>1)rd=0;
                        while(!MODE)display();
                        re_disp=0;
                }
        if(!SET)                                       
                {
                        while(!SET)display();        //等待按键释放,如一直按下一直调用显示函数,防止显示中断
                        re_disp=0;                                //清除记数,重新开始10s定时
                        id++;if(id>2)id=0;                //id加1,后面根据id值对应调整项目
                }
        if(id==0){hour=0;minute=0;}        //根据id值跳到相应处理函数
        if(id==1){hour=1;id_case1_key();}                //id为1,选择调整小时位,闪烁标志位置1,然后跳到键盘处理函数,下同
        if(id==2){hour=0;minute=1;id_case1_key();}
        if(rd==1){if(id==0)id_case2_key();}

//        counthou=eeprom_Read(0x2000);
//        countmin=eeprom_Read(0x2001);
        checkhou=Read1302(hou|read)/16*10+Read1302(hou|read)%16;
        checkmin=Read1302(min|read)/16*10+Read1302(min|read)%16;
        checksec=Read1302(sec|read)/16*10+Read1302(sec|read)%16;
        counthou=eeprom_Read(houchek);
        countmin=eeprom_Read(minchek);
        if((checkhou==counthou)&&(checkmin==countmin)&&(checksec==0))Runbeep();
}
void id_case2_key(void)
{
        display();                                                               
        if (!DOWN) //减少
              {
                       while(!DOWN)display();                        //等待按键释放,如一直按下一直调用显示函数,防止显示中断
                        re_disp=0;                                                //清除记数,重新开始10s定时
                        project=JUDGE(project,0);        //

              }
           if (!UP)//增加
              {
                       while(!UP)display();
                        re_disp=0;
                        project=JUDGE(project,1);
              }       
}
unsigned char JUDGE(unsigned char pro,unsigned char pro_1)
{
        if(pro_1==0)pro--; else pro++;
        if(pro<0)pro=23;
        if(pro>23)pro=0;
        return pro;               
}

void id_case1_key(void)                                                //键盘处理函数,只有按下set键时才会进入,
{
        display();                                                               
        if (!DOWN) //减少
              {
                       while(!DOWN)display();                        //等待按键释放,如一直按下一直调用显示函数,防止显示中断
                        re_disp=0;                                                //清除记数,重新开始10s定时
                        Set_id(id,0);                                        //,
              }
           if (!UP)//增加
              {
                       while(!UP)display();
                        re_disp=0;
                           Set_id(id,1);   
              }
}

//根据选择调整相应项目并写入DS1302
void Set_id(unsigned char sel,unsigned char sel_1)                //执行调整项目的函数
{
        signed char max,mini,address,item;                                       
        if(sel==1){address=hou; max=23;mini=0;}    //小时        //根据id值确定要调整的项,并确定调整上下限,下同
        if(sel==2){address=min; max=59;mini=0;}    //分钟
//if(sel==3){address=sec; max=0;mini=0;}   //秒
        if(!rd)
        {
                item=Read1302(address|read)/16*10+Read1302(address|read)%16;        //从相应的地址读取当前数据并转换为十进制
        }
        else
        {
                if(sel==1)item=stringhou;
                if(sel==2)item=stringmin;
        }
        if (sel_1==0) item--;else item++;                                                                //确定是对项目加还是减,并对越限处理
        if(item>max) item=mini;   
        if(item<mini) item=max;
        if(!rd)
        {
                Write1302(0x8e,0x00);//允许写操作       
                Write1302(address,item/10*16+item%10);                                                        //将调整结果转换成压缩BCD码重新写入1302
                Write1302(0x8e,0x80);//写保护,禁止写操作
        }
        else
        {
                if(sel==1){stringhou=item;}//Set_Time();}                //优化意识
                if(sel==2){stringmin=item;Set_Time();}
        }
       
}
void Set_Time(void)
{
        unsigned int i, houadd=0x2000, minadd=0x2001;
        eeprom_Erase(0x2000);
//        eeprom_Write(0x2001,35);
//        eeprom_Write(0x2000,17);       
//        eeprom_Erase(0x2000);

        for(i=0;i<24;i++,houadd+=2, minadd+=2)
        {       
                eeprom_Write(houadd,stringhou);
//                ISP_DATA=0;
               
                eeprom_Write(minadd,stringmin);
        }
}       

void Runbeep(void)
{          
    run_beep=0;
        while(run_beep<100)//判断flag1是否到100
   {
   buzz=1;//没有,则,继续驱动蜂鸣器响,时间约为:10s=50ms*200
   display();
   }
   buzz=0;//关闭蜂鸣器
}       
void Init()
{
        unsigned int i, j, q;
        for(i=0,j=0x2000,q=0x2001;i<24;i++,j+=2,q+=2)
        {
                stringhou=eeprom_Read(j);
                stringmin=eeprom_Read(q);
        }
}
void main()                                                        //主函数        {
{               
                TMOD=0x01;                                        //初始化定时器
                TH0=(65535-50000)/256;
                TL0=(65535-50000)%256;
                EA=1;
                ET0=1;
                TR0=1;
                Write1302(0x90,0xa0);//关闭充电二级管,不能对后备电池进行充电,防止发胀,原来的程序是打开的请关闭
                Write1302(0x8e,0x80);//写保护,禁止写操作
                Set1302(inittime);
                buzz=0;//防止上电复位高电平蜂鸣器一直工作
//                Set_Time();
                Init();
                if(!UP&!DOWN)Set1302(inittime);                        //如果同时按下UP和DOWN键则初始化1302,该语句在while(1)前,只执行一次,需要复位,防止误操作
                while(1)
                        {
                                Scan_Key();                                                //主程序一直调用键盘检测函数即可
                                houchek+=2;
                                minchek+=2;
                                if(houchek>0x2047)houchek=0x2000;
                                if(minchek>0x2048)minchek=0x2001;
                                Init();
                        }
}

phrol 发表于 2012-11-19 21:04:21

876192514 发表于 2012-11-17 22:46 static/image/common/back.gif
//                        秒分钟 小时日   月   年星期
unsigned charhouchek=0x2000, minchek ...

谢谢你的帮助终于弄好了。{:lol:}
页: [1]
查看完整版本: 求助stc90c52里面的eeprom,救命。