使用软件:IAR FOR STM8

编程方式:固件库

硬件配套:STM8S105C6T6实验板

1. DS1302.h

  • 引脚定义
  • 函数封装
  • 时间数据结构体定义
  • 数据缓冲区定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#ifndef __DS1302_H
#define __DS1302_H

/****************************驱动 RTC 芯片 DS1302******************************/

/* Includes ------------------------------------------------------------------*/

#include "stm8s.h"

/* Defines -------------------------------------------------------------------*/

#define RTC_RESET_TIME_EN 0u

#define RTC_SCK_PORT (GPIOD)
#define RTC_SCK_PIN (GPIO_PIN_2) // PD2
#define RTC_SCK_HIGH() GPIO_WriteHigh(RTC_SCK_PORT, RTC_SCK_PIN)
#define RTC_SCK_LOW() GPIO_WriteLow (RTC_SCK_PORT, RTC_SCK_PIN)

#define RTC_IO_PORT (GPIOD)
#define RTC_IO_PIN (GPIO_PIN_3) // PD3

#define RTC_IO_IN() GPIO_Init(RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_IN_PU_NO_IT)
#define RTC_IO_STATUS() GPIO_ReadInputPin(RTC_IO_PORT, RTC_IO_PIN)

#define RTC_IO_OUT() GPIO_Init(RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define RTC_IO_HIGH() GPIO_WriteHigh(RTC_IO_PORT, RTC_IO_PIN)
#define RTC_IO_LOW() GPIO_WriteLow (RTC_IO_PORT, RTC_IO_PIN)

#define RTC_RST_PORT (GPIOD)
#define RTC_RST_PIN (GPIO_PIN_7) // PD7
#define RTC_RST_HIGH() GPIO_WriteHigh(RTC_RST_PORT, RTC_RST_PIN)
#define RTC_RST_LOW() GPIO_WriteLow (RTC_RST_PORT, RTC_RST_PIN)

/* Values --------------------------------------------------------------------*/

typedef struct Time
{
uint8_t year; // year 0-99
uint8_t month; // month 01-12
uint8_t day; // day 01-28,29,30,31
uint8_t week; // week 01-07
uint8_t hour; // hour 01-12 or 00-23
uint8_t minute; // minute 00-59
uint8_t second; // second 00-59
}TimeTypeDef;

static TimeTypeDef TimeBuffer; // 数据缓冲区(8421-BCD码)

/* Functions -----------------------------------------------------------------*/

void DS1302_Init (void);

static void DS1302_WriteByte (uint8_t byte);
static uint8_t DS1302_ReadByte (void);
static void DS1302_WriteData (uint8_t addr, uint8_t data);
static uint8_t DS1302_ReadData (uint8_t addr);

TimeTypeDef DS1302_ReadTime (void);
void DS1302_WriteTime (TimeTypeDef *TimeDisplay);

static uint8_t DectoBCD (uint8_t num);
static uint8_t BCDtoDec (uint8_t num);

static void DS1302_DLY_ms(uint16_t nCount);
static void DS1302_DLY_us(uint16_t nCount);

#endif /* __DS1302_H */

2. DS1302.c

  • 引脚初始化
  • 数据传输协议实现
  • BCD 码和十进制数互相转换
  • 数据处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
#include "ds1302.h"

