引言

本设计以AT89S52单片机为控制核心,时钟芯片DS1302提供时钟源,配合LCD1602液晶显示模块,组成基本硬件系统,同时利用HC-05嵌入式蓝牙串口通讯模块,可在手机端进行日期、时间的校准。具有走时精确,功耗低,显示直观,调整简单方便等优点。

功能描述

基本显示:

第一行为日期,依次为:年-月-日-星期

第二行为时间,依次为:时:分:秒

说明:

每月的天数,闰年的天数可自动调整

蓝牙校准日期:

命令d+年月日星期+#,如设置2016年12月8日星期四,手机发送命令:d16120804

蓝牙校准时间:

命令t+时分秒+#,如设置15:11:46,手机发送命令:t151146#

硬件电路设计

硬件概述:

AT89S52单片机介绍:AT89S52_百度百科

DS1302时钟芯片介绍:DS1302_百度百科

LCD1602液晶模块介绍:LCD1602_百度百科

HC-05嵌入式蓝牙串口通讯模块介绍:HC-05

蓝牙通信原理:

硬件电路图:

程序设计:

主程序:main.c

 #include <reg52.h>
#include <LCD1602.c>
#include <DS1302.c>
#include <bluetooth.c>
void serial_initial()
{
EA = ; //开总中断
ES = ; //开串口中断
TMOD = 0x20; //定时器1,方式2,8位自动重装,作波特率发生器
TH1 = 0xfa; //波特率9600
TL1 = 0xfa;
TR1 = ;
SCON = 0x50; //串口工作方式1,允许接收
PCON = 0x80; //SMOD=1,bps倍增9600
}
void clock_initial()
{
lcd_initial(); //1602初始化
serial_initial(); //中断初始化
Set_DS1302_Time(0x80); //先写入寄存器起始地址设置时钟日历初值
dis_string(0x80,"Date:11-11-11-11");
dis_string(0xc0,"Time: 11:11:11 ");
flag_date = ;
flag_time = ;
bt_flag = ;
} void main()
{
clock_initial();
while()
{
if(flag_date == &&cmd_end==)
date_set();
if(flag_time == &&cmd_end==)
time_set();
Read_DS1302_Time(0x81);
dis_twonum (, , TimeData[]); //年
dis_twonum (, , TimeData[]); //月
dis_twonum (, , TimeData[]); //日
dis_twonum (, , TimeData[]); //星期
dis_twonum (, , TimeData[]); //时
dis_twonum (, , TimeData[]); //分
dis_twonum (, , TimeData[]); //秒
Delay_Ms(); //延时
}
} void serial_int() interrupt
{
uchar temp; //定义串口接收数据变量 ES = ; //关串口中断
RI = ; //令接收中断标志位为0(软件清零)
temp = SBUF; //将接收到的数据送入变量 temp
data_deal(temp); //对收到数据进行处理
ES = ; //开串口中断
/*SBUF = temp; //将接收的数据发送回去
while(TI == 0);
TI = 0; */
}  

DS1302时钟芯片驱动程序:DS1302.c

 sbit TSCLK = P2 ^ ; //时钟
