Simulation of Household Digital Clock and Thermometer Based on 51 Single Chip Microcomputer

Simulation diagram:

Characteristics of the chip/module:

Introduction to AT89C52:
AT89C52 is a classic 8-bit microcontroller, one of a series of microcontrollers produced by STMicroelectronics. It is based on the 8051 core and has many features compatible with it.

The main features of AT89C52 are as follows:

Internal memory: AT89C52 has 8KB of flash memory (Flash) memory, which can be used to store user programs and data. The contents of these memories can be programmed and erased by a programmer.

RAM memory: AT89C52 is equipped with 256 bytes of random access memory (RAM) for temporary storage of data and program variables.

External scalability: AT89C52 supports the connection of various external expansion devices, including external memory (such as RAM, EEPROM) and peripherals (such as ADC, LCD, UART, etc.), through external hardware connections, the functions and applications of the microcontroller can be expanded.

General-purpose I/O pins: AT89C52 has 32 programmable general-purpose input/output pins, which can be used to connect external devices and communicate with other chips.

Timer/counter: AT89C52 built-in three 16-bit timer/counters and a programmable serial timer/counter. These timer/counters can be used to implement timing functions, generate pulse signals, measure time intervals, and more. 0

Serial communication: AT89C52 supports serial communication interfaces, including UART (serial asynchronous communication) and SPI (serial peripheral interface), which is convenient for data communication and interaction with other devices.

Low power consumption mode: AT89C52 has a variety of low power consumption modes, such as idle mode and power down mode, the CPU can enter a low power consumption state to save energy when it does not need to perform tasks.

Wide Supply Voltage Range: The AT89C52 typically operates from 4.0V to 5.5V, which can meet most application needs.
DS1302 Features:
High-precision time counting: DS1302 can provide high-precision real-time clock counting, and can record time information such as year, month, day, week, hour, minute and second. It integrates a crystal oscillator inside to provide a stable clock signal.

Low power consumption design: DS1302 adopts low power consumption design, and can operate in low power consumption mode, effectively prolonging battery life. Even in the event of a power outage, it retains time data and continues to provide timekeeping through an externally connected battery.

Serial Interface: The DS1302 communicates and controls through a serial real-time clock interface (SPI). Data exchange and clock synchronization with a master device is possible using a handful of pins.

Easy to integrate: DS1302 integrates clock counting and RAM memory functions, and has simple interfaces and commands, and is easy to integrate with various microcontrollers and microcontrollers. It does not require complicated control signals and can be operated by simple read and write commands.

Programmable control function: DS1302 has a programmable control function, which can set special functions such as alarm clock and write protection. It also supports a choice of multiple time formats, such as 24-hour or 12-hour.

Temperature compensation: DS1302 has a built-in temperature compensation function, which can correct the influence of temperature on the clock frequency and improve the accuracy of clock counting.

High stability and anti-vibration ability: DS1302 has high stability and anti-vibration ability, suitable for various industrial and consumer application scenarios.

DS18B20 Features:

  1. Single bus interface: DS18B20 uses a single bus interface for communication, only one pin is needed to connect multiple sensors, which simplifies circuit design and connection.
  2. Digital output: DS18B20 outputs the temperature value in digital form, no additional analog-to-digital converter is required. It uses 12-bit resolution to represent the temperature value, which can realize high-precision temperature measurement.
  3. High Accuracy: The DS18B20 can provide a temperature measurement range from -55°C to +125°C with a temperature accuracy of ±0.5°C. Therefore, it can provide reliable and accurate temperature measurement results in many applications.
  4. Versatility: In addition to measuring temperature, DS18B20 can also perform other functions, such as temperature alarm function. It can set upper and lower temperature thresholds and trigger an alarm when the temperature exceeds or falls below these thresholds.
  5. Low power consumption: DS18B20 adopts low power consumption design, the operating current is extremely low, and only requires very little energy for temperature measurement and communication.
  6. Durability: DS18B20 has good durability and reliability, and its packaging material and structural design make it suitable for applications under various environmental conditions.

Main program:

#include <reg52.h>
#include <intrins.h>
#include "delay.h"
#include "lcd1602.h"
#include "ds1302.h"
#include "eeprom52.h"

#define uchar unsigned char
#define uint unsigned int
#define LCDIO P0

