Driving Part – DS1302
1
Introduction to RTC
Real Time Clock, abbreviated as RTC, is also available in the STM32 peripherals, but the RTC of the STM32F1 series actually only has a counter function. If you need year, month, and day, you have to write software to calculate it yourself, which is quite troublesome. At this time, you can use an RTC chip with year, month, and day, commonly used is DS1302, which can calculate leap years by itself. For specific information, you can check here.
https://item.szlcsc.com/3148832.html

2
Introduction to DS1302
Mainly looking at the communication method and registers of DS1302. Its communication method is somewhat similar to IIC, also with a clock line + data line, but it also has a reset (chip select) line, and the timing is also different, with not as many signals as IIC. The registers are shown in the figure below:


The year is from 00 to 99, which corresponds to the years 2000 to 2099, and the data format is BCD code.
Let’s start with the header file:

Mainly defines the time structure, pin structure, and IO related functions. The addresses of the registers are defined according to the manual.
3
Initialization
First, initialize the clock, data, and reset three pins, where the data pin sometimes needs to be used as input. The specific code is as follows:
/* ================================================================================Description : Hardware initializationInput : Output : ================================================================================*/void drv_ds1302_init(GPIO_TypeDef* port_clk, uint32_t pin_clk, GPIO_TypeDef* port_io, uint32_t pin_io, GPIO_TypeDef* port_rst, uint32_t pin_rst, Ds1302RtcStruct *rtc_initpara){ g_sDs1302Drv.port_clk=port_clk; g_sDs1302Drv.pin_clk=pin_clk; g_sDs1302Drv.port_io=port_io; g_sDs1302Drv.pin_io=pin_io; g_sDs1302Drv.port_rst=port_rst; g_sDs1302Drv.pin_rst=pin_rst; GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = pin_clk; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(port_clk, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = pin_io; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(port_io, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = pin_rst; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(port_rst, &GPIO_InitStruct); DS1302_RST_0; DS1302_CLK_0; delay_us(5); drv_ds1302_set_wp(false); drv_ds1302_write(0x90, 0xA7);//Charge register drv_ds1302_set_wp(true); drv_ds1302_set_hour_format(true);//24-hour format if(drv_ds1302_read(0x81)&0x80)//Check if DS1302 clock is running, if the clock has stopped: start the clock + initialize the clock { printf("DS1302 stop!\n"); drv_ds1302_set_time(rtc_initpara); drv_ds1302_start(); } } /* ================================================================================Description : Data pin read/write conversionInput : Output : ================================================================================*/void drv_ds1302_set_io_mode(bool is_out){ if(is_out) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = g_sDs1302Drv.pin_io; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(g_sDs1302Drv.port_io, &GPIO_InitStruct); } else { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = g_sDs1302Drv.pin_io; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(g_sDs1302Drv.port_io, &GPIO_InitStruct); }}
If the clock has not lost power, there is no need to start it again.
4
Byte Read/Write
The following is the most basic byte read and write function, the timing should refer to the manual.
/* ================================================================================Description : Write byteInput : Output : ================================================================================*/void drv_ds1302_write(u8 reg_addr, u8 reg_data){ DS1302_RST_0; DS1302_CLK_0; delay_us(2); DS1302_RST_1; delay_us(5); for(u8 i=0; i<8; i++) { if(reg_addr&0x01)DS1302_IO_1; else DS1302_IO_0; DS1302_CLK_1; delay_us(5); DS1302_CLK_0; reg_addr=reg_addr>>1; } for(u8 i=0; i<8; i++) { if(reg_data&0x01)DS1302_IO_1; else DS1302_IO_0; DS1302_CLK_1; delay_us(5); DS1302_CLK_0; reg_data=reg_data>>1; } DS1302_RST_0; delay_us(5);} /* ================================================================================Description : Read byteInput : Output : ================================================================================*/u8 drv_ds1302_read(u8 reg_addr){ DS1302_RST_1; delay_us(5); for(u8 i=0; i<8; i++) { if(reg_addr&0x01)DS1302_IO_1; else DS1302_IO_0; DS1302_CLK_1; delay_us(5); DS1302_CLK_0; reg_addr=reg_addr>>1; } drv_ds1302_set_io_mode(0); u8 value=0; for(u8 i=0; i<8; i++) { value=value>>1; if(DS1302_IO_READ()>0)value|=0x80; DS1302_CLK_1; delay_us(5); DS1302_CLK_0; } drv_ds1302_set_io_mode(1); DS1302_RST_0; delay_us(5); return value; }
Every time you read and write, the reset pin must be pulled high to proceed, and the data is transmitted in low order first.
5
Function Functions
With the basic read and write functions, you can set functions based on the register addresses. For example, the following is to start and stop:

/* ================================================================================Description : StopInput : Output : ================================================================================*/void drv_ds1302_stop(void){ drv_ds1302_set_wp(false); u8 ret=drv_ds1302_read(0x81); ret=ret|0x80; drv_ds1302_write(0x80,ret); drv_ds1302_set_wp(true);} /* ================================================================================Description : StartInput : Output : ================================================================================*/void drv_ds1302_start(void){ drv_ds1302_set_wp(false); u8 ret=drv_ds1302_read(0x81); ret=ret&0x7F; drv_ds1302_write(0x80,ret); drv_ds1302_set_wp(true);}
Time setting:
/* ================================================================================Description : Time settingInput : Output : ================================================================================*/void drv_ds1302_set_time(Ds1302RtcStruct *rtc_initpara){ if(rtc_initpara==NULL) return; printf("drv_ds1302_set_time=20%02x-%02x-%02x %02x:%02x:%02x\n", rtc_initpara->rtc_year, rtc_initpara->rtc_month, rtc_initpara->rtc_date, rtc_initpara->rtc_hour, rtc_initpara->rtc_minute, rtc_initpara->rtc_second ); drv_ds1302_set_wp(false); drv_ds1302_write(DS1302_SEC_ADDR,rtc_initpara->rtc_second); drv_ds1302_write(DS1302_MIN_ADDR,rtc_initpara->rtc_minute); drv_ds1302_write(DS1302_HOUR_ADDR,rtc_initpara->rtc_hour); drv_ds1302_write(DS1302_DATE_ADDR,rtc_initpara->rtc_date); drv_ds1302_write(DS1302_MONTH_ADDR,rtc_initpara->rtc_month); drv_ds1302_write(DS1302_YEAR_ADDR,rtc_initpara->rtc_year); drv_ds1302_set_wp(true);}
Time reading:
/* ================================================================================Description : Time readingInput : Output : ================================================================================*/void drv_ds1302_get_time(Ds1302RtcStruct *rtc_initpara){ if(rtc_initpara==NULL) return; rtc_initpara->rtc_second=drv_ds1302_read(0x81); rtc_initpara->rtc_minute=drv_ds1302_read(0x83); rtc_initpara->rtc_hour=drv_ds1302_read(0x85); rtc_initpara->rtc_date=drv_ds1302_read(0x87); rtc_initpara->rtc_month=drv_ds1302_read(0x89); rtc_initpara->rtc_year=drv_ds1302_read(0x8D);// printf("drv_ds1302_get_time=20%02x-%02x-%02x %02x:%02x:%02x\n", rtc_initpara->rtc_year, rtc_initpara->rtc_month, rtc_initpara->rtc_date,// rtc_initpara->rtc_hour, rtc_initpara->rtc_minute, rtc_initpara->rtc_second ); }
All setting classes must unlock the write protection before performing corresponding operations.
Overall, using DS1302 is not complicated. As long as the timing is clear and the registers are set correctly, there should be no problem.
Code link:https://download.csdn.net/download/ypp240124016/89117651
For the code project, please click the end of the articleRead the original text to obtain.
The navigation address for the blogger’s series of articles is as follows:
https://blog.csdn.net/ypp240124016/article/details/143068017
QQ group: 701889554

WeChat ID
WalleFarm
Public Account
Endpoint IoT