51单片机+TM1638+DS3232驱动数码管按键切换显示时间和日期

Posted perseverance52

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机+TM1638+DS3232驱动数码管按键切换显示时间和日期相关的知识,希望对你有一定的参考价值。

51单片机+TM1638+DS3232驱动数码管按键切换显示时间和日期


  • Proteus仿真
  • AT89C52、8位共阴数码管、DS3232

实例代码

#include <reg51.h>
#include <intrins.h>
#include "tm1638.h"

#define uchar unsigned char
#define uint unsigned int
sbit SDA = P3 ^ 6; //??I2C?????SDA
sbit SCL = P3 ^ 7; //??I2C?????SCL
sbit INT = P3 ^ 2;
sbit RESET = P3 ^ 3;
sbit led0 = P1 ^ 0;
sbit led1 = P1 ^ 1;
sbit led2 = P1 ^ 2;
sbit led3 = P1 ^ 3;
sbit led4 = P1 ^ 4;
sbit led5 = P1 ^ 5;
sbit led6 = P1 ^ 6;
sbit led7 = P1 ^ 7;
bit ack; //?????

#define DS3231_WriteAddress 0xD0 //?????
#define DS3231_ReadAddress 0xD1  //?????
#define DS3231_SECOND 0x00       //?
#define DS3231_MINUTE 0x01       //?
#define DS3231_HOUR 0x02         //?
#define DS3231_WEEK 0x03         //??
#define DS3231_DAY 0x04          //?
#define DS3231_MONTH 0x05        //?
#define DS3231_YEAR 0x06         //?
//??1
#define DS3231_SALARM1ECOND 0x07 //?
#define DS3231_ALARM1MINUTE 0x08 //?
#define DS3231_ALARM1HOUR 0x09   //?
#define DS3231_ALARM1WEEK 0x0A   //??/?
//??2
#define DS3231_ALARM2MINUTE 0x0b //?
#define DS3231_ALARM2HOUR 0x0c   //?
#define DS3231_ALARM2WEEK 0x0d   //??/?
#define DS3231_CONTROL 0x0e      //?????
#define DS3231_STATUS 0x0f       //?????
#define BSY 2                    //?
#define OSF 7                    //???????
#define DS3231_XTAL 0x10         //???????
#define DS3231_TEMPERATUREH 0x11 //????????(8?)
#define DS3231_TEMPERATUREL 0x12 //????????(?2?)

uchar code dis_code[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,
                         0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71}; // 4,5,6,7,8,9,off
uchar data dis_buf[8];
uchar data dis_index;
uchar data dis_digit;

uchar BCD2HEX(uchar val) //BCD???Byte
{
    return (val >> 4) * 10 + (val & 0x0F);
}

uchar HEX2BCD(uchar val) //B????BCD?
{
    return ((val / 10) << 4) | (val % 10);
}

void delayus(uint us)
{
    while (us--)
        ;
}

void Start_I2C()
{
    SDA = 1; //???????????
    delayus(1);
    SCL = 1;
    delayus(5); //??????????4.7us,??

    SDA = 0;    //??????
    delayus(5); // ??????????4?s

    SCL = 0; //??I2C??,?????????
    delayus(2);
}

void Stop_I2C()
{
    SDA = 0;    //???????????
    delayus(1); //???????????
    SCL = 1;    //??????????4us
    delayus(5);

    SDA = 1; //??I2C??????
    delayus(4);
}

void SendByte(uchar c)
{
    uchar BitCnt;

    for (BitCnt = 0; BitCnt < 8; BitCnt++) //?????????8?
    {
        if ((c << BitCnt) & 0x80)
            SDA = 1; //?????
        else
            SDA = 0;
        delayus(1);
        SCL = 1;    //??????,????????????
        delayus(5); //???????????4?s
        SCL = 0;
    }

    delayus(2);
    SDA = 1; //8??????????,???????
    delayus(2);
    SCL = 1;
    delayus(3);
    if (SDA == 1)
        ack = 0;
    else
        ack = 1; //???????????
    SCL = 0;
    delayus(2);
}