//pin definition
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit LED_STATUS = P2^5;
sbit BUZZER = P3^5;
sbit DQ = P1^0; //ds18b20 and MCU connection port
sbit KEY_TIMESET = P2^3; //menu
sbit KEY_ADD = P2^6; //Add one
sbit KEY_SUB = P2^4;
sbit KEY_ALARMSET = P2^7;
sbit KEY_STOPWATCH = P3^6;

//Variable definitions
int time10MsCnt = 0, timeSecondCnt = 0, timeMinuteCnt = 0;
uint tempValue; //temperature value
uchar data dispTempData[5];
bit is Negative;
bit AlarmSwitch = 0;
uchar row0[] = {"20 - - "};
uchar row1[] = {" : : "};
char alarmTime[3] = {0, 0, 0};
unsigned char isNew = 0;
unsigned char g_mode = 0;
unsigned char g_setLocation = 0;
bit refreshTempFlag = 1;
// bit stopwatchFlag = 0;

//function declaration
void DispStopwatch();
void Timer_Init();
void DispTime();
void DS18B20_Delay(unsigned int i);
void DS18B20_Rst();
uchar DS18B20_Read();
void DS18B20_Write(uchar wdata);
uint ReadTemp();
void DispTemp();
void DispAlarmTime();
void KeyScan();
void SetAlarmTime();
void SetTime();

void main()
{
Init_EEPROM();
    if (!isNew)
    {
        DS1302_Read_Time();
    }
    else
    {
DS1302_Init();
    }
LCD_Init();
LCD_Clear();
LCD_Write_String(0, 0, row0);
LCD_Write_String(0, 1, row1);

Timer_Init();
// Init_DS1302(); //Initialize 1302
BUZZER = 1;
\t
while (1)
{
if (g_mode == 0) //Normal display time
{
DS1302_Read_Time();
DispTime();
if (refreshTempFlag) // Refresh the temperature once in 2s
{
TR1 = 0;
ReadTemp(); //read temperature
refreshTempFlag = 0;
TR1 = 1;
}
DispTemp(); //display temperature
}
else if (g_mode == 1) //display stopwatch
{
DispStopwatch();
}
else if (g_mode == 2) //display alarm clock time
{
SetAlarmTime();
}
else if (g_mode == 3) //set time
{
SetTime();
}
else;

if (AlarmSwitch == 1)
{
if (timeBufDec[4] == alarmTime[0] & amp; & amp; timeBufDec[5] == alarmTime[1] & amp; & amp; timeBufDec[6] == alarmTime[2])
{
BUZZER = 0;
}
}

KeyScan();


}

}

void DispStopwatch()
{
LCD_Write_String(0, 0, "Stopwatch");
LCD_Write_Char(4, 1, timeMinuteCnt / 10 + '0');
LCD_Write_Char(5, 1, timeMinuteCnt % 10 + '0');
LCD_Write_Char(6, 1, ':');
LCD_Write_Char(7, 1, timeSecondCnt / 10 + '0');
LCD_Write_Char(8, 1, timeSecondCnt % 10 + '0');
LCD_Write_Char(9, 1, ':');
LCD_Write_Char(10, 1, time10MsCnt / 10 + '0');
LCD_Write_Char(11, 1, time10MsCnt % 10 + '0');
}

void DispTime()
{
row0[2] = '0' + timeBufDec[1] / 10;
row0[3] = '0' + timeBufDec[1] % 10;
row0[5] = '0' + timeBufDec[2] / 10;
row0[6] = '0' + timeBufDec[2] % 10;
row0[8] = '0' + timeBufDec[3] / 10;
row0[9] = '0' + timeBufDec[3] % 10;

row1[0] = '0' + timeBufDec[4] / 10;
row1[1] = '0' + timeBufDec[4] % 10;
row1[3] = '0' + timeBufDec[5] / 10;
row1[4] = '0' + timeBufDec[5] % 10;
row1[6] = '0' + timeBufDec[6] / 10;
row1[7] = '0' + timeBufDec[6] % 10;

LCD_Write_String(0, 0, row0);
LCD_Write_String(0, 1, row1);

switch (timeBufDec[7])
{
    case 1: LCD_Write_String(12, 0, " Sun"); break;
case 2: LCD_Write_String(12, 0, " Mon"); break;
case 3: LCD_Write_String(12, 0, "Tues"); break;
case 4: LCD_Write_String(12, 0, " Wed"); break;
case 5: LCD_Write_String(12, 0, "Thur"); break;
case 6: LCD_Write_String(12, 0, " Fri"); break;
case 7: LCD_Write_String(12, 0, "Sat"); break;
}
}

void DS18B20_Rst() /*ds1820 reset*/
{
unsigned char ack = 0;
DQ = 0; //DQ pulled low
DelayUs10x(50); //Precise delay is greater than 480us and less than 960us
DQ = 1; //pull high
DelayUs10x(6); //Wait for the resistor to pull up
    ack = DQ; //If ack=0, the initialization is successful, if ack=1, the initialization fails
    while(!DQ);
}

uchar DS18B20_Read() /*read data*/
{
unsigned char i = 0;
unsigned char dat = 0;
for (i = 8; i > 0; i--)
{
DQ = 0; //give pulse signal
dat >>= 1;
DQ = 1; //give pulse signal
if (DQ)
dat |= 0x80;
DelayUs10x(6); //Delay another 60us
}
return (dat);
}

void DS18B20_Write(uchar wdata) /*write data*/
{
unsigned char i = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
DQ = wdata & 0x01;
DelayUs10x(6); //Delay another 60us
DQ = 1;
wdata >>= 1;
}
}

uint ReadTemp() /* read the temperature value and convert it */
{
uchar a, b;
DS18B20_Rst();
DS18B20_Write(0xcc); //*Skip read serial number*/
DS18B20_Write(0x44); //*start temperature conversion*/
DS18B20_Rst();
DS18B20_Write(0xcc); //*Skip read serial number*/
DS18B20_Write(0xbe); //*read temperature*/
a = DS18B20_Read();
b = DS18B20_Read();
tempValue = b;
tempValue <<= 8;
tempValue = tempValue | a;
if (tempValue < 0x0fff)
isNegative = 0;
else
{
tempValue = ~tempValue + 1;
isNegative = 1;
}
tempValue = tempValue * (0.625); //The temperature value is expanded by 10 times, accurate to 1 decimal place
return (tempValue);
}

void DispTemp() //Temperature value display
{
uchar flagdat;
dispTempData[0] = tempValue / 1000 + '0'; //hundreds
dispTempData[1] = tempValue % 1000 / 100 + '0'; // ten digits
dispTempData[2] = tempValue % 100 / 10 + '0'; // single digit
dispTempData[3] = tempValue % 10 + '0'; //decimal places

if (isNegative == 0)
flagdat = 0x20; //No symbol for positive temperature
else
flagdat = 0x2d; // Negative temperature display negative sign:-

if (dispTempData[0] == 0x30)
{
dispTempData[0] = 0x20; //If the hundreds digit is 0, it will not be displayed
if (dispTempData[1] == 0x30)
{
dispTempData[1] = 0x20; //If the hundreds digit is 0 and the tens digit is 0, it will not be displayed
}
}
LCD_Write_Char(9, 1, flagdat);
LCD_Write_Char(10, 1, dispTempData[0]);
LCD_Write_Char(11, 1, dispTempData[1]);
LCD_Write_Char(12, 1, dispTempData[2]);
LCD_Write_Char(13, 1, '.');
LCD_Write_Char(14, 1, dispTempData[3]);
LCD_Write_Char(15, 1, 'C');
}

void DispAlarmTime()
{
if (AlarmSwitch)
{
LCD_Write_String(0, 0, "Alarm Clock On ");
}
else
{
LCD_Write_String(0, 0, "Alarm Clock Off");
}
LCD_Write_Char(4, 1, alarmTime[0] / 10 + '0');
LCD_Write_Char(5, 1, alarmTime[0] % 10 + '0');
LCD_Write_Char(6, 1, ':');
LCD_Write_Char(7, 1, alarmTime[1] / 10 + '0');
LCD_Write_Char(8, 1, alarmTime[1] % 10 + '0');
LCD_Write_Char(9, 1, ':');
LCD_Write_Char(10, 1, alarmTime[2] / 10 + '0');
LCD_Write_Char(11, 1, alarmTime[2] % 10 + '0');

}

void SetAlarmTime()
{
TR1 = 0;
LcdWriteCommand(0x0F, 0);
    switch (g_setLocation)
    {
        case 1: LcdWriteCommand(0x80 + 0x40 + 5, 0); break;
        case 2: LcdWriteCommand(0x80 + 0x40 + 8, 0); break;
        case 3: LcdWriteCommand(0x80 + 0x40 + 11, 0); break;
        case 4: LcdWriteCommand(0x0C, 0); DelayMs(5); LCD_Clear(); Write_EEPROM(); g_setLocation = 0; g_mode = 0; break;
default: ;
    }
TR1 = 1;
}

void SetTime()
{
TR1 = 0;
LcdWriteCommand(0x0F, 0);
    switch (g_setLocation)
    {
        case 1: LcdWriteCommand(0x80 + 3, 0); break;
        case 2: LcdWriteCommand(0x80 + 6, 0); break;
        case 3: LcdWriteCommand(0x80 + 9, 0); break;
        case 4: LcdWriteCommand(0x80 + 15, 0); break;
        case 5: LcdWriteCommand(0x80 + 0x40 + 1, 0); break;
        case 6: LcdWriteCommand(0x80 + 0x40 + 4, 0); break;
        case 7: LcdWriteCommand(0x80 + 0x40 + 7, 0); break;
        case 8: LcdWriteCommand(0x0C, 0); DelayMs(5); LCD_Clear(); DS1302_Write_Time(); g_setLocation = 0; g_mode = 0; break;
default: ;
    }
TR1 = 1;
}

void KeyScan()
{
if (!KEY_STOPWATCH) //Enter the countdown
{
DelayMs(5);
if (!KEY_STOPWATCH)
{
if (g_mode == 0)
{
LCD_Clear();
g_mode = 1;
}
else if (g_mode == 1)
{
LCD_Clear();
g_mode = 0;
}
}
while (!KEY_STOPWATCH);
}

if (!KEY_TIMESET) //Enter the countdown
{
DelayMs(5);
if (!KEY_TIMESET)
{
if (g_mode == 0)
{
g_mode = 3;
g_setLocation = 1;
}
else if (g_mode == 2)
{
AlarmSwitch = ~AlarmSwitch;
}
else if (g_mode == 3)
{
g_setLocation++;
}
}
while (!KEY_TIMESET);
}

if (!KEY_ALARMSET) //Enter the countdown
{
DelayMs(5);
if (!KEY_ALARMSET)
{
if (g_mode == 0)
{
LCD_Clear();
g_mode = 2;
g_setLocation = 1;
}
else if (g_mode == 1)
{
LED_STATUS = 1;
time10MsCnt = 0;
timeSecondCnt = 0;
timeMinuteCnt = 0;
}
else if (g_mode == 2)
{
g_setLocation++;
}
}
while (!KEY_ALARMSET);
}


if (!KEY_ADD)
{
DelayMs(5);
if (!KEY_ADD)
{
if (g_mode == 1)
{
TR0 = 1;
}
else if (g_mode == 2)
{
switch (g_setLocation)
{
case 1:
{
alarmTime[0]++;
if (alarmTime[0] > 23)
{
alarmTime[0] = 0;
}
break;
}
case 2:
{
alarmTime[1] + + ;
if (alarmTime[1] > 59)
{
alarmTime[1] = 0;
}
break;
}
case 3:
{
alarmTime[2] + + ;
if (alarmTime[2] > 59)
{
alarmTime[2] = 0;
}
break;
}
}
}
else if (g_mode == 3)
{
switch (g_setLocation)
{
case 1:
{
timeBufDec[1] + + ;
if (timeBufDec[1] > 99)
{
timeBufDec[1] = 0;
}
break;
}
case 2:
{
timeBufDec[2] + + ;
if (timeBufDec[2] > 12)
{
timeBufDec[2] = 1;
}
break;
}
case 3:
{
timeBufDec[3] + + ;
if (timeBufDec[3] > YDay(timeBufDec[1], timeBufDec[2]))
{
timeBufDec[3] = 1;
}
break;
}
case 4:
{
timeBufDec[7]++;
if (timeBufDec[7] > 7)
{
timeBufDec[7] = 1;
}
break;
}
case 5:
{
timeBufDec[4] + + ;
if (timeBufDec[4] > 23)
{
timeBufDec[4] = 0;
}
break;
}
case 6:
{
timeBufDec[5] + + ;
if (timeBufDec[5] > 59)
{
timeBufDec[5] = 0;
}
break;
}
case 7:
{
timeBufDec[6] + + ;
if (timeBufDec[6] > 59)
{
timeBufDec[6] = 0;
}
break;
}
}
}
}
else
{
BUZZER = 1;
}
while (!KEY_ADD);
}

if (!KEY_SUB)
{
DelayMs(5);
if (!KEY_SUB)
{
if (g_mode == 1)
{
TR0 = 0;
}
else if (g_mode == 2)
{
switch (g_setLocation)
{
case 1:
{
if (alarmTime[0] <= 0)
{
alarmTime[0] = 24;
}
alarmTime[0]--;
break;
}
case 2:
{

if (alarmTime[1] <= 0)
{
alarmTime[1] = 60;
}
alarmTime[1]--;
break;
}
case 3:
{
if (alarmTime[2] <= 0)
{
alarmTime[2] = 60;
}
alarmTime[2]--;
break;
}
}
}
else if (g_mode == 3)
{
switch (g_setLocation)
                    {
                    case 1:
                    {
                        if (timeBufDec[1] == 0)
                        {
                            timeBufDec[1] = 100;
                        }
                        timeBufDec[1]--;
                        break;
                    }
                    case 2:
                    {
                        timeBufDec[2]--;
                        if (timeBufDec[2] < 1)
                        {
                            timeBufDec[2] = 12;
                        }
                        break;
                    }
                    case 3:
                    {
                        timeBufDec[3]--;
                        if (timeBufDec[3] < 1)
                        {
                            timeBufDec[3] = YDay(timeBufDec[1], timeBufDec[2]);
                        }
                        break;
                    }
                    case 4:
                    {
timeBufDec[7]--;
                        if (timeBufDec[7] < 1)
                        {
                            timeBufDec[7] = 7;
                        }
                        break;
                    }
                    case 5:
                    {
                        if (timeBufDec[4] == 0)
                        {
                            timeBufDec[4] = 24;
                        }
                        timeBufDec[4]--;
                        break;
                    }
                    case 6:
                    {
                        if (timeBufDec[5] == 0)
                        {
                            timeBufDec[5] = 60;
                        }
                        timeBufDec[5]--;
                        break;
                    }
                    case 7:
                    {
                        if (timeBufDec[6] == 0)
                        {
                            timeBufDec[6] = 60;
                        }
timeBufDec[6]--;
                        break;
                    }
                    default:;
                    }
}
else
{
BUZZER = 1;
}
}
while (!KEY_SUB);
}
}

void Timer_Init()
{
TMOD = 0x11; //T0 is timer mode 1 T1 is timer mode 1
TH0 = (65536 - 9216) / 256;
TL0 = (65536 - 9216) % 256;
TH1 = (65536 - 9216) / 256;
TL1 = (65536 - 9216) % 256;
ET0 = 1;
ET1 = 1;
TR1 = 1;
EA = 1;
}

void Timer0_Interrupt() interrupt 1
{
TH0 = (65536 - 9216) / 256; //10ms
TL0 = (65536 - 9216) % 256;
time10MsCnt++;
if (time10MsCnt >= 100)
{
time10MsCnt = 0;
LED_STATUS = ~LED_STATUS;
timeSecondCnt = timeSecondCnt + 1;
if (timeSecondCnt > 59)
{
timeSecondCnt = 0;
timeMinuteCnt = timeMinuteCnt + 1;
if (timeMinuteCnt > 59)
timeMinuteCnt = 0;
}
}
}

void Timer1_Interrupt() interrupt 3
{
static unsigned char cnt = 0;
static unsigned char cnt1 = 0;
\t
TH1 = (65536 - 9216) / 256; //10ms
TL1 = (65536 - 9216) % 256;

if (g_mode == 2)
{
if (cnt1 >= 10)
{
DispAlarmTime();
cnt1 = 0;
}
else
{
cnt1++;
}
}
else if (g_mode == 3)
{
if (cnt1 >= 10)
{
DispTime();
cnt1 = 0;
}
else
{
cnt1++;
}
}

if (g_mode == 0)
{
if (cnt >= 200)
{
refreshTempFlag = 1;
cnt = 0;
}
else
{
cnt + + ;
}
}
}

Designing Documents:

Link: https://pan.baidu.com/s/131u1m-vcKF6w9xOm_RpzwQ?pwd=2mcd