/*************************************************************************
初始化
--------------------------------------------------------------------------
无参数
--------------------------------------------------------------------------
无返回值
*************************************************************************/
void DS1302_Init (void)
{
GPIO_Init(RTC_SCK_PORT, RTC_SCK_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(RTC_RST_PORT, RTC_RST_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW);

RTC_SCK_LOW();
RTC_IO_LOW();
RTC_RST_LOW();
}

/*************************************************************************
写一字节数据
--------------------------------------------------------------------------
byte:一字节数据
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_WriteByte (uint8_t byte)
{
uint8_t i;
BitStatus bit;

RTC_IO_OUT(); // IO 配置为输出模式

for (i = 0; i < 8; i++)
{
RTC_SCK_LOW();

bit = (BitStatus)(byte & 0x01);
if (bit != RESET)
RTC_IO_HIGH();
else
RTC_IO_LOW();

RTC_SCK_HIGH();
byte >>= 1;

//DS1302_DLY_ms(1);
}
}

/*************************************************************************
读一字节数据
--------------------------------------------------------------------------
addr:地址
--------------------------------------------------------------------------
返回值:一字节数据
*************************************************************************/
static uint8_t DS1302_ReadByte (void)
{
uint8_t i;
uint8_t data = 0;
BitStatus bit;

RTC_IO_IN(); // IO 配置为输入模式

for (i = 0; i < 8; i++)
{
data >>= 1;
RTC_SCK_LOW();

bit = RTC_IO_STATUS();
if (bit != RESET)
data |= 0x80;
else
data &= 0x7F;

RTC_SCK_HIGH();

//DS1302_DLY_ms(1);
}

return data;
}

/*************************************************************************
往指定寄存器写入一字节数据
--------------------------------------------------------------------------
addr:地址 data:一字节数据
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_WriteData (uint8_t addr, uint8_t data)
{
// 数据传输开始
RTC_RST_LOW();
RTC_SCK_LOW();
RTC_RST_HIGH();

DS1302_WriteByte (addr); // 写入的地址
DS1302_WriteByte (data); // 写入的数据

// 数据传输结束
RTC_RST_LOW();
}

/*************************************************************************
在指定寄存器读出一字节数据
--------------------------------------------------------------------------
addr:地址
--------------------------------------------------------------------------
返回值:一字节数据
*************************************************************************/
static uint8_t DS1302_ReadData (uint8_t addr)
{
uint8_t data;

// 数据传输开始
RTC_RST_LOW();
RTC_SCK_LOW();
RTC_RST_HIGH();

DS1302_WriteByte (addr); // 要读的地址
data = DS1302_ReadByte(); // 要读的数据

// 数据传输结束
RTC_RST_LOW();

return data;
}

/*************************************************************************
读时间
--------------------------------------------------------------------------
无参数
--------------------------------------------------------------------------
返回值:时间数据
*************************************************************************/
TimeTypeDef DS1302_ReadTime (void)
{
TimeTypeDef TimeDisplay;

// 读出来的数据是 BCD 码
TimeBuffer.year = DS1302_ReadData (0x8D);
TimeBuffer.month = DS1302_ReadData (0x89);
TimeBuffer.day = DS1302_ReadData (0x87);
TimeBuffer.week = DS1302_ReadData (0x8B);
TimeBuffer.hour = DS1302_ReadData (0x85);
TimeBuffer.minute = DS1302_ReadData (0x83);
TimeBuffer.second = DS1302_ReadData (0x81); // bit7 定义为时钟暂停标志(CH)

// BCD 码转换为十进制
TimeDisplay.year = BCDtoDec (TimeBuffer.year);
TimeDisplay.month = BCDtoDec (TimeBuffer.month);
TimeDisplay.day = BCDtoDec (TimeBuffer.day);
TimeDisplay.week = BCDtoDec (TimeBuffer.week);
TimeDisplay.hour = BCDtoDec (TimeBuffer.hour);
TimeDisplay.minute = BCDtoDec (TimeBuffer.minute);
TimeDisplay.second = BCDtoDec (TimeBuffer.second);

return TimeDisplay;
}

/*************************************************************************
修改时间
--------------------------------------------------------------------------
*TimeDisplay:要显示的时间(十进制)
--------------------------------------------------------------------------
无返回值
*************************************************************************/
void DS1302_WriteTime (TimeTypeDef *TimeDisplay)
{
// 十进制转换为 BCD 码
TimeBuffer.year = DectoBCD (TimeDisplay->year);
TimeBuffer.month = DectoBCD (TimeDisplay->month);
TimeBuffer.day = DectoBCD (TimeDisplay->day);
TimeBuffer.week = DectoBCD (TimeDisplay->week);
TimeBuffer.hour = DectoBCD (TimeDisplay->hour);
TimeBuffer.minute = DectoBCD (TimeDisplay->minute);
TimeBuffer.second = DectoBCD (TimeDisplay->second);

// 关闭写保护(控制寄存器:8FH、8EH bit7:保护位)
DS1302_WriteData (0x8E, 0x00);

// 写入的数据是 BCD 码
DS1302_WriteData (0x8C, TimeBuffer.year);
DS1302_WriteData (0x88, TimeBuffer.month);
DS1302_WriteData (0x86, TimeBuffer.day);
DS1302_WriteData (0x8A, TimeBuffer.week);
DS1302_WriteData (0x84, TimeBuffer.hour);
DS1302_WriteData (0x82, TimeBuffer.minute);
DS1302_WriteData (0x80, TimeBuffer.second); // bit7 定义为时钟暂停标志(CH)

// 开启写保护(控制寄存器:8FH、8EH bit7:保护位)
DS1302_WriteData (0x8E, 0x80);
}

/*************************************************************************
十进制转BCD码
--------------------------------------------------------------------------
num:十进制数
--------------------------------------------------------------------------
返回值:BCD码
*************************************************************************/
static uint8_t DectoBCD (uint8_t num)
{
uint8_t result;
uint8_t temp1, temp2;

temp1 = (num / 10) << 4; // 十位 / 10 * 16
temp2 = num % 10; // 个位 % 10
result = temp1 + temp2;

return result;
}

/*************************************************************************
BCD码转十进制
--------------------------------------------------------------------------
num:BCD码
--------------------------------------------------------------------------
返回值:十进制
*************************************************************************/
static uint8_t BCDtoDec (uint8_t num)
{
uint8_t result;
uint8_t temp1, temp2;

temp1 = (num >> 4) * 10; // 十位 / 16 * 10
temp2 = num & 0x0F; // 个位 % 16
result = temp1 + temp2;

return result;
}

/*************************************************************************
软件延时(ms级别)
--------------------------------------------------------------------------
nCount:延时长度
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_DLY_ms(uint16_t nCount)
{
while(nCount--)
{
DS1302_DLY_us(1000);
}
}

/*************************************************************************
软件延时(us级别)
--------------------------------------------------------------------------
nCount:延时长度
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_DLY_us(uint16_t nCount)
{
nCount *= 2;
while(--nCount);
}

3. main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "stm8s.h"
#include "ds1302.h"
#include "uart.h"

void SystemInit_CLK(void);

void main(void)
{
// 数据显示区(十进制)
// 初始值:2022.02.25 Fri. 01:59:50
TimeTypeDef TimeDisplay = {22, 02, 25, 5, 01, 59, 50};
uint8_t TimeSecPre;

SystemInit_CLK();
UART2_Config();
DS1302_Init();

printf("Init Success!\r\n");

#if RTC_RESET_TIME_EN > 0u
DS1302_WriteTime(&TimeDisplay);
#endif

while (1)
{
TimeDisplay = DS1302_ReadTime();
if (TimeSecPre != TimeDisplay.second)
{
TimeSecPre = TimeDisplay.second;
printf("20%d年%d月%d日 星期%d\r\n", TimeDisplay.year, TimeDisplay.month, TimeDisplay.day,
TimeDisplay.week);
printf("%d时%d分%d秒\r\n", TimeDisplay.hour, TimeDisplay.minute, TimeDisplay.second);
printf("\r\n");
}
}
}

void SystemInit_CLK(void)
{
CLK_DeInit();
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); // 16MHz
CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
CLK_HSICmd(ENABLE);
}


#ifdef USE_FULL_ASSERT

/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* Infinite loop */
while (1)
{
}
}
#endif

在串口打印时间:

---EOF---