标题:
单片机51单片机时钟可调程序+电路图
[打印本页]
作者:
mmm12333
时间:
2019-6-2 14:36
标题:
单片机51单片机时钟可调程序+电路图
如图是电路原理图如下:
0.jpg
(32.62 KB, 下载次数: 23)
下载附件
2019-6-3 05:00 上传
单片机源程序如下:
/*********************************************************************************
* 【外部晶振】: 11.0592mhz
* 【主控芯片】: STC89C52
* 【编译环境】: Keil μVisio3
* 【程序功能】: LCD1602显示DS1302时钟 ,按键可以调
* 【使用说明】: 液晶1脚接1602黑色排母的1脚 如果是无背光的液晶只有14个脚 排母右边空2个位
请把液晶对比度电位器顺时针调制10点钟方向,请勿多调超出极限位置会损坏电位器!
使用前是用杜邦线分别把DS1302旁边3个脚的排针与P1口的0~2接相接
接线方式是 请看开饭背面有丝印
TSCLK - P10
TIO - P11
TRST - P12
-------------------------------调节时钟--------------------------------------------
按下S2依次选择秒分时、星期日月年,S3 加,S4减
* 说明:免费开源,不提供源代码分析.
**********************************************************************************/
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar a,miao,shi,fen,ri,yue,nian,week,flag,temp,key1n;
uchar ge,shi,bai,qian;
#define yh 0x80 //第一行的初始位置
#define er 0x80+0x40 //第二行初始位置
#define keyport P2
//sbit dula=P2^6;
//sbit wela=P2^7;
bit f_systick_1ms=0;
bit f_systick_2ms=0;
uchar cnt_systick_2ms=0;
bit f_systick_4ms=0;
uchar cnt_systick_4ms=0;
bit f_systick_10ms=0;
uchar cnt_systick_10ms=0;
uchar cnt_systick_101ms=0;
bit f_systick_505ms=0;
uchar cnt_systick_505ms=0;
bit f_systick_1s=0;
uchar cnt_systick_1s=0;
uchar data current_Event = 0;
bit flag_Alarm_blink;
bit swatch_Start_Flag = 0; //秒表计时开始标致位
sbit wr=P1^1;
sbit rs=P1^0;
sbit en=P1^2;
sbit SCLK=P3^5;
sbit IO=P3^6;
sbit RST=P3^7;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit key=P2^0;
sbit key1=P2^1;
sbit key2=P2^2;
sbit key3=P2^3;
uchar keyvalue=0;
uchar code tab1[]={" - - "};
uchar code tab2[]={" : : "};
uchar code tab3[]={"SWITCH"};
void delay(uint xms)//延时函数
{
uint x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
}
/*************定时器T0的初始化********************/
void Timer1_Init(void)
{
TMOD=0x11; //T1定时器工作方式1
TH1=0xfc; //1ms初值
TL1=0x18;
ET1=1; //开定时器T0中断
EA=1; //开总中断
// TR1=1; //启动定时器T0
}
/****************T0定时器中断*********************/
void ISR_T1(void) interrupt 3 //1ms中断
{
TH1=0xfc;
TL1=0x18; //重装1ms中断
f_systick_1ms=1; //1ms时基标志位
}
/*****************时基处理函数**********************/
void SysTick_intgnd(void)
{
if(f_systick_1ms==1)
{
f_systick_1ms=0;
cnt_systick_2ms++;
if(cnt_systick_2ms==2)
{
cnt_systick_2ms=0;
f_systick_2ms=1; //按键扫描标志位
}
cnt_systick_4ms++;
if(cnt_systick_4ms==4)
{
cnt_systick_4ms=0;
f_systick_4ms=1; //数码管扫描标志位
}
cnt_systick_10ms++;
if(cnt_systick_10ms==10)
{
cnt_systick_10ms=0;
f_systick_10ms=1;
cnt_systick_1s++;
if(cnt_systick_1s==100)
{
cnt_systick_1s=0;
f_systick_1s=1; //时钟1s更新一次标志位
}
}
cnt_systick_101ms++;
if(cnt_systick_101ms==101)
{
cnt_systick_101ms=0;
flag_Alarm_blink = ~ flag_Alarm_blink; //闹钟报警标志位
cnt_systick_505ms++;
if(cnt_systick_505ms==5)
{
cnt_systick_505ms=0;
f_systick_505ms=1;
}
}
}
}
/******************液晶写入************************/
write_1602com(uchar com)//液晶写入指令函数
{
rs=0;//置为写入命令
P0=com;//送入数据
delay(1);
en=1;//拉高使能端
delay(1);
en=0;//完成高脉冲
}
write_1602dat(uchar dat)
{
rs=1;//置为写入数据
P0=dat;//送入数据
delay(1);
en=1;
delay(1);
en=0;
}
/*********************over***********************/
/********************ds1302****************************/
void write_byte(uchar dat)
{
ACC=dat;
RST=1;
for(a=8;a>0;a--)
{
IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>>1;
}
}
uchar read_byte()
{
RST=1;
for(a=8;a>0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return (ACC);
}
void write_1302(uchar add,uchar dat)
{
RST=0;
SCLK=0;
RST=1;
write_byte(add);
write_byte(dat);
SCLK=1;
RST=0;
}
uchar read_1302(uchar add)
{
uchar temp;
RST=0;
SCLK=0;
RST=1;
write_byte(add);
temp=read_byte();
SCLK=1;
RST=0;
return(temp);
}
uchar BCD_Decimal(uchar bcd)
{
uchar Decimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0F));
}
void ds1302_init()
{
RST=0;
SCLK=0;
write_1302(0x80,miao|0x00);//允许写
}
void write_sfm(uchar add,uchar dat)//写时分秒
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(er+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
void write_nyr(uchar add,uchar dat) //写年月日
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(yh+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
write_1602com(yh+6);
}
void write_week(uchar week)//写星期函数
{
write_1602com(yh+0x0d);
switch(week)
{
case 1:write_1602dat('M');//delay(5);
write_1602dat('O');//delay(5);
write_1602dat('N');
break;
case 2:write_1602dat('T');//delay(5);
write_1602dat('U');//delay(5);
write_1602dat('E');
break;
case 3:write_1602dat('W');//delay(5);
write_1602dat('E');//delay(5);
write_1602dat('D');
break;
case 4:write_1602dat('T');//delay(5);
write_1602dat('H');//delay(5);
write_1602dat('U');
break;
case 5:write_1602dat('F');//delay(5);
write_1602dat('R');//delay(5);
write_1602dat('I');
break;
case 6:write_1602dat('S');//delay(5);
write_1602dat('T');//delay(5);
write_1602dat('A');
break;
case 7:write_1602dat('S');//delay(5);
write_1602dat('U');//delay(5);
write_1602dat('N');
break;
}
}
lcd_init()//液晶初始化函数
{ wr=0;
write_1602com(0x38);//设置液晶工作模式
write_1602com(0x0c);//开显示不显示光标
write_1602com(0x06);//整屏不移动,指针加一
write_1602com(0x01);
delay(10);
// write_1602com(yh+2);//字符写入的位置
// for(a=0;a<14;a++)
// {
// write_1602dat(tab1[a]);
// //delay(3);
// }
// write_1602com(er+4);
// for(a=0;a<8;a++)
// {
// write_1602dat(tab2[a]);
// //delay(3);
// }
}
void keyscan()
{
//key=0;
if(key==0)
{
delay(5);
if(key==0)
{
TR0=0;
TR1=0;
write_1602com(0x01);
delay(1);
if(keyvalue==2)
keyvalue=0;
keyvalue++; //设置菜单界面
}
}
switch(keyvalue)
{
case 0:
case 1: //钟表
{
TR0=1;TR1=0;
if(key1==0)//key1为功能键
{
delay(5);
if(key1==0)
{
TR0=0;
TR1=0;
while(!key1);
key1n++;
if(key1n==9)
key1n=1;
}
}
switch(key1n)
{
case 1:
{
TR0=0; //关闭定时器
TR1=0;
write_1602com(er+0x0b);//写入光标位置
delay(5);
write_1602com(0x0f);//设置光标为闪烁
delay(5);
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);//miao
write_1302(0x8e,0x80);
}
break;
case 2:
TR0=0; //关闭定时器
TR1=0;
write_1602com(er+8);//fen
//write_1602com(0x0f);
break;
case 3:
TR0=0; //关闭定时器
TR1=0;
write_1602com(er+5);//shi
//write_1602com(0x0f);
break;
case 4:
TR0=0; //关闭定时器
TR1=0;
write_1602com(yh+0x0f);//week
//write_1602com(0x0f);
break;
case 5:
TR0=0; //关闭定时器
TR1=0;
write_1602com(yh+0x0b);//ri
//write_1602com(0x0f);
break;
case 6:
TR0=0; //关闭定时器
TR1=0;
write_1602com(yh+0x08);//yue
//write_1602com(0x0f);
break;
case 7:
TR0=0; //关闭定时器
TR1=0;
write_1602com(yh+0x05);//nian
//write_1602com(0x0f);
break;
case 8:
write_1602com(0x0c);//设置光标不闪烁
TR0=1;//打开定时器
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x00|temp);//miao
write_1302(0x8e,0x80);
break;
}
if(key1n!=0)//当key1按下以下。再按以下键才有效
{
if(key2==0) //上调键
{
delay(5);
if(key2==0)
{
while(!key2);
switch(key1n)
{
case 1:miao++;
if(miao==60)
miao=0;
write_sfm(0x0a,miao);//写入新的秒数
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);
write_1302(0x8e,0x80);
write_1602com(er+0x0b);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
//write_1602com(0x0b);
break;
case 2:fen++;
if(fen==60)
fen=0;
write_sfm(0x07,fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
write_1602com(er+8);
break;
case 3:shi++;
if(shi==24)
shi=0;
write_sfm(4,shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
write_1602com(er+5);
break;
case 4:week++;
if(week==8)
week=0;
write_week(week);
write_1602com(yh+0x0f);
break;
case 5:ri++;
if(ri==31)
ri=0;
write_nyr(10,ri);
temp=(ri)/10*16+(ri)%10;
write_1302(0x8e,0x00);
write_1302(0x86,temp);
write_1302(0x8e,0x80);
write_1602com(yh+11);
break;
case 6:yue++;
if(yue==13)
yue=0;
write_nyr(7,yue);
temp=(yue)/10*16+(yue)%10;
write_1302(0x8e,0x00);
write_1302(0x88,temp);
write_1302(0x8e,0x80);
write_1602com(yh+8);
break;
case 7:nian++;
if(nian==100)
nian=0;
write_nyr(4,nian);
write_1602com(yh+5);
break;
} //switchkeyln
}//key2
}
if(key3==0)
{
delay(5);
if(key3==0)
{
while(!key3);
switch(key1n)
{
case 1:miao--;
if(miao==-1)
miao=59;
write_sfm(0x0a,miao);//写入新的秒数
write_1602com(er+0x0b);//因为设置液晶的模式是写入数据后,指针自动加一,在这里是写回原来的位置
//write_1602com(0x0b);
break;
case 2:fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
temp=(fen)/10*16+(fen)%10;
write_1302(0x8e,0x00);
write_1302(0x82,temp);
write_1302(0x8e,0x80);
write_1602com(er+8);
break;
case 3:shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
temp=(shi)/10*16+(shi)%10;
write_1302(0x8e,0x00);
write_1302(0x84,temp);
write_1302(0x8e,0x80);
write_1602com(er+5);
break;
case 4:week--;
if(week==-1)
week=7;
write_week(week);
write_1602com(yh+0x0f);
break;
case 5:ri--;
if(ri==-1)
ri=30;
write_nyr(10,ri);
temp=(ri)/10*16+(ri)%10;
write_1302(0x8e,0x00);
write_1302(0x86,temp);
write_1302(0x8e,0x80);
write_1602com(yh+11);
break;
case 6:yue--;
if(yue==-1)
yue=12;
write_nyr(7,yue);
temp=(yue)/10*16+(yue)%10;
write_1302(0x8e,0x00);
write_1302(0x88,temp);
write_1302(0x8e,0x80);
write_1602com(yh+8);
break;
case 7:nian--;
if(nian==-1)
nian=99;
write_nyr(4,nian);
write_1602com(yh+5);
break;
} //switchkeyln
}
} //key3
}
}//case1 菜单
break;
case 2:
{
static uint data count;
TR0=0;TR1=1;
SysTick_intgnd();
if(key1==0)//秒表计时开始
{
delay(5);
if(key1==0)
{
write_1602com(0x01);
delay(1);
swatch_Start_Flag =1;
}
}
if(key2==0)//秒表计时结束
{
delay(5);
if(key2==0)
swatch_Start_Flag =0;
}
if(key3==0)//复位
{
delay(5);
if(key3==0)
swatch_Start_Flag =0;
count=0;
}
if(swatch_Start_Flag ==1)
{
if(f_systick_10ms == 1) //产生跑秒
{
f_systick_10ms = 0;
count++;
if(count==9999) count = 0;
}
}
ge=count%10;
shi=count/10%10;
bai=count/100%10;
qian=count/1000;
// lcd_init();
write_1602com(yh+3);
write_1602dat(ge+0x30);
write_1602com(yh+2);
write_1602dat(shi+0x30);
write_1602com(yh+1);
write_1602dat(bai+0x30);
write_1602com(yh+0);
write_1602dat(qian+0x30);
}
break;
}
}
void init()
{
TMOD=0x11;
TH0=0;
TL0=0;
EA=1;
ET0=1;
//TR0=1;
}
//void cmg(void)//数码管锁存函数
//{
//dula=1;
//P0=0x00;
//dula=0;
//wela=1;
//P0=0x00;
//wela=0;
//}
void timer0() interrupt 1
{
miao = BCD_Decimal(read_1302(0x81));
fen = BCD_Decimal(read_1302(0x83));
shi = BCD_Decimal(read_1302(0x85));
ri = BCD_Decimal(read_1302(0x87));
yue = BCD_Decimal(read_1302(0x89));
nian=BCD_Decimal(read_1302(0x8d));
week=BCD_Decimal(read_1302(0x8b));
//keyscan();
write_sfm(10,miao);
write_1602com(er+0x09);
write_1602dat(':');
write_sfm(7,fen);
write_1602com(er+0x06);
write_1602dat(':');
write_sfm(4,shi);
write_nyr(4,nian);
write_1602com(yh+0x06);
write_1602dat('-');
write_nyr(10,ri);
write_nyr(7,yue);
write_1602com(yh+0x09);
write_1602dat('-');
write_week(week);
}
void main()
{
// cmg();//数码管锁存
lcd_init();
ds1302_init();
init();
Timer1_Init();
SysTick_intgnd();
while(1)
{
//TH0=(65536-60000)/256;
//TL0=(65536-60000)%256;
// if(f_systick_1ms==1)
// timer0();
keyscan();
}
}
复制代码
所有资料51hei提供下载:
【实验104】DS1302时钟显示.rar
(294.79 KB, 下载次数: 17)
2019-6-2 14:34 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1