sbit TIO = P2 ^ ; //数据
sbit TRST = P2 ^ ; //使能 //时钟日历暂存数组,秒、分、时、日、月、周、年 初值为= 16年2月15日 周1 23:58:50
uchar TimeData[] = {, , , , , , };
void Delay_Ms(uint ms)
{
uint i;
do {
i = / ;
while(--i); //96T per loop
} while(--ms);
}
/*写一字节*/
void DS1302_W_Byte(uchar dat)
{
uchar i;
for(i = ; i < ; i++) //每次写1bit,写8次
{
TSCLK = ; //拉低时钟总线
TIO = dat & 0x01; //从一字节最低位开始写
TSCLK = ; //拉高时钟总线,DS1302把数据读走
dat >>= ; //数据右移一位
}
}
/*读一字节*/
uchar DS1302_R_Byte()
{
uchar i, dat;
for(i = ; i < ; i++)
{
TSCLK = ;
dat >>= ;
if(TIO) dat |= 0x80;//读取数据
TSCLK = ;
}
return dat; //返回读取的数据
}
/*写数据,命令*/
void DS1302_W_DAT(uchar cmd, uchar dat)
{
TRST = ;
TSCLK = ;
TRST = ;
DS1302_W_Byte(cmd);
DS1302_W_Byte(dat);
}
/*读数据*/
uchar DS1302_R_DAT(uchar cmd)
{
uchar dat;
TRST = ;
TSCLK = ;
TRST = ;
DS1302_W_Byte(cmd);
dat = DS1302_R_Byte();
return dat;
} /*清除写保护*/
void DS1302_Clear_WP()
{
DS1302_W_DAT(0x8e, 0x00);
}
/*设置写保护*/
void DS1302_Set_WP()
{
DS1302_W_DAT(0x8e, 0x80);
TRST = ;
TSCLK = ;
}
/*时间预设*/
void Set_DS1302_Time(uchar addr)
{
uchar i, j;
DS1302_Clear_WP(); //清除写保护
for(i = ; i < ; i++) //写入7个字节的时钟初始值
{
j = TimeData[i] / ; //BCD码转换
TimeData[i] %= ;
TimeData[i] += j * ;
DS1302_W_DAT(addr, TimeData[i]);
addr += ;
}
DS1302_Set_WP(); //开写保护
}
/*读取1302时间*/
void Read_DS1302_Time(uchar addr)
{
uchar i;
DS1302_Clear_WP();
for(i = ; i < ; i++) //从DS1302读取7个字节的时钟日历数据
{
TimeData[i] = DS1302_R_DAT(addr);
addr += ;
}
DS1302_Set_WP();
}

LCD1602液晶模块驱动程序:LCD1602.c

 #define uint unsigned int
#define uchar unsigned char
sbit RS = P2 ^ ;
sbit RW = P2 ^ ;
sbit EN = P2 ^ ; void check_busy() //检测是否忙
{
uchar dat;
P0 = 0xff;
RS = ;
RW = ;
do
{
EN = ;
dat = P0;
EN = ;
} while(dat & 0x80);
} void write_cmd(uchar cmd) //写命令
{
check_busy();
RS = ;
RW = ;
P0 = cmd;
EN = ;
EN = ;
} void write_data(uchar dat) //写数据
{
check_busy();
RS = ;
RW = ;
P0 = dat;
EN = ;
EN = ;
}
/*显示一位数字*/
void dis_onenum (uchar X, uchar Y, uchar dat)
{
if(Y) X |= 0X40;
X |= 0X80;
write_cmd(X);
write_data(dat);
}
/*显示两位数字*/
void dis_twonum (uchar X, uchar Y, uchar dat)
{
dis_onenum (X, Y, dat / + '');
dis_onenum (X+, Y, dat % + '');
}
/*显示字符串*/
void dis_string(uchar location,uchar *p)
{
write_cmd(location);
while(*p)
{
write_data(*p);
p++;
}
} void lcd_initial()
{
write_cmd(0x38);
write_cmd(0x0c);
write_cmd(0x06);
write_cmd(0x01);
}

蓝牙控制程序:bluetooth.c

 uchar date[],time[];
uchar cmd_index, cmd_start, cmd_end, bt_flag;
bit flag_time, flag_date; void time_set()
{
uchar a;
uchar i, j, addr = 0x80;
for(a = ; a < ; a++)
time[a] = time[a] - 0x30; //数据处理
TimeData[] = (time[] * + time[]) % ; //小时
TimeData[] = (time[] * + time[]) % ; //分钟
TimeData[] = (time[] * + time[]) % ; //秒 DS1302_Clear_WP(); //清除写保护
for(i = ; i < ; i++) //写入时间设置值
{
j = TimeData[i] / ; //BCD码转换
TimeData[i] %= ;
TimeData[i] += j * ;
DS1302_W_DAT(addr, TimeData[i]);
addr += ;
}
DS1302_Set_WP(); //开写保护
flag_time = ;
} void date_set()
{
uchar a;
uchar i, j, addr = 0x86;
for(a = ; a < ; a++)
date[a] = date[a] - 0x30; //对数据处理
TimeData[] = (date[] * + date[]) ; //日
TimeData[] = (date[] * + date[]) ; //月
TimeData[] = (date[] * + date[]) ; //年
TimeData[] = (date[] * + date[]) ; //周 DS1302_Clear_WP();
for(i = ; i < ; i++) //写入日期设置值
{
j = TimeData[i] / ; //BCD码转换
TimeData[i] %= ;
TimeData[i] += j * ;
DS1302_W_DAT(addr, TimeData[i]);
addr += ;
}
DS1302_Set_WP(); //开写保护
flag_date = ;
} void data_deal(uchar data_buf)
{
switch(data_buf)
{
case 'd':
cmd_start = ;
cmd_end = ;
flag_date = ;
cmd_index = ;
bt_flag = ;
break;
case 't':
cmd_start = ;
cmd_end = ;
flag_time = ;
cmd_index = ;
bt_flag = ;
break;
case '#':
cmd_start = ;
cmd_end = ;
break;
default:break;
}
if (cmd_start == )
{
switch (bt_flag)
{
case :
date[cmd_index] = data_buf;
cmd_index++;
break;
case :
time[cmd_index] = data_buf;
cmd_index++;
break;
default:break;
}
if (cmd_index >= )
cmd_index = ;
}
}

