Skip to content

Commit 05f008a

Browse files
Merge pull request #334 from csnol/master
Update F103 RTClock library for RTC sketch.
2 parents 3c2fce6 + c25957e commit 05f008a

File tree

4 files changed

+346
-23
lines changed

4 files changed

+346
-23
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/* STM32F103C8 Blue Pill ( PC13)
2+
3+
Serialport set and display RTC clock , Write by CSNOL https://github.com/csnol/STM32-Examples
4+
based on https://github.com/rogerclarkmelbourne/Arduino_STM32
5+
6+
1. Blink on PC13 per 4s or 7s by attachAlarmInterrupt for 10 times
7+
2. Second counter by attachSecondsInterrpt
8+
3. Serial output on(41s) or off(21s) by creatAlarm
9+
4. change to your timezone in the sketch; .
10+
3. get Unix epoch time from https://www.epochconverter.com/ ;
11+
4. last step input the 10 bits number( example: 1503945555) to Serialport ;
12+
5. the clock will be reset to you wanted.
13+
14+
## Why the 10 bits Unix epoch time be used?
15+
****Because I wanna connect to NTP server by ESP-8266.
16+
****in the <NTPClient.h> library. getNtpTime() will return this 10 bits Unix epoch time.
17+
*
18+
* 嗨!朋友们, 这是一个STM32F10x系列的RTC应用的例子,希望对你的编码有所帮助
19+
* 这个程序基于https://github.com/rogerclarkmelbourne/Arduino_STM32 , 感谢所有贡献者的付出。
20+
* 程序测试了 F10x系列RTC 的 几种中断, 并通过LED和串口进行表达。
21+
* RTClock 使用 UTC 作为时间标准, 你可以从https://www.epochconverter.com/ 获得 Unix epoch time数值
22+
* 并通过串口进行设置, 当然你也可以略微修改一下串口接收处理方法,直接从串口接收日期形式。如 2017-9-13-10:30:00,
23+
* 另外一个方法是通过ESP8266获取NTP网络时间,并定期发送给F10x进行更新。
24+
*/
25+
26+
27+
#include <RTClock.h>
28+
29+
RTClock rtclock (RTCSEL_LSE); // initialise
30+
int timezone = 8; // change to your timezone
31+
time_t tt;
32+
time_t tt1;
33+
tm_t mtt = { 47, 9, 13, 3, 11, 22, 30, 30 }; // init time 47+1970 = 2017 Unix epoch Time counted from 00:00:00 1 Jan 1970
34+
char weekday1[][7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; // 0,1,2,3,4,5,6
35+
uint8_t dateread[11];
36+
int globAlmCount = 0;
37+
int lastGlobAlmCount;
38+
int SPECAlmCount = 0;
39+
int lastSPECAlmCount;
40+
int i = 0;
41+
int alarmcount = 3;
42+
uint8_t AlarmExchange = 0;
43+
bool dispflag = true;
44+
45+
#define LED_PIN PC13
46+
47+
// This function is called in the attachSecondsInterrpt
48+
void SecondCount ()
49+
{
50+
tt++;
51+
}
52+
// This function is called in the attachAlarmInterrpt
53+
void blink ()
54+
{
55+
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
56+
globAlmCount++;
57+
//tt++;
58+
}
59+
60+
void OnOffSerial ()
61+
{
62+
dispflag = !dispflag;
63+
SPECAlmCount++;
64+
}
65+
66+
void setup()
67+
{
68+
lastGlobAlmCount = ~globAlmCount;
69+
lastSPECAlmCount = ~SPECAlmCount;
70+
Serial.begin(115200);
71+
pinMode(LED_PIN, OUTPUT);
72+
tt = rtclock.makeTime(mtt);
73+
rtclock.setTime(tt);
74+
tt1 = tt;
75+
rtclock.attachAlarmInterrupt(blink);// Call blink
76+
rtclock.attachSecondsInterrupt(SecondCount);// Call SecondCount
77+
}
78+
79+
void loop()
80+
{
81+
while (Serial.available())
82+
{ dateread[i] = Serial.read();
83+
if (i < 11) {
84+
i++;
85+
}
86+
else {
87+
i = 0;
88+
tt = (dateread[0] - '0') * 1000000000 + (dateread[1] - '0') * 100000000 + (dateread[2] - '0') * 10000000 + (dateread[3] - '0') * 1000000 + (dateread[4] - '0') * 100000;
89+
tt += (dateread[5] - '0') * 10000 + (dateread[6] - '0') * 1000 + (dateread[7] - '0') * 100 + (dateread[8] - '0') * 10 + (dateread[9] - '0');
90+
rtclock.TimeZone(tt, timezone); //adjust to your local date
91+
rtclock.setTime(rtclock.TimeZone(tt, timezone));
92+
}
93+
}
94+
if (lastGlobAlmCount != globAlmCount | lastSPECAlmCount != SPECAlmCount ) {
95+
if (globAlmCount == 10) { // to detachAlarmInterrupt and start creatAlarm after 10 times about 110s
96+
rtclock.detachAlarmInterrupt();
97+
globAlmCount = 0;
98+
rtclock.createAlarm(OnOffSerial, (rtclock.getTime() + 20)); // call OnOffSerial stop output date from Serial after 2 mins
99+
alarmcount = 20; //change to creatAlarm 21S close Serial output and 41s open Serial output.
100+
}
101+
else {
102+
lastGlobAlmCount = globAlmCount;
103+
lastSPECAlmCount = SPECAlmCount;
104+
Serial.println(" Say hello to every guys ");
105+
if(dispflag == false)
106+
Serial.println(" SPECAlarm turn Display Off ");
107+
switch (AlarmExchange) {
108+
case 0:
109+
rtclock.setAlarmTime(rtclock.getTime() + alarmcount); // reset alarm = current time + 4s for attachAlarmInterrupt, 21s for creatAlarm
110+
AlarmExchange = 1;
111+
break;
112+
case 1:
113+
rtclock.breakTime(rtclock.getTime() + alarmcount * 2, mtt); //// reset alarm = current time + 7s for attachAlarmInterrupt, 41s for creatAlarm
114+
rtclock.setAlarmTime(mtt);
115+
AlarmExchange = 0;
116+
break;
117+
}
118+
}
119+
}
120+
if (tt1 != tt & dispflag == true )
121+
{
122+
tt1 = tt;
123+
//rtclock.breakTime(tt, mtt);
124+
Serial.print("Date: ");
125+
Serial.print(rtclock.day());
126+
Serial.print("- ");
127+
Serial.print(rtclock.month());
128+
Serial.print(" ");
129+
Serial.print(rtclock.year() + 1970);
130+
Serial.print(" ");
131+
Serial.print(weekday1[rtclock.weekday()]);
132+
Serial.print(" Time: ");
133+
Serial.print(rtclock.hour());
134+
Serial.print(" : ");
135+
Serial.print(rtclock.minute());
136+
Serial.print(" : ");
137+
Serial.println(rtclock.second());
138+
}
139+
}

STM32F1/libraries/RTClock/keywords.txt

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,36 @@
55
#######################################
66
# Datatypes (KEYWORD1)
77
#######################################
8-
RTClock KEYWORD1
98

9+
RTClock KEYWORD1
1010

11-
setTime KEYWORD2
12-
getTime KEYWORD2
1311

14-
createAlarm KEYWORD2
12+
setTime KEYWORD2
13+
getTime KEYWORD2
14+
15+
createAlarm KEYWORD2
16+
removeAlarm KEYWORD2
17+
setAlarmTime KEYWORD2
18+
1519
attachSecondsInterrupt KEYWORD2
1620
detachSecondsInterrupt KEYWORD2
17-
setAlarmTime KEYWORD2
21+
22+
attachAlarmInterrupt KEYWORD2
23+
detachAlarmInterrupt KEYWORD2
24+
25+
breakTime KEYWORD2
26+
makeTime KEYWORD2
27+
28+
TimeZone KEYWORD2
29+
now KEYWORD2
30+
year KEYWORD2
31+
month KEYWORD2
32+
day KEYWORD2
33+
weekday KEYWORD2
34+
hour KEYWORD2
35+
minute KEYWORD2
36+
second KEYWORD2
37+
isPM KEYWORD2
1838

1939

2040
#######################################

STM32F1/libraries/RTClock/src/RTClock.cpp

Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,45 +80,153 @@
8080
}
8181
*/
8282

