单片机课程设计——《基于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嵌入式蓝牙串口通讯模块介绍: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位微处理器,它的指令执行速度、驱动能力、程序存储等其他片内资源都是非常有限的,已经不能满足当今科技发展的需要,所以为了更好的发展,还要学习其他性能更强大的单片机。课程设计结束了,还要感谢老师的的指导我才能完成课程设计,衷心的感谢老师的帮助和提出的建议。

转载于:https://www.cnblogs.com/wanghuaijun/p/8024806.html

26页,7342字数 摘 要 时钟,自从它发明的那天起,就成为人类的朋友,但随着时间的推移,科学技术的不断发展,人们对时间计量的精度要求越来越高,应用越来越广。怎样让时钟更好的为人民服务,怎样让我们的老朋友焕发青春呢?这就要求人们不断设计出新型时钟数字电子钟的设计方法有多种,其中,利用单片机实现的电子钟具有编程灵活,便于电子钟功能的扩充,即可用该电子钟发出各种控制信号,精确度高等特点,同时可以用该电子钟发出各种控制信号。 本文主要介绍用单片机内部的定时/计数器来实现电子时钟的方法,本设计由单片机AT89S52芯片和LED数码管为核心,辅以必要的电路,构成了一个单片机电子时钟。与传统机械表相比,它具有走时精确,显示直观等特点。它的计时周期为24小时,显满刻度为“23时59分59秒”,另外具有校时功能等特点。该电子钟可以做到的功能: 上电或按键复位后能自动显示系统提示符“P.”进入时钟准备状态2.第一次按电子钟启动/调整键,电子钟从0时0分0秒开始运行,进入时钟运行状态。再次按电子钟启动/调整键,则电子钟进入时钟调整状态,此时可利用各调整键调整时间,调整结束后可按启动/调整键再次进入时钟运行状态。通过设置的A、B、C、D四个键来调整运行,并且利用了8位LED显示时分秒。 此电子钟严格按照要求设计,最终达到预期的效果,能够正确显示“P”点以及时分秒的计时,算是一次比较成功的设计了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值