总结:

2016.12.05——2016.12.07三天的单片机课程设计结束了,我的课程设计是——《基于AT89S52单片机和DS1302时钟芯片的电子钟(可手机蓝牙校准)》,此次设计让我对AT89S52单片机有了更深的认识,为了完成设计,我又学习了DS1302时钟芯片时间写入,时间读取等基本的读写操作时序,对DS1302的操作方法有了一定了解。

  当液晶时钟第一次被成功的校准时,我很激动和兴奋,也很有成就感。由于使用了蓝牙串口校准时间,所以又复习了串口通讯的原理,在调试的过程中,对串口数据的处理也有了一定的经验:由于串口是一个一个字符接收的,当接收到下一个字符时,上一个字符就会丢失,为了保存接收到的每个字符,先将接收到的数据存放到数组中,然后数组指针加一,这样串口接收的每一个数据就会按照接收的先后顺序有序的存放到数组中,然后数组中的元素就可以被我们拿来进行各种操作了,如本设计中的设置时间和日期。

  由于课程设计的时间较短,所以此设计仅在时间显示的基础上,增加了蓝牙串口校准时间功能,此设计还有很多可以完善和改进的功能,如:

1.增加闹钟功能,增加按键校准时间日期、设置闹钟功能,

3.增加星期计算功能,调整时只需调整年月日,调整完毕后自动计算出星期几,

4.增加DS18B20温度传感器实时显示温度,手机可远程获取温度,

5.星期显示为英文缩写,如周一:Mon,

6.简单报警功能,   等其他功能,这些功能都是可以实现的。

虽然单片机课程设计结束了, 但我的学习之路还没有结束,我将继续学习51单片机的其他扩展功能,以及其他的通讯协议,如IIC通讯,SPI通讯,红外通信,WiFI无线通讯,为以后学习性能更强大的单片机做个准备,MCS-51系列单片机虽然是低功耗可编程处理器,但它也只是8位微处理器,它的指令执行速度、驱动能力、程序存储等其他片内资源都是非常有限的,已经不能满足当今科技发展的需要,所以为了更好的发展,还要学习其他性能更强大的单片机。课程设计结束了,还要感谢老师的的指导我才能完成课程设计,衷心的感谢老师的帮助和提出的建议。


今天开通了博客园的个人博客,因为之前是用的新浪博客,没有插入代码的功能,所以排版非常乱,现在有了这个博客就可以美美的插入代码了,哈哈,就把上学期做的课程设计作为新家的第一篇文章吧!

2017-03-12  18:24:01

欢迎大家关注我的个人博客 http://www.wangchaochao.top/
微信扫码关注我的公众号

不定期更新个人学习笔记和技术总结,欢迎大家互相学习交流!