83+
void RTClock::setTime (tm_t & tmm) {
84+
time_t mktm = makeTime(tmm); // time will be make to mktm
85+
setTime(mktm);
86+
//rtc_set_count(time_stamp);
87+
}
88+
8389
void RTClock::setTime (time_t time_stamp) {
8490
rtc_set_count(time_stamp);
8591
}
8692

87-
void RTClock::setTime (struct tm* tm_ptr) {
88-
rtc_set_count(mktime (tm_ptr));
89-
}
93+
#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
9094

95+
//-----------------------------------------------------------------------------
96+
void RTClock::breakTime(time_t timeInput, tm_t & tmm)
97+
{
98+
// break the given time_t into time components
99+
// this is a more compact version of the C library localtime function
100+
// note that year is offset from 1970 !!!
101+
102+
uint8_t year;
103+
uint8_t month, monthLength;
104+
uint32_t time;
105+
uint32_t days;
106+
107+
time = (uint32_t)timeInput;
108+
tmm.second = time % 60;
109+
time /= 60; // now it is minutes
110+
tmm.minute = time % 60;
111+
time /= 60; // now it is hours
112+
tmm.hour = time % 24;
113+
time /= 24; // now it is days
114+
tmm.weekday = ((time + 4) % 7); // Monday is day 1 // + 1; // Sunday is day 1
115+
116+
year = 0;
117+
days = 0;
118+
while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
119+
year++;
120+
}
121+
tmm.year = year; // year is offset from 1970
122+
123+
days -= LEAP_YEAR(year) ? 366 : 365;
124+
time -= days; // now it is days in this year, starting at 0
125+
126+
days = 0;
127+
month = 0;
128+
monthLength = 0;
129+
for (month=0; month<12; month++) {
130+
if (month==1) { // february
131+
if (LEAP_YEAR(year)) {
132+
monthLength=29;
133+
} else {
134+
monthLength=28;
135+
}
136+
} else {
137+
monthLength = monthDays[month];
138+
}
139+
140+
if (time >= monthLength) {
141+
time -= monthLength;
142+
} else {
143+
break;
144+
}
145+
}
146+
tmm.month = month + 1; // jan is month 1
147+
tmm.day = time + 1; // day of month
148+
}
149+
150+
//-----------------------------------------------------------------------------
151+
time_t RTClock::makeTime(tm_t & tmm)
152+
{
153+
// assemble time elements into time_t
154+
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
155+
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
156+
157+
int i;
158+
uint32_t seconds;
159+
160+
// seconds from 1970 till 1 jan 00:00:00 of the given year
161+
seconds = tmm.year*(SECS_PER_DAY * 365);
162+
for (i = 0; i < tmm.year; i++) {
163+
if (LEAP_YEAR(i)) {
164+
seconds += SECS_PER_DAY; // add extra days for leap years
165+
}
166+
}
167+
168+
// add days for this year, months start from 1
169+
for (i = 1; i < tmm.month; i++) {
170+
if ( (i == 2) && LEAP_YEAR(tmm.year)) {
171+
seconds += SECS_PER_DAY * 29;
172+
} else {
173+
seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
174+
}
175+
}
176+
seconds+= (tmm.day-1) * SECS_PER_DAY;
177+
seconds+= tmm.hour * SECS_PER_HOUR;
178+
seconds+= tmm.minute * SECS_PER_MIN;
179+
seconds+= tmm.second;
180+
return (time_t)seconds;
181+
}
182+
91183
time_t RTClock::getTime() {
92184
return rtc_get_count();
93185
}
94-
95-
struct tm* RTClock::getTime(struct tm* tm_ptr) {
186+
187+
void RTClock::getTime(tm_t & tm_ptr) {
96188
time_t res = rtc_get_count();
97-
tm_ptr = gmtime(&res); //why not gmtime?
98-
return tm_ptr;
189+
breakTime(res, tm_ptr);
99190
}
100191

101192
void RTClock::createAlarm(voidFuncPtr function, time_t alarm_time_t) {
102193
rtc_set_alarm(alarm_time_t); //must be int... for standardization sake.
103194
rtc_attach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT, function);
104195
}
105196

