8266+DS3231时钟之开发个时钟遇到的N个坑【一】

这个时钟系列目前五篇分别是:

《8266+DS3231时钟之开发个时钟遇到的N个坑【一】》
《8266+ds3231时钟之arduino官网发布的DS3231库的分析【二】》
《8266+DS3231时钟之DS3231具体实现及代码【三】》
《8266+DS3231时钟之显示TM1638的使用【四】上》
《8266+DS3231时钟之显示TM1638的使用【四】下》
《8266+DS3231时钟之语音MP3-TF-16P模块使用【五】》
有兴趣的可以去看看,如果觉得对你有帮助,请点个赞。

最近玩这个8266上瘾了,正好手上有一块DS3231,就想着做一个互联网时钟玩玩,哪知道本以为很简单的一个东西却做了我一周的时间,踩平了N个坑。既然掉坑里了又爬了出来就会有所收获,赶快过来记录一下,备忘备忘。
第一个坑,关于I2C引脚的问题。
我用的是nodeMCU 8266-E 的开发板,所查了一下乐鑫原厂的技术资料,资料上清楚的写着如下:
在这里插入图片描述
我也没多想,就把DS3231的SCL和SDA直接接上了IO4 和IO2。结果就是死活读不到数据。后来抱着试试的心态想着程序没错的话应该就是硬件的问题,上度娘上查了前人的文章,发现有两个博主连接的是GPIO5 和GPIO4 ,于是抱着试试的态度果断打出如下代码。
#define SCL 5 //d1 I2C-SCL
#define SDA 4 //d2 I2C-SDA
结果一运行,立刻搞定。。。就这么一个低级坑,就坑了我一天时间。要不是自已有怀疑精神,这个坑估计能把我埋了。

第二个坑更深了,但现在看来简单一句话就是DS3231在启动后,至少20秒内不能用setYear(),setHour()等这些个设置语句。
这里补充一下,我用的是arduino 的IDE环境。因此自然使用的是arduino提供的官方下载的DS3231驱动。https://www.arduino.cc/reference/en/libraries/ds3231/
我的时钟原本就是在联上网后会有一个自动对时功能,从NTP上取下网络时间,然后设置给DS3231,就为了这个功能,恶梦开始了,程序一运行,怎么都无法读出准确的时间,反而读出一堆乱码。我又开始了自查程序。查了N遍怎么都不可能错了,然后开始分析官方提供的驱动,发现也没有问题。然后很偶然的把一开机就设置时间的功能去掉,发现一切正常上了。经过反复比较,反复查看DS3231的技术资料,都没有对这一情况进行说明。这里权猜测是因为DS3231在开机上电的一段时间里寄存器初始化等作业不允许用设置指定吧。但可以用读取指令。

第三个坑最深。。为了解决这个坑,上网各种搜查都没能找到好的办法,最后还是根据驱动程序源码并合理猜测才得以解决。这个坑是关于闹钟设置并输出中断的功能的。功能就是通过APP设置闹钟写入DS3231里,时间到后,必须从INT/SQW这个端口输出中断信号给8266,8266再去处理这个中断。但是我遇到几个问题。一是每次一设完闹钟参数,3231就直接输出了一个低电平,也就是说设完闹钟中断就启动了,不管时间到没到。二是我对8266读中断的模式设为LOW也就是低电平触发,但这里死活都没办法触发。。。这两个问题中的第一个必须涉及到寄存器的解释,
在这里插入图片描述
另一个是状态寄存器
在这里插入图片描述
详细的内容网上有大把的资料,需要的话可以去查,这里只讲和这个坑有关的内容。
根据上面的两个寄存器解释。要想让低电平有效的中断在闹钟启动后触发,必须完成这几个寄存器置位。
1 控制寄存器的INTCN置1
2 控制寄存器的A1IE和A2IE置1
3 闹钟时间到时对状态寄存器的A1F或A2F的置位
这样就能使中断触发。
可是我设置了1,2两部后,才用setA1Time()命令后,INT-SQW就一直处于低电平,也就是闹钟时间没到,中断就有效了。这让我很无语,又是一通各种查,把驱动源码又看了N遍。最好才明白了,3231会自已偷偷的置位A1F或A2F。也就是说,3231不会自已清除A1F或A2F的标志,必须手工去清除。搞清楚这点后,一切就简单 了。如下:

//时钟初始化   同步闹钟
   //enableOscillator(bool TF, bool battery, byte frequency)
   //当第一位TF为true 控制寄存器的 ~EOSC to 0  and INTCN to 0.,
   //EOSC置0则启动振荡器INTCN置0(第二位battery为true VCC<VPF时会输出1HZ方波)
   RTC.enableOscillator(true,false,0);
   RTC.checkIfAlarm(1);  //该函数检测完后状态寄存器A1F或A2F就把标志位清0
   RTC.checkIfAlarm(2);
   

   ReadData(EEPROMBase1,Alarm1);
   ReadData(EEPROMBase2,Alarm2);
      
   if (Alarm1.flag==1){
      RTC.setA1Time(Alarm1.ADay,Alarm1.AHour,Alarm1.AMinute,Alarm1.ASecond,Alarm1.AlarmBits1,Alarm1.ADy,Alarm1.AH12,Alarm1.APM);
      //把控制寄存器的INTCN位和A1IE位置1,使能闹钟一的中断。一旦状态寄存器的A1F因为闹钟时间到而置1则在INTCN输出中断
      RTC.turnOnAlarm(1); 
      if (RTC.checkAlarmEnabled(1)){   
        Serial.println("闹钟1启动,定时为每日的:"+String(Alarm1.AHour)+":"+String(Alarm1.AMinute));  
         DebugeTime(1,Temp); 
      };  
   }else {
    RTC.turnOffAlarm(1);
    
   }
   
   if (Alarm2.flag==1){
      RTC.setA2Time(Alarm2.ADay,Alarm2.AHour,Alarm2.AMinute,Alarm2.AlarmBits2,Alarm2.ADy,Alarm2.AH12,Alarm2.APM);
      //把控制寄存器的INTCN位和A2IE位置1,使能闹钟一的中断。一旦状态寄存器的A2F因为闹钟时间到而置1则在INTCN输出中断
      RTC.turnOnAlarm(2);
      if (RTC.checkAlarmEnabled(2)){   
        Serial.println("闹钟2启动,定时为每日的:"+String(Alarm1.AHour)+":"+String(Alarm1.AMinute));   
        DebugeTime(2,Temp); 
      };  
   }else{
    RTC.turnOffAlarm(2);
     
   }

上面的关键就是那几个RTC对象相关的方法的执行顺序。
第二个问题就是关于8266中断触发的问题。由于用的是arduino IDE环境 所以经常会把arduino的语句与8266混用,尽管大多是一样的,但还是有区别。比如,中断的触发。arduino可以用(LOW, HIGH ,FALLING,CHANGE,RISING).而8266就只有三种(FALLING,CHANGE,RISING)。
先写到这里,详细的驱动程序 的分析明天再写。

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑牛唱剧本

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值