今天来做DS23231的闹钟功能
前几天已经做好了DS3231的闹钟启动函数,现在也测试成功,
来晒一下开启和关闭的程序:
#include <reg51.h>
  • #include <intrins.h>
  • /*DS3231使用功能定义*/
  • typedef unsigned char uchar;   
  • typedef unsigned int  uint ;   
  • sbit SDA=P1^3;     //模拟I2C数据传送位SDA      
  • sbit SCL=P1^1;     //模拟I2C时钟控制位SCL
  • sbit SQW=P3^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  DS3231Time[9]={0x40,0x59,0x05,0x21,0x05,0x08,0x06,0x00,0x00}; //秒分时年月日周温度高字节温度低字节
  • /*全局函数定义*/
  • extern void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec,uchar wee);
  • extern void  get_show_Temperature(void);
  • extern void READ_Time();
  • extern void DS3231_Init();                        
  • extern uchar DS3231_Time[9];
  • void delayus(uint us)
  • {
  •     while(us--);
  • }
  • uchar BCD2HEX(uchar val)    //BCD转换为Byte
  • {
  •     uchar temp;
  •     temp=val&0x0f;                          
  •     val>>=4;
  •     val&=0x0f;
  •     val*=10;
  •     temp+=val;
  •   
  •     return temp;
  • }
  • uchar HEX2BCD(uchar val)    //B码转换为BCD码
  • {
  •     uchar i,j,k;
  •     i=val/10;
  •     j=val;
  •     k=j+(i<<4);
  •     return k;
  • }
  • 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 wee)
  • {
  •     uchar temp=0;
  •   
  •     //temp=HEX2BCD(yea);
  •     write_byte(DS3231_YEAR,yea);   //修改年
  •   
  •     //temp=HEX2BCD(mon);
  •     write_byte(DS3231_MONTH,mon);  //修改月
  •   
  •     //temp=HEX2BCD(da);
  •     write_byte(DS3231_DAY,da);    //修改日
  •          
  •     //temp=HEX2BCD(hou);
  •     write_byte(DS3231_HOUR,hou);   //修改时
  •   
  •     //temp=HEX2BCD(min);
  •     write_byte(DS3231_MINUTE,min); //修改分
  •          
  •     //temp=HEX2BCD(sec);
  •     write_byte(DS3231_SECOND,sec); //修改秒
  •         write_byte(DS3231_WEEK,wee); //修改周
  • }
  • void  get_show_Temperature(void)
  • {
  •     uchar Ttemp1,Ttemp2;
  •           write_byte(0x0e,0x20);
  •     Ttemp1=read_random(DS3231_TEMPERATUREH);    //温度 高字节
  •           DS3231Time[7]=Ttemp1;
  •     Ttemp2=read_random(DS3231_TEMPERATUREL);    //温度低字节
  •         Ttemp2=(Ttemp2>>6)*25;
  •         DS3231Time[8]=Ttemp2;
  • }
  • void READ_Time()
  • {
  •    
  •     DS3231Time[0]=read_random(DS3231_SECOND);
  •         DS3231Time[1]=read_random(DS3231_MINUTE);
  •         DS3231Time[2]=read_random(DS3231_HOUR);
  •         DS3231Time[3]=read_random(DS3231_YEAR);
  •         DS3231Time[4]=read_random(DS3231_MONTH);
  •         DS3231Time[5]=read_random(DS3231_DAY);
  •         DS3231Time[6]=read_random(DS3231_WEEK);
  •         get_show_Temperature();
  • }
  • void DS3231_opennz1(uchar second,minute,hour,day)
  • {
  •     write_byte(0x0e,0x1d);  
  •         write_byte(DS3231_SALARM1ECOND,second);//秒
  •         write_byte(DS3231_ALARM1MINUTE,minute);//分
  •         write_byte(DS3231_ALARM1HOUR,hour);//时
  •         write_byte(DS3231_ALARM1WEEK,day);//星期/日
  • }
  • void DS3231_opennz2(minute,hour,day)
  • {
  •     write_byte(0x0e,0x1e);  
  •         write_byte(DS3231_ALARM2MINUTE,minute);//分
  •         write_byte(DS3231_ALARM2HOUR,hour);//时
  •         write_byte(DS3231_ALARM2WEEK,day);//星期/日
  • }
  • void DS3231_Init()
  • {
  •     ModifyTime(DS3231Time[3],DS3231Time[4],DS3231Time[5],DS3231Time[2],DS3231Time[1],DS3231Time[0],DS3231Time[6]);
  • }
  • 复制代码
    其中void DS3231_opennz1(uchar second,minute,hour,day)和void DS3231_opennz2(minute,hour,day)分别是闹钟1和闹钟2的启动程序,
    下面是闹钟的关闭程序:
    unsigned char i;
    write_byte(0x0f,i|=0x00);
    这是停止闹钟2和闹钟1。
    闹钟判断程序:
    void nz_if()
    {
        unsigned char i;
            i=read_random(0x0f);//读取状态寄存器
            i=i&0x02;//闹钟2写i=i&0x02;闹钟1写i=i&0x01;
            if(i == 0x02)//闹钟2写i==0x02;闹钟1写i==0x01;
            {        
                //闹钟提醒程序,你们想怎么搞就怎么搞
            }

    希望能帮到你们!