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



引言

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

功能描述

基本显示:

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

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

说明:

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

蓝牙校准日期:

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

蓝牙校准时间:

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

硬件电路设计

硬件概述:

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

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

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

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

蓝牙通信原理:

硬件电路图:

程序设计:

主程序:main.c

 1 #include <reg52.h>
 2 #include <LCD1602.c>
 3 #include <DS1302.c>
 4 #include <bluetooth.c>
 5 void serial_initial()
 6 {
 7     EA = 1;                //开总中断
 8     ES = 1;                //开串口中断
 9     TMOD = 0x20;        //定时器1,方式2,8位自动重装,作波特率发生器
10     TH1 = 0xfa;            //波特率9600
11     TL1 = 0xfa;
12     TR1 = 1;
13     SCON = 0x50;        //串口工作方式1,允许接收
14     PCON = 0x80;        //SMOD=1,bps倍增9600
15 }
16 void clock_initial()
17 {
18     lcd_initial();                 //1602初始化
19     serial_initial();            //中断初始化
20     Set_DS1302_Time(0x80);        //先写入寄存器起始地址设置时钟日历初值
21     dis_string(0x80,"Date:11-11-11-11");
22     dis_string(0xc0,"Time: 11:11:11  ");
23     flag_date = 0;
24     flag_time = 0;
25     bt_flag = 0;
26 }
27
28 void main()
29 {
30     clock_initial();
31     while(1)
32     {
33         if(flag_date == 1&&cmd_end==1)
34             date_set();
35         if(flag_time == 1&&cmd_end==1)
36             time_set();
37         Read_DS1302_Time(0x81);
38         dis_twonum (5, 0, TimeData[6]); //年
39         dis_twonum (8, 0, TimeData[4]); //月
40         dis_twonum (11, 0, TimeData[3]); //日
41         dis_twonum (14, 0, TimeData[5]); //星期
42         dis_twonum (6, 1, TimeData[2]); //时
43         dis_twonum (9, 1, TimeData[1]); //分
44         dis_twonum (12, 1, TimeData[0]); //秒
45         Delay_Ms(1000);                     //延时
46     }
47 }
48
49
50 void serial_int() interrupt 4
51 {
52     uchar  temp;             //定义串口接收数据变量
53
54     ES = 0;                 //关串口中断
55     RI = 0;                    //令接收中断标志位为0(软件清零)
56     temp = SBUF;            //将接收到的数据送入变量 temp
57     data_deal(temp);        //对收到数据进行处理
58     ES = 1;                 //开串口中断
59     /*SBUF = temp;    //将接收的数据发送回去
60     while(TI == 0);
61     TI = 0;    */
62 } ?

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

  1 sbit TSCLK = P2 ^ 0; //时钟
  2 sbit TIO = P2 ^ 1; //数据
  3 sbit TRST = P2 ^ 2; //使能
  4
  5 //时钟日历暂存数组,秒、分、时、日、月、周、年 初值为= 16年2月15日 周1 23:58:50
  6 uchar TimeData[7] = {50, 58, 23, 15, 2, 1, 16};
  7 void Delay_Ms(uint ms)
  8 {
  9     uint i;
 10     do {
 11         i = 11059200 / 96000;
 12         while(--i);   //96T per loop
 13     } while(--ms);
 14 }
 15 /*写一字节*/
 16 void DS1302_W_Byte(uchar dat)
 17 {
 18     uchar i;
 19     for(i = 0; i < 8; i++) //每次写1bit,写8次
 20     {
 21         TSCLK = 0;           //拉低时钟总线
 22         TIO = dat & 0x01;  //从一字节最低位开始写
 23         TSCLK = 1;           //拉高时钟总线,DS1302把数据读走
 24         dat >>= 1;           //数据右移一位
 25     }
 26 }
 27 /*读一字节*/
 28 uchar DS1302_R_Byte()
 29 {
 30     uchar i, dat;
 31     for(i = 0; i < 8; i++)
 32     {
 33         TSCLK = 0;
 34         dat >>= 1;
 35         if(TIO)    dat |= 0x80;//读取数据
 36         TSCLK = 1;
 37     }
 38     return dat;                //返回读取的数据
 39 }
 40 /*写数据,命令*/
 41 void DS1302_W_DAT(uchar cmd, uchar dat)
 42 {
 43     TRST = 0;
 44     TSCLK = 0;
 45     TRST = 1;
 46     DS1302_W_Byte(cmd);
 47     DS1302_W_Byte(dat);
 48 }
 49 /*读数据*/
 50 uchar DS1302_R_DAT(uchar cmd)
 51 {
 52     uchar dat;
 53     TRST = 0;
 54     TSCLK = 0;
 55     TRST = 1;
 56     DS1302_W_Byte(cmd);
 57     dat = DS1302_R_Byte();
 58     return dat;
 59 }
 60
 61 /*清除写保护*/
 62 void DS1302_Clear_WP()
 63 {
 64     DS1302_W_DAT(0x8e, 0x00);
 65 }
 66 /*设置写保护*/
 67 void DS1302_Set_WP()
 68 {
 69     DS1302_W_DAT(0x8e, 0x80);
 70     TRST = 0;
 71     TSCLK = 0;
 72 }
 73 /*时间预设*/
 74 void Set_DS1302_Time(uchar addr)
 75 {
 76     uchar i, j;
 77     DS1302_Clear_WP();        //清除写保护
 78     for(i = 0; i < 7; i++)    //写入7个字节的时钟初始值
 79     {
 80         j = TimeData[i] / 10;     //BCD码转换
 81         TimeData[i] %= 10;
 82         TimeData[i] += j * 16;
 83         DS1302_W_DAT(addr, TimeData[i]);
 84         addr += 2;
 85     }
 86     DS1302_Set_WP(); //开写保护
 87 }
 88 /*读取1302时间*/
 89 void Read_DS1302_Time(uchar addr)
 90 {
 91     uchar i;
 92     DS1302_Clear_WP();
 93     for(i = 0; i < 7; i++)    //从DS1302读取7个字节的时钟日历数据
 94     {
 95         TimeData[i] = DS1302_R_DAT(addr);
 96         addr += 2;
 97     }
 98     DS1302_Set_WP();
 99 }
