If you don’t want to miss my updates, remember to check the public account in the upper right corner and set it as a star, I would appreciate it.


The graduation project shared this time is a relatively low-difficulty 51 single-chip microcontroller clock eternal calendar. If you are a beginner, it is very suitable to get started. If it is used as a graduation project, it may be difficult to pass in some schools, but more functions can be added based on this, which will increase the difficulty of the work and improve its functionality.
Let’s take a look at the features:
1. Can display the current time, day of the week, and date
2. Can modify the current time, day of the week, and date
3. Can obtain the ambient temperature and display it on the LCD
4. Can set an alarm, when the time arrives, the buzzer sounds, and it stops ringing after pressing the button
Main control selection: STC89C52RC
STC89C52 is a low-power, high-performance CMOS 8-bit microcontroller with 8K in-system programmable Flash memory. It has a clever 8-bit CPU and in-system programmable Flash on a single chip, making STC89C52 provide highly flexible and efficient solutions for many embedded control application systems. Currently, STC89C52 still has some market share.
Display selection: LCD1602
LCD1602 goes without saying, it is the most common hardware graduation project. It consists of a character liquid crystal display (LCD), control driver main circuit HD44780 and its extended driver circuit HD44100, as well as a small number of resistors, capacitors, and structural components assembled on a PCB. The LCD1602 chips produced by different manufacturers may vary, but the usage is the same. To reduce costs, most manufacturers directly mount the bare chips onto the board.
Clock chip selection: DS1302
DS1302 is a low-power real-time clock chip launched by DALLAS in the United States, which has the ability to charge with a tiny current. It can keep track of the year, month, day, week, hour, minute, and second, and has various functions such as leap year compensation.
Temperature sensor selection: DS18B20
DS18B20 is a commonly used digital temperature sensor that outputs a digital signal, characterized by small size, low hardware overhead, strong anti-interference ability, and high precision. [1] The DS18B20 digital temperature sensor is easy to wire, and after packaging, it can be applied in various occasions, such as pipe type, threaded type, magnetic adsorption type, stainless steel packaged type, and various models, including LTM8877, LTM8874, etc.
Peripheral devices: buttons, buzzers, switches, button batteries, potentiometers, transistors, etc.
In terms of schematic design, the first is the minimum system of the microcontroller, including power supply, crystal oscillator, and reset circuit.



Clock chip circuit: 3 pins connect to the microcontroller IO port for control

PCB design:

Here is the complete code for reference and learning:
#include "reg52.h" // This file defines some special function registers of the microcontroller#include "ds1302.h"#include "temp.h"#include "lcd.h"#include "eeprom.h"
sbit k1 = P1^0; // Button
sbit k2 = P1^1;
sbit k3 = P1^2;
sbit k4 = P1^3;
sbit lcdled = P2^4; // LCD backlight
sbit beep = P1^4; // Buzzer
unsigned int ti=0,alarm=0; // Modify which time parameter, modify which alarm parameter
unsigned char alarm_hour=0x12,alarm_min=0x00; // Alarm hour, minute parameters
enum Mode // Define enumeration, three modes
{ DISPLAYDATA,MODIFYDATA,SETALARMCLOCK,NONE,ALARMCLOCK}mode;
enum Alarmswitch // Define alarm switch
{ OFF,ON}alarmswitch;
/********* Delay function ***********/ void delay(unsigned int t) // Short delay
{ while(t--);}
void delay_ms(unsigned int t) // Millisecond delay
{ unsigned int a,b; for(a=0;a<t;a++) for(b=0;b<120;b++);}
/******** Display date, time, week ***********/void display_data(void){ LcdWriteCom(0x80); LcdWritestr("20"); LcdWriteData(TIME[6]/16+0x30); // Year LcdWriteData(TIME[6]%16+0x30); LcdWriteData('-'); LcdWriteData(TIME[4]/16+0x30); // Month LcdWriteData(TIME[4]%16+0x30); LcdWriteData('-'); LcdWriteData(TIME[3]/16+0x30); // Day LcdWriteData(TIME[3]%16+0x30);
LcdWritestr(" "); switch(TIME[5]) // Display week {
case 0:LcdWritestr("Mon"); break; case 1:LcdWritestr("Tue"); break; case 2:LcdWritestr("Wed"); break; case 3:LcdWritestr("Thu"); break; case 4:LcdWritestr("Fri"); break; case 5:LcdWritestr("Sat"); break; case 6:LcdWritestr("Sun"); break; } if(alarmswitch==ON)LcdWriteData('.'); else LcdWriteData(' ');
LcdWriteCom(0xC0); LcdWriteData(' '); LcdWriteData(TIME[2]/16+0x30); // Hour LcdWriteData(TIME[2]%16+0x30); LcdWriteData(':'); LcdWriteData(TIME[1]/16+0x30); // Minute LcdWriteData(TIME[1]%16+0x30); LcdWriteData(':'); LcdWriteData(TIME[0]/16+0x30); // Second LcdWriteData(TIME[0]%16+0x30); LcdWritestr(" ");}
/********* Display temperature ***********/void displaytemp(int temp) // Display temperature
{ float tp; static char flag = 1; if(temp< 0) {
LcdWriteCom(0xca); LcdWriteData('-'); temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; } else { LcdWriteCom(0xca); LcdWriteData('+'); tp=temp; temp=tp*0.0625*100+0.5; } if(flag) { flag =0; temp = 2600; } if(temp==8500) return ; LcdWriteData(temp % 10000 / 1000 + 0x30); LcdWriteData(temp % 1000 / 100 + 0x30); LcdWriteData('.'); LcdWriteData(temp % 100 / 10 + 0x30); LcdWriteData(temp % 10 + 0x30);}
/******************************************************************************** 函 数 名 : keypros* 函数功能 : Button processing function, judge whether button K1 is pressed*******************************************************************************/void keypros() // Initial page button detection
{ if(k1 == 0) // Switch mode {
delay(1000); // Eliminate jitter, generally about 10ms if(k1==0) // Re-judge whether the button is pressed {
mode+= 1;if(mode == 3)mode = DISPLAYDATA; }
while(k1 == 0); } else if(k2 == 0) // Buzzer test {
delay(1000); // Eliminate jitter, generally about 10ms if(k2==0) // Re-judge whether the button is pressed {
beep = !beep; }
while(k2 == 0); } else if(k3 == 0) // Backlight test {
delay(1000); // Eliminate jitter, generally about 10ms if(k3==0) // Re-judge whether the button is pressed {
lcdled = !lcdled; }
while(k3 == 0); } else if(k4 == 0) // Backlight test {
delay(1000); // Eliminate jitter, generally about 10ms if(k4==0) // Re-judge whether the button is pressed {
alarmswitch=!alarmswitch; }
while(k4 == 0); } }
/************* Modify time ************/void modify(void){ static int time=0; time++; if(k1 == 0) // Switch mode {
delay(1000); // Eliminate jitter, generally about 10ms if(k1==0) // Re-judge whether the button is pressed {
mode+= 1;if(mode == 3)mode = DISPLAYDATA; }
while(k1 == 0); } else if(k2 == 0) // Select modification parameter {
delay(1000); // Eliminate jitter, generally about 10ms if(k2==0) // Re-judge whether the button is pressed {
ti++; if(ti == 8)ti=0; }
while(k2 == 0); } else if(k3 == 0 ||k4 == 0) switch(ti) // Select to enter modification parameters {
case 0: if(k4==0 | k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4==0 | k3 ==0) // Re-judge whether the button is pressed {
TIME[0]=0; }
while(k4 == 0 | k3==0); }
break; //? case 1: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
TIME[1]++;
if(TIME[1]%16 == 0x0a) {
TIME[1] += 16; TIME[1] &= 0xf0; }
if(TIME[1]==0x60)TIME[1]=0; }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
TIME[1]--;
if(TIME[1]%16==0x0f && TIME[1]!=0xff) {
TIME[1] &= 0xf9; }
if(TIME[1]==0xff)TIME[1]=0x59; }
while(k4==0); }
break; //? case 2: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
TIME[2]++;
if(TIME[2]%16 == 0x0a) {
TIME[2] += 16; TIME[2] &= 0xf0; }
if(TIME[2]==0x24)TIME[2]=0; }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
TIME[2]--;
if(TIME[2]%16==0x0f && TIME[2]!=0xff) {
TIME[2] &= 0xf9; }
if(TIME[2]==0xff)TIME[2]=0x23; }
while(k4==0); }
break; //? case 3: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
TIME[3]++;
if(TIME[3]%16 == 0x0a) {
TIME[3] += 16; TIME[3] &= 0xf0; }
if(TIME[3]==0x32)TIME[3]=0; }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
TIME[3]--;
if(TIME[3]%16==0x0f && TIME[3]!=0xff) {
TIME[3] &= 0xf9; }
if(TIME[3]==0xff)TIME[3]=0x31; }
while(k4==0); }
break; // Day case 4: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
TIME[4]++;
if(TIME[4]%16 == 0x0a) {
TIME[4] += 16; TIME[4] &= 0xf0; }
if(TIME[4]==0x13)TIME[4]=0; }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
TIME[4]--;
if(TIME[4]%16==0x0f && TIME[4]!=0xff) {
TIME[4] &= 0xf9; }
if(TIME[4]==0xff)TIME[4]=0x12; }
while(k4==0); }
break; // Month case 5: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
TIME[5]++;if(TIME[5]==7)TIME[5]=0; }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
TIME[5]--;
if(TIME[5]==0xff)TIME[5]=6; }
while(k4==0); }
break; // Week case 6: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
TIME[6]++;
if(TIME[6]%16 == 0x0a) {
TIME[6] += 16; TIME[6] &= 0xf0; }
if(TIME[6]==0xa0)TIME[6]=0; }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
TIME[6]--;
if(TIME[6]%16==0x0f && TIME[6]!=0xff) {
TIME[6] &= 0xf9; }
if(TIME[6]==0xff)TIME[6]=0x99; }
while(k4==0); }
break; // Year case 7: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
mode=DISPLAYDATA; ti=0; }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
Ds1302Init(); // Clock initialization mode = DISPLAYDATA; // Return to date ti = 0; // Restore initial modification }
while(k4==0); }
break; // Year }
if(time == 200) { display_data(); if(ti == 7){ LcdWriteCom(0xca); LcdWritestr(" <- OK"); } } else if(time == 400) switch(ti) // Select to enter modification parameters {
case 0: LcdWriteCom(0xc7); LcdWritestr(" "); break; case 1: LcdWriteCom(0xc4); LcdWritestr(" "); break; case 2: LcdWriteCom(0xc1); LcdWritestr(" "); break; case 3: LcdWriteCom(0x88); LcdWritestr(" "); break; case 4: LcdWriteCom(0x85); LcdWritestr(" "); break; case 5: LcdWriteCom(0x8c); LcdWritestr(" "); break; case 6: LcdWriteCom(0x80); LcdWritestr(" "); break; case 7: LcdWriteCom(0xca); LcdWritestr(" "); break; }else if(time>400) time=0; delay_ms(1); }
void setalarmclock(void) // Set alarm mode{ static int time=0; time++; if(k1 == 0) // Switch mode {
delay(1000); // Eliminate jitter, generally about 10ms if(k1==0) // Re-judge whether the button is pressed {
mode+= 1;if(mode == 3)mode = DISPLAYDATA; }
while(k1 == 0); } if(k2 == 0) // Select alarm modification parameter {
delay(1000); // Eliminate jitter, generally about 10ms if(k2==0) // Re-judge whether the button is pressed {
alarm++; if(alarm == 3)alarm=0; }
while(k2 == 0); } switch(alarm) // Select to enter modification parameters {
case 0: if(k3 == 0) // Control alarm on {
delay(1000); // Eliminate jitter, generally about 10ms if(k3==0) // Re-judge whether the button is pressed {
alarmswitch = ON; SectorErase(0x2401); byte_write(0x2401,alarmswitch); }
while(k3 == 0); } if(k4 == 0) // Control alarm off {
delay(1000); // Eliminate jitter, generally about 10ms if(k4==0) // Re-judge whether the button is pressed {
alarmswitch = OFF; SectorErase(0x2401); byte_write(0x2401,alarmswitch); }
while(k4 == 0); } break; case 1: if(k3==0) // Control alarm hour increase {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
alarm_hour++;
if(alarm_hour%16 == 0x0a) {
alarm_hour += 16; alarm_hour &= 0xf0; }
if(alarm_hour==0x24)alarm_hour=0; SectorErase(0x2601); byte_write(0x2601,alarm_hour); }
while(k3==0); } if(k4==0) // Control alarm hour decrease {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
alarm_hour--;
if(alarm_hour%16==0x0f && alarm_hour!=0xff) {
alarm_hour &= 0xf9; }
if(alarm_hour==0xff)alarm_hour=0x23; SectorErase(0x2601); byte_write(0x2601,alarm_hour); }
while(k4==0); } break; case 2: if(k3==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k3 ==0) // Re-judge whether the button is pressed {
alarm_min++;
if(alarm_min%16 == 0x0a) {
alarm_min += 16; alarm_min &= 0xf0; }
if(alarm_min==0x60)alarm_min=0; SectorErase(0x2201); byte_write(0x2201,alarm_min); }
while(k3==0); }
if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
alarm_min--;
if(alarm_min%16==0x0f && alarm_min!=0xff) {
alarm_min &= 0xf9; }
if(alarm_min==0xff)alarm_min=0x59; SectorErase(0x2201); byte_write(0x2201,alarm_min); }
while(k4==0); } break; }
if(time == 200) { alarm_hour=byte_read(0x2601); alarm_min=byte_read(0x2201); alarmswitch=byte_read(0x2401); LcdWriteCom(0x80); // Display LcdWritestr("alarm clock: "); LcdWriteCom(0xc0); if(alarmswitch == OFF)LcdWritestr(" OFF "); else LcdWritestr(" ON "); LcdWriteCom(0xc9); LcdWriteData(alarm_hour/16+0x30); LcdWriteData(alarm_hour%16+0x30); LcdWriteData(':'); LcdWriteData(alarm_min/16+0x30); LcdWriteData(alarm_min%16+0x30); LcdWritestr(" "); } else if(time == 400) switch(alarm) // Select to enter modification parameters {
case 0: LcdWriteCom(0xc0); LcdWritestr(" "); break; case 1: LcdWriteCom(0xc9); LcdWritestr(" "); break; case 2: LcdWriteCom(0xcc); LcdWritestr(" "); break; }else if(time>400) time=0; delay_ms(1);}
/************ Alarm mode *****************/void alarmclock(void){ if(alarmswitch==ON && alarm_hour==TIME[2] && alarm_min==TIME[1]) // Alarm { beep=1; delay_ms(100); beep=0; delay_ms(100); beep=1; delay_ms(100); beep=0; LcdWriteCom(0x80); LcdWritestr(" time out! "); LcdWriteCom(0xc0); LcdWritestr("now time: "); LcdWriteData(alarm_hour/16+0x30); LcdWriteData(alarm_hour%16+0x30); LcdWriteData(':'); LcdWriteData(alarm_min/16+0x30); LcdWriteData(alarm_min%16+0x30); LcdWritestr(" "); delay_ms(500); LcdClean(); } else mode=DISPLAYDATA; if(k4==0) {
delay(1000); // Eliminate jitter, generally about 10ms if(k4 ==0) // Re-judge whether the button is pressed {
alarmswitch=OFF; }
while(k4==0); } }
/******************************************************************************** 函 数 名 : main*******************************************************************************/void main(void){ int ucount=0; unsigned char lastSec; beep= 0; LcdInit(); // LCD initialization //Ds1302Init(); // Clock initialization Ds18b20Init(); // Temperature sensor initialization SectorErase(0x2001);// byte_write(0x2001,0x08); // Execute initialization// byte_write(0x2201,0x00);// byte_write(0x2401,0x00); alarm_hour=byte_read(0x2601); alarm_min=byte_read(0x2201); alarmswitch=byte_read(0x2401);
while(1) { switch(mode) // Mode selection { case DISPLAYDATA: // Time display mode Ds1302ReadTime(); // Update time if(TIME[0] != lastSec) { lastSec = TIME[0]; display_data(); // Display time Seconds, minutes, hours, days, months, years displaytemp(Ds18b20ReadTemp());// Display temperature if(alarmswitch==ON && alarm_hour==TIME[2] && alarm_min==TIME[1]) // Alarm { mode = ALARMCLOCK; } } keypros(); // Button detection break; case MODIFYDATA: // Time modification mode modify(); break; case SETALARMCLOCK: // Set alarm mode setalarmclock(); break; case ALARMCLOCK: // Alarm mode alarmclock(); break; } } }
This sharing comes from Huazuo Chen, if you are interested in the project, you can go to Huazuo Chen’s CSDN blog for communication, or you can add his QQ: 2809786963.

Graduation Project Series:
1. Temperature/Heart Rate/Step Count Design Based on STM32
2. Intelligent Automatic Light Seeking Fire Extinguishing Car
3. Simple Electronic Scale Realized with 51 Single Chip Microcontroller + HX711
4. Low-Cost STM32 IoT Portable Power Meter
5. STM32 + OV7670 Design License Plate Recognition System
6. Self-Made Mobile App with Arduino for Intelligent Monitoring and Control System
7. STM32F103 + NB Module + MQTT Implement IoT Data Collection System
8. Complete Gesture-Controlled ESP32 WIFI Electronic Photo Album in 7 Days
9. Self-Made Universal Meter, Beats 500 Yuan Regular Brand
10. Simple Blood Oxygen Heart Rate Monitor Made with STM32 + MAX30100
11. STM32 + Zigbee Networked Ordering System
12. STM32 Intelligent Trash Can Automatically Identifies Various Types of Trash
13. “Artificial” Parking Assistant Implemented Based on MCU Development Board + Camera
14. Body Sensing Gimbal Design Implemented with STM32 and MPU6050
15. A Smarter “Xiao Ai”?
16. Bionic Robot Dog Realized with STM32F4 + H7
17. Low-Cost 360° Monitoring System
18. STM32 Version RFID Medical Order Special Wristband
19. Intelligent Home System Design Controlled by STM32 Single Chip Microcontroller
20. STM32F4 Electronic Reader Production Tutorial
21. Graduation Project | Intelligent Infusion Monitoring System
22. Raspberry Pi 3B+ and OpenCV3 + PyQt5 Implement Face Recognition Access Control
23. Gesture-Controlled Dot Matrix Display Design Based on STM32
24. Learn and Apply Immediately, Share the Whole Process of Building a Fingerprint Recognition System
25. Self-Made Six-Legged Robot, Difficult, Enter with Caution
26. True Human-Machine Interaction, Cloud Intelligent Butler (My Graduation Project, My Efforts)
27. STM32 Bluetooth Smart Car (Share Code and Android APK)
28. STM32 + TI BQ76940 Design 48V BMS Scheme (Data Sharing)
29. STM32 Slope Driving Line Following Car Production Tutorial
30. Simple Fatigue Driving Detection Under 100 Yuan
31. STM32 + OneNET Implement NB-IOT Power Collection System
32. Using ARM Platform to Design Parking Lot Management System (With Tutorial & Data)
33. Intelligent WIFI LED Light Design
33. LCD Digital BOOST Circuit Design
34. STM32 Intelligent Baby Bed Monitoring (Basic Version)
35. STM32 + UART HMI, Play Minesweeper Game
36. Two-Wheeled Self-Balancing Car, Including Source Code, Schematic/PCB Source Files
37. STM32 Logistics Handling Car
38. STM32F407 Smart Car: Most Complete Functions Online, Open Source Code
39. Microcontroller Automatic Sorting Car (Loading/Unloading/WIFI Recognition)
40. Self-Balancing Robot on a Ball
41. Multifunctional IoT Smart Home Design
42. Self-Made Yogurt Machine
43. STM32F103 Full-Color FFT Music Spectrum + LED Calendar Alarm Clock Display
44. Voice Recognition Smart Home Production
Project Sharing | Electric Competition Series | Artificial Intelligence | Postgraduate Entrance Examination
Must-Know Knowledge Points | Graduation Project | Switching Power Supply | Job Hunting
We are Nimo, the founder of Darwin, who only talks about technology and not flirting. Darwin Online Education Platform aims to serve professionals in the electronics industry, providing skill training videos covering hot topics in various subfields, such as embedded systems, FPGA, artificial intelligence, etc. It customizes hierarchical learning content for different groups, such as commonly used knowledge points, disassembly assessments, electric competitions/intelligent cars/postgraduate entrance examinations, etc. Welcome to follow.