uchar RcvByte()
{
    uchar retc;
    uchar BitCnt;

    retc = 0;
    SDA = 1; //?????????
    for (BitCnt = 0; BitCnt < 8; BitCnt++)
    {
        delayus(1);
        SCL = 0; //??????,???????

        delayus(5); //?????????4.7?s

        SCL = 1; //???????????????
        delayus(3);
        retc = retc << 1;
        if (SDA == 1)
            retc = retc + 1; //????,????????retc?
        delayus(2);
    }
    SCL = 0;
    delayus(2);
    return (retc);
}

void Ack_I2C(bit a)
{

    if (a == 0)
        SDA = 0; //????????????
    else
        SDA = 1;
    delayus(3);
    SCL = 1;

    delayus(5); //?????????4?s

    SCL = 0; //????,??I2C????????
    delayus(2);
}

uchar write_byte(uchar addr, uchar write_data)
{
    Start_I2C();
    SendByte(DS3231_WriteAddress);
    if (ack == 0)
        return 0;

    SendByte(addr);
    if (ack == 0)
        return 0;

    SendByte(write_data);
    if (ack == 0)
        return 0;

    Stop_I2C();
    delayus(10);
    return 1;
}

uchar read_current()
{
    uchar read_data;
    Start_I2C();
    SendByte(DS3231_ReadAddress);
    if (ack == 0)
        return (0);

    read_data = RcvByte();
    Ack_I2C(1);
    Stop_I2C();
    return read_data;
}

uchar read_random(uchar random_addr)
{
    Start_I2C();
    SendByte(DS3231_WriteAddress);
    if (ack == 0)
        return (0);

    SendByte(random_addr);
    if (ack == 0)
        return (0);

    return (read_current());
}

void ModifyTime(uchar yea, uchar mon, uchar da, uchar hou, uchar min, uchar sec)
{
    uchar temp = 0;

    temp = HEX2BCD(yea);
    write_byte(DS3231_YEAR, temp); //???

    temp = HEX2BCD(mon);
    write_byte(DS3231_MONTH, temp); //???

    temp = HEX2BCD(da);
    write_byte(DS3231_DAY, temp); //???

    temp = HEX2BCD(hou);
    write_byte(DS3231_HOUR, temp); //???

    temp = HEX2BCD(min);
    write_byte(DS3231_MINUTE, temp); //???

    temp = HEX2BCD(sec);
    write_byte(DS3231_SECOND, temp); //???
}

void TimeDisplay(uchar Dhour, uchar Dmin, uchar Dsec)
{
    dis_buf[7] = dis_code[Dhour / 10]; // ???
    dis_buf[6] = dis_code[Dhour % 10]; // ???
    dis_buf[4] = dis_code[Dmin / 10];  // ???
    dis_buf[3] = dis_code[Dmin % 10];  // ???
    dis_buf[1] = dis_code[Dsec / 10];  // ???
    dis_buf[0] = dis_code[Dsec % 10];  // ???
    dis_buf[2] = 0x40;                 // ??"-"
    dis_buf[5] = 0x40;
}

void DateDisplay(uchar Dyear, uchar Dmonth, uchar Dday)
{
    dis_buf[7] = dis_code[Dyear / 10];  // ???
    dis_buf[6] = dis_code[Dyear % 10];  // ???
    dis_buf[4] = dis_code[Dmonth / 10]; // ???
    dis_buf[3] = dis_code[Dmonth % 10]; // ???
    dis_buf[1] = dis_code[Dday / 10];   // ???
    dis_buf[0] = dis_code[Dday % 10];   // ???
    dis_buf[2] = 0x40;                  // ??"-"
    dis_buf[5] = 0x40;
}

void get_show_time(void)
{
    uchar Htemp1, Htemp2, Mtemp1, Mtemp2, Stemp1, Stemp2;

    Htemp1 = read_random(DS3231_HOUR); //? 24???
    Htemp1 &= 0x3f;
    Htemp2 = BCD2HEX(Htemp1);

    Mtemp1 = read_random(DS3231_MINUTE); //?
    Mtemp2 = BCD2HEX(Mtemp1);

    Stemp1 = read_random(DS3231_SECOND); //?
    Stemp2 = BCD2HEX(Stemp1);

    TimeDisplay(Htemp2, Mtemp2, Stemp2);
}

void get_show_date(void)
{
    uchar Ytemp1, Ytemp2, Mtemp1, Mtemp2, Dtemp1, Dtemp2;

    Ytemp1 = read_random(DS3231_YEAR); //?
    Ytemp2 = BCD2HEX(Ytemp1);

    Mtemp1 = read_random(DS3231_MONTH); //?
    Mtemp2 = BCD2HEX(Mtemp1);

    Dtemp1 = read_random(DS3231_DAY); //?
    Dtemp2 = BCD2HEX(Dtemp1);

    DateDisplay(Ytemp2, Mtemp2, Dtemp2);
}

void get_show_Temperature(void)
{
    uchar Ttemp1, Ttemp2, Ttemp3, Ttemp4;

    Ttemp1 = read_random(DS3231_TEMPERATUREH); //?? ???
    Ttemp2 = BCD2HEX(Ttemp1);

    Ttemp3 = read_random(DS3231_TEMPERATUREL); //?????
    Ttemp4 = BCD2HEX(Ttemp3);

    dis_buf[7] = 0;                            // ???
    dis_buf[6] = 0;                            // ???
    dis_buf[3] = dis_code[Ttemp2 / 10];        // ???
    dis_buf[2] = dis_code[Ttemp2 % 10] | 0x80; // ???
    dis_buf[1] = dis_code[Ttemp4 / 10];        // ???
    dis_buf[0] = dis_code[Ttemp4 % 10];        // ???
    dis_buf[5] = 0;                            // ??"-"
    dis_buf[4] = 0;
    //    DateDisplay(0,Ttemp2,Ttemp4);
}

void main()
{
    int i;
    int status;

    RESET = 0x1; //DS3231????,?????????????
    delayus(5000);

    led0 = 0;
    led1 = 0;
    led2 = 0;
    led3 = 0;
    led4 = 0;

    P0 = 0xff;
    P2 = 0xff;

    dis_digit = 0xfe;
    dis_index = 0;

    //TimeDisplay(12, 5, 18);
			DateDisplay(21,9,8);
    /*
    TMOD=0x11;          // ???0, 1????1, 16?????
    TH0=0xDC;
    TL0=0x00;
    
    TCON=0x01;
    IE=0x82;            // ??timer0,1 ??
    
    TR0=1;
    */

    if (write_byte(DS3231_CONTROL, 0x1C) == 0)
        led0 = 1;

    if (write_byte(DS3231_STATUS, 0x00) == 0)
        led1 = 1;

    ModifyTime(21,9,8,8,29,00);       //2021/9/08,08-29-00

    init_TM1638(); //初始化TM1638
    for (i = 0; i < 8; i++)
        Write_DATA(i << 1, tab[i]); //

    status = 0;

    while (1)
    {

        i = Read_key();
        if (i < 3)
        {
            while (Read_key() == i)
                ;
            status = i;
        }

        switch (status)
        {
        case 0:
            get_show_time();
            break;
        case 1:
            get_show_date();
            break;
        case 2:
            get_show_Temperature();
            break;
        }

        for (i = 0; i < 8; i++)
        {
            Write_DATA(i << 1, dis_buf[7 - i]);
        }
        delayus(10000);
    }
}
  • tm1638.h文件
#ifndef	_TM1638_H
#define	_TM1638_H

#include	<REGX51.H>

#define	DATA_COMMAND	0X40
#define	DISP_COMMAND	0x80
#define	ADDR_COMMAND	0XC0

//TM1638模块引脚定义
sbit	DIO=P2^0;
sbit	CLK=P2TM1638芯片的显存地址详细解读

51单片机 3个IO口 + TM1638+24个独立按键扫描(非自锁按键)+驱动8位共阳数码管显示+Proteus仿真

51单片机驱动TM1638芯片+Proteus仿真

Arduino UNO 利用3个IO口 + TM1638+驱动8位数码管显示+24个独立按键

.NET 与树莓派LED 数码管驱动模块——TM1638

51单片机+DS1302+MAX7219驱动8位共阴数码管显示时间