197+
void RTClock::removeAlarm() {
198+
rtc_detach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT);
199+
}
200+
106201
void RTClock::attachSecondsInterrupt(voidFuncPtr function) {
107202
rtc_attach_interrupt(RTC_SECONDS_INTERRUPT, function);
108203
}
109204
void RTClock::detachSecondsInterrupt() {
110205
rtc_detach_interrupt(RTC_SECONDS_INTERRUPT);
111206
}
112207

208+
void RTClock::attachAlarmInterrupt(voidFuncPtr function, time_t alarm_time) { // Don't need run RTClock::setAlarmTime(time_t alarm_time)
209+
rtc_set_alarm(alarm_time);
210+
rtc_attach_interrupt(RTC_ALARM_GLOBAL_INTERRUPT, function);
211+
}
212+
213+
void RTClock::attachAlarmInterrupt(voidFuncPtr function) { // Must run RTClock::setAlarmTime (time_t alarm_time or tm_t & alarm_tm) first
214+
rtc_attach_interrupt(RTC_ALARM_GLOBAL_INTERRUPT, function);
215+
}
113216

114-
void RTClock::createAlarm(voidFuncPtr function, tm* alarm_tm) {
115-
time_t alarm = mktime(alarm_tm);//convert to time_t
217+
void RTClock::detachAlarmInterrupt() {
218+
rtc_detach_interrupt(RTC_ALARM_GLOBAL_INTERRUPT);
219+
}
220+
221+
void RTClock::createAlarm(voidFuncPtr function, tm_t & alarm_tm) {
222+
time_t alarm = makeTime(alarm_tm);//convert to time_t
116223
createAlarm(function, alarm);
117224
}
118225

119226
//change alarm time
120-
void RTClock::setAlarmTime (tm * tm_ptr) {
121-
time_t time = mktime(tm_ptr);//convert to time_t
227+
228+
void RTClock::setAlarmTime (tm_t & tm_ptr) {
229+
time_t time = makeTime(tm_ptr);//convert to time_t
122230
rtc_set_alarm(time); //must be int... for standardization sake.
123231
}
124232

0 commit comments

Comments
 (0)