51单片机+DS1302设计一个电子钟(LCD1602显示时间)
一、前言
电子钟是一种能够准确显示时间的设备,广泛应用于家庭、办公场所和公共场所,为人们提供了方便和准确的时间信息。本项目设计一个基于51单片机的电子钟,使用DS1302作为RTC时钟芯片,LCD1602作为显示屏,并通过串口方式连接上位机进行时间设置和闹钟设置。
STC89C52作为主控芯片,具有较高的性能和稳定性,可完成对外设的控制和数据处理。DS1302是一款低功耗的实时时钟芯片,能够提供准确的时间计数和日期功能。LCD1602是一款常用的字符型液晶显示屏,具有两行16列的显示区域,能够清晰显示时间和其他相关信息。
通过串口连接上位机,用户可以方便地设置电子钟的时间和闹钟时间,实现个性化需求。电子钟带有一个蜂鸣器,可以根据设置的闹钟时间进行响铃,提醒用户。
电子钟具有以下功能:
(1)显示当前时间和日期:LCD1602显示屏将实时更新并显示当前的时间和日期信息。
(2)时间设置:通过串口连接上位机,用户可以进行时间的设置,包括小时、分钟和秒。
(3)日期设置:用户可以通过上位机设置当前的年、月和日。
(4)闹钟设置:用户可以设置闹钟的时间,包括小时和分钟。到达设定时间时,蜂鸣器将响铃提醒用户。
(5)整点报时:每到整点,蜂鸣器将发出短促的提示音,提醒用户当前时间。
(6)闹钟响铃:当闹钟时间到达时,蜂鸣器将持续响铃,直到用户停止。
(7)该项目将借助STC89C52单片机的控制能力和串口通信功能,结合DS1302时钟芯片和LCD1602显示屏,实现一个简单而实用的电子钟。用户可以根据自己的
(8)需求进行时间设置和闹钟设置,方便实用,并且具有较高的准确性和稳定性。
二、项目的设计思路
项目的设计思路分为硬件设计和软件设计两部分。
2.1 硬件设计思路
(1)主控芯片选择:选择STC89C52作为主控芯片,由于其较高的性能和稳定性,适合用于控制和数据处理。
(2)RTC时钟芯片选择:选择DS1302作为RTC时钟芯片,具有低功耗、精确计时和日期功能。
(3)显示屏选择:选择LCD1602作为显示屏,它具有两行16列的字符显示区域,能够清晰显示时间和其他相关信息。
(4)串口连接:设计串口连接电路,实现与上位机的通信,用于时间设置和闹钟设置。
(5)蜂鸣器:添加蜂鸣器模块,用于整点报时和闹钟响铃功能。
(6)按键输入:添加按键输入模块,用于用户操作,如切换设置模式、调整时间和设置闹钟。
2.2 软件设计思路
(1)初始化设置:在程序启动时,进行硬件初始化,包括配置主控芯片的引脚、初始化DS1302时钟芯片和LCD1602显示屏。
(2)时间获取与显示:通过DS1302时钟芯片获取当前的时间和日期,并将其显示在LCD1602显示屏上。
(3)串口通信:通过串口与上位机进行通信,接收上位机发送的时间设置和闹钟设置指令,并进行相应的处理
(4)时间设置:根据上位机发送的时间设置指令,更新DS1302时钟芯片的时间计数器。
(5)日期设置:根据上位机发送的日期设置指令,更新DS1302时钟芯片的日期计数器。
(6)闹钟设置:根据上位机发送的闹钟设置指令,设置闹钟时间,并将其保存在主控芯片的内部存储器中。
(7)整点报时:通过检测DS1302时钟芯片的小时计数器,当小时值变化时,触发蜂鸣器发出短促的提示音。
(8)闹钟响铃:通过比较当前时间和保存的闹钟时间,当达到闹钟时间时,触发蜂鸣器持续响铃,直到用户停止或设定的时间段结束。
三、项目硬件接线
(1)STC89C52与DS1302:
STC89C52的P2.0口连接到DS1302的SCLK(时钟)引脚,用于提供时钟信号。
STC89C52的P2.1口连接到DS1302的IO(数据)引脚,用于数据传输。
STC89C52的P2.2口连接到DS1302的RST(复位)引脚,用于对DS1302进行复位操作。
(2)STC89C52与LCD1602:
STC89C52的P0口连接到LCD1602的D0-D7引脚,用于传输字符数据和控制信号。
STC89C52的P2.3口连接到LCD1602的RS(寄存器选择)引脚,用于选择数据或命令寄存器。
STC89C52的P2.4口连接到LCD1602的RW(读写选择)引脚,用于选择读或写操作。
STC89C52的P2.5口连接到LCD1602的E(使能)引脚,用于启动传输。
(3)STC89C52与蜂鸣器模块:
STC89C52的P3.7口连接到蜂鸣器模块的信号引脚,用于触发蜂鸣器响铃。
(4)串口通信接口。在STC89C52单片机上,串口引脚如下:
UART接收线(RXD):连接至外部设备的发送线。
STC89C52的P3.0口(RXD)用于接收串口数据。
UART发送线(TXD):连接至外部设备的接收线。
STC89C52的P3.1口(TXD)用于发送串口数据。
四、项目代码
4.1 DS1302时钟读取、设置
下面代码实现了,STC89C52读取DS1302时钟信息打印到串口,以及设置闹钟、时间读取、打印到串口的功能。其中,采用了UART通信进行与上位机交互,可以接收上位机发送过来的时间字符串,并据此设置闹钟和时间。
#include <reg52.h>
#include <stdio.h>#define uchar unsigned char
#define uint unsigned int// 定义DS1302时钟寄存器地址
#define DS1302_SEC_REG 0x80
#define DS1302_MIN_REG 0x82
#define DS1302_HR_REG 0x84
#define DS1302_DAY_REG 0x86
#define DS1302_MONTH_REG 0x88
#define DS1302_YEAR_REG 0x8C// 定义DS1302控制寄存器命令
#define DS1302_CMD_WRITE 0x80
#define DS1302_CMD_READ 0x81// 定义串口波特率为9600
#define BAUDRATE 9600
#define FOSC 11059200L
#define TIMER_INTERVAL (65536 - FOSC / 12 / BAUDRATE)// 声明全局变量
uchar time_buffer[20]; // 存放时间字符串
uchar alarm_buffer[20]; // 存放闹钟时间字符串
uint i;
bit flag; // 标记是否接收到上位机的时间字符串// 初始化UART模块
void InitUart() {TMOD &= 0x0F;TMOD |= 0x20;TH1 = TIMER_INTERVAL / 256;TL1 = TIMER_INTERVAL % 256;PCON |= 0x80;SCON = 0x50;ES = 1;TR1 = 1;EA = 1;
}// 将单个字节发送到串口
void SendData(uchar dat) {SBUF = dat;while (!TI);TI = 0;
}// 将字符串发送到串口
void SendString(uchar *s) {while (*s != '\0') {SendData(*s++);}
}// 初始化DS1302时钟芯片
void InitDS1302() {uchar i;// 使能DS1302写保护功能DS1302_CE = 0;DS1302_SCL = 0;DS1302_CE = 1;Write_DS1302(DS1302_CMD_WRITE | 0x8e, 0x80);// 关闭时钟允许,准备写入数据Write_DS1302(DS1302_CMD_WRITE | 0x90, 0x00);// 写入年月日时分秒周Write_DS1302(DS1302_SEC_REG, 0x00);Write_DS1302(DS1302_MIN_REG, 0x30);Write_DS1302(DS1302_HR_REG, 0x11);Write_DS1302(DS1302_DAY_REG, 0x08);Write_DS1302(DS1302_MONTH_REG, 0x09);Write_DS1302(DS1302_YEAR_REG, 0x21);Write_DS1302(0x8e, 0x00);// 初始化闹钟时间for (i = 0; i < 20; i++) {alarm_buffer[i] = 0;}
}// 向DS1302写入数据
void Write_DS1302(uchar addr, uchar dat) {uchar i;DS1302_CE = 0;DS1302_SCL = 0;// 发送起始信号DS1302_CE = 1;DS1302_SCL = 1;DS1302_CE = 0;// 发送命令字节地址DS1302_WriteByte(addr);// 发送数据字节DS1302_WriteByte(dat);// 停止信号DS1302_SCL = 0;DS1302_CE = 1;// 延时至少1usfor (i = 0; i < 10; i++);
}// 向DS1302读取数据
uchar Read_DS1302(uchar addr) {uchar dat;uchar i;DS1302_CE = 0;DS1302_SCL = 0;// 发送起始信号DS1302_CE = 1;DS1302_SCL = 1;DS1302_CE = 0;// 发送命令字节地址DS1302_WriteByte(addr | 0x01);// 读取数据字节dat = DS1302_ReadByte();// 停止信号DS1302_SCL = 0;DS1302_CE = 1;// 延时至少1usfor (i = 0; i < 10; i++);return dat;
}// 读取DS1302时间并打印到串口
void ReadTime() {uchar sec, min, hour, day, month, year;sprintf(time_buffer, "Time: ");sec = Read_DS1302(DS1302_SEC_REG);min = Read_DS1302(DS1302_MIN_REG);hour = Read_DS1302(DS1302_HR_REG);day = Read_DS1302(DS1302_DAY_REG);month = Read_DS1302(DS1302_MONTH_REG);year = Read_DS1302(DS1302_YEAR_REG);sprintf(time_buffer + 6, "%02d:%02d:%02d %02d/%02d/%02d\r\n", hour, min, sec, day, month, year);SendString(time_buffer);
}// 向DS1302写入闹钟时间
void SetAlarm(uchar *str) {uint i = 0;// 将字符串转换为数字while (str[i] != '\0') {alarm_buffer[i] = str[i] - '0';i++;if (i > 19) // 防止溢出break;}// 写入闹钟时间Write_DS1302(DS1302_CMD_WRITE | 0x81, alarm_buffer[10] << 4 | alarm_buffer[11]);Write_DS1302(DS1302_CMD_WRITE | 0x83, alarm_buffer[8] << 4 | alarm_buffer[9]);Write_DS1302(DS1302_CMD_WRITE | 0x85, alarm_buffer[6] << 4 | alarm_buffer[7]);
}// 从串口接收数据中解析出时间信息
void ParseTime() {uchar i, j;uchar temp;for (i = 0; i < 20; i++) {time_buffer[i] = 0;}// 接收字符串格式为:hh:mm:ss dd/mm/yyfor (i = 0; i < 8; i++) {temp = 0;for (j = 0; j < 2; j++) {temp *= 10;temp += (SBUF - '0');while (!RI); // 等待接收完成RI = 0;}time_buffer[i] = temp;if (i == 2 || i == 4) {while (SBUF != ' '); // 跳过空格字符while (!RI); // 等待接收完成RI = 0;}}flag = 1; // 标记已经接收到字符串
}// 主函数
void main() {InitUart();InitDS1302();flag = 0;while (1) {if (flag) { // 接收到时间字符串,设置闹钟和时间SetAlarm(time_buffer);Write_DS1302(DS1302_CMD_WRITE | 0x80, time_buffer[6] << 4 | time_buffer[7]);Write_DS1302(DS1302_CMD_WRITE | 0x82, time_buffer[3] << 4 | time_buffer[4]);Write_DS1302(DS1302_CMD_WRITE | 0x84, time_buffer[0] << 4 | time_buffer[1]);flag = 0;}ReadTime(); // 读取当前时间并发送到串口}
}// UART接收中断函数
void UartIsr() interrupt 4 {if (RI) { // 接收到数据ParseTime(); // 解析时间字符串}RI = 0;
}
4.2 LCD1602显示时钟
基于STC89C52控制LCD1602显示时间字符串的实现代码。
#include <reg52.h>
#include <stdio.h>// 定义Data和Command寄存器选择端口
sbit LCD_RS = P2^0; // RS引脚(寄存器选择)
sbit LCD_RW = P2^1; // RW引脚(读写选择)
sbit LCD_EN = P2^2; // EN引脚(使能)// 定义数据总线端口
#define LCD_DATA P0 void DelayMs(unsigned int ms) {unsigned int i, j;for (i = 0; i < ms; i++)for (j = 0; j < 120; j++);
}void WriteCommand(unsigned char cmd) {LCD_RS = 0; // 选择指令寄存器LCD_RW = 0; // 写模式LCD_EN = 0; // 低电平使能LCD_DATA = cmd; // 发送指令DelayMs(1); // 延时等待指令写入LCD_EN = 1; // 高电平使能DelayMs(1); // 持续一段时间LCD_EN = 0; // 结束使能
}void WriteData(unsigned char dat) {LCD_RS = 1; // 选择数据寄存器LCD_RW = 0; // 写模式LCD_EN = 0; // 低电平使能LCD_DATA = dat; // 发送数据DelayMs(1); // 延时等待数据写入LCD_EN = 1; // 高电平使能DelayMs(1); // 持续一段时间LCD_EN = 0; // 结束使能
}void LCDInit() {WriteCommand(0x38); // 设置显示模式为2行、5x8点阵字符WriteCommand(0x0C); // 显示器开,光标关闭WriteCommand(0x06); // 光标右移,整屏不移动WriteCommand(0x01); // 清除显示并设置光标回到初始位置
}void LCDDisplayTime(char* time) {int i;WriteCommand(0x80); // 设置光标位置为第一行的起始位置for (i = 0; i < 16; i++) {WriteData(time[i]); // 在第一行显示时间字符串}WriteCommand(0xC0); // 设置光标位置为第二行的起始位置for (i = 0; i < 16; i++) {WriteData(time[16 + i]); // 在第二行显示时间字符串}
}void main() {char time_buffer[32] = "Current Time: 00:00:00"; // 时间字符串unsigned char sec = 0, min = 0, hour = 0; // 当前时间变量LCDInit(); // 初始化LCD显示器while (1) {// 更新时间变量sec++;if (sec >= 60) {sec = 0;min++;if (min >= 60) {min = 0;hour++;if (hour >= 24) {hour = 0;}}}// 格式化时间字符串sprintf(time_buffer + 14, "%02d:%02d:%02d", hour, min, sec);// 显示时间字符串LCDDisplayTime(time_buffer);DelayMs(1000); // 延时1秒}
}
代码使用LCD_RS
、LCD_RW
和LCD_EN
分别表示LCD1602的RS、RW和EN引脚。数据总线通过LCD_DATA
定义,连接到P0端口。先初始化LCD显示器,在一个无限循环中更新时间变量并格式化时间字符串,最后在LCD上显示时间字符串。
相关文章:

51单片机+DS1302设计一个电子钟(LCD1602显示时间)
一、前言 电子钟是一种能够准确显示时间的设备,广泛应用于家庭、办公场所和公共场所,为人们提供了方便和准确的时间信息。本项目设计一个基于51单片机的电子钟,使用DS1302作为RTC时钟芯片,LCD1602作为显示屏,并通过串…...

vue项目中在scss代码中使用data中的变量
尽管在日常开发中,这类情况实际上很少出现。 VUE2: 在HTML中使用时,请确保将cssVars绑定在需要使用CSS变量的元素或该元素的上层元素上。 <template><div :style"cssVars"><div class"test"/></div><…...

uni-app报错“本应用使用HBuilderX x.x.x 或对应的cli版本编译,而手机端SDK版本是x.x.x不匹配的版本可能造成应用异常”
uniapp开发的一个跨平台软件,在安卓模拟器上启动的时候报警告: 官方给的解释:uni-app运行环境版本和编译器版本不一致的问题 - DCloud问答 解决办法有两个 方法一:添加忽略警告的配置 项目根目录下找到 manifest.json…...

[sd_scripts]之train
https://github.com/kohya-ss/sd-scripts/blob/main/docs/train_README-zh.mdhttps://github.com/kohya-ss/sd-scripts/blob/main/docs/train_README-zh.md 支持模型fine-tune,dreambooth,lora,textual inversion。 1.数据准备 在任意多个…...

samba 共享目录write permission deny问题修复 可读取内容但不可修改 删除 新增文件
关于 update/delete/write permission deny问题修复 0.首先在服务器端执行testparm -s ,测试 Samba 配置并显示结果。需确保服务器端参数 read only No ,共享目录有写入权限 一、若配置了允许匿名访问,使用匿名访问来操作smb需要做如下处理…...

UDP主要丢包原因及具体问题分析
一、主要丢包原因 1、接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来的包可能丢失。对于这种情况可以修改接收端,将包接收后存入…...

647. 回文子串 516.最长回文子序列
647. 回文子串 题目: 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串,即使是由相…...

点云从入门到精通技术详解100篇-双传感器模式的非结构化环境检测与识别
目录 前言 国内外研究现状 可通行区域检测的研究 障碍物检测的研究...

Nginx-反向代理
反向代理 1 语法 server {listen 82; server_name www.liyong.f.com;location ~* .*(css|js|html|images). {proxy_pass http://11.22.19.81:8088; } 上面的示例的意思是: 当访问:http://www.liyong.f.com:82/static/css/OneMap.b728e2e4.css 转发到 …...

Java封装一个根据指定的字段来获取子集的工具类
工具类 ZhLambdaUtils SuppressWarnings("all") public class ZhLambdaUtils {/*** METHOD_NAME*/private static final String METHOD_NAME "writeReplace";/*** 获取到lambda参数的方法名称** param <T> parameter* param function functi…...

【HUST】网安纳米|2023年研究生纳米技术考试参考
目录 1 纳米材料是什么 2 纳米材料的结构特性 3 纳米结构的其他特性 4 纳米结构的检测技术 5 纳米材料的应用 打印建议:PPT彩印(这样重点比较突出),每面12张PPT,简单做一下关键词目录,亲测可以看清。如…...

【移远QuecPython】EC800M物联网开发板的MQTT协议腾讯云数据上报
【移远QuecPython】EC800M物联网开发板的MQTT协议腾讯云数据上报 文章目录 导入库初始化设置MQTT注册回调订阅发布功能开启服务发送消息函数打包调用测试效果附录:列表的赋值类型和py打包列表赋值BUG复现代码改进优化总结 py打包 导入库 from TenCentYun import TX…...

关灯游戏及扩展
7.8 图形界面应用案例——关灯游戏 题目: [案例]游戏初步——关灯游戏。 关灯游戏是很有意思的益智游戏,玩家通过单击关掉(或打开)一盏灯。如果关(掉(或打开)一个电灯,其周围(上下左右)的电灯也会触及开关,成…...

深度解析:用Python爬虫逆向破解dappradar的URL加密参数(最详细逆向实战教程,小白进阶高手之路)
特别声明:本篇文章仅供学习与研究使用,不得用做任何非法用途,请大家遵守相关法律法规 目录 一、逆向目标二、准备工作三、逆向分析 - 太详细了!3.1 逆向前的一些想法3.1.1 加密字符串属性猜测3.1.2 是否可以手动复制加密API?3.2 XHR断点调试3.3 加密前各参数属性的变化情况…...

论文笔记:AttnMove: History Enhanced Trajectory Recovery via AttentionalNetwork
AAAI 2021 1 intro 1.1 背景 将用户稀疏的轨迹数据恢复至细粒度的轨迹数据是十分重要的恢复稀疏轨迹数据至细粒度轨迹数据是非常困难的 已观察到的用户位置数据十分稀疏,使得未观察到的用户位置存在较多的不确定性真实数据中存在大量噪声,如何有效的挖…...

Django之视图层
目录 一、三板斧的使用 二、JsonReponse序列化类的使用 三、 form表单上传文件 数据准备 数据处理 (1)post请求数据 (2)文件数据获取 四、 FBV与CBV 五、CBV的源码分析 as_view 方法 一、三板斧的使用 HttpResponse 返回字符串类型render 渲染html页面,并…...

DAY54 392.判断子序列 + 115.不同的子序列
392.判断子序列 题目要求:给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是…...

【Nginx】nginx | 微信小程序验证域名配置
【Nginx】nginx | 微信小程序验证域名配置 一、说明二、域名管理 一、说明 小程序需要添加头条的功能,内容涉及到富文本内容显示图片资源存储在minio中,域名访问。微信小程序需要验证才能显示。 二、域名管理 服务器是阿里云,用的宝塔管理…...

大数据Doris(二十二):数据查看导入
文章目录 数据查看导入 数据查看导入 Broker load 导入方式由于是异步的,所以用户必须将创建导入的 Label 记录,并且在查看导入命令中使用 Label 来查看导入结果。查看导入命令在所有导入方式中是通用的,具体语法可执行 HELP SHOW LOAD 查看。 show load order by create…...

STM32 I2C详解
STM32 I2C详解 I2C简介 I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线 两根通信线: SCL(Serial Clock)串行时钟线,使用同步的时序,降低对硬件的依赖,同时同步的时序稳定…...

软考 系统架构设计师系列知识点之云计算(1)
所属章节: 第11章. 未来信息综合技术 第6节. 云计算和大数据技术概述 大数据和云计算已成为IT领域的两种主流技术。“数据是重要资产”这一概念已成为大家的共识,众多公司争相分析、挖掘大数据背后的重要财富。同时学术界、产业界和政府都对云计算产生了…...

VS Code画流程图:draw.io插件
文章目录 简介快捷键 简介 Draw.io是著名的流程图绘制软件,开源免费,对标Visio,用过的都说好。而且除了提供常规的桌面软件之外,直接访问draw.io就可以在线使用,堪称百分之百跨平台,便捷性直接拉满。 那么…...

计算机 - - - 浏览器网页打开本地exe程序,网页打开微信,网页打开迅雷
效果 在电脑中安装了微信和迅雷,可以通过在地址栏中输入weixin:打开微信,输入magnet:打开迅雷。 同理:在网页中使用a标签,点击后跳转链接打开weixin:,也会同样打开微信。 运用同样的原理,在网页中点击超…...

C_6练习题
一、单项选择题(本大题共20小题,每小题2分,共40分。在每小题给出的四个备选项中,选出一个正确的答案,并将所选项前的字母填写在答题纸的相应位置上。) 下列叙述中正确的是()。 A.C语言程序将从源程序中第一个函数开始执行 B.可以在程序中由用户指定任意一个函数作为…...

XUbuntu22.04之安装pkg-config(一百九十二)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...

【Proteus仿真】【51单片机】拔河游戏设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器,使用按键、LED、动态数码管模块等。 主要功能: 系统运行后,指示灯处于中间位置,数码管显示得分0,当按下…...

第3关:集合操作100
任务描述相关知识编程要求测试说明 任务描述 本关任务:使用 集合操作解决实际问题 相关知识 1.集合并操作符 可转换为SQL 若R,S的属性名不同,可使用重命名使相应列名一致后进行并操作 例如:R(A,B,C) S(D,E,F) select A,B from R union sel…...

八:ffmpeg命令提取像素格式和PCM数据
一、提取YUV #提取3秒数据,分辨率和源视频一致 fmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p yuv420p_orig.yuv#提取3秒数据,分辨率转为320x240 ffmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p -s 320x240 yuv420p_320x240.yuv 二、提取RGB…...

rinex3.04 导航文件
GPS GLA BDS GLO...

linux rsyslog日志采集格式设定二
linux rsyslog日志采集格式设定二 1.创建日志接收模板 打开/etc/rsyslog.conf文件,在GLOBAL DIRECTIVES模块下任意位置添加以下内容 命令: vim /etc/rsyslog.conf 测试:rsyslog.conf文件结尾添加以下内容 $template ztj,"%timegenerated% %hostname% %TIMESTAMP:…...