树莓派54/100 - Pico连接DS1307时钟模块,做个实时数字钟
我一開始以為樹莓派Pico沒有時鐘模塊,但查了相關(guān)資料,Pico仍有基本的RTC支持,只不過它在掉電的時候,無法再維護(hù)精確的時間。
這里的RTC,是實(shí)時時鐘(Real Time Clock)的縮寫,MicroPython里也提供了RTC標(biāo)準(zhǔn)類的支持,用datetime()函數(shù)可以獲取8元組的時間數(shù)據(jù)。
import machine rtc_pico = machine.RTC() print(rtc_pico.datetime())8元組是指(year, month, day, weekday, hours, minutes, seconds, subseconds),其中weekday表示星期幾,從0到6,值得注意的是0表示星期一,6表示星期日,符合ISO8601國際標(biāo)準(zhǔn)定義。
subseconds與硬件相關(guān),Pico不支持這個數(shù)據(jù)。
給datetime()函數(shù)傳遞8元組的參數(shù),可以設(shè)置Pico的時間。下面的代碼把時間設(shè)置為雙十一的零點(diǎn)(周四),注意必須是兩層括號。
rtc_pico.datetime((2021, 11, 11, 3, 0, 0, 0, 0))我的Pico連接Windows的USB,用Thonny調(diào)試程序,datetime會自動與電腦的時間同步,我現(xiàn)在還不清楚這是Thonny的功能,還是MicroPython的功能。
Pico如果不連網(wǎng),得到的時間不是很準(zhǔn)確,只能用于相對時間參考。如果想獲得更加準(zhǔn)確的時間,則要外購實(shí)時時鐘模塊,我在網(wǎng)上搜索時鐘模塊,常見的有三種型號:DS1302、DS1307和DS3231。
DS3231好像更加精確,但價格貴不少,我就鎖定在前2種型號了。
DS1302和DS1307的精度差不多,區(qū)別主要在于通訊接口上,DS1302總共要5根線,而DS1307可以用標(biāo)準(zhǔn)的I2C協(xié)議,只需要連4根線,為了編程方便還省一根線,還可以離線保存56個字節(jié)的信息(你沒看錯,只有56個字節(jié)),我就下單買了DS1307,某多平臺到手價3.8元,還包郵。DS1307模塊到貨后,它的模樣是這樣的。
商家一般不焊接排針,需要自己動手,這個模塊在一側(cè)有5根針,另一側(cè)有7根針,我只用I2C編程,就只焊了5根針,足夠用了。第一次用烙鐵,焊錫非常不均勻,但也成功了。
5根針只用到4根,分別是VCC、GND、SDA和SCL。
1)GND不用多說了,接地
2)VCC,模塊的用戶手冊說要接5V電壓,我接3.3V也能正常工作
3)SDA/SCL接GP16/GP17
在接5V還是3.3V的時候,還糾結(jié)了好一陣子。網(wǎng)上有人說接5V電壓后,SDA/SCL出來的信號也是5V,而Pico工作電壓為3.3V,可能會損壞Pico板子。但也有人說,DS1307這個模塊上已經(jīng)接好了上拉電阻,放心接SDA/SCL就行。
我就先接3.3V試試,數(shù)據(jù)獲取穩(wěn)定,后來改接5V電壓也正常,實(shí)際連接圖。
DS1307的通訊協(xié)議,可以暫時不用了解,別人已經(jīng)寫好類庫了,只有70行,直接拿來用即可,請把文件名保存為 ds1307.py 。
from micropython import constDATETIME_REG = const(0) # 0x00-0x06 CHIP_HALT = const(128) CONTROL_REG = const(7) # 0x07 RAM_REG = const(8) # 0x08-0x3Fclass DS1307(object):"""Driver for the DS1307 RTC."""def __init__(self, i2c, addr=0x68):self.i2c = i2cself.addr = addrself.weekday_start = 1self._halt = Falsedef _dec2bcd(self, value):"""Convert decimal to binary coded decimal (BCD) format"""return (value // 10) << 4 | (value % 10)def _bcd2dec(self, value):"""Convert binary coded decimal (BCD) format to decimal"""return ((value >> 4) * 10) + (value & 0x0F)def datetime(self, datetime=None):"""Get or set datetime"""if datetime is None:buf = self.i2c.readfrom_mem(self.addr, DATETIME_REG, 7)return (self._bcd2dec(buf[6]) + 2000, # yearself._bcd2dec(buf[5]), # monthself._bcd2dec(buf[4]), # dayself._bcd2dec(buf[3] - self.weekday_start), # weekdayself._bcd2dec(buf[2]), # hourself._bcd2dec(buf[1]), # minuteself._bcd2dec(buf[0] & 0x7F), # second0 # subseconds)buf = bytearray(7)buf[0] = self._dec2bcd(datetime[6]) & 0x7F # second, msb = CH, 1=halt, 0=gobuf[1] = self._dec2bcd(datetime[5]) # minutebuf[2] = self._dec2bcd(datetime[4]) # hourbuf[3] = self._dec2bcd(datetime[3] + self.weekday_start) # weekdaybuf[4] = self._dec2bcd(datetime[2]) # daybuf[5] = self._dec2bcd(datetime[1]) # monthbuf[6] = self._dec2bcd(datetime[0] - 2000) # yearif (self._halt):buf[0] |= (1 << 7)self.i2c.writeto_mem(self.addr, DATETIME_REG, buf)def halt(self, val=None):"""Power up, power down or check status"""if val is None:return self._haltreg = self.i2c.readfrom_mem(self.addr, DATETIME_REG, 1)[0]if val:reg |= CHIP_HALTelse:reg &= ~CHIP_HALTself._halt = bool(val)self.i2c.writeto_mem(self.addr, DATETIME_REG, bytearray([reg]))def square_wave(self, sqw=0, out=0):"""Output square wave on pin SQ at 1Hz, 4.096kHz, 8.192kHz or 32.768kHz,or disable the oscillator and output logic level high/low."""rs0 = 1 if sqw == 4 or sqw == 32 else 0rs1 = 1 if sqw == 8 or sqw == 32 else 0out = 1 if out > 0 else 0sqw = 1 if sqw > 0 else 0reg = rs0 | rs1 << 1 | sqw << 4 | out << 7self.i2c.writeto_mem(self.addr, CONTROL_REG, bytearray([reg]))開始寫主程序了:
import machine import ds1307rtc_pico = machine.RTC() #rtc_pico.datetime((2021, 11, 11, 3, 0, 0, 0, 0)) print("系統(tǒng)時間:", rtc_pico.datetime())i2c = machine.I2C(0, sda = machine.Pin(16), scl = machine.Pin(17), freq = 100000) print("ds1307 I2C 地址:", machine.I2C.scan(i2c)) rtc_ds1307 = ds1307.DS1307(i2c) print("DS1307時間:", rtc_ds1307.datetime())DS1307的I2C掃描地址有2個: [80, 104],一開始比較納悶,一個芯片應(yīng)該就只有一個地址的。后來才知道,DS1307模塊上一般會集成AT24C32N EEPROM,它的地址是80,而DS1307芯片的地址是104。
剛拿到的DS1307可能時間不正確,需要自己設(shè)定一下,用下面的函數(shù)。
def update_time():str_time = input("請輸入【年 月 日 星期 時 分 秒】:")if str_time == '': return givenTime = tuple(map(int, tuple(str_time.split(' '))))print(givenTime)rtc_ds1307.datetime(givenTime)比如,你輸入“2021 11 27 5 19 18 10”,一共7個數(shù),中間用空格隔開,update_time()函數(shù)一般只調(diào)用一次,設(shè)置好時間后,一般就不用管了,它自身帶的CR2032紐扣電池用于給它持續(xù)供電,聲稱10年不用換電池。
最后我們再來看看DS1307的關(guān)鍵特性:
DS1307 是美國DALLAS公司推出的I2C總線接口實(shí)時時鐘芯片,它可獨(dú)立于CPU工作,不受CPU主晶振及其電容的影響,且計時準(zhǔn)確,月累積誤差一般小于10秒。芯片還具有主電源掉電情況下的時鐘保護(hù)電路,DS1307的時鐘靠后備電池維持工作,拒絕CPU對其讀出和寫入訪問。同時還具有備用電源自動切換控制電路,因而可在主電源掉電和其它一些惡劣環(huán)境場合中保證系統(tǒng)時鐘的定時準(zhǔn)確性。具有產(chǎn)生秒、分、時、日、月、年等功能,且具有閏年自動調(diào)整功能。同時,DS1307 芯片內(nèi)部還集成有56字節(jié)掉電保存的靜態(tài)RAM,可用于保存一些關(guān)鍵數(shù)據(jù)。
DS1307是一款低功耗,具有56字節(jié)非失性RAM的全BCD碼時鐘日歷實(shí)時時鐘芯片,地址和數(shù)據(jù)通過兩線雙向的串行總線的傳輸,芯片可以提供秒,分,小時等信息,每一個月的天數(shù)能自動調(diào)整。并且有閏年補(bǔ)償功能。AM/PM 標(biāo)志位決定時鐘工作于24小時或12小時模式,芯片有一個內(nèi)置的電源感應(yīng)電路,具有掉電檢測和電池切換功能。
官方Datasheet上的描述是:
- Real time clock counts seconds, minutes, hours, date of the month, month, day of the week, and year with leap year compensation valid up to 2100
- 56 byte nonvolatile RAM for data storage
- 2-wire serial interface
- Programmable squarewave output signal
- Automatic power-fail detect and switch circuitry
- Consumes less than 500 nA in battery backup mode with oscillator running
- Optional industrial temperature range -40°C to +85°C
- Available in 8-pin DIP or SOIC
- Recognized by Underwriters Laboratory
現(xiàn)在拿出我的LCD1602,可以做一個實(shí)時時鐘,SDA/SCL接GP2/GP3,實(shí)際連線圖。
每秒在LCD上刷新日期、時間即可。
另外,我在研究56個字節(jié)的信息時,發(fā)現(xiàn)DS1307模塊里還帶著AT24C32N EEPROM這個小芯片,可以離線保存32K(是32768個二進(jìn)制位,4096字節(jié))的數(shù)據(jù),下一篇再研究它。
參考文章:
https://www.iotstarters.com/diy-digital-clock-with-rtc-ds1307-and-raspberry-pi-pico/
https://en.wikipedia.org/wiki/ISO_8601
https://docs.micropython.org/en/latest/library/machine.RTC.html#machine-rtc
https://github.com/mcauser/micropython-tinyrtc-i2c
推薦閱讀:
樹莓派Pico開發(fā)系列文章
總結(jié)
以上是生活随笔為你收集整理的树莓派54/100 - Pico连接DS1307时钟模块,做个实时数字钟的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模拟电路中晶体管阵列的性能感知公共质心布
- 下一篇: oracle 数据更新