找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3489|回复: 6
收起左侧

[原创设计][电子手表制作]第3期V1.2版(DS3231闹钟程序)

  [复制链接]
ID:884042 发表于 2021-7-14 12:09 | 显示全部楼层 |阅读模式
本帖最后由 xjx51 于 2021-8-11 16:06 编辑

今天来做DS23231的闹钟功能
前几天已经做好了DS3231的闹钟启动函数,现在也测试成功,
来晒一下开启和关闭的程序:
  1. #include <reg51.h>
  2. #include <intrins.h>

  3. /*DS3231使用功能定义*/
  4. typedef unsigned char uchar;   
  5. typedef unsigned int  uint ;   

  6. sbit SDA=P1^3;     //模拟I2C数据传送位SDA      
  7. sbit SCL=P1^1;     //模拟I2C时钟控制位SCL
  8. sbit SQW=P3^7;

  9. bit  ack;          //应答标志位

  10. #define DS3231_WriteAddress 0xD0    //器件写地址
  11. #define DS3231_ReadAddress  0xD1    //器件读地址

  12. #define DS3231_SECOND       0x00    //秒
  13. #define DS3231_MINUTE       0x01    //分
  14. #define DS3231_HOUR         0x02    //时
  15. #define DS3231_WEEK         0x03    //星期
  16. #define DS3231_DAY          0x04    //日
  17. #define DS3231_MONTH        0x05    //月
  18. #define DS3231_YEAR         0x06    //年
  19. //闹铃1           
  20. #define DS3231_SALARM1ECOND 0x07    //秒
  21. #define DS3231_ALARM1MINUTE 0x08    //分
  22. #define DS3231_ALARM1HOUR   0x09    //时
  23. #define DS3231_ALARM1WEEK   0x0A    //星期/日
  24. //闹铃2
  25. #define DS3231_ALARM2MINUTE 0x0b    //分
  26. #define DS3231_ALARM2HOUR   0x0c    //时
  27. #define DS3231_ALARM2WEEK   0x0d    //星期/日
  28. #define DS3231_CONTROL      0x0e    //控制寄存器
  29. #define DS3231_STATUS       0x0f    //状态寄存器
  30. #define BSY                 2       //忙
  31. #define OSF                 7       //振荡器停止标志
  32. #define DS3231_XTAL         0x10    //晶体老化寄存器
  33. #define DS3231_TEMPERATUREH 0x11    //温度寄存器高字节(8位)
  34. #define DS3231_TEMPERATUREL 0x12    //温度寄存器低字节(高2位)
  35. uchar  DS3231Time[9]={0x40,0x59,0x05,0x21,0x05,0x08,0x06,0x00,0x00}; //秒分时年月日周温度高字节温度低字节
  36. /*全局函数定义*/
  37. extern void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec,uchar wee);
  38. extern void  get_show_Temperature(void);
  39. extern void READ_Time();
  40. extern void DS3231_Init();                        
  41. extern uchar DS3231_Time[9];
  42. void delayus(uint us)
  43. {
  44.     while(us--);
  45. }
  46. uchar BCD2HEX(uchar val)    //BCD转换为Byte
  47. {
  48.     uchar temp;
  49.     temp=val&0x0f;                          
  50.     val>>=4;
  51.     val&=0x0f;
  52.     val*=10;
  53.     temp+=val;
  54.   
  55.     return temp;
  56. }


  57. uchar HEX2BCD(uchar val)    //B码转换为BCD码
  58. {
  59.     uchar i,j,k;
  60.     i=val/10;
  61.     j=val;
  62.     k=j+(i<<4);
  63.     return k;
  64. }
  65. void Start_I2C()
  66. {
  67.     SDA=1;                  //发送起始条件的数据信号
  68.     delayus(1);
  69.     SCL=1;
  70.     delayus(5);             //起始条件建立时间大于4.7us,延时
  71.   
  72.     SDA=0;                  //发送起始信号
  73.     delayus(5);             // 起始条件锁定时间大于4μs
  74.       
  75.     SCL=0;                  //钳住I2C总线,准备发送或接收数据
  76.     delayus(2);
  77. }


  78. void Stop_I2C()
  79. {
  80.     SDA=0;                  //发送结束条件的数据信号
  81.     delayus(1);             //发送结束条件的时钟信号
  82.     SCL=1;                  //结束条件建立时间大于4us
  83.     delayus(5);
  84.   
  85.     SDA=1;                  //发送I2C总线结束信号
  86.     delayus(4);
  87. }


  88. void SendByte(uchar c)
  89. {
  90.     uchar BitCnt;
  91.   
  92.     for(BitCnt=0;BitCnt<8;BitCnt++)         //要传送的数据长度为8位
  93.     {
  94.         if((c<<BitCnt)&0x80)
  95.             SDA=1;                          //判断发送位
  96.         else
  97.             SDA=0;              
  98.           delayus(1);
  99.           SCL=1;                            //置时钟线为高,通知被控器开始接收数据位
  100.           delayus(5);                       //保证时钟高电平周期大于4μs  
  101.           SCL=0;
  102.     }
  103.   
  104.     delayus(2);
  105.     SDA=1;                                  //8位发送完后释放数据线,准备接收应答位
  106.     delayus(2);
  107.     SCL=1;
  108.     delayus(3);
  109.     if(SDA==1)
  110.         ack=0;   
  111.     else
  112.         ack=1;                              //判断是否接收到应答信号
  113.     SCL=0;
  114.     delayus(2);
  115. }


  116. uchar RcvByte()
  117. {
  118.    uchar retc;
  119.    uchar BitCnt;

  120.    retc=0;
  121.    SDA=1;                           //置数据线为输入方式
  122.    for(BitCnt=0;BitCnt<8;BitCnt++)
  123.    {
  124.         delayus(1);
  125.         SCL=0;                      //置时钟线为低,准备接收数据位
  126.       
  127.         delayus(5);                 //时钟低电平周期大于4.7μs
  128.      
  129.         SCL=1;                      //置时钟线为高使数据线上数据有效
  130.         delayus(3);
  131.         retc=retc<<1;
  132.         if(SDA==1)
  133.             retc=retc+1;            //读数据位,接收的数据位放入retc中
  134.         delayus(2);
  135.    }
  136.    SCL=0;
  137.    delayus(2);
  138.    return(retc);
  139. }




  140. void Ack_I2C(bit a)
  141. {

  142.     if(a==0)
  143.         SDA=0;              //在此发出应答或非应答信号
  144.     else
  145.         SDA=1;
  146.     delayus(3);   
  147.     SCL=1;
  148.   
  149.     delayus(5);             //时钟低电平周期大于4μs
  150.   
  151.     SCL=0;                  //清时钟线,钳住I2C总线以便继续接收
  152.     delayus(2);  
  153. }




  154. uchar write_byte(uchar addr, uchar write_data)
  155. {
  156.     Start_I2C();
  157.     SendByte(DS3231_WriteAddress);
  158.     if (ack == 0)
  159.         return 0;
  160.   
  161.     SendByte(addr);  
  162.     if (ack == 0)
  163.         return 0;
  164.   
  165.     SendByte(write_data);
  166.     if (ack == 0)
  167.         return 0;
  168.   
  169.     Stop_I2C();
  170.     delayus(10);     
  171.     return 1;
  172. }




  173. uchar read_current()
  174. {
  175.     uchar read_data;
  176.     Start_I2C();
  177.     SendByte(DS3231_ReadAddress);
  178.     if(ack==0)
  179.         return(0);
  180.   
  181.     read_data = RcvByte();
  182.     Ack_I2C(1);
  183.     Stop_I2C();
  184.     return read_data;
  185. }




  186. uchar read_random(uchar random_addr)
  187. {
  188.     Start_I2C();
  189.     SendByte(DS3231_WriteAddress);
  190.     if(ack==0)
  191.         return(0);
  192.   
  193.     SendByte(random_addr);
  194.     if(ack==0)
  195.         return(0);
  196.   
  197.     return(read_current());
  198. }




  199. void ModifyTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec,uchar wee)
  200. {
  201.     uchar temp=0;
  202.   
  203.     //temp=HEX2BCD(yea);
  204.     write_byte(DS3231_YEAR,yea);   //修改年
  205.   
  206.     //temp=HEX2BCD(mon);
  207.     write_byte(DS3231_MONTH,mon);  //修改月
  208.   
  209.     //temp=HEX2BCD(da);
  210.     write_byte(DS3231_DAY,da);    //修改日
  211.          
  212.     //temp=HEX2BCD(hou);
  213.     write_byte(DS3231_HOUR,hou);   //修改时
  214.   
  215.     //temp=HEX2BCD(min);
  216.     write_byte(DS3231_MINUTE,min); //修改分
  217.          
  218.     //temp=HEX2BCD(sec);
  219.     write_byte(DS3231_SECOND,sec); //修改秒

  220.         write_byte(DS3231_WEEK,wee); //修改周
  221. }
  222. void  get_show_Temperature(void)
  223. {
  224.     uchar Ttemp1,Ttemp2;
  225.           write_byte(0x0e,0x20);
  226.     Ttemp1=read_random(DS3231_TEMPERATUREH);    //温度 高字节
  227.           DS3231Time[7]=Ttemp1;
  228.     Ttemp2=read_random(DS3231_TEMPERATUREL);    //温度低字节
  229.         Ttemp2=(Ttemp2>>6)*25;
  230.         DS3231Time[8]=Ttemp2;
  231. }
  232. void READ_Time()
  233. {
  234.    
  235.     DS3231Time[0]=read_random(DS3231_SECOND);
  236.         DS3231Time[1]=read_random(DS3231_MINUTE);
  237.         DS3231Time[2]=read_random(DS3231_HOUR);
  238.         DS3231Time[3]=read_random(DS3231_YEAR);
  239.         DS3231Time[4]=read_random(DS3231_MONTH);
  240.         DS3231Time[5]=read_random(DS3231_DAY);
  241.         DS3231Time[6]=read_random(DS3231_WEEK);
  242.         get_show_Temperature();
  243. }
  244. void DS3231_opennz1(uchar second,minute,hour,day)
  245. {
  246.     write_byte(0x0e,0x1d);  
  247.         write_byte(DS3231_SALARM1ECOND,second);//秒
  248.         write_byte(DS3231_ALARM1MINUTE,minute);//分
  249.         write_byte(DS3231_ALARM1HOUR,hour);//时
  250.         write_byte(DS3231_ALARM1WEEK,day);//星期/日
  251. }
  252. void DS3231_opennz2(minute,hour,day)
  253. {
  254.     write_byte(0x0e,0x1e);  
  255.         write_byte(DS3231_ALARM2MINUTE,minute);//分
  256.         write_byte(DS3231_ALARM2HOUR,hour);//时
  257.         write_byte(DS3231_ALARM2WEEK,day);//星期/日
  258. }
  259. void DS3231_Init()
  260. {
  261.     ModifyTime(DS3231Time[3],DS3231Time[4],DS3231Time[5],DS3231Time[2],DS3231Time[1],DS3231Time[0],DS3231Time[6]);
  262. }
