650) this.width=650;" "/>

DS3231高精度时钟模块,IIC,C51 8051单片机I2C 测试程序 开源

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DS3231高精度时钟模块,IIC,C51 8051单片机I2C 测试程序 开源相关的知识,希望对你有一定的参考价值。


实物图


技术分享

技术分享


技术分享







原理图

技术分享



效果图

技术分享



程序烧录:

技术分享



/***************************************************************************** 
*文件名称:main.c
*版    本:Keil uVision4
*控 制 器:STC89C52RC/12M
功能:显示时间到串口

*说    明:
1,DS3231实时时钟模块测试程序 
2,1T的单片机用不了
3,晶振12M
4,串口波特率2400

编译结果:
Rebuild target ‘Demo_DS3231‘
compiling main.c...
linking...
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?_UART_SENDBYTE?MAIN
Program Size: data=61.2 xdata=0 code=2059
creating hex file from "Demo_DS3231"...
"Demo_DS3231" - 0 Error(s), 1 Warning(s).


*****************************************************************************/

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

//#define  Effective                  0x01
//#define  Ineffectiveness            0x00
#define  DS3231WriteAddress         0xd0
#define  DS3231ReadAddress          0xd1
//#define  DS3231_SecondRegister      0x00
#define  DS3231_TimeFirstRegister   0x00
#define  DS3231_MinuteRegister      0x01
#define  DS3231_HourRegister        0x02
#define  DS3231_WeekRegister        0x03
#define  DS3231_DayRegister         0x04
#define  DS3231_MonthRegister       0x05
#define  DS3231_YearRegister        0x06
#define  DS3231_InterruptRegister   0x0e
#define  DS3231_AlarmRegister       0x0f
#define  DS3231_ResetSCL()     DS3231_scl = 0   
#define  DS3231_SetSCL()       DS3231_scl = 1
#define  DS3231_ResetSDA()     DS3231_sda = 0
#define  DS3231_SetSDA()       DS3231_sda = 1
#define  DS3231_ReadPinSDA()   DS3231_sda
#define Time0_TH0  0xec	        //定义计数器0计数寄存器装载的高8位值
#define Time0_TL0  0x78	        //定义计数器0计数寄存器装载的低8位值

//--------------------------秒-分-时-星期-日-月-年
unsigned int   SetTime[] = {12,12,12,1,1,1,15};
unsigned int   CurrentT[7];
bit            Flag_Collect = 0;         //定义采集扫描标志变量
unsigned char	 SweepInterval_Collect;	   //定义采集扫描时间累加变量
sbit    DS3231_scl = P2^1;  //DS3231 clock 
sbit    DS3231_sda = P2^0;  //DS3231 data 

void DS3231_Delay(void) {    //DS3231通信速率延时,延时5微秒  12T单片机@12M
	unsigned char Number = 8;
	while (Number--)    {
        _nop_();
        _nop_();
    } 
}

void DS3231_DelayForWrite(void){  //DS3231写字节延时,延时5毫秒 12T单片机@12M
	unsigned int Number = 2500;
	while (Number--){
			_nop_();
      _nop_();
			_nop_();
			_nop_();
			_nop_();
    } 
}

void DS3231_Start(void) { //模拟DS3231通信开始信号,SCL=1期间,在SDA上产生一个下降沿
	DS3231_SetSDA();
	DS3231_SetSCL();DS3231_Delay(); 
	DS3231_ResetSDA();DS3231_Delay(); 
} 

void DS3231_Stop(void) //模拟DS3231通信结束信号,SCL=1期间,在SDA上产生一个上升沿
{   
	DS3231_ResetSDA();DS3231_Delay();
	DS3231_ResetSDA();DS3231_Delay();	 
	DS3231_SetSCL();DS3231_Delay();
	DS3231_SetSCL();DS3231_Delay();
	DS3231_SetSDA();DS3231_Delay();
} 

unsigned char DS3231_WriteByte(unsigned char SendByte){ //向DS3231设备写一字节数据及8为二进制数据,高位在前 
	unsigned char i=8;
	DS3231_ResetSCL();	 
	for(i=0; i<8; i++)	{ 
		if(SendByte&0x80) {DS3231_SetSDA();}
		else {DS3231_ResetSDA();}
		DS3231_ResetSCL();DS3231_Delay();				   
		DS3231_SetSCL(); DS3231_Delay(); 
		SendByte=SendByte<<1;
		DS3231_ResetSCL();DS3231_Delay(); 
	}
	DS3231_SetSDA();DS3231_Delay();
	DS3231_ResetSCL();DS3231_Delay();
	DS3231_SetSCL();DS3231_Delay();
	i = DS3231_ReadPinSDA();DS3231_Delay();
	DS3231_ResetSCL();DS3231_Delay();
	return i;		 
} 

