8266+DS3231開發個時鐘遇到的N個坑
最近玩這個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)。
先寫到這裡,詳細的驅動程式 的分析明天再寫。
相關文章
- linux安裝nginx時遇到的一個坑LinuxNginx
- 初學 GoLang 遇到的一個關於時間的坑...Golang
- API 開發中可選擇傳遞 token 介面遇到的一個坑API
- 一個android 的HAL示例中遇到的坑。Android
- 開發以太坊遇到的幾個問題
- 記錄從0開發一個vue的富文字外掛過程以及遇到的坑Vue
- 使用constexpr時遇到的小坑
- 微信小程式開發遇到的那些坑微信小程式
- 記錄我開發工作中遇到HTTP跨域和OPTION請求的一個坑HTTP跨域
- 一個圓形時鐘
- 刪除外部表時遇到的坑
- 使用MySQL時遇到的各種坑MySql
- 嵌入式軟硬體開發中遇到的坑
- 一分鐘開發一個表單
- 總結:使用MyBatis Generator時遇到的坑MyBatis
- 使用Golang時遇到的一些坑Golang
- 遷移Report Server DataBase時遇到的坑ServerDatabase
- 皮膚開發過程中遇到的3個問題
- CSS 繪製一個時鐘CSS
- 學習openresty時,nginx的一個坑RESTNginx
- Springboot 開發過程中遇到坑點 (一)Spring Boot
- 微信H5頁面前端開發,大多數人都會遇到的幾個相容性坑H5前端
- 物聯網初創企業會遇到的四個坑兒
- SpringBoot 專案中配置多個 Jackson 的 ObjectMapper ,以及配置遇到的坑Spring BootObjectAPP
- 南京求個測開的坑位
- [微信小程式]開發中遇到的一些“坑”微信小程式
- 微信小程式開發中遇到的幾個小問題微信小程式
- 微信小程式開發需要注意的29個坑微信小程式
- 遇到一個建表時出現的問題
- Nginx 轉發時的一個坑,運維居然讓我背鍋!!Nginx運維
- 記錄內網Docker啟動Stable-Diffusion遇到的幾個坑內網Docker
- Bootstrap 檔案中使用 $_SERVER ['REQUEST_URI'] 遇到的一個小坑bootServer
- Go 1.13版本引入的bug,你遇到過這個坑麼?Go
- 【eclipse遇到的坑】Eclipse
- NSString 遇到的坑
- mpvue遇到的坑Vue
- 目前下載VS2017你可能會遇到這個坑
- wepy+weappx開發小程式遇到的坑以及解決方案APP