标题:
DS1302红外4位时钟定时器
[打印本页]
作者:
Qin51
时间:
2017-10-15 12:33
标题:
DS1302红外4位时钟定时器
新手上传一个自用程序
/***************************************************************************
标题: 定时器中断 24小时时钟程序
效果: 数码管显示24小时制时钟
工作于:LY5A-L2A开发板
作者: 林洋电子吧
说明: 板使用12M晶振
******************************************************************************/
//头文件:
#include<reg51.h>
#include<intrins.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
#define S_RST DS_RST=1
#define C_RST DS_RST=0
#define S_CLK DS_CLK=1
#define C_CLK DS_CLK=0
//引脚定义:
sbit SMG_q = P3^4; //定义数码管阳级控制脚(千位)
sbit SMG_b = P3^5; //定义数码管阳级控制脚(百位)
sbit SMG_s = P3^6; //定义数码管阳级控制脚(十位)
sbit SMG_g = P3^7; //定义数码管阳级控制脚(个位)
sbit IR=P3^3; //红外接收数据引脚,
sbit DS_RST = P0^0; //DS复位端
sbit DS_IO = P0^1; //IO端
sbit DS_CLK = P0^2; //SCLK端
sbit SPK = P0^7; //续电器
sbit LED = P0^6;
sbit LED1 = P0^5;
//变量定义:
code unsigned char table[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xBF};
//表:共阳数码管 0-9
unsigned char l_posit=0; //显示位置
unsigned char ly_tt=0; //作为计数时间量
unsigned char SET=0; //设置标识
unsigned char dskg=0;
unsigned char ddss=0;//掉电标识
unsigned char ss=0; //闪烁标识
unsigned char ss1=0;
unsigned char ss2=0;
unsigned char ss3=0;
unsigned char ts1=0;
//////////////////////
signed char time;
unsigned char shi;
unsigned char fen;
unsigned char miao;
unsigned char yue;
unsigned char ri;
unsigned char nian;
unsigned char zhou;
unsigned char qi;
unsigned char ba;
unsigned char sh;
unsigned char ge;
//函数声明:
void display(unsigned char q,unsigned char b,unsigned char s,unsigned char g);//定义显示函数,参数为显示时分
void delay(uint a);
void init(); //初如化函数
void gettime();
uchar BCD_s(uchar BCDs);
uchar s_BCD(uchar sBCD);
void RW_DS1302(uchar reg, uchar byte);
uchar Read_DS1302(uchar reg);//从DS1302寄存器读数据
void DS1302_InputByte(uchar byte); //往DS1302写入1Byte数据
uchar DS1302_OutputByte(void); //从DS1302读取1Byte数据
void ts();
/**************************红外接收处理***********************************
**************************************************************************
*************************************************************************/
unsigned char irtime;//红外用全局变量
bit irpro_ok=0,irok=0;
unsigned char IRcord[4];
unsigned char irdata[33];
unsigned char xs=0;
unsigned char xstt=2;
unsigned char xs_tt=0;
signed char ds_time;
unsigned char k_fen;
unsigned char k_shi;
unsigned char g_fen;
unsigned char g_shi;
signed char date;
/*------------------------------------------------
函数声明
------------------------------------------------*/
void Ir_work(void);
void Ircordpro(void);
void EX0init(void);
void TIM0init(void);//定时器0初始化
/**************************红外接收处理***********************************
**************************************************************************
*************************************************************************/
//初始化函数
void init()
{
P1=0XFF;
SMG_q=0;
SMG_b=0;
SMG_s=0;
SMG_g=0;
SPK=1;
delay(500);
// TMOD=0X02; //设置定时器1为模式一,即16位计算模式
// TH0=0X00;
// TL0=0X00;
// EA=1; //开启总中断
// ET0=1; //开启定时器0中断
// TR0=1; //启动定时器
// EX1=1; //开启外部中断1,红外接收数据引脚
// IT1=1; //设置成下降沿触发方式
RW_DS1302(0x8e,0x80);delay(10);
delay(500);
}
//显示函数,参数为显示内容
void display(unsigned char q,unsigned char b,unsigned char s,unsigned char g)
{
P1=0XFF; //
switch(l_posit){
case 0: //选择千位数码管,关闭其它位
SMG_q=1;
SMG_b=0;
SMG_s=0;
SMG_g=0;
P1=table[q/10]; //输出显示内容
break;
case 1: //选择百位数码管,关闭其它位
SMG_q=0;
SMG_b=1;
SMG_s=0;
SMG_g=0;
P1=table[b%10];
break;
case 2: //选择十位数码管,关闭其它位
SMG_q=0;
SMG_b=0;
SMG_s=1;
SMG_g=0;
P1=table[s/10];
break;
case 3: //选择个位数码管,关闭其它位
SMG_q=0;
SMG_b=0;
SMG_s=0;
SMG_g=1;
P1=table[g%10];
break;
}
l_posit++; //每调用一次将轮流显示一位
if(l_posit>3)
l_posit=0;
}
//延时子函数,短暂延时
void delay(uint a)
{
uint k;
while(a--)
{
for(k=0;k<120;k++){;}
}
}
///////////////////////////////////////////////////////////////////////////////////////
/********************************************************
* *
* DS1302时钟芯片程序段 *
* *
********************************************************/
void DS1302_InputByte(uchar byte) //往DS1302写入1Byte数据
{
uchar i;
uchar temp;
temp = byte;
for(i=8; i>0; i--)
{
DS_IO = temp&0x01;
S_CLK;
C_CLK;
temp = temp >> 1;
}
}
uchar DS1302_OutputByte(void) //从DS1302读取1Byte数据
{
uchar i;
uchar temp=0;
for(i=0; i<8;i++)
{
C_CLK;
if(DS_IO!=0) temp|=(1<<i);
S_CLK;
}
return(temp);
}
void RW_DS1302(uchar reg, uchar byte)//向DS1302寄存器写数据
{
C_RST;
C_CLK;
S_RST;
DS1302_InputByte(reg);
DS1302_InputByte(byte);
S_CLK;
C_RST;
}
uchar Read_DS1302(uchar reg)//从DS1302寄存器读数据
{
uchar byte;
C_RST;
C_CLK;
S_RST;
DS1302_InputByte(reg);
byte = DS1302_OutputByte();
S_CLK;
C_RST;
return(byte);
}
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////转码
uchar BCD_s(uchar BCDs)//十六进制转化为10进制
{
BCDs=(BCDs>>4)*10+(BCDs&0x0f);//将读出来的十六进制转化为10进制
delay(1);
return(BCDs);
}
uchar s_BCD(uchar sBCD)//10进制转化为十六进制
{
sBCD=((sBCD/10)<<4)+(sBCD%10);//将10进制转化为十六进制
delay(1);
return(sBCD);
}
/////////////////////////////////////////////////
void gettime()
{
time=Read_DS1302(0x85);//读小时
shi=BCD_s(time);
time=Read_DS1302(0x83);//读分
fen=BCD_s(time);
time=Read_DS1302(0x81);//读秒
time&=0x7f;//这句代码的意思是:因为秒的最高位第七位分为两种可能,一:它是0,如果是0的话,时钟会自动的计时,如果是1的话,时钟会停止走动,相当于中断
miao=BCD_s(time);//将分读出来的十六进制转化为10进制
time=Read_DS1302(0x89);//读月
yue=BCD_s(time);
time=Read_DS1302(0x87);//读日
ri=BCD_s(time);
time=Read_DS1302(0x8D);//读年
nian=BCD_s(time);
time=Read_DS1302(0x8b);//读zhou
zhou=BCD_s(time);
ds_time=Read_DS1302(0xc1);
k_fen=BCD_s(ds_time);
ds_time=Read_DS1302(0xc9);
k_shi=BCD_s(ds_time);
ds_time=Read_DS1302(0xc5);
g_fen=BCD_s(ds_time);
ds_time=Read_DS1302(0xc7);
g_shi=BCD_s(ds_time);
}
/**************************红外接收处理***********************************
**************************************************************************
*************************************************************************/
/*------------------------------------------------
定时器0中断处理
------------------------------------------------*/
void tim0_isr (void) interrupt 1 using 1
{
irtime++; //用于计数2个下降沿之间的时间
xs_tt++;
if(xs_tt==xstt){xs_tt=0;} //亮度变量
if(xs_tt==1)
{ if(ss==1)
{ if(ss2>=10)
{ SMG_q=0;
SMG_b=0;
SMG_s=0;
SMG_g=0;
P0=0xFF;
}
else
display(qi,ba,sh,ge);
}
else
display(qi,ba,sh,ge);
}
else
P1=0xFF;
ss1++;
if(ss1==250)
{ ss1=0;
ss2++;
if(ss2==16)
{ ss2=0;
}
}
}
/*void tim1_isr (void) interrupt 3
{
xs_tt++;
if(xs_tt==xstt){xs_tt=0;}
if(xs_tt==1)
{display();}
else
P0=0xFF;
}*/
/*------------------------------------------------
外部中断0中断处理
------------------------------------------------*/
void EX0_ISR (void) interrupt 2 //外部中断0服务函数
{
static unsigned char i; //接收红外信号处理
static bit startflag; //是否开始处理标志位
if(startflag)
{
if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
i=0;
irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
else
{
irtime=0;
startflag=1;
}
}
/*------------------------------------------------
定时器0初始化
------------------------------------------------*/
void TIM0init(void)//定时器0初始化
{
TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
TH0=0x00; //重载值
TL0=0x00; //初始化值
ET0=1; //开中断
TR0=1;
// TH1=0x00; //重载值
// TL1=0x00; //初始化值
// TR1=1;
// ET1=1; //开中断
}
/*------------------------------------------------
外部中断0初始化
------------------------------------------------*/
void EX0init(void)
{
IT1 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
EX1 = 1; //使能外部中断
EA = 1; //开总中断
}
/*------------------------------------------------
键值处理
------------------------------------------------*/
void Ir_work(void)//红外键值散转程序
{
// uchar date;
if(SET==0){
switch(IRcord[2])//判断第三个数码值
{
case 0x16:if(IRcord[3]==0xe9){
ddss=1;}
break;//1 显示相应的按键值
case 0x0c:if(IRcord[3]==0xf3){
xs=0;}
break;//1 显示相应的按键值
case 0x18:if(IRcord[3]==0xe7){
xs=1;}
break;//1 显示相应的按键值
case 0x5e:if(IRcord[3]==0xa1){
xs=2;}
break;//1 显示相应的按键值
case 0x0d:if(IRcord[3]==0xf2){
xstt=2;}
break;//1 显示相应的按键值
case 0x19:if(IRcord[3]==0xe6){
xstt=15;}
break;//1 显示相应的按键值
// case 0x0d:if(IRcord[3]==0xf2){
// xstt=30;}
// break;//1 显示相应的按键值
case 0x09:if(IRcord[3]==0xf6){
SPK=~SPK;}
break;//1 显示相应的按键值
case 0x15:if(IRcord[3]==0xea){
dskg=1;}
break;//1 显示相应的按键值
case 0x07:if(IRcord[3]==0xf8){
dskg=0;}
break;//1 显示相应的按键值
default:break;
// IRcord[2]=0;
}}
/////////////////////////////////////////////////////////////////////////////////////////////////////
if(SET==0){
if(IRcord[2]==0x42){
if(IRcord[3]==0xbd){
RW_DS1302(0x8e,0x00);delay(10);//允许写操作
date=Read_DS1302(0x81);//先将秒读出来
date=0x80|date;//这句就是将秒置为最高位
RW_DS1302(0x80,date);delay(10);//再将秒写进去
RW_DS1302(0x8e,0x80);delay(10);//写完了关闭
SET=1;ss=1;}
IRcord[2]=0;
irpro_ok=0;}
if(IRcord[2]==0x08){
if(IRcord[3]==0xf7){
SET=4;}
IRcord[2]=0;
irpro_ok=0;}}
if(SET==1){
if(IRcord[2]==0x42){
if(IRcord[3]==0xbd){
SET=2;ss=1;
IRcord[2]=0;
irpro_ok=0;}}
if(IRcord[2]==0x4a){
if(IRcord[3]==0xb5){
RW_DS1302(0x8e,0x00);delay(10);
time=Read_DS1302(0x83);
time=BCD_s(time);//这是修改分的主要代码,好好研究就成了
time++;
if(time>59)
{
time=0;
}
time=s_BCD(time);
RW_DS1302(0x82,time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}
if(IRcord[2]==0x52){
if(IRcord[3]==0xad){
RW_DS1302(0x8e,0x00);delay(10);
time=Read_DS1302(0x85);
time=BCD_s(time);
time++;
if(time>23)
{
time=0;
}
time=s_BCD(time);
RW_DS1302(0x84,time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}}
if(SET==2){
if(IRcord[2]==0x42){
if(IRcord[3]==0xbd){
SET=3;ss=1;
IRcord[2]=0;
irpro_ok=0;}}
if(IRcord[2]==0x4a){
if(IRcord[3]==0xb5){
RW_DS1302(0x8e,0x00);delay(10);
time=Read_DS1302(0x87);
time=BCD_s(time);//这是修改分的主要代码,好好研究就成了
time++;
if(time>31)
{
time=1;
}
time=s_BCD(time);
RW_DS1302(0x86,time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}
if(IRcord[2]==0x52){
if(IRcord[3]==0xad){
RW_DS1302(0x8e,0x00);delay(10);
time=Read_DS1302(0x89);
time=BCD_s(time);
time++;
if(time>12)
{
time=1;
}
time=s_BCD(time);
RW_DS1302(0x88,time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}
}
if(SET==3){
if(IRcord[2]==0x42){
if(IRcord[3]==0xbd){
RW_DS1302(0x8e,0x00);
date=Read_DS1302(0x81);
date&=0x7f;//将秒的最高位置零表示重新开始工作
RW_DS1302(0x80,date);
RW_DS1302(0x8e,0x80);
SET=0;
ss=0;}
IRcord[2]=0;
irpro_ok=0;}
if(IRcord[2]==0x52){
if(IRcord[3]==0xad){
RW_DS1302(0x8e,0x00);delay(10);
time=Read_DS1302(0x8D);
time=BCD_s(time);
time++;
if(time>99)
{
time=0;
}
time=s_BCD(time);
RW_DS1302(0x8C,time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}
if(IRcord[2]==0x4a){
if(IRcord[3]==0xb5){
RW_DS1302(0x8e,0x00);delay(10);
time=Read_DS1302(0x8B);
time=BCD_s(time);
time++;
if(time>7)
{
time=1;
}
time=s_BCD(time);
RW_DS1302(0x8A,time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}
}
/* if(SET==4){
if(IRcord[2]==0x42){
if(IRcord[3]==0xbd){
RW_DS1302(0x8e,0x00);
date=Read_DS1302(0x81);
date&=0x7f;//将秒的最高位置零表示重新开始工作
RW_DS1302(0x80,date);
RW_DS1302(0x8e,0x80);
SET=0;
ss=0;}
IRcord[2]=0;
irpro_ok=0;}} */
if(SET==4){
if(IRcord[2]==0x08){
if(IRcord[3]==0xf7){
SET=5;ss=1;
IRcord[2]=0;
irpro_ok=0;}}
if(IRcord[2]==0x5a){
if(IRcord[3]==0xa5){
RW_DS1302(0x8e,0x00);delay(10);
ds_time=Read_DS1302(0xc1);
ds_time=BCD_s(ds_time);
ds_time++;
if(ds_time>59)
{
ds_time=0;
}
ds_time=s_BCD(ds_time);
RW_DS1302(0xc0,ds_time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}
if(IRcord[2]==0x1c){
if(IRcord[3]==0xe3){
RW_DS1302(0x8e,0x00);delay(10);
ds_time=Read_DS1302(0xc9);
ds_time=BCD_s(ds_time);
ds_time++;
if(ds_time>23)
{
ds_time=0;
}
ds_time=s_BCD(ds_time);
RW_DS1302(0xc8,ds_time);
RW_DS1302(0x8e,0x80);
IRcord[2]=0;
irpro_ok=0;}}}
if(SET==5){
if(IRcord[2]==0x08){
if(IRcord[3]==0xf7){
SET=0;ss=0;}
IRcord[2]=0;
irpro_ok=0;}
if(IRcord[2]==0x5a){
if(IRcord[3]==0xa5){
RW_DS1302(0x8e,0x00);delay(10);
ds_time=Read_DS1302(0xc5);
ds_time=BCD_s(ds_time);
ds_time++;
if(ds_time>59)
{
ds_time=0;
}
ds_time=s_BCD(ds_time);
RW_DS1302(0xc4,ds_time);
RW_DS1302(0x8e,0x80);}
IRcord[2]=0;
irpro_ok=0;}
if(IRcord[2]==0x1c){
if(IRcord[3]==0xe3){
RW_DS1302(0x8e,0x00);delay(10);
ds_time=Read_DS1302(0xc7);
ds_time=BCD_s(ds_time);
ds_time++;
if(ds_time>23)
{
ds_time=0;
}
ds_time=s_BCD(ds_time);
RW_DS1302(0xc6,ds_time);
RW_DS1302(0x8e,0x80); }
IRcord[2]=0;
irpro_ok=0;}}
irpro_ok=0;//处理完成标志
}
/*------------------------------------------------
红外码值处理
------------------------------------------------*/
void Ircordpro(void)//红外码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
cord=irdata[k];
if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
value|=0x80;
if(j<8)
{
value>>=1;
}
k++;
}
IRcord[i]=value;
value=0;
}
irpro_ok=1;//处理完毕标志位置1
}
/**************************红外接收处理***********************************
**************************************************************************
*************************************************************************/
//主函数,C语言的入口函数:
void main()
{
init(); //初始化中断控制寄存器
EX0init(); //初始化外部中断
TIM0init();//初始化定时器
while(1)
{
if(ss2==2)
gettime();
/////////////////////////////////////
if(irok) //如果接收好了进行红外处理
{
Ircordpro();
irok=0;
}
if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
{
Ir_work();
}
//////////////////////////////////////////
if(dskg==1)
{ if(shi==k_shi)
{ if(fen==k_fen)
{ SPK=0; }
}
if(shi==g_shi)
{ if(fen==g_fen)
{ SPK=1; }
}
}
/* if(SET==0)
{ qi=shi;
ba=shi;
sh=fen;
ge=fen;
if(ss2>=8)
{ LED=0;}
else
LED=1;
}*/
if(SET==1)
{ qi=shi;
ba=shi;
sh=fen;
ge=fen;
LED=0;}
if(SET==2)
{ qi=yue;
ba=yue;
sh=ri;
ge=ri;
LED=1;}
if(SET==3)
{ qi=nian;
ba=nian;
sh=0;
ge=zhou;
LED=1;}
/* if(SET==4)
{ qi=shi;
ba=shi;
sh=fen;
ge=fen;
LED=1;}*/
if(SET==4)
{ ss=1;
qi=k_shi;
ba=k_shi;
sh=k_fen;
ge=k_fen;
if(ss2>=8)
{ LED=0;}
else
LED=1;
}
if(SET==5)
{ ss=1;
qi=g_shi;
ba=g_shi;
sh=g_fen;
ge=g_fen;
if(ss2>=8)
{ LED=0;}
else
LED=1;
}
if(SET==0){
if(xs==0)
{ qi=shi;
ba=shi;
sh=fen;
ge=fen;
LED=1;
if(ss2>=8)
{ LED=0;}
else
LED=1;}
if(xs==1)
{ qi=yue;
ba=yue;
sh=ri;
ge=ri;
LED=1;}
if(xs==2)
{ qi=zhou;
ba=zhou;
sh=miao;
ge=miao;
LED=1;} }
if(dskg==1)
{ LED1=0;}
if(dskg==0)
{ LED1=1;}
if(ddss==0)
{ if(ss2>=8)
{ LED1=0;}
else
LED1=1;
}
if(shi==7)
{ xstt=2;}
if(shi==19)
{ xstt=15;}
////////////////////////////////////
if(zhou==6)
{ ts();}
////////////////////////////
}
}
//////////////////////////////////////////
////////////////////////////////////////////时间校准
void ts()
{
if(shi==0)
{ if(fen==0)
{ if(miao==30)//0x30是30秒
{ ts1=1;
}
}
}
//////////////////////////////////////////////////
if(ts1==1)
{ if(shi==1)
{ if(fen==1)
{ if(miao==15)
{ ts1=0;
RW_DS1302(0x8e,0x00);delay(10);
RW_DS1302(0x80,0x31);delay(10);//0x80写秒0x30就是31秒
RW_DS1302(0x8e,0x80);delay(10);
}
}
}
}
}
复制代码
作者:
dragon19790000
时间:
2018-1-9 18:44
膜拜了,向楼主学习!!!!!!!!!!!!!
作者:
数码家园
时间:
2018-6-8 09:02
谢谢分享!
作者:
javewow
时间:
2018-6-8 14:20
谢谢分享!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1