单片机课程设计——《基于AT89S52单片机和DS1302时钟芯片的电子时钟(可蓝牙校准)》的更多相关文章

  1. 单片机课程设计-四位加法计算器设计参考程序(c语言)

    #include<reg52.h> typedef unsigned char uint8; typedef unsigned int uint16; sbit rw=P2^; sbit ...

  2. 课程设计- 基于ssm的捐赠物资分配管理系统 && 基于java的申请救援管理系统

    课程设计- 基于ssm的捐赠物资分配管理系统 && 基于java的申请救援管理系统 注意:该项目只展示部分功能,如需了解,评论区咨询即可. 1.开发环境 开发语言:Java 后台框架: ...

  3. 单片机课程设计——课程设计之四位加法计算器(2)(C代码)

    #include<reg52.h> typedef unsigned char uint8; typedef unsigned int uint16; sbit rw=P2^5; sbit ...

  4. 嵌入式系统及应用课程设计——基于STM32的温湿度监测系统

    大三上学期期末总结,嗯,没错上学期,写在新学期开始,hhh. 上学期学了一门嵌入式系统及应用的课程,期末的课程设计题目是基于STM32的温湿度监测系统. 记得刚开始做课程设计的时候,听说先设计画出原理 ...

  5. 单片机DIY制作-基于STM32单片机甲醛二氧化碳温度湿度采集系统

    基于STM32单片机甲醛二氧化碳温度湿度采集系统 实践制作DIY-GC008-甲醛二氧化碳温度湿度采集系统 一.功能说明: 基于STM32单片机设计-甲醛二氧化碳温度湿度采集系统 二.功能介绍: 1. ...

  6. Java团队课程设计——基于学院的搜索引擎

    团队名称.团队成员介绍.任务分配,团队成员课程设计博客链接 姓名 成员介绍 任务分配 课程设计博客地址 谢晓淞(组长) 团队输出主力 爬虫功能实现,Web前端设计及其后端衔接 爬虫:https://w ...

  7. 单片机课程设计>八音盒

    2017—2018学年度第一学期 <单片机原理及应用>作品考试 八音盒 2017-2018-1<单片机原理及应用>作品设计提交文档 一.作品设计目的 1.利用51单片机的各个部 ...

  8. j2ee课程设计—基于activiti的请休假系统

    前言 课设基于SSM框架,数据库采用mysql,主要业务交给activiti,版本控制利用github. 参考资料: Intellij 部署SSM框架 Activiti就是这么简单 方大师的教材 下文 ...

  9. 课程设计-基于SSM的在线课程教学系统代码-基于java的线上课程资源共享论坛系统

    注意:该项目只展示部分功能,如需了解,评论区咨询即可. 1.开发环境 开发语言:Java 后台框架:SSM 前端框架:vue 数据库:MySQL 设计模式:MVC 架构:B/S 源码类型: Web 编 ...

随机推荐

  1. iOS实现视频和图片的上传

    关于iOS如何实现视频和图片的上传, 我们先理清下思路 思路: #1. 如何获取图片? #2. 如何获取视频? #3. 如何把图片存到缓存路径中? #4. 如何把视频存到缓存路径中? #5. 如何上传 ...

  2. 3408: [Usaco2009 Oct]Heat Wave 热浪

    3408: [Usaco2009 Oct]Heat Wave 热浪 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 67  Solved: 55[Subm ...

  3. 3DES 加密 解密

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c91b13 } p.p2 { margin: 0.0px 0. ...

  4. Jaro-Winkler Distance

    发现commons-lang 中有实现: StringUtils.class public static double getJaroWinklerDistance(final CharSequenc ...

  5. android 仿摩拜单车共享单车进度条实现StepView

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6552712.html 先看效果图: Step1:定义StepBean 定义五个状态,分别为:为完成.正在进行 ...

  6. python 接口自动化测试(一)

    一.测试需求描述 对服务后台一系列SOAP接口功能测试 参数传入:根据接口描述构造不同的参数输入值(Json格式) 二.程序设计 通过Excel配置具体的测试用例数据 保存参数为Json格式,预写入预 ...

  7. linux 私房菜 CH6 Linux 的档案权限与目录配置

    查看文件属性 ls -al 第一栏:类型与权限 d:目录: -:档案: l:链接档: b:可随机存取装置: c:一次性存取装置: 第二栏:有多少档名连结到此节点 第三栏:拥有者 第四栏:所属群组 第五 ...

  8. mui和zepto的tap事件

    zepto.js和mui一起使用的时候,tap事件会发生两次,这时只要不引用zepto.js的touch.js就可以了,只用mui的tap事件转自[B5教程网]:http://www.bcty365. ...

  9. 利用Register protocol实现网页调用桌面程序(类似迅雷、QQ等)

    前言 我们经常看到 tencent://.. thunder://     这两种开头的网址,往往觉得很奇怪,很想弄懂其中的原理,是如何实现的,我查找了相关的 资料,终于找到了,跟大家分享下. 原理篇 ...

  10. Nginx的配置文件详解

    主配置文件: 查看nginx的进程可以看到nginx所使用的配置文件: 主配置一般会被用来设置一些全局的参数: 参数详解: user nobody nobody;          //设置nginx ...