基于MCS-51单片机的数字时钟设计
项目面试问题
C/C++/嵌入式—面试题汇总
一、项目描述
1.基于DS1302时钟模块,可以完成年、月、日、时、分、秒、周的正确显示。
2.可以通过外部按键对当前时间进行校准。
3.能够以12小时和24小时制表示方式显示时间。
4.能够通过外部按键设置闹钟提醒时间。
实际操作:
LCD1602显示时钟,按K3键进入时钟设置,此时秒钟停止走动,按K1键选择设置的秒、分、时、
日、月、星期、年,按K2键进行加1,设置完成后,再次按下K3键继续走时,按下K4进入闹钟
界面设置(在闹钟界面不能按下K3),K1进行选择时、分,K2进行加一,再按下K4返回时钟界面,
当时间走到设置时间时,蜂鸣器会响起大概五秒钟,之后继续走时。按下矩阵按键P15进行12/24小时制切换。
二、项目功能展示
1.日期显示
2.闹钟时间设置
3.二十四小时制显示
4.十二小时制显示
三、代码展示
1、main.c
/*******************************************************************************
参考LCD1602液晶显示实验接线图
参考DS1302时钟实验接线图
K1-->P31
K2-->P30
K3-->P32
K4-->P33(该按键未做功能,可扩展)
实验操作:
LCD1602显示时钟,按K3键进入时钟设置,此时秒钟停止走动,按K1键选择设置的秒、分、时、
日、月、星期、年,按K2键进行加1,设置完成后,再次按下K3键继续走时,按下K4进入闹钟
界面设置(在闹钟界面不能按下K3),K1进行选择时、分,K2进行加一,再按下K4返回时钟界面,
当时间走到设置时间时,蜂鸣器会响起大概五秒钟,之后继续走时。
按下矩阵按键P15进行12/24小时制切换。
此时开机时钟默认为12:00:55,闹钟时间为12:01(分)
*******************************************************************************/
#include <reg51.h>
#include "lcd.h"
#include "ds1302.h"
#define GPIO_KEY P1
sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3; //管脚接线
sbit beep=P1^5;
sbit line=P1^4;
sbit list1=P1^3;
sbit list2=P1^2;
sbit led1=P2^0;
sbit led2=P2^1;
sbit led3=P2^2;
sbit led4=P2^3;
sbit led5=P2^4;
void Int0Configuration();
void LcdDisplay();
void DisplayTime();
void DisplayClock();
void write_sfm(uchar add,uchar date);
unsigned char toCompare();
unsigned char SetState,SetPlace,SetClock;
bit ClockPlace;
bit ClockFlag;
void Delay10ms(void); //误差 0us
unsigned char C_shi=12,C_fen=1;
int count = 0;
uint APM = 0; //为0时表示24小时制,为1时表示上午,为2时表示下午
int temp = 0; //为0时表示24小时制,为1时表示12小时制
uint h=0x23; //默认初始24小时制
uint key;
uint key_num;//键盘扫描值,键盘键值
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void delay(uint i)
{
while(i--);
}
void main()
{
uint keynum();
unsigned char result;
unsigned int i;
unsigned int time = 1500;
Int0Configuration();
LcdInit();
Ds1302Init();
while(1)
{
key=16;
key = keynum();
if(key==7) //检测按键K2是否按下
{
led5=0;
delay(20000);
led5=1;
Delay10ms(); //消除抖动
if(key==7)
{
led5=0;
delay(20000);
led5=1;
SetPlace=2;
if((TIME[SetPlace]>=0x0c) && (temp==0))
{
/*LcdWriteCom(0x80+0x40+10);
LcdWriteData('P');LcdWriteData('M'); */
TIME[SetPlace]=TIME[SetPlace]-18;
APM = 2;
temp = 1;
}
else if((TIME[SetPlace]<0x0c) && (temp==0))
{
/*LcdWriteCom(0x80+0x40+10);
LcdWriteData('A');LcdWriteData('M'); */
APM = 1;
temp = 1;
}
else if((TIME[SetPlace]<0x0c) && (APM==2))
{
/*LcdWriteCom(0x80+0x40+10);
LcdWriteData(' ');LcdWriteData(' ');*/
TIME[SetPlace]=TIME[SetPlace]+18;
APM = 0;
temp = 0;
}
else if((TIME[SetPlace]<0x0c) && (APM==0))
{
/*LcdWriteCom(0x80+0x40+10);
LcdWriteData('A');LcdWriteData('M'); */
APM = 1;
temp = 1;
}
else if((TIME[SetPlace]<0x0c) && (APM==1))
{
/*LcdWriteCom(0x80+0x40+10);
LcdWriteData(' ');LcdWriteData(' '); */
APM = 0;
temp = 0;
}
}
while((i<50)&&(key==7)) //检测按键是否松开
{
Delay10ms();
i++;
}
i=0;
}
if(APM == 0)
{
LcdWriteCom(0x80+0x40+10);
LcdWriteData(' ');LcdWriteData(' ');
}
else if(APM == 1)
{
LcdWriteCom(0x80+0x40+10);
LcdWriteData('A');LcdWriteData('M');
}
else if(APM == 2)
{
LcdWriteCom(0x80+0x40+10);
LcdWriteData('P');LcdWriteData('M');
}
if(ClockFlag)
{
while(time>0)
{
time--;
beep=0;
i=150;
while(i>0)
{
i--;
}
beep=1;
i=150;
while(i>0)
{
i--;
}
}
}
if(K4==0)
{
led4=0;
delay(20000);
led4=1;
Delay10ms(); //消除抖动
if(K4==0)
{
while(!K4); //等待按键释放
SetClock = ~SetClock;
LcdWriteCom(0x01); //清屏
}
}
if(SetClock == 0)
{
DisplayTime();
result=toCompare();
if(result) //闹钟响起
ClockFlag=1;
}
else
DisplayClock();
}
}
/********************************************************************/
//函数名:delay_1ms(uint x)
//功能:利用定时器0精确定时1ms; 自加 time_t的值为后面时间调整函数服务
//调用函数:
//输入参数:x,1ms计数
//输出参数:
//说明:延时的时间为1ms乘以x
/********************************************************************/
void delay_1ms(uint x)
{
TMOD=0X01;//开定时器0,工作方式为1
TR0=1;//启动定时器0;
while(x--)
{
TH0=0Xfc;//定时1ms初值的高8位装入TH0
TL0=0X18;//定时1ms初值的低8位装入TL0
while(!TF0);//等待,直到TF0为1
TF0=0;
}
TR0=0;//停止定时器0;
}
/**********************************************************/
//函数名:keyscan()
//功能:得出4x4键盘的行列扫描值
//调用函数:delay_1ms(uint x)
//输入参数:
//输出参数:
//说明:通过P1口的扫描得出扫描值key,无键按下key为16
/**********************************************************/
uchar keyscan()
{
uchar code_h; //行扫描值
uchar code_l; //列扫描值
P1=0XF0; //P1.0-P1.3全为0,(行状态全为低电平)
if((P1&0xF0)!=0XF0) //如果P1.4-P1.7不全为1,可能有键按下(为准确识别按键动作)
{
delay_1ms(5); //廷时去抖动,为准确识别按键动作
if((P1&0xF0)!=0XF0)//重读高4位(列状态),若还是不全为1,定有键按下
{
code_h=0xfe; //开始行扫描 (0xfe:11111110)
while((code_h&0x10)!=0x00)//判断是否扫描四行(X0~X3)完毕,若不是,继续扫描(0x10:00010000)
{
P1=code_h; //第1次P1.0置为0,其余高电平;第2次P1.1置为0,其余高电平 ;第3次P1.2置为0,其余高电平;第4次P1.3置为0,其余高电平
if((P1&0xF0)!=0XF0) //如果P1.4-P1.7不全为1,该行有键按下(0xF0:11110000)
{
code_l=(P1&0xF0|0x0F);//保留P1口高4位,低4位变为1,作为列值
return((~code_h)+(~code_l));//键盘编码=行扫描值+列扫描值 (取反后用,相当于改为按下按键对应的行、列标识为1,其它为0)
}
else //左移后补0,但是我们需要将其他位置1,所以+1
code_h=(code_h<<1)|0x01; //若该行无键按下,行扫描值左移+1,扫描下一行
}
}
}
return(16); //无键按下,返回16
}
/**********************************************************/
//函数名:keynum()
//功能:得出4x4按键的键值
//调用函数:keyscan()
//输入参数:
//输出参数:
//说明:通过key的值确定按键键值
/**********************************************************/
uint keynum()
{
int i=0,j=0;
int tab[4][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11},{12,13,14,15}};
//4x4键盘各键值标注
key=16;
key = keyscan();//引入key值
if((key&0x01)!=0) i=0; //判断出按下按键的行列号 (即找出低电平的行、列)
if((key&0x02)!=0) i=1;
if((key&0x04)!=0) i=2;
if((key&0x08)!=0) i=3;
if((key&0x10)!=0) j=0;
if((key&0x20)!=0) j=1;
if((key&0x40)!=0) j=2;
if((key&0x80)!=0) j=3;
key_num=key;
if(key!=16)
{
key_num = tab[i][j];//通过比较得出4x4键盘的键值
}
return key_num;
}
/*******************************************************************************
* 函数名 : toCompare()
* 函数功能 : 比较闹钟和时钟
* 输入 : 无
* 输出 : 0:时间不同 1:时间相同
*******************************************************************************/
unsigned char toCompare()
{
unsigned char shi,fen;
shi = (TIME[2]/16)*10 + TIME[2]&0x0f;
fen = (TIME[1]/16)*10 + TIME[1]&0x0f;
if((shi==C_shi)&&(fen==C_fen))
return 1;
else
return 0;
}
/*******************************************************************************
* 函数名 : DisplayClock()
* 函数功能 : 闹钟显示的函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void DisplayClock()
{
LcdInit();
LcdWriteCom(0x80);
LcdWriteData('C');LcdWriteData('l');LcdWriteData('o');LcdWriteData('c');LcdWriteData('k');LcdWriteData(':');
if(K1==0)
{
led1=0;
delay(20000);
led1=1;
Delay10ms();
if(K1==0)
{
led1=0;
delay(20000);
led1=1;
while(!K1); //等待按键释放
ClockPlace = ~ClockPlace;
}
}
if(K2==0)
{
led2=0;
delay(2000);
led2=1;
Delay10ms();
if(K2==0)
{
led2=0;
delay(20000);
led2=1;
while(!K2);
if(ClockPlace == 0)
{
C_shi++;
if(C_shi>23)
C_shi=0;
LcdWriteCom(0x80+0x40+6);
LcdWriteCom(0x0f);
}
if(ClockPlace == 1)
{
C_fen++;
if(C_fen>59)
C_fen=0;
LcdWriteCom(0x80+0x40+9);
LcdWriteCom(0x0f);
}
}
}
Delay10ms();
LcdWriteCom(0x80+0x40+7);LcdWriteData(':');
Delay10ms();
write_sfm(5,C_shi);
Delay10ms();
write_sfm(8,C_fen);
Delay10ms();
}
void write_sfm(uchar add,uchar date) //在液晶上写时分秒
{
uchar shi,ge;
shi=date/10;
ge=date%10;
LcdWriteCom(0x80+0x40+add); //说明显示位置
LcdWriteData(shi+0x30);
LcdWriteData(ge+0x30);
}
/*******************************************************************************
* 函数名 : DisplayTime()
* 函数功能 : 时钟显示的函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void DisplayTime()
{
unsigned char i;
if(SetState==0)
{
Ds1302ReadTime();
}
else //key3按下,进入校准界面
{
count=0;
if(temp==0)
{
h = 0x23 ; //此时为24小时制
}
else if(temp==1)
{
h = 0x11; //此时为12小时制
}
if(K1==0) //检测按键K1是否按下
{
led1=0;
delay(20000);
led1=1;
Delay10ms(); //消除抖动
if(K1==0)
{
led1=0;
delay(20000);
led1=1;
SetPlace++;
if(SetPlace>=7)
SetPlace=0;
}
while((i<50)&&(K1==0)) //检测按键是否松开
{
Delay10ms();
i++;
}
i=0;
}
if(K2==0) //检测按键K2是否按下
{
led2=0;
delay(20000);
led2=1;
Delay10ms(); //消除抖动
if(K2==0)
{
led2=0;
delay(20000);
led2=1;
TIME[SetPlace]++;
if((TIME[SetPlace]&0x0f)>9) //换成BCD码。
{
TIME[SetPlace]=TIME[SetPlace]+6;
}
if((TIME[SetPlace]>=0x60)&&(SetPlace<2)) //分秒只能到59
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>h)&&(SetPlace==2)) //小时只能到23
{
TIME[SetPlace]=0;
if(APM==1)
{
APM=2;
}
else if(APM==2)
{
APM=1;
}
}
if((TIME[SetPlace]>=0x32)&&(SetPlace==3)) //日只能到31
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>=0x13)&&(SetPlace==4)) //月只能到12
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>=0x7)&&(SetPlace==5)) //周只能到7
{
TIME[SetPlace]=1;
}
// if(SetPlace==5) //月只能到12
// {
// TIME[SetPlace]=;
// }
}
while((i<50)&&(K2==0)) //检测按键是否松开
{
Delay10ms();
i++;
}
i=0;
}
key=16;
key = keynum();
if(key==4) //检测减键是否按下
{
led3=0;
delay(20000);
led3=1;
Delay10ms(); //消除抖动
if(key==4)
{
led3=0;
delay(20000);
led3=1;
if(TIME[SetPlace]==0x00)
{
count=1;
}
else if((TIME[SetPlace]&0x0f)==0x00)
{
TIME[SetPlace]=TIME[SetPlace]-6;
}
TIME[SetPlace]--;
//if(TIME[SetPlace]<0) //换成BCD码。
//{
// TIME[SetPlace]=TIME[SetPlace]+10;
//}
if((count==1)&&(SetPlace<2)) //分秒只能到59
{
TIME[SetPlace]=0x59;
}
if((count==1)&&(SetPlace==2)) //小时只能到h
{
TIME[SetPlace]=h;
if(APM==1)
{
APM=2;
}
else if(APM==2)
{
APM=1;
}
}
if((TIME[SetPlace]<=0x00)&&(SetPlace==3)) //日只能到31
{
TIME[SetPlace]=0x31;
}
if((TIME[SetPlace]<=0x00)&&(SetPlace==4)) //月只能到12
{
TIME[SetPlace]=0x12;
}
if((TIME[SetPlace]<=0x00)&&(SetPlace==5)) //周只能到7
{
TIME[SetPlace]=0x07;
}
// if(SetPlace==5) //月只能到12
// {
// TIME[SetPlace]=;
// }
}
while((i<50)&&(key==4)) //检测按键是否松开
{
Delay10ms();
i++;
}
i=0;
}
}
LcdDisplay();
}
/*******************************************************************************
* 函数名 : LcdDisplay()
* 函数功能 : 显示函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void LcdDisplay()
{
LcdWriteCom(0x80+0X40);
LcdWriteData('0'+TIME[2]/16); //时
LcdWriteData('0'+(TIME[2]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[1]/16); //分
LcdWriteData('0'+(TIME[1]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[0]/16); //秒
LcdWriteData('0'+(TIME[0]&0x0f));
LcdWriteCom(0x80);
LcdWriteData('2');
LcdWriteData('0');
LcdWriteData('0'+TIME[6]/16); //年
LcdWriteData('0'+(TIME[6]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[4]/16); //月
LcdWriteData('0'+(TIME[4]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[3]/16); //日
LcdWriteData('0'+(TIME[3]&0x0f));
LcdWriteCom(0x8D);
LcdWriteData('0'+(TIME[5]&0x07)); //星期
}
/*******************************************************************************
* 函数名 : Int0Configuration()
* 函数功能 : 配置外部中断0
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Int0Configuration()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
/*******************************************************************************
* 函数名 : Int0()
* 函数功能 : 外部中断0 中断函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Int0() interrupt 0
{
Delay10ms();
//keynum();
if(K3==0)
{
led3=0;
delay(20000);
led3=1;
SetState=~SetState;
SetPlace=0;
Ds1302Init();
}
}
/*******************************************************************************
* 函数名 : Delay10ms
* 函数功能 : 延时函数,延时10ms
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Delay10ms(void) //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}
2、led.c
#include"lcd.h"
/*******************************************************************************
* 函 数 名 : Lcd1602_Delay1ms
* 函数功能 : 延时函数,延时1ms
* 输 入 : c
* 输 出 : 无
* 说 明 : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 数 名 : LcdWriteCom
* 函数功能 : 向LCD写入一个字节的命令
* 输 入 : com
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //选择写入命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
// Lcd1602_Delay1ms(1);
LCD1602_DATAPINS = com << 4; //发送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdWriteData
* 函数功能 : 向LCD写入一个字节的数据
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择写入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdInit()
* 函数功能 : 初始化LCD屏
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //将8位总线转为4位总线
LcdWriteCom(0x28); //在四位线下的初始化
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#endif
3、ds1302.c
#include"ds1302.h"
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0x55, 0, 0x12, 0x23, 0x03, 0x02, 0x21};
/*******************************************************************************
* 函 数 名 : Ds1302Write
* 函数功能 : 向DS1302命令(地址+数据)
* 输 入 : addr,dat
* 输 出 : 无
*******************************************************************************/
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//写入8位数据
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}
/*******************************************************************************
* 函 数 名 : Ds1302Read
* 函数功能 : 读取一个地址的数据
* 输 入 : addr
* 输 出 : dat
*******************************************************************************/
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_(); //以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
/*******************************************************************************
* 函 数 名 : Ds1302Init
* 函数功能 : 初始化DS1302.
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
/*******************************************************************************
* 函 数 名 : Ds1302ReadTime
* 函数功能 : 读取时钟信息
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Ds1302ReadTime()
{
uchar n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
4.DS1302.H
#ifndef __DS1302_H_
#define __DS1302_H_
//---包含头文件---//
#include<reg51.h>
#include<intrins.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
//---定义ds1302使用的IO口---//
sbit DSIO=P3^4;
sbit RST=P3^5;
sbit SCLK=P3^6;
//---定义全局函数---//
void Ds1302Write(uchar addr, uchar dat);
uchar Ds1302Read(uchar addr);
void Ds1302Init();
void Ds1302ReadTime();
//---加入全局变量--//
extern uchar TIME[7]; //加入全局变量
#endif
5、LCD.H
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include<reg51.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c); //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat);
/*LCD1602初始化子程序*/
void LcdInit();
#endif