100 ?

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

 1 #define uint unsigned int
 2 #define uchar unsigned char
 3 sbit RS = P2 ^ 3;
 4 sbit RW = P2 ^ 4;
 5 sbit EN = P2 ^ 5;
 6
 7 void check_busy()           //检测是否忙
 8 {
 9     uchar dat;
10     P0 = 0xff;
11     RS = 0;
12     RW = 1;
13     do
14     {
15         EN = 1;
16         dat = P0;
17         EN = 0;
18     } while(dat & 0x80);
19 }
20
21 void write_cmd(uchar cmd)     //写命令
22 {
23     check_busy();
24     RS = 0;
25     RW = 0;
26     P0 = cmd;
27     EN = 1;
28     EN = 0;
29 }
30
31 void write_data(uchar dat)   //写数据
32 {
33     check_busy();
34     RS = 1;
35     RW = 0;
36     P0 = dat;
37     EN = 1;
38     EN = 0;
39 }
40 /*显示一位数字*/
41 void dis_onenum (uchar X, uchar Y, uchar dat)
42 {
43     if(Y) X |= 0X40;
44     X |= 0X80;
45     write_cmd(X);
46     write_data(dat);
47 }
48 /*显示两位数字*/
49 void dis_twonum (uchar X, uchar Y, uchar dat)
50 {
51     dis_onenum (X, Y, dat / 16 + ‘0‘);
52     dis_onenum (X+1, Y, dat % 16 + ‘0‘);
53 }
54 /*显示字符串*/
55 void dis_string(uchar location,uchar *p)
56 {
57     write_cmd(location);
58     while(*p)
59     {
60         write_data(*p);
61             p++;
62     }
63 }
64
65 void lcd_initial()
66 {
67     write_cmd(0x38);
68     write_cmd(0x0c);
69     write_cmd(0x06);
70     write_cmd(0x01);
71 }
72 ?

