求助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操作。//
} 有没有人救救我啊。{:cry:} 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);
// }
}
不知道怎么变成斜体了。。。好像是我的【i】这个东西不见了的原因 // 秒分钟 小时日 月 年星期
unsigned charhouchek=0x2000, minchek=0x2001;
改成
// 秒分钟 小时日 月 年星期
unsigned inthouchek=0x2000, minchek=0x2001;
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 static/image/common/back.gif
下面那个总是数据类型不对了吧
我改了的还是不行。还是老毛病。只能传一个17的时候才会响,传了35就不响了 为什么改来改去还是斜体啊。。悲剧 本帖最后由 phrol 于 2012-11-17 23:00 编辑
876192514 发表于 2012-11-17 22:49 static/image/common/back.gif
下面那个总是数据类型不对了吧
辛苦了。{:loveliness:} 虽然问题没有解决,还是谢谢 表示程序这么长只能分析出这些问题了 几个建议 显示如果使用数码管动态扫描的话的话 还是丢到定时器里面去比较好 还有操作EEPROM没必要关中断 再有按键不要做成死循环判断松开按键(此处给你两个思路 一个是判断按键数值两次相同则将按键置为无效的数值(反正程序只用到一次) 或者做成再有标位置的 只能当按键电平有效 并且标志位有效(进入后置位标志这样下次就不会在进入了 按键松开后清除标志)然后置位某个变量 程序检测到这个变量用完后清除(或者用来判断按键时长也行)) 本帖最后由 876192514 于 2012-11-17 23:24 编辑
phrol 发表于 2012-11-17 22:58 static/image/common/back.gif
辛苦了。 虽然问题没有解决,还是谢谢
反正只会玩STC 所以来看看
你可以把数据写入到时钟芯片的RAM中 反正提供了很多空间 876192514 发表于 2012-11-17 23:16 static/image/common/back.gif
反正只会玩STC 所以来看看
你可以把数据写入到时钟芯片的RAM中 反正提供了很多空间 ...
谢谢了,我自己再查查资料。昨晚因为用户组的限制不能回复你实在抱歉了 有大神吗?顶一个,我现在去图书馆复习电磁波了。苦逼 再顶个{:lol:} 顶一个,这周三就要交了,郁闷了 顶起来。。 我自己SB了,没烧到单片机里去,结果仿真不行,实物就行了。我编辑下我现在的函数。唉。实践出真知啊。 #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();
}
} 876192514 发表于 2012-11-17 22:46 static/image/common/back.gif
// 秒分钟 小时日 月 年星期
unsigned charhouchek=0x2000, minchek ...
谢谢你的帮助终于弄好了。{:lol:}
页:
[1]