复制代码
其中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;
        {        
            //闹钟提醒程序,你们想怎么搞就怎么搞
        }

希望能帮到你们!




评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:934353 发表于 2021-7-15 15:42 | 显示全部楼层
厉害了,值得参考
回复

使用道具 举报

ID:898540 发表于 2021-10-21 20:50 | 显示全部楼层
uchar  DS3231Time[9]={0x40,0x59,0x05,0x21,0x05,0x08,0x06,0x00,0x00}; //秒分时年月日周温度高字节温度低字节        请问这行的数据是什么意思,怎么数据手册没有看到?
回复

使用道具 举报

ID:898540 发表于 2021-11-12 23:03 | 显示全部楼层

uchar  DS3231Time[9]={0x40,0x59,0x05,0x21,0x05,0x08,0x06,0x00,0x00};   同问这个,什么意思?
回复

使用道具 举报

ID:884042 发表于 2022-7-25 01:05 | 显示全部楼层
combo111 发表于 2021-11-12 23:03
uchar  DS3231Time[9]={0x40,0x59,0x05,0x21,0x05,0x08,0x06,0x00,0x00};   同问这个,什么意思?

好久没上论坛,所以没看到,请谅解,这个是时钟数据,用一个数组,比如要读秒就调用:
i=DS3231Time[0];
这里用的是BCD码,所以还需解码,
second=(i/16*10)+(i&0x0f);
回复

使用道具 举报

ID:1093241 发表于 2023-10-5 19:35 | 显示全部楼层
如何能设置多个闹钟呢
回复

使用道具 举报

ID:1112603 发表于 2024-5-1 11:33 | 显示全部楼层
学习了,非常感谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表