蓝牙控制程序:bluetooth.c

 1 uchar date[20],time[20];
 2 uchar cmd_index, cmd_start, cmd_end, bt_flag;
 3 bit flag_time, flag_date;
 4
 5 void time_set()
 6 {
 7     uchar a;
 8     uchar i, j, addr = 0x80;
 9     for(a = 1; a < 7; a++)
10         time[a] = time[a] - 0x30;            //数据处理
11     TimeData[2] = (time[1] * 10 + time[2]) % 24;    //小时
12     TimeData[1] = (time[3] * 10 + time[4]) % 60;    //分钟
13     TimeData[0] = (time[5] * 10 + time[6]) % 60;    //秒
14
15     DS1302_Clear_WP();            //清除写保护
16     for(i = 0; i < 3; i++)        //写入时间设置值
17     {
18         j = TimeData[i] / 10;     //BCD码转换
19         TimeData[i] %= 10;
20         TimeData[i] += j * 16;
21         DS1302_W_DAT(addr, TimeData[i]);
22         addr += 2;
23     }
24     DS1302_Set_WP();             //开写保护
25     flag_time = 0;
26 }
27
28 void date_set()
29 {
30     uchar a;
31     uchar i, j, addr = 0x86;
32     for(a = 1; a < 9; a++)
33         date[a] = date[a] - 0x30;        //对数据处理
34     TimeData[3] = (date[5] * 10 + date[6]) ;            //日
35     TimeData[4] = (date[3] * 10 + date[4]) ;            //月
36     TimeData[6] = (date[1] * 10 + date[2]) ;            //年
37     TimeData[5] = (date[7] * 10 + date[8]) ;            //周
38
39     DS1302_Clear_WP();
40     for(i = 3; i < 7; i++)                //写入日期设置值
41     {
42         j = TimeData[i] / 10;     //BCD码转换
43         TimeData[i] %= 10;
44         TimeData[i] += j * 16;
45         DS1302_W_DAT(addr, TimeData[i]);
46         addr += 2;
47     }
48     DS1302_Set_WP();             //开写保护
49     flag_date = 0;
50 }
51
52 void data_deal(uchar data_buf)
53 {
54     switch(data_buf)
55     {
56     case ‘d‘:
57         cmd_start = 1;
58         cmd_end = 0;
59         flag_date = 1;
60         cmd_index = 0;
61         bt_flag = 1;
62         break;
63     case ‘t‘:
64         cmd_start = 1;
65         cmd_end = 0;
66         flag_time = 1;
67         cmd_index = 0;
68         bt_flag = 2;
69         break;
70     case ‘#‘:
71         cmd_start = 0;
72         cmd_end = 1;
73         break;
74     default:break;
75     }
76     if (cmd_start == 1)
77     {
78         switch (bt_flag)
79         {
80         case 1:
81             date[cmd_index] = data_buf;
82             cmd_index++;
83             break;
84         case 2:
85             time[cmd_index] = data_buf;
86             cmd_index++;
87             break;
88         default:break;
89         }
90         if (cmd_index >= 20)
91             cmd_index = 0;
92     }
93 } 

总结:

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

时间: 2024-10-05 00:50:47

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

单片机课程设计——基于51单片机温湿度检测系统的设计与实现

1 #include <reg52.h> 2 #include "1602.h" 3 #include "dht.h" 4 #include "2402.h" 5 6 //定义三个LED灯 7 sbit Led_qushi=P1^6; //去湿灯 8 sbit Led_jiangwen=P1^5; //降温灯 9 sbit Led_shengwen=P1^4; //升温灯 10 sbit Key_TH1 = P3^2; 11 sbit

51单片机课程设计:基于DS18B20的温度报警器

51单片机课程设计:基于DS18B20的温度报警器 本程序用于读取DS18B20温度,同时具备报警功能,工程分为3个文件,main.c.temp.c.temp.h,经本人修改部分代码,适用于吉林农业大学51开发板,其他朋友亦可移植到其他型号开发板.工程文件在文章最下方. 1.main.c文件 /*********************************说明****************************************** 本程序用于读取温度检测模块DS18B20数值,并

51单片机课程设计:基于MQ-3的酒精浓度报警器

51单片机课程设计:基于MQ-3的酒精浓度报警器 本程序用于将MQ-3上读取到的模拟信号转换为对应的数字信号,经51单片机处理后,在数码管显示,同时具有报警功能,当检测值高于预警值,蜂鸣器报警.除了可以检测MQ-3酒精浓度模块的AD值,也适用于MQ系列的其他模块,原理基本都相同,都是将读取到的AD值转换为数字信号,程序修改后,如果接线方法正确,可以在吉林农业大学51开发板上完美运行,相关工程文件见最下方附件. /*************************************说明***

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

1 #include<reg52.h> 2 typedef unsigned char uint8; 3 typedef unsigned int uint16; 4 5 sbit rw=P2^5; 6 sbit rs=P2^6; 7 sbit e=P2^7; 8 sbit led=P3^7; 9 10 uint8 key,num,ei,eii,p; 11 uint8 fuhao;//定义具体的那个符号,是加减还是乘除. 12 uint8 flag; //定义有没有按下符号键,这个是统称 13

2020_1课程设计—基于BC的证书格式转换工具的设计与实现—Week1

2020_1课程设计-基于BC的证书格式转换工具的设计与实现-Week1 目录 2020_1课程设计-基于BC的证书格式转换工具的设计与实现-Week1 任务要求 Week1 任务安排 实践过程 学习证书格式的相关知识 学习OpenSSL的使用方法 安装OpenSSL 使用OpenSSL查看证书,并实现证书格式转换 创建根证书CA 颁发证书 证书格式转换 遇到问题 参考链接 任务要求 清楚.pem .pfx /.keystore .crt .cer .der 这些格式的文件用openssl如何产

java课程设计团队(搜索引擎)

JAVA课程设计 基于学院网站的搜索引擎 对学院网站进行抓取.建索(需要中文分词).排序(可选).搜索.摘要显示.可以是GUI界面,也可以是Web界面. 一.团队介绍 学号 班级 姓名 简介 201621123049 网络1612 [组长]袁德兴 热衷于网络安全 201621123047 网络1612 陈芳毅 有思想,有深度 ,有能力 201621044079 网络1612 韩烨 学习力强,人称韩可爱 201621123055 网络1612 刘兵 人称五社区发哥,动手能力强 2016211230

[原创]基于51单片机的红外遥控课程设计

[注]: 一眨眼,大学接近尾声,具有找工作需要,所以把大学做的电子设计“劣作”放上来.希望考研失意,还能赶上“好工作”的春招班车.如果大伙有什么工作推荐也可以联系我哦,因为一年考研少接触了这方面,所以难免有些生疏.但请相信我!给我机会我会很认真学的! 邮箱:[email protected] 转载请注明出处呀! 基于51单片机的红外遥控课程设计 目录 第一章 设计简介... 3 第二章 系统方案... 3 一.设计方案对比... 3 二.方案设计... 4 第三章 硬件设计... 5 一.红外遥

电子时钟万年历+51单片机+1602液晶屏+DS1302+DS18B20+按键

这次课程设计要完成的是制作一个基于51单片机的电子时钟的万年历(protues仿真),需要用到1602液晶屏+DS1302+DS18B20+按键等模块.各个的模块就不在一一介绍,直接讲解这个系统的功能,首先是四个按键,第一个按键是选中需要修改时间位置,在按一次选中下一个,依次类推,第二个按键是对数值进行加一,第三个按键对数值进行减一,第四个按键确认. 先放仿真图 然后是代码: main.c #include <REG52.H> #include <intrins.h> #defin

基于51单片机的温度控制系统毕设

分享一下单片机毕设课程计参考资料33个,献给大四的朋友,毕业设计就不用愁了,如果有什么不懂的地方可以加群大家一起交流:813238832资料下载的地址:https://bbs.usoftchina.com/thread-208012-1-1.html 1.CDMA通信系统中的接入信道部分进行仿真与分析2.USB接口设计3.毕业设计(论文)OFDM通信系统基带数据4.电气工程系毕业设计开题报告5.电信运营商收入保障系统设计与实现6.基于51单片机的16×16点阵(滚动显示)7.基于51单片机的LE