标签:iic ds3231高精度时钟模块 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){//5ms@12M
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){ //2400@12M
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 测试程序 【开源】
标签:iic ds3231高精度时钟模块 c51 8051单片机i2c 测试程序 【开源】
原文地址:http://990487026.blog.51cto.com/10133282/1737914