This article describes programming to use the DS1302 (Figure 1), another RTC (Real-Time Clock) IC (previously written to PCF8583 in Python and Arduino C++). And it is a module that is popular for beginners because it is a module in the learning kit of Arduino, IoT, 37-Sensors or 45 Sensors, etc.
DS1302
The features of the DS1302 are as follows.
- Store seconds, minutes, hours, day of month, month, day of week, year.
- Year values are valid starting until 2100.
- It has 31 bytes of 8-bit RAM memory (RAM) backed up by battery.
- Operates at 2.0VDC to 5.5VDC
- Use current less than 300nA when using 2VDC voltage.
- Work in temperature -40°C to 85°C
The arrangement of the pins of the IC chassis is as shown in Figure 2, it is found that there are a total of 8 pins, namely Vcc1, Vcc2, X1, X2, GND, CE, SCLK and I/O. Pin X1, X2 are the pins connected to crystal, and the pins for connecting to the microcontroller are Vcc, GND, SCLK, CE (for reset) and I/O as shown in Figure 3.
The address of the internal memory DS1302 is shown in Figure 4.
The format of the instruction sent to the RTC is 8 bits, with each bit meaning as shown in Figure 5.
From Figure 5, it can be seen that the different bits have the following meanings:
- RAM or CK/
- A0-A4, address value to be accessed
- RD , WR/
The format of data transmission in communication between the microcontroller and DS1302 is shown in Figure 6.
The time-diagram of writing and reading data of the DS1302 is shown in Figures 7 and 8, respectively.
From the picture of the format of transmitting and receiving data, it is noted that before sending bits, the SCLK state must be changed from 0 to 1, and when it is sent, it must be changed from 1 to 0 and alternated until all data is transmitted.
- Change the status of the CE pin from 0 to 1.
- Send the R/W’ bit to indicate the transmission flag.
- Send bits A0, A1, A2, A3 and A4 to indicate the address.
- Send R/C’ bit.
- End with bit 1.
- Send 8-bit data in order of D0, D1, D2, …, D7.
- Change the status of the CE pin from 1 to 0.
Example Code
Example code for setting and displaying time by connecting between ESP32 and Module DS1302 as shown in Figure 9.
################################################
# demo_ds1302.py
# (C) 2021, JarutEx (https://www.jarutex.com
################################################
from machine import Pin
import time
# setting
class DS1302:
REG_SECOND = const(0x80)
REG_MINUTE = const(0x82)
REG_HOUR = const(0x84)
REG_DAY = const(0x86)
REG_MONTH = const(0x88)
REG_WEEKDAY= const(0x8A)
REG_YEAR = const(0x8C)
REG_WP = const(0x8E)
REG_CTRL = const(0x90)
REG_RAM = const(0xC0)
def __init__(self, _sclk=12, _io=13, _ce=14):
self.pinClk = Pin( _sclk, Pin.OUT )
self.pinIO = Pin( _io )
self.pinCE = Pin( _ce, Pin.OUT )
self.pinCE.value(0) # disable
self.pinClk.value(0)
self.rtc = [0,0,0,0,0,0,0] # y/m/d/dw/h/mi/s
def dec2bcd(self, n):
return ((n // 10 * 16) + (n % 10))
def bcd2dec(self, n):
return ((n // 16 * 10) + (n % 16))
def write(self, data):
self.pinIO.init(Pin.OUT)
for i in range(8):
bit = (data & 0x01)
data = (data >> 1)
self.pinIO.value(bit)
self.pinClk.value(1)
self.pinClk.value(0)
def read(self):
self.pinIO.init( Pin.IN )
byte = 0
for i in range(8):
bit = self.pinIO.value() & 0x01
bit = (bit << i)
byte = (byte | bit)
self.pinClk.value(1)
self.pinClk.value(0)
return byte
def set(self, reg, data):
self.pinCE.value(1)
self.write( reg )
self.write( data )
self.pinCE.value(0)
def get(self, reg):
self.pinCE.value(1)
self.write( reg+1 )
data = self.read()
self.pinCE.value(0)
return data
def now(self):
self.rtc[0] = self.bcd2dec(self.get(REG_YEAR))+2000
self.rtc[1] = self.bcd2dec(self.get(REG_MONTH))
self.rtc[2] = self.bcd2dec(self.get(REG_DAY))
self.rtc[3] = self.bcd2dec(self.get(REG_WEEKDAY))
self.rtc[4] = self.bcd2dec(self.get(REG_HOUR))
self.rtc[5] = self.bcd2dec(self.get(REG_MINUTE))
self.rtc[6] = self.bcd2dec(self.get(REG_SECOND))
def adjust(self, day, month, year, dow, hour, minute, second ):
# convert
year = year - 2000
year = self.dec2bcd(year)
month = self.dec2bcd(month)
day = self.dec2bcd(day)
dow = self.dec2bcd(dow)
minute = self.dec2bcd(minute)
hour = hour & 0x1F
hour = self.dec2bcd(hour)
second = self.dec2bcd(second)
# adjust
self.set(REG_YEAR, year)
self.set(REG_MONTH, month)
self.set(REG_DAY, day)
self.set(REG_WEEKDAY, dow)
self.set(REG_HOUR, hour)
self.set(REG_MINUTE, minute)
self.set(REG_SECOND, second)
def show(self):
print("{} {}-{}-{} {}:{}:{}".format(
self.rtc[3],
self.rtc[0], self.rtc[1], self.rtc[2],
self.rtc[4], self.rtc[5], self.rtc[6]
))
# main program
rtc = DS1302()
rtc.adjust(7,7,2021, 3, 17,57,00)
while True:
rtc.now()
rtc.show()
time.sleep_ms(1000)
The result is as shown in Figure 10.
Conclusion
From this article, you will find that Python programming has the same hardware accessibility as pure C++, but the execution speed may vary. However, the ease of reading and porting code to the other systems makes this language interesting. Finally, we hope that this article will be more or less useful. And have fun with programming.
If you want to talk with us, feel free to leave comments below!!
Reference
(C) 2020-2021, By Jarut Busarathid and Danai Jedsadathitikul
Updated 2021-10-19