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仿真