制作出来的实物图如下:
部分源代码:
#include "reg51.h"#include "intrins.h" #include "codetab.h" #include "nongli.h" #define uint unsigned int #define uchar unsigned char // ------------------------------------------------------------ // IO口模拟I2C通信 // ------------------------------------------------------------ sbit SCL=P3^6; //串行时钟 sbit SDA=P3^7; //串行数据 sbit KEY1= P3^0; //调整 sbit KEY2= P3^1; //++ sbit KEY3= P3^2; //-- sbit KEY4= P3^3; //退出 uchar a1,a2,a3,a4; //按键消抖用 uchar disflag=0; //时间调整相关 #define Brightness 0xcf // #define X_WIDTH 128 #define Y_WIDTH 64 /******************************************************************************************************** ** DS3231常数定义 ********************************************************************************************************/ #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 //年 #define DS3231_TEMPERATUREH 0x11 //温度寄存器高字节(8位) 整数部分 #define DS3231_TEMPERATUREL 0x12 //温度寄存器低字节(低2位) 小数部分 #define NACK 1 #define ACK 0 uchar shan_count; //:号闪烁计时变量 uchar shan_js; //校时闪烁计时变量 bit flag; //校时闪烁标志 char hour,minute,second,year,month,day,date,week; uint TH3231; bit ack; //应答标志位 /*********************OLED驱动程序用的延时程序************************************/ /*void delay(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=1100;y>0;y--); } */ void Delay5US() //@12.000MHz 延时5us { _nop_(); _nop_(); _nop_();_nop_(); //1T单片机用4个nop,12T用1个nop } /**************************/ void Timer0Init(void) //10毫秒@11.0592MHz { // AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器0,16位模式 TL0 = 0x00; //设置定时初值 TH0 = 0xDC; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; EA = 1; } /********************************************** //IIC Start **********************************************/ void IIC_Start() { SCL = 1; SDA = 1; SDA = 0; SCL = 0; } /********************************************** //IIC Stop **********************************************/ void IIC_Stop() { SCL = 0; SDA = 0; SCL = 1; SDA = 1; } /******************************************************************************************************** ** 3231 ********************************************************************************************************/ uchar BCD2HEX(uchar val) { return ((val>>4)*10)+(val&0x0f); } uchar HEX2BCD(uchar val) { return (((val%100)/10)<<4)|(val%10); } void SendByte(uchar c) { uchar BitCnt; for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位 { if((c<<BitCnt)&0x80) SDA=1; //判断发送位 else SDA=0; SCL=1; //置时钟线为高,通知被控器开始接收数据位 Delay5US(); //保证时钟高电平周期大于4μs SCL=0; } SDA=1; //8位发送完后释放数据线,准备接收应答位 SCL=1; Delay5US(); if(SDA==1) ack=0; else ack=1; //判断是否接收到应答信号 SCL=0; Delay5US(); } uchar RcvByte() { uchar retc; uchar BitCnt; retc=0; SDA=1; //置数据线为输入方式 for(BitCnt=0;BitCnt<8;BitCnt++) { SCL=0; //置时钟线为低,准备接收数据位 Delay5US(); //时钟低电平周期大于4.7μs SCL=1; //置时钟线为高使数据线上数据有效 Delay5US(); retc=retc<<1; if(SDA==1) retc=retc+1; //读数据位,接收的数据位放入retc中 Delay5US(); } SCL=0; return(retc); } void Ack_I2C(bit a) { SDA = a; SCL=1; Delay5US(); //时钟低电平周期大于4us SCL=0; //清时钟线,钳住I2C总线以便继续接收 Delay5US(); } uchar write_byte(uchar addr, uchar write_data) { IIC_Start(); SendByte(DS3231_WriteAddress); if (ack == 0) return 0; SendByte(addr); if (ack == 0) return 0; SendByte(write_data); if (ack == 0) return 0; IIC_Stop(); Delay5US(); Delay5US(); return 1; } uchar read_current() { uchar read_data; IIC_Start(); SendByte(DS3231_ReadAddress); if(ack==0) return(0); read_data = RcvByte(); Ack_I2C(1); IIC_Stop(); return read_data; } uchar read_random(uchar random_addr) { uchar Tmp; IIC_Start(); SendByte(DS3231_WriteAddress); if(ack==0) return(0); SendByte(random_addr); if(ack==0) return(0); Tmp=read_current(); if(random_addr==DS3231_HOUR) Tmp&=0x3f; return(BCD2HEX(Tmp));//都转10进制输出 } /***********************/ uchar read_random1(uchar random_addr) //这个是读温度函数 { uchar Tmp; write_byte(0x0e,0x20);//0x0e寄存器的CONV位置1开启温度转换,要这句,温度实时刷新,这句不要,温度要64s才刷新1次 IIC_Start(); SendByte(DS3231_WriteAddress); if(ack==0) return(0); SendByte(random_addr); if(ack==0) return(0); Tmp=read_current(); return Tmp; } void ModifyTime(uchar address,uchar num) { uchar temp=0; if(address>6 && address <0) return; temp=HEX2BCD(num); write_byte(address,temp); }
复制代码