📄 rtc935.c
字号:
/*****************************************************************************
*文件名: Timer.C
*版权:
*功能:
*日期:
*****************************************************************************/
#include <Reg935.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
/////////////////////////////////////////////////////////////////////////////
sfr FMADRH=0xE7; //定义IAP-Lite相关寄存器地址
sfr FMADRL=0xE6;
sfr FMDATA=0xE5;
sfr FMCON=0xE4;
//-----------------------------------------------------------------------------
sbit DAT=P2^2; //595数据位
sbit CS=P0^6; //595锁存位
sbit CLK=P2^5; //595时钟位
sbit W2=P1^0; //数码管位选2
sbit W1=P1^1; //数码管位选1
sbit KEY=P1^5;
sbit CONTROL=P2^3;
////////////////////////////////////////////////////////////////////////////////
uchar Time_M; //系统运行时的时间参数(分)
uchar Time_S; //系统运行时的时间参数(秒)
uchar Load_M;
uchar Load_S;
////////////////////////////////////////////////////////////////////////////////
void SendData(uchar c);
void Save_time();
void Load_time(uint addr);
void Inc_time();
void Disp_time(uchar i,uchar j);
void Disp_DP(uchar i,uchar j);
void RTC_Init();
void HexToBCD(uchar num);
void Delayms(uchar n);
//-----------------------------------------------------------------------------
//功能:RTC中断服务程序
//-----------------------------------------------------------------------------
void RTC_ISR() interrupt 10
{
EA=0;
RTCCON&=0x63; //清除RTC中断标志位
Inc_time();
Load_time(0x03F0);
if(Load_M==Time_M) //发送显示信号,并控制外围器件
{
HexToBCD(Time_M);
Time_M=0;
CONTROL=~CONTROL; //控制外部继电器开关
}
else
{
HexToBCD(Time_M); //显示当前分钟值
}
EA=1;
}
//------------------------------
void main()
{
uchar Flag1=0;
uchar Flag2=0;
uint Count=0;
RTC_Init(); //RTC初始化
while(1)
{
EA=0;
while(KEY==0)
{
Delayms(20);
Count++; //记录按键时长
}
if(Count>100) //按键未松要保持在2s以上
{
if(Flag2==0)
{
RTCCON=0x00; //停止RTC模块
Flag2=1; //标志位置1
HexToBCD(77); //显示77,表示进入选择模式
}
else if(Flag2==1)
{
Flag2=0; //标志位清0
Save_time(); //利用IAP-Lite特性存储所选择的时间
HexToBCD(99); //显示99,表示退出选择模式
RTCCON=0x03; //重新启动RTC模块
}
Count=0; //计数值清0
}
else if((Count>0)&&(Count<40)) //按键有效,且按键时间在800ms以内时
{
Flag1++; //计数值递增
switch(Flag1)
{
case 1:
{
Load_M=10; //准备存入到Flash中的数
HexToBCD(10); //显示记录的值
}
break;
case 2:
{
Load_M=20; //准备存入到Flash中的数
HexToBCD(20); //显示记录的值
}
break;
case 3:
{
Load_M=30; //准备存入到Flash中的数
HexToBCD(30); //显示记录的值
}
break;
default: Flag1=0;break;
}
Count=0; //计数值清0
}
EA=1;
}
}
//------------------------------
//功能:发送数据到74HC595
//入口参数:uchar c
//------------------------------
void SendData(uchar c)
{
uchar i;
CS=0; //选择
for(i=0;i<8;i++)
{
CLK=0; //时钟拉低
DAT=c&0x80; //送数据高位
c=c<<1;
CLK=1; //时钟拉高
}
CS=1; //关闭
}
//------------------------------
//功能,保存数据到Flash代码区
//------------------------------
void Save_time()
{
do
{
FMCON=0x00; //装载数据指令
FMADRH=0x03;
FMADRL=0xF0; //装载地址
FMDATA=Load_M; //装载数据,地址自增1
FMDATA=Load_S; //装载数据,地址自增1
FMCON=0x68; //擦除编程操作
}while((FMCON&0x0F)!=0); //等待编程操作完成
}
//------------------------------
//功能:读取存储在FLash空间的变量
//------------------------------
void Load_time(uint addr)
{
uchar code *readp; //定义读数据指针
readp = addr; //设置指针
Load_M=*readp; //将读取的值附给Load_M变量
addr++; //地址加1
Load_S=*readp; //将读取的值附给Load_S变量
}
//------------------------------
//功能:模拟时钟变化,
//Time_S为秒,Time_M为分
//------------------------------
void Inc_time()
{
Time_S++;
if(Time_S>59)
{
Time_S=0;
Time_M++;
if(Time_M>59)
{
Time_M=0;
}
}
}
//------------------------------
//功能:正常显示位,
//入口参数:i为数码管的位选,j为欲显示的值
//------------------------------
void Disp_time(uchar i,uchar j)
{
if(i==1) //根据i,决定开启的位
{
W1=0;
}
else if(i==2)
{
W2=0;
}
switch(j) //根据j,显示相应的段值
{
case 0:
{SendData(~0x3F);}break;
case 1:
{SendData(~0x06);}break;
case 2:
{SendData(~0x5B);}break;
case 3:
{SendData(~0x4F);}break;
case 4:
{SendData(~0x66);}break;
case 5:
{SendData(~0x6D);}break;
case 6:
{SendData(~0x7D);}break;
case 7:
{SendData(~0x07);}break;
case 8:
{SendData(~0x7F);}break;
case 9:
{SendData(~0x6F);}break;
default:
break;
}
Delayms(4); //延迟4ms,以达到良好的显示效果
if(i==1) //关闭相应位
{
W1=1;
}else if(i==2)
{
W2=1;
}
}
//------------------------------
//功能:数码管显示,十位正常,个位带DP,
//入口参数:i为数码管的位选,j为欲显示的值
//------------------------------
void Disp_DP(uchar i,uchar j)
{
if(i==1) //根据i,决定开启的位
{
W1=0;
}else if(i==2)
{
W2=0;
}
switch(j) //根据j,显示相应的段值
{
case 0:
{SendData(~0xBF);}break;
case 1:
{SendData(~0x86);}break;
case 2:
{SendData(~0xDB);}break;
case 3:
{SendData(~0xCF);}break;
case 4:
{SendData(~0xE6);}break;
case 5:
{SendData(~0xED);}break;
case 6:
{SendData(~0xFD);}break;
case 7:
{SendData(~0x87);}break;
case 8:
{SendData(~0xFF);}break;
case 9:
{SendData(~0xEF);}break;
default:
break;
}
Delayms(4); //延迟4ms,以达到良好的显示效果
if(i==1) //关闭相应位
{
W1=1;
}else if(i==2)
{
W2=1;
}
}
//------------------------------
//功能:RTC初始化
//------------------------------
void RTC_Init()
{
P0M1=0x00;
P0M2=0x00;
P1M1=0x00;
P1M2=0x00;
P2M1=0x00;
P2M2=0x00; //端口均初始化为准双向
Time_S=0;
Time_M=0; //Time_M,Time_S初始化为0
IEN0=0xC0; //使能RTC中断,使能EA中断
WDCON=0xE0; //关闭看门狗中断
RTCH=0xE0;
RTCL=0xFF; //7.3728MHz下,1s中断1次时,RTC的定时值
RTCCON=0x03; //开启RTC模块
}
//------------------------------
//功能:将要显示的数转换为两个分离的BCD数
//入口参数:uchar num
//------------------------------
void HexToBCD(uchar num)
{
uint i;
uchar num1=0,num2=num; //将num存入num2
while(num2>9) //当num2大于9时
{
num2=num2-10; //num2自减10
num1++; //num1加1
}
for(i=0;i<50;i++) //前400ms,正常显示
{
Disp_time(1,num1);
Disp_time(2,num2);
}
for(i=0;i<50;i++) //后400ms,显示时个位带DP段
{
Disp_time(1,num1);
Disp_DP(2,num2); //显示个位时,带DP段
}
}
//------------------------------
//功能:ms级别延时(7.373Mhz)
//入口参数:uchar n
//------------------------------
void Delayms(uchar n)
{
int j;
while(n>0)
{
for(j=0;j<=669;j++);
n--;
}
}
//------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -