使用DS3231SN制作数字时钟

本项目使用STC15W4K58S4单片机作为控制部分,其速度是传统单片机的12倍。使用有2片74H595驱动的四位数码管显示。
由按键实现时间的调整,时间和温度的切换。通过串口的输出显示,实现对程序的监控,方便debug。

DS3231SN的温度传感,精确到0.25°
DS3231SN的时钟,支持两路闹钟,拥有内部晶振,在有备用电源情况下,精准的进行计时。
DS3231SN支持电压测量。


完整整项目下载:http://download.csdn.net/detail/c1194758555/9596071

DN3231SN中文数据手册:http://download.csdn.net/detail/c1194758555/9596066


项目所用的全部头文件:

####################################################################

IIC通信:

IIC.h

#ifndef _IIC_H_
#define _IIC_H_

#define uchar unsigned char

/*模拟IIC通信*/
#define SCL   P03
#define SDA   P04

void start(void);          /*通信开始*/
void stop(void);           /*通信停止*/
uchar send_bit(uchar dat); /*发送一个bit*/
char Read_bit(void);       /*读取一个bit*/
uchar ASLK(uchar Bit);     /*应答信号*/

#endif

######################################################################

######################################################################

数据的读写:

write_or_read.h


#ifndef _READ_OR_WRITE_H_
#define _READ_OR_WRITE_H_
#include "IIC.h"

uchar W_char(uchar Add,uchar Dat);
char R_w_add_char(uchar Add);
uchar bcd_hex(uchar bcd);
uchar hex_bcd(uchar hex);

#endif

########################################################################

########################################################################

初始化设置时间:

DS3231.h


#ifndef _DS3231_H_
#define _DS3231_H_
#include "IIC.h"

/*存储时间*/
extern          char Time[8];
extern unsigned char Hour;
extern unsigned char Minutes;
extern unsigned char Seconds;
extern          char Wdh;
extern          char Wdl;
extern unsigned char ERRON;

/*地址的定义*/

#define H   0x02            
#define M   0x01
#define S   0x00
#define WDH 0x11
#define WDL 0x12
#define Con 0x0e
#define Pws 0x0f
#define A_W 0xD0
#define A_R 0xD1

uchar Get_H(void);       /*获得小时*/
uchar Get_M(void);       /*获得分钟*/
uchar Get_S(void);       /*获得秒*/
uchar Get_WDH(void);     /*获取温度整数位*/
uchar Get_WDL(void);     /*获取温度小数位*/

uchar init_DS3231(uchar con);                                   /*初始化DS3231*/
uchar Set_time(uchar data_H,uchar data_M,uchar data_S);         /*设置时间*/

#endif
#################################################################################

#################################################################################

对时间设置,时间温度切换控制,时间温度显示:

Interrupt.h

#ifndef _Interrupt_H_
#define _Interrupt_H_
#include "IIC.h"

#define init(x) x ? Read_WD() : Read_SJ()

void init_0(void);     /*初始化定时器0*/
void set_time_key(uchar f); /*设置时间加1*/
void Read_WD(void);  /*读取温度*/
void Read_SJ(void);  /*读取时间*/
void display_us(unsigned int tt); /*μ秒级*/
void display_ms(unsigned int tt);  /*微妙级*/

#endif

###################################################################################

对按键的操作:

key.h

#ifndef _KEY_H_
#define _KEY_H_
#include "IIC.h"

/*按键输入*/
#define key1 P20
#define key2 P21
#define key3 P22
#define key4 P23

extern unsigned char KEY;

uchar Key_NO(void); /*按键检测*/

#endif

###################################################################################

###################################################################################

串口通信,方便debug:

uart.h

#ifndef _UART_H_
#define _UART_H_



void init_uart1(void);    /*初始化串口*/
void OutChar(char c);     /*输出一个字符*/
void OutString(char* str); /*输出一个字符串*/
void Out_Time_WD(void);    /*输出温度或时间*/


#endif


#######################################################################################


模拟IIC通信函数:

#include <STC15W4K58S4.h>
#include "Interrupt.h"
#include "IIC.h"
#include "uart.h"

void start(void) /*开始通信*/
{
	SDA = 1;
	
	display_us(1);
	
	SCL = 1;
	
	display_us(5); /*高电平必须持续大于5μ秒*/
	
	SDA = 0;
	
	display_us(5);
	
	SCL = 0;
	
	display_us(2);
	
}

void stop(void) /*停止通信*/
{
	
	SCL = 1;
	
	display_us(1);
	
	SDA = 0;
	
	display_us(5);
	
	SDA = 1;
	display_us(3);
	
}

uchar ack(void)  /*检测从机应答信号*/
{
	uchar ans;
	
	SDA = 1;
	
	display_us(2);
	
	SCL = 1;
	
	display_us(3);
	
	ans = SDA;
	
	SCL = 0;
	
	display_us(2);
	
	return ans;
}

uchar send_bit(uchar dat) /*发送一个字节*/
{
	uchar i;
	uchar j;
	
	for(i = 0; i < 8; i++)
	{
		if((dat << i) & 0x80)
			j = SDA = 1;
		else
			j = SDA = 0;
		
		SCL = 1;
		display_us(5);
		
		SCL = 0;
		display_us(1);
	}
	display_us(2);
	
	return ack();
}

char Read_bit(void)  /*读取一个字节*/
{
	uchar i;
	char date = 0;
	
	SDA = 1;
	
	for(i = 0; i < 8; i++)
	{
		display_us(1);
		
		SCL = 0;
		display_us(5);
		
		SCL = 1;
		display_us(3);
		
		date = date << 1;
		
		if(SDA)
			date += 1;
		
		display_us(2);
	}
	
	SCL = 0;
	display_us(2);
	
	return date;
}

uchar ASLK(uchar Bit) /*主机应答信号*/
{
	uchar ans = 1;
	
	
	if(!Bit)
		SDA = 0;
	else
		SDA = 1;
	display_us(2);
	
	SCL = 1;
	display_us(5);
	
	SCL = 0;
	display_us(2);
	
	return ans;
}


对数据的操纵函数:

#include "read_or_write.h"
#include "IIC.h"
#include "DS3231.h"
#include "Interrupt.h"
#include "uart.h"

uchar bcd_hex(uchar bcd)         /*bcd码转换为十六进制*/
{
	uchar temp = bcd & 0x0f;
	bcd = bcd >> 4;
	bcd %= 0xf;
	
	return bcd *10 + temp;
}

uchar hex_bcd(uchar hex)        /*十六进制转化为BCD码*/
{
	uchar temp = hex / 10;
	temp = temp << 4;
	
	OutChar(((temp + (hex % 10)) / 16 )+ '0');
	OutChar(((temp + (hex % 10) ) % 16 )+ '0');
	OutChar('\r');
	OutChar('\n');
	
	
	return temp + hex % 10;
}

uchar W_char(uchar Add,uchar Dat) /*写数据*/
{
	start();
	
	if(send_bit(A_W))
		return 0;
  
	if(send_bit(Add))
		return 0;
	
	if(send_bit(Dat))
		return 0;
	
	stop();

	display_us(2);
	
	return 1;
}

char R_char()                    /*读取一个字符*/
{
	char temp;
	
	start();
	
	if(send_bit(A_R))
		return 0;
	
  temp = Read_bit();
	
  
	ASLK(1);
	
	stop();
	
	return temp;
}

char R_w_add_char(uchar Add)  /*读取数据*/
{
	char temp;
	start();

  if(send_bit(A_W))
      return 0;

	
	if(send_bit(Add))
		return 0;

	
	display_us(2);

	
	temp = R_char();
	
	return temp;
}



对DS3231SN的设置:

#include "IIC.h"
#include "read_or_write.h"
#include "DS3231.h"
#include "uart.h"

 char Time[8];                               /*存储时间*/
unsigned char Hour;                         /*小时*/
unsigned char Minutes;                      /*分钟*/
unsigned char Seconds;                      /*秒*/
char Wdh;
char Wdl;
unsigned char ERRON;                          /*出错标志*/

uchar init_DS3231(uchar con)                  /*初始化DS3231*/
{
	uchar f = 0;
	f = W_char(Con,con);
	return f;
}

uchar Get_H(void)                                       /*获得小时*/
{
	uchar temp = R_w_add_char(H);
	temp = bcd_hex(temp);
	temp &= 0x3f;
	return temp;
}

uchar Get_M(void)                                       /*获得分钟*/
{
	uchar temp = R_w_add_char(M);
	temp = bcd_hex(temp);
	return temp;
}

uchar Get_S(void)                                       /*获得秒*/
{
	uchar temp = R_w_add_char(S);
	temp = bcd_hex(temp);
	return temp;
}

uchar Get_WDH(void)                                    /*获得温度整数位*/
{
	return R_w_add_char(WDH);
}

uchar Get_WDL(void)                                    /*获得温度小数位*/
{
	return R_w_add_char(WDL);
}



对时间温度的切换,时间的设置,定时器的初始化:

#include <STC15W4K58S4.h>
#include "Interrupt.h"
#include "IIC.h"
#include "DS3231.h"
#include "led.h"
#include "led.h"
#include "key.h"
#include "uart.h"

void display_us(unsigned int tt) /*μ秒级*/
{
	while(tt--);
}

void display_ms(unsigned int tt) /*毫妙级*/
{
	
	while(tt--)
	{
		display_us(100);
	}
}

void init_0(void) /*定时器0中断初始化,用于显示时间*/
{
	TMOD &= ~0x0f;
	AUXR &= ~0x80;
	TH0 = 65036 >> 8;
	TL0 = 65036;
	TR0 = 1;
	ET0 = 1;
	EA = 1;
}

void Read_WD(void)  /*读取温度*/
{
	 uchar Wdh,Wdl;
	 unsigned int tt;
	 unsigned int t;
	 init_DS3231(0x3C);
	
	do
	{
	  Wdh = Get_WDH();
	  Wdl = Get_WDL();
	
	  Wdl = Wdl >> 6;
	  Wdl &= 0x03;
	  Wdl *= 25;
	
	  Time[3] = Wdh / 10;
	  Time[2] = Wdh % 10;
	  Time[1] = Wdl / 10;
	  Time[0] = Wdl % 10;
		Out_Time_WD();
		
	   tt = 1000;
		 while(tt--)
		 {
       t = 1000;	
			 while(t--)
			 {
			   KEY = Key_NO();
				 if(KEY == 3)
					 return;
			 }
		 }
	}
	while(KEY == 0 || KEY == 1);
}

void set_time_key(uchar f) /*更改时间位*/
{
	if(f == 1)
	{
		Hour += 1;
		if(Hour >= 24)
			Hour = 0;
	  Time[3] = Hour / 10;
	  Time[2] = Hour % 10;
	}
	else if(f == 2)
	{
	  Minutes += 1;
		if(Minutes > 59)
			Minutes = 0;
		
	  Time[1] = Minutes / 10;
	  Time[0] = Minutes % 10;
	}
}

void Read_SJ(void)  /*读取时间*/
{
  unsigned int tt;
	unsigned int t;
	uchar j = 1;
	init_DS3231(0x1C);
	
	do
	{
   	  
		 Hour =  Get_H();
	   Minutes = Get_M();
	   Seconds = Get_S();
	
	   Time[3] = Hour / 10;
	   Time[2] = Hour % 10;
	   Time[1] = Minutes / 10;
	   Time[0] = Minutes %10;
		 Out_Time_WD();
		 tt = 1000;
		 while(tt--)
		 {
       t = 1000;	
			 while(t--)
			 {
			   KEY = Key_NO();
				 if(KEY ==1 || KEY == 3)
					 return;
			 }
		 }
		}
		while(KEY == 0);
}



按键检测:

#include <STC15W4K58S4.h>
#include "Interrupt.h"
#include "key.h"
#include "IIC.h"
#include "uart.h"

unsigned char KEY; 


uchar Key_NO(void)               /*按键检测*/
{
	unsigned int time = 1000;
       if(!key1  || !key2 || !key3 || !key4)
      {
		 OutString("有键按下\r\n");
		 display_ms(10);
		 if(!key1 || !key2 || !key3  || !key4)
                {
			 if(!key1)
			 {
				 OutString("key1\r\n");
				 while(!key1 && time--)
					 display_us(1000);
				 return 1;
			 }
			 
			 if(!key2)
			 {
				  OutString("key2\r\n");
				 while(!key2 && time--)
					 display_us(1000);
				 return 2;
			 }
			 
			 if(!key3)
			 {
				 OutString("key3\r\n");
				 while(!key3 && time--)
					 display_us(1000);
				 return 3;
			 }
			 
			 if(!key4)
			 {
				 OutString("key4\r\n");
				 while(!key4 && time--);
				 return 4;
			 }
	        }
		 	 
	}
  return 0;	
}

led的显示:

#include <STC15W4K58S4.h>
#include "led.h"

const unsigned char table[12] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x7F}; /*段码*/

void S_CLK()   /*移位信号*/
{
	 SCLK = 0;
	 SCLK = 1;
}

void R_CLK() /*位选信号*/
{
	RCLK = 0;
	RCLK = 1;
}

void led_on(unsigned char led_num) /*点亮一个LED*/
{
	unsigned char i ;
	for(i = 0; i < 8; i++)
	{
		 if(led_num & 0x80)
			 DIO = 1;
		 else
			 DIO = 0;
		 led_num <<= 1;
		 S_CLK();
	}
}

void led_one(unsigned char LEDNO, unsigned char NO) /*扫描一遍四个数码管*/
{
	
	  led_on(LEDNO);
	  led_on(NO);
	  R_CLK();
}

串口通信,方便debug:

#include <STC15W4K58S4.h>
#include "Interrupt.h"
#include "DS3231.h"


void init_uart1(void) /*初始化串口*/
{
	SCON |= 0x50;
	TMOD &= ~0xf0;
	AUXR |= 0x40;
	AUXR &= 0xFE;
	TH1 = 65224 >> 8;
	TL1 = 65224;
	ET1 = 0;
	
	TR1 = 1;
}

void OutChar(char c) /*输出一个字符*/
{
	SBUF  = c;
	while(!TI);
	TI = 0;
}

void Out_Time_WD(void) /*输出时间或温度*/
{
	uchar temp;
	char i;
	for(i = 3; i >= 0; i--)
	{
		temp = Time[i] + '0';
		OutChar(temp);
	}
	OutChar('\r');
	OutChar('\n');
}

void OutString(char* str) /*输出字符串*/
{
	while(*str != '\0')
		OutChar(*str++);
		
}


main函数:

#include <STC15W4K58S4.h>
#include "read_or_write.h"
#include "Interrupt.h"
#include "led.h"
#include "IIC.h"
#include "key.h"
#include "uart.h"
#include "DS3231.h"

static uchar f = 0;                              /*时间温度状态切换标志量*/
static uchar flag;                               /*设置时间使用的状态变量*/
static unsigned int SUM = 1000;                  /*设置时间时相应位闪动的时间间隔*/
static unsigned int NO;
int main()
{
	uchar set;
	KEY = 0;                                 	/*按键*/
	ERRON = 1;                                /*出错标志位*/
	flag = 0;
	
	/*设置为准双向输出*/
	
	P2M0 = 0x00;
	P2M1 = 0x00;
	
	Time[0] = 5;
	Time[1] = 5;
	Time[2] = 5;
	Time[3] = 5;
	init_uart1();                             /*初始化串口,用于监控代码运行,方便调试*/
	init_0();

	init_DS3231(0x1C);                         /*初始化DS3231*/

	
	//OutChar(Set_time(0x0C,0x01,0x0) + '0');  /*设置时间*/
	
  Out_Time_WD();
	init(f);                                 /*初始化定时器0,显示时间*/
	
	Out_Time_WD();
	
	while(1)
	{
		OutString("进入while\r\n");
		switch(KEY)
		{
			case 1:
				if(!f)
				{
					flag = 1;
					while(flag < 3)
					{
						set = Key_NO();          /*检测按键变化*/
						
						switch(set)
						{
							case 1: { if(flag == 1) W_char(H,hex_bcd(Hour)); if(flag == 2) W_char(M,hex_bcd(Minutes)); flag += 1; }			break;       /*分钟位开始闪烁*/
							case 2: set_time_key(flag); break;   /*加1*/
						}
					}
					
					display_ms(100);
					flag = 0;
					KEY = 0;
					
				}
				init(f);                           /*时间正常显示*/
				break;
				
			case 3:
				f = !f;                            /*切换状态*/
				init(f);                           /*显示为设置的工作状态*/
				break;	
		}
	}
}

/*定时器1的中断函数,用于刷新led数码管*/
void init_time0() interrupt 1
{
	uchar i,k;
	uchar j = 1;
	
	
	if(flag ==1)
	{
		if(NO >= SUM)
		{
			i = 0;
			k = 4;
		}
		else
		{
			i = 0;
		  k = 2;
		}
	}
	else if(flag == 2)
	{
		if(NO >= SUM)
		{
			i = 0;
			k = 4;
		}
		else
		{
			i = 2;
		  k = 4;
		}
	}
	else
	{
		i = 0;
		k = 4;
	}
	
	if(NO == 2*SUM)
		 NO = 0;
	NO += 1;
	
	for(;i < k; i++)
	{
		if(f && i == 2)
		{
			led_one((table[Time[i]] & 0x7F),(j << i));
		}
		else if(!f && i == 2 && NO <= SUM && !flag)
		{
			led_one((table[Time[i]] & 0x7F),(j << i));
		}
		else
		 led_one(table[Time[i]],(j << i));
	}
	for(i= 0;i < 4; i++)
	{
		 led_one(0xff,(j << i));
	}
  
}



                                                                       

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
你好!为了制作一个时钟,你将需要以下硬件和软件: 硬件: 1. ESP32 C3 开发板:ESP32 C3 是一款低成本、低功耗的Wi-Fi和蓝牙芯片,非常适合物联网应用。 2. DS3231SN 实时时钟模块:DS3231SN 是一款高精度的实时时钟模块,可以提供准确的时间信息。 3. SSD1306 OLED 显示屏:SSD1306 是一款0.96英寸的OLED显示屏,可以显示时钟和其他信息。 4. 连线:用于连 ESP32、DS3231SN 和 SSD1306。 软件: 1. MicroPython:MicroPython 是一种精简版的 Python 解释器,可以在嵌入式系统上运行。 下面是制作时钟的步骤: 1. 连硬件: - 将 ESP32 C3 与 DS3231SN 和 SSD1306 连起来。确保连正确,参考硬件连图。 - 将 DS3231SN 和 SSD1306 分别连到 ESP32 的 I2C 口。 2. 安装 MicroPython: - 在你的计算机上下载并安装 MicroPython。 - 使用 USB 数据线将 ESP32 C3 连到计算机。 3. 编写 MicroPython 代码: - 打开一个文本编辑器,创建一个新的 MicroPython 脚本。 - 导入必要的库,例如 machine、ssd1306 和 ds3231。 - 初始化 I2C 总线和 DS3231SN 模块。 - 设置 SSD1306 OLED 显示屏的参数。 - 使用 DS3231SN 模块获取当前时间。 - 在 OLED 显示屏上显示时间。 4. 上传代码到 ESP32 C3: - 将编写好的 MicroPython 代码保存为 main.py 文件。 - 使用 MicroPython 工具将 main.py 上传到 ESP32 C3 开发板上。 5. 测试和调试: - 断开 ESP32 C3 与计算机的连。 - 将 ESP32 C3 与电源连,启动时钟程序。 - 监视 SSD1306 OLED 显示屏,确保时间正确显示。 这是一个基本的框架,你可以根据自己的需求进行进一步的扩展和美化。希望对你有所帮助!如果你有任何问题,请随时向我提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值