unsigned char DS3231_ReceiveByte(unsigned char Response) { //接收DS3231发送的数据
	unsigned char i=8; 
	unsigned char ReceiveByte=0;
	DS3231_SetSDA();DS3231_Delay();	
	DS3231_ResetSCL();DS3231_Delay();	 
	for(i=0; i<8; i++){ 
		DS3231_SetSCL();DS3231_Delay();
		ReceiveByte = ReceiveByte << 1;       
		ReceiveByte=ReceiveByte|(unsigned char)DS3231_ReadPinSDA(); 
		DS3231_ResetSCL();DS3231_Delay(); 
	}
	if(Response) DS3231_SetSDA();		
	else DS3231_ResetSDA();		
	DS3231_Delay();
	DS3231_SetSCL();DS3231_Delay();
	DS3231_ResetSCL();DS3231_Delay();
	DS3231_SetSDA();DS3231_Delay(); 
	return ReceiveByte; 
}                                                               

unsigned char DS3231_ReadOneByteFromE2PROM(unsigned char DataAddress) {//读指定地址E2PROM中的数据
	unsigned char ReadData;
	DS3231_Start();                       //DS3231芯片IIC通信开始信号
	DS3231_WriteByte(DS3231WriteAddress); //写入芯片IIC写地址
	DS3231_WriteByte(DataAddress);        //写入状态寄存器地址
	DS3231_Start();                       //DS3231芯片IIC通信开始信号
	DS3231_WriteByte(DS3231ReadAddress);  //写入芯片IIC读地址
	ReadData = DS3231_ReceiveByte(0x01);
	DS3231_Stop();                         //DS3231芯片IIC通信停止信号
	return ReadData; 	 
}

void DS3231_Initialization(){            //初始化时钟芯片DS3231,先选择要写入的寄存器,在写入需要设置的指令
	DS3231_Start();											 	 //IIC通信起始信号
	DS3231_WriteByte(DS3231WriteAddress);  //写入芯片IIC写地址
	DS3231_WriteByte(DS3231_HourRegister); //选择时寄存器为写入地址
	DS3231_WriteByte(0x00);                //写入指令,时钟范围为0-23,即24小时制式
	DS3231_Stop(); 
	
	DS3231_Start();														 //IIC通信起始信号
	DS3231_WriteByte(DS3231WriteAddress);      //写入芯片IIC写地址
	DS3231_WriteByte(DS3231_InterruptRegister);//选择中断寄存器为写入地址	  
	DS3231_WriteByte(0x04);                    //中断寄存器初始化,关闭方波信号,关闭闹钟中断
	DS3231_WriteByte(0x00);                    //状态寄存器初始化,失效32KHz信号输出,不匹配闹钟
	DS3231_Stop(); 
}

void DS3231_SetTime(unsigned int *Pointer){ //向DS3231写入设置时间信息
	unsigned char Number = 0x00;
  unsigned char TransitionData = 0x00;
	DS3231_Start();                             //DS3231芯片IIC通信开始信号
	DS3231_WriteByte(DS3231WriteAddress);       //写入芯片IIC写地址
	DS3231_WriteByte(DS3231_TimeFirstRegister); //写入时间寄存器首地址
  for(Number=0; Number<7; Number++)  {
    TransitionData = *Pointer++;
    DS3231_WriteByte((TransitionData/10)*16+TransitionData%10);   //向DS3231写入设置时间信息
  }
  DS3231_Stop();                                   //DS3231芯片IIC通信停止信号
	DS3231_DelayForWrite();
}

void DS3231_ReadTime(unsigned int *Pointer){       //从DS3231中读出当前时间
	unsigned char Number  = 7;
  unsigned char Time    = 0x00;
	DS3231_Start();                                  //DS3231芯片IIC通信开始信号
	DS3231_WriteByte(DS3231WriteAddress);            //写入芯片IIC写地址
	DS3231_WriteByte(DS3231_AlarmRegister);          //写入闹钟寄存器首地址
	DS3231_WriteByte(0x00);                          //关闭闹钟中断标志位
	DS3231_Stop();                                   //DS3231芯片IIC通信停止信号

	DS3231_Start();                                  //DS3231芯片IIC通信开始信号
	DS3231_WriteByte(DS3231WriteAddress);            //写入芯片IIC写地址
	DS3231_WriteByte(DS3231_TimeFirstRegister);      //写入时间寄存器首地址
	DS3231_Start();                                  //DS3231芯片IIC通信开始信号
	DS3231_WriteByte(DS3231ReadAddress);             //写入芯片IIC读地址
  for(Number=0; Number<6; Number++) {
		Time = DS3231_ReceiveByte(0x00);
    *Pointer++ = (Time/16*10+Time%16);    
  }
	Time = DS3231_ReceiveByte(0x01);
	*Pointer++ = (Time/16*10+Time%16); 
  DS3231_Stop();                                 //DS3231芯片IIC通信停止信号
}

void Time0_Initialization(void){//[email protected] 
		TMOD=0x21;        //T0,工作方式1
		TH0=Time0_TH0;    //装载定时器0寄存器高8位值
		TL0=Time0_TL0;    //装载定时器0寄存器低8位值
		TR0=1;            //开启T0定时器
		ET0=1;            //允许T0定时器中断
		EA=1;             //开启总中断允许
}

void UART_Initialization(void){  //[email protected]
		SCON = 0x50;       //选择串口工作方式1,打开接收允许
		TMOD = 0x21;       //定时器1工作在方式2,定时器0工作在方式1
		TH1  = 0xe6;       //实现波特率2400(系统时钟12MHZ)
		TCON = 0x40;       //定时器1开始计数
		PCON = 0x80;       //波特率倍频
		RI   = 0x00;			 //清接收标志
		TI   = 0x01;			 //清发送标志
		TR1  = 0x01;       //启动定时器T1
}

void UART_SendByte(unsigned char SendByte){
    SBUF = SendByte; //输出字符
    while(!TI);		   //判断是否发完
    TI=0;			       //清TI
}

void main(){                                             //定时采集DS3231时钟芯片时间信息,通过RS232串口打印
	unsigned char State_Timing;
	unsigned int  Value_Contrast;
	UART_Initialization();
	State_Timing = DS3231_ReadOneByteFromE2PROM(DS3231_AlarmRegister);//判断是否校时
	if(State_Timing & 0x80){                                 //判断芯片是否有掉电
		DS3231_Initialization();                               //初始化时间时钟芯片DS3231
		DS3231_SetTime(SetTime);
	}
	
	DS3231_ReadTime(CurrentT);                               //掉电检测操作,电源短路或者供电系统电量彻底消耗掉才有效 每次上电读取一次当前时间信息
	if(CurrentT[6] == 0x00){                                 //年份信息为0x00,芯片时间需要初始化
		DS3231_Initialization();                               //初始化时间时钟芯片DS3231
		DS3231_SetTime(SetTime);                               
	}
	Time0_Initialization();	          //定时器初始化

	while(1){
		while(Flag_Collect){           // 中断控制
			EA = 0;                      //关闭总中断
			DS3231_ReadTime(CurrentT);   //读取当前时间信息
			if(Value_Contrast != CurrentT[0]){
				Value_Contrast = CurrentT[0];
				printf("Week=%d\r\n",CurrentT[3]);			
				printf("Data=20%d/%d/%d\r\n",CurrentT[6],CurrentT[5],CurrentT[4]);
				printf("Time=%d:%d:%d\r\n",CurrentT[2],CurrentT[1],CurrentT[0]);
				printf("\r\n");
			}			  							  					
			Flag_Collect = 0;           
			EA = 1;
		}
	}
}


void Time0_Handle(void) interrupt 1 using 3 {
	TR0 = 0;                            //关闭T0定时器   
	TH0 = Time0_TH0;                    //重新装载定时器0寄存器高8位值
	TL0 = Time0_TL0;                    //重新装载定时器0寄存器低8位值
	TR0 = 1;                            //开启T0定时器
	if(SweepInterval_Collect >= 0x3c){     //大约0.3s采集一次时钟信息
		Flag_Collect = 1;                   //采集扫描标志变量置位
		SweepInterval_Collect = 0;          //采集扫描时间变量清零
	}
	else	{SweepInterval_Collect++;}			//采集扫描时间累加		
}


以上是关于DS3231高精度时钟模块,IIC,C51 8051单片机I2C 测试程序 开源的主要内容,如果未能解决你的问题,请参考以下文章

基于STM8的IIC协议--实例篇--时钟模块(DS3231)读取

DS12C887,DS1302,DS3231时钟芯片那个精度比较高?

DS12C887,DS1302,DS3231时钟芯片哪个精度比较高

玩转 RTC时钟库 DS3231

张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231

张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231