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: