51 microcontroller + DS1302 design an electronic clock (LCD1602 displays time)

1. Preface

An electronic clock is a device that can accurately display time. It is widely used in homes, offices and public places, providing people with convenient and accurate time information. This project designs an electronic clock based on 51 microcontroller, using DS1302 as the RTC clock chip, LCD1602 as the display screen, and connecting to the host computer through the serial port for time setting and alarm clock setting.

As the main control chip, STC89C52 has high performance and stability, and can complete the control and data processing of peripherals. DS1302 is a low-power real-time clock chip that can provide accurate time counting and date functions. LCD1602 is a commonly used character-type liquid crystal display with a display area of two rows and 16 columns, which can clearly display time and other related information.

By connecting to the host computer through the serial port, users can easily set the time and alarm time of the electronic clock to meet personalized needs. The electronic clock has a buzzer that can sound according to the set alarm time to remind the user.

image-20230913112300737

image-20230913112208076

The electronic clock has the following functions:

(1) Display the current time and date: The LCD1602 display will update and display the current time and date information in real time.

(2) Time setting: By connecting to the host computer through the serial port, the user can set the time, including hours, minutes and seconds.

(3) Date setting: The user can set the current year, month and day through the host computer.

(4) Alarm clock setting: Users can set the alarm time, including hours and minutes. When the set time is reached, the buzzer will sound to remind the user.

(5) Hourly time chime: Every time the hour comes, the buzzer will sound a short tone to remind the user of the current time.

(6) Alarm clock ringing: When the alarm time arrives, the buzzer will continue to ring until the user stops.

(7) This project will use the control capabilities and serial communication functions of the STC89C52 microcontroller, combined with the DS1302 clock chip and LCD1602 display screen, to realize a simple and practical electronic clock. Users can use their own

(8) It is necessary to set the time and alarm clock, which is convenient and practical, and has high accuracy and stability.

2. Project design ideas

The design idea of the project is divided into two parts: hardware design and software design.

2.1 Hardware design ideas

(1) Main control chip selection: STC89C52 is selected as the main control chip. Due to its high performance and stability, it is suitable for control and data processing.

(2) RTC clock chip selection: DS1302 is selected as the RTC clock chip, which has low power consumption, precise timing and date functions.

(3) Display screen selection: Select LCD1602 as the display screen. It has a character display area with two rows and 16 columns, which can clearly display time and other related information.

(4) Serial port connection: Design a serial port connection circuit to realize communication with the host computer for time setting and alarm clock setting.

(5) Buzzer: Add a buzzer module for hourly time reporting and alarm clock ringing functions.

(6) Key input: Add a key input module for user operations, such as switching setting modes, adjusting time and setting alarm clocks.

2.2 Software design ideas

(1) Initialization settings: When the program starts, perform hardware initialization, including configuring the pins of the main control chip, initializing the DS1302 clock chip and LCD1602 display.

(2) Time acquisition and display: Obtain the current time and date through the DS1302 clock chip and display it on the LCD1602 display.

(3) Serial communication: Communicate with the host computer through the serial port, receive the time setting and alarm setting instructions sent by the host computer, and process them accordingly

(4) Time setting: Update the time counter of the DS1302 clock chip according to the time setting instruction sent by the host computer.

(5) Date setting: Update the date counter of the DS1302 clock chip according to the date setting instruction sent by the host computer.

(6) Alarm clock setting: Set the alarm time according to the alarm clock setting instruction sent by the host computer, and save it in the internal memory of the main control chip.

(7) Hourly time: By detecting the hour counter of the DS1302 clock chip, when the hour value changes, the buzzer is triggered to emit a short tone.

(8) Alarm clock ringing: By comparing the current time with the saved alarm time, when the alarm time is reached, the buzzer is triggered and continues to ring until the user stops or the set time period ends.

3. Project hardware wiring

(1) STC89C52 and DS1302:

The P2.0 port of STC89C52 is connected to the SCLK (clock) pin of DS1302 to provide a clock signal.

The P2.1 port of STC89C52 is connected to the IO (data) pin of DS1302 for data transmission.

The P2.2 port of STC89C52 is connected to the RST (reset) pin of DS1302, which is used to reset the DS1302.

(2) STC89C52 and LCD1602:

The P0 port of STC89C52 is connected to the D0-D7 pins of LCD1602 for transmitting character data and control signals.

The P2.3 port of STC89C52 is connected to the RS (register selection) pin of LCD1602, which is used to select the data or command register.

The P2.4 port of STC89C52 is connected to the RW (read and write selection) pin of LCD1602, which is used to select read or write operations.

The P2.5 port of STC89C52 is connected to the E (enable) pin of LCD1602, which is used to start transmission.

(3) STC89C52 and buzzer module:

The P3.7 port of STC89C52 is connected to the signal pin of the buzzer module, which is used to trigger the buzzer.

(4) Serial communication interface. On the STC89C52 microcontroller, the serial port pins are as follows:

UART receive line (RXD): The transmit line connected to the external device.

The P3.0 port (RXD) of STC89C52 is used to receive serial port data.

UART transmit line (TXD): The receive line connected to the external device.

The P3.1 port (TXD) of STC89C52 is used to send serial port data.

4. Project code

4.1 DS1302 clock reading and setting

The following code implements the functions of STC89C52 reading DS1302 clock information and printing to the serial port, as well as setting the alarm clock, reading time, and printing to the serial port. Among them, UART communication is used to interact with the host computer, which can receive the time string sent by the host computer and set the alarm clock and time accordingly.

#include <reg52.h>
#include <stdio.h>

#define uchar unsigned char
#define uint unsigned int

//Define DS1302 clock register address
#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

//Define DS1302 control register command
#define DS1302_CMD_WRITE 0x80
#define DS1302_CMD_READ 0x81

//Define the serial port baud rate to 9600
#define BAUDRATE 9600
#define FOSC 11059200L
#define TIMER_INTERVAL (65536 - FOSC / 12 / BAUDRATE)

// Declare global variables
uchar time_buffer[20]; //Storage time string
uchar alarm_buffer[20]; //Storage alarm time string
uint i;
bit flag; // Mark whether the time string from the host computer is received

//Initialize UART module
void InitUart() {<!-- -->
    TMOD &= 0x0F;
    TMOD |= 0x20;
    TH1 = TIMER_INTERVAL / 256;
    TL1 = TIMER_INTERVAL % 256;
    PCON |= 0x80;
    SCON = 0x50;
    ES = 1;
    TR1 = 1;
    EA = 1;
}

// Send a single byte to the serial port
void SendData(uchar dat) {<!-- -->
    SBUF = dat;
    while (!TI);
    TI = 0;
}

//Send the string to the serial port
void SendString(uchar *s) {<!-- -->
    while (*s != '\0') {<!-- -->
        SendData(*s + + );
    }
}

//Initialize DS1302 clock chip
void InitDS1302() {<!-- -->
    uchar i;

    // Enable DS1302 write protection function
    DS1302_CE = 0;
    DS1302_SCL = 0;
    DS1302_CE = 1;
    Write_DS1302(DS1302_CMD_WRITE | 0x8e, 0x80);

    // Turn off clock enable and prepare to write data
    Write_DS1302(DS1302_CMD_WRITE | 0x90, 0x00);

    //Write year, month, day, hour, minute, second and week
    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);

    //Initialize alarm time
    for (i = 0; i < 20; i + + ) {<!-- -->
        alarm_buffer[i] = 0;
    }
}

//Write data to DS1302
void Write_DS1302(uchar addr, uchar dat) {<!-- -->
    uchar i;

    DS1302_CE = 0;
    DS1302_SCL = 0;

    //Send start signal
    DS1302_CE = 1;
    DS1302_SCL = 1;
    DS1302_CE = 0;

    //Send command byte address
    DS1302_WriteByte(addr);
    // Send data bytes
    DS1302_WriteByte(dat);

    // stop signal
    DS1302_SCL = 0;
    DS1302_CE = 1;

    // Delay at least 1us
    for (i = 0; i < 10; i + + );
}

//Read data from DS1302
uchar Read_DS1302(uchar addr) {<!-- -->
    uchar dat;
    uchar i;

    DS1302_CE = 0;
    DS1302_SCL = 0;

    //Send start signal
    DS1302_CE = 1;
    DS1302_SCL = 1;
    DS1302_CE = 0;

    //Send command byte address
    DS1302_WriteByte(addr | 0x01);
    //Read data bytes
    dat = DS1302_ReadByte();

    // stop signal
    DS1302_SCL = 0;
    DS1302_CE = 1;

    // Delay at least 1us
    for (i = 0; i < 10; i + + );
    return dat;
}

//Read the DS1302 time and print it to the serial port
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, " d: d: d d/ d/ d\r\
", hour, min, sec, day, month, year);
    SendString(time_buffer);
}

//Write alarm time to DS1302
void SetAlarm(uchar *str) {<!-- -->
    uint i = 0;

    //Convert string to number
    while (str[i] != '\0') {<!-- -->
        alarm_buffer[i] = str[i] - '0';
        i + + ;
        if (i > 19) // prevent overflow
            break;
    }

    //Write alarm time
    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]);
}

// Parse the time information from the serial port received data
void ParseTime() {<!-- -->
    uchar i, j;
    uchar temp;
    for (i = 0; i < 20; i + + ) {<!-- -->
        time_buffer[i] = 0;
    }

    // The format of the received string is: hh:mm:ss dd/mm/yy
    for (i = 0; i < 8; i + + ) {<!-- -->
        temp = 0;
        for (j = 0; j < 2; j + + ) {<!-- -->
            temp *= 10;
            temp + = (SBUF - '0');
            while (!RI); // Wait for reception to complete
            RI = 0;
        }
        time_buffer[i] = temp;
        if (i == 2 || i == 4) {<!-- -->
            while (SBUF != ' '); // Skip space characters
            while (!RI); // Wait for reception to complete
            RI = 0;
        }
    }
    flag = 1; // Mark that the string has been received
}

// main function
void main() {<!-- -->
    InitUart();
    InitDS1302();
    flag = 0;
    while (1) {<!-- -->
        if (flag) {<!-- --> // Receive time string, set alarm clock and time
            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(); // Read the current time and send it to the serial port
    }
}

//UART receive interrupt function
void UartIsr() interrupt 4 {<!-- -->
    if (RI) {<!-- --> // Data received
        ParseTime(); // Parse time string
    }
    RI = 0;
}

4.2 LCD1602 display clock

Implementation code based on STC89C52 to control LCD1602 to display time string.

#include <reg52.h>
#include <stdio.h>

//Define Data and Command register selection port
sbit LCD_RS = P2^0; // RS pin (register selection)
sbit LCD_RW = P2^1; // RW pin (read and write selection)
sbit LCD_EN = P2^2; // EN pin (enable)

//Define data bus port
#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; // Select command register
    LCD_RW = 0; // Write mode
    LCD_EN = 0; // low level enable
    LCD_DATA = cmd; // Send command
    DelayMs(1); // Delay waiting for instruction writing
    LCD_EN = 1; // High level enable
    DelayMs(1); // last for a period of time
    LCD_EN = 0; // End enable
}

void WriteData(unsigned char dat) {<!-- -->
    LCD_RS = 1; //Select data register
    LCD_RW = 0; // Write mode
    LCD_EN = 0; // low level enable
    LCD_DATA = dat; // Send data
    DelayMs(1); // Delay waiting for data to be written
    LCD_EN = 1; // High level enable
    DelayMs(1); // last for a period of time
    LCD_EN = 0; // End enable
}

void LCDInit() {<!-- -->
    WriteCommand(0x38); //Set the display mode to 2 lines, 5x8 dot matrix characters
    WriteCommand(0x0C); //Display on, cursor off
    WriteCommand(0x06); //The cursor moves to the right without moving the entire screen
    WriteCommand(0x01); //Clear the display and set the cursor back to the initial position
}

void LCDDisplayTime(char* time) {<!-- -->
    int i;
    WriteCommand(0x80); // Set the cursor position to the starting position of the first line

    for (i = 0; i < 16; i + + ) {<!-- -->
        WriteData(time[i]); // Display the time string in the first line
    }

    WriteCommand(0xC0); //Set the cursor position to the starting position of the second line

    for (i = 0; i < 16; i + + ) {<!-- -->
        WriteData(time[16 + i]); // Display the time string on the second line
    }
}

void main() {<!-- -->
    char time_buffer[32] = "Current Time: 00:00:00"; // time string
    unsigned char sec = 0, min = 0, hour = 0; // current time variable

    LCDInit(); //Initialize the LCD display

    while (1) {<!-- -->
        //Update time variable
        sec++;
        if (sec >= 60) {<!-- -->
            sec = 0;
            min + + ;
            if (min >= 60) {<!-- -->
                min = 0;
                hour + + ;
                if (hour >= 24) {<!-- -->
                    hour = 0;
                }
            }
        }

        //Format time string
        sprintf(time_buffer + 14, " d: d: d", hour, min, sec);

        //Display time string
        LCDDisplayTime(time_buffer);

        DelayMs(1000); // Delay 1 second
    }
}

The code uses LCD_RS, LCD_RW and LCD_EN to represent the RS, RW and EN pins of the LCD1602 respectively. The data bus is defined by LCD_DATA and connected to the P0 port. First initialize the LCD display, update the time variable and format the time string in an infinite loop, and finally display the time string on the LCD.