source: S-port/trunk/Core/Src/Time.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 9.4 KB
RevLine 
[1]1#include "Time.h"
2#include "main.h"
3#include "i2c.h"
4#include "cmsis_os.h"
5#include "log_and_debug.h"
6
7#define TIMEOUT_RTC 2000
8
9//struct sntp_msg sntp_msg;
10RealTimeClock_typeDef RealTimeClock = {0};
11void vClockTask(void *param);
12
13uint8_t buff[8] = {0};
14/*********************************************/
15#define _XT_SIGNED
16#define _TBIAS_DAYS ((70 * (uint32_t)365) + 17)
17#define _TBIAS_SECS (_TBIAS_DAYS * (int32_t)86400)
18#define _TBIAS_YEAR 1900
19#define MONTAB(year) ((((year) & 03) || ((year) == 0)) ? mos : lmos)
20
21const int16_t lmos[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
22const int16_t mos[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
23
24#define Daysto32(year, mon) (((year - 1) / 4) + MONTAB(year)[mon])
25
26void clock_init(void)
27{
28 xTaskCreate(vClockTask, "ClockTask", 1024, NULL, osPriorityNormal, NULL); // priority: above normal
29}
30
31int32_t time_to_unix(RealTimeClock_typeDef *t) // âîçâðàùàåò unixTime
32{
33int32_t days;
34int32_t secs;
35int32_t mon, year;
36
37 mon = t->Data.Month - 1;
38 year = t->Data.Year - _TBIAS_YEAR;
39 days = Daysto32(year, mon) - 1;
40 days += 365 * year;
41 days += t->Data.Day;
42 days -= _TBIAS_DAYS;
43
44 secs = 3600 * t->Time.Hour;
45 secs += 60 * t->Time.Min;
46 secs += t->Time.Sec;
47
48 secs += (days * (int32_t)86400);
49
50 return (secs);
51}
52
53void unix_to_time(RealTimeClock_typeDef *t, int32_t secsarg)
54{
55uint32_t secs;
56int32_t days;
57int32_t mon;
58int32_t year;
59int32_t i;
60const int16_t* pm;
61
62 #ifdef _XT_SIGNED
63 if (secsarg >= 0) {
64 secs = (uint32_t)secsarg;
65 days = _TBIAS_DAYS;
66 } else {
67 secs = (uint32_t)secsarg + _TBIAS_SECS;
68 days = 0;
69 }
70 #else
71 secs = secsarg;
72 days = _TBIAS_DAYS;
73 #endif
74
75 days += secs / 86400;
76 secs = secs % 86400;
77 t->Time.Hour = secs / 3600;
78 secs %= 3600;
79 t->Time.Min = secs / 60;
80 t->Time.Sec = secs % 60;
81
82 for (year = days / 365; days < (i = Daysto32(year, 0) + 365*year); ) { --year; }
83 days -= i;
84 t->Data.Year = year + _TBIAS_YEAR;
85
86 pm = MONTAB(year);
87 for (mon = 12; days < pm[--mon]; );
88 t->Data.Month = mon + 1;
89 t->Data.Day= days - pm[mon] + 1;
90}
91
92uint8_t ErrBus_RTC(HAL_StatusTypeDef stat)
93{
94 if(stat != HAL_OK){
95 if((stat == HAL_BUSY) && (hi2c1.Instance->SR2 & I2C_SR2_BUSY)){ // øèíà çàíÿòà
96 MX_I2C1_Init(); // øèíà çàíÿòà, ïåðåèíèöèàëèçèðóåì èíòåðôåéñ
97 }
98 else if(hi2c1.Instance->SR1 & 0x1F00){ // îùèáêà øèíû ïî timeout
99 hi2c1.Instance->CR1 &= ~I2C_CR1_PE;
100 osDelay(1);
101 hi2c1.Instance->CR1 |= I2C_CR1_PE;
102 }
103 return 0;
104 }
105 return 1;
106}
107
108uint8_t SetDisable_RTC(void)
109{
110 buff[0] = 0x01;
111 buff[1] = 0x80;
112 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 2, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
113 return 1;
114}
115
116uint8_t isEnable_RTC(void)
117{
118 buff[0] = 0x01;
119 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
120 if(!ErrBus_RTC(HAL_I2C_Master_Receive(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïðèåìó
121 return (buff[0] & 0x80) ? 0: 1;
122}
123
124uint8_t SetEnable_RTC(void)
125{
126 if(!isEnable_RTC()){
127 buff[0] = 0x01;
128 buff[1] = 0x00;
129 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 2, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
130 }
131
132 buff[0] = 0x08; // âû÷èòûâàåì ðåãèñòð, ÷òî áû óçíàòü âêëþ÷åí ëè áèò FT
133 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
134 if(!ErrBus_RTC(HAL_I2C_Master_Receive(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïðèåìó
135
136 if(!(buff[0] & (1 << 6))){
137 buff[1] = buff[0] | (1 << 6);
138 buff[0] = 0x08; /* âêëþ÷àåì áèò FT äëÿ èçìåðåíèÿ ÷àñòîòû */
139 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 2, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
140 }
141
142 return 1;
143}
144
145void ClearBitHT_RTC(void)
146{
147 buff[0] = 0x0C;
148 buff[1] = 0x00;
149 ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 2, TIMEOUT_RTC)); // ïðîâåðÿåì íå áûëî ëè îøèáîê ïî øèíå
150}
151
152uint8_t SetCurrent_RTC(RealTimeClock_typeDef *ptrClock)
153{
154 uint8_t Century = 0;
155 Century = ((ptrClock->Data.Year - 2000) / 100);
156
157 buff[0] = 0x01;
158 buff[1] = (((ptrClock->Time.Sec / 10) << 4) | (ptrClock->Time.Sec % 10)) & 0x7F;
159 buff[2] = (((ptrClock->Time.Min / 10) << 4) | (ptrClock->Time.Min % 10)) & 0x7F;
160 buff[3] = ((((ptrClock->Time.Hour / 10) << 4) | (ptrClock->Time.Hour % 10)) & 0x3F) | (Century << 6); // + âåê
161 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 4, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïåðåäà÷è
162
163 buff[0] = 0x05;
164 buff[1] = (((ptrClock->Data.Day / 10) << 4) | (ptrClock->Data.Day % 10)) & 0x3F;
165 buff[2] = (((ptrClock->Data.Month / 10) << 4) | (ptrClock->Data.Month % 10)) & 0x1F;
166 buff[3] = ((((ptrClock->Data.Year - 2000) - (Century * 100)) / 10) << 4) | (((ptrClock->Data.Year - 2000) - (Century * 100)) % 10); //(((ptrClock->Data.Year - Century * 1000) / 10) << 4) | ((ptrClock->Data.Year - Century * 1000) % 10);
167 return ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 4, TIMEOUT_RTC));
168}
169
170uint8_t GetCurrent_RTC(RealTimeClock_typeDef *ptrClock) // òóò æå ïðî÷èòàòü ôëàãè
171{
172 if(ptrClock->Flags.OSC_FAIL){ // åñëè ïðè ïðåäûäóùåì ÷òåíèè áûë óñòàíîâëåí ôëàã
173 buff[1] = buff[0] & ~0x04;
174 buff[0] = 0x0F;
175 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 2, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
176 }
177
178 buff[0] = 0x01; // ÷èòàåì ñ ðåãèñòðà 0
179 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
180 if(!ErrBus_RTC(HAL_I2C_Master_Receive(&hi2c1, M41T82_ADDR, buff, 7, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïðèåìó
181
182 ptrClock->Time.Sec = (((buff[0] & 0x70) >> 4) * 10) + (buff[0] & 0x0F);
183 ptrClock->Time.Min = (((buff[1] & 0x70) >> 4) * 10) + (buff[1] & 0x0F);
184 ptrClock->Time.Hour = (((buff[2] & 0x30) >> 4) * 10) + (buff[2] & 0x0F);
185
186 ptrClock->Data.Day = (((buff[4] & 0x30) >> 4) * 10) + (buff[4] & 0x0F);
187 ptrClock->Data.Month = (((buff[5] & 0x10) >> 4) * 10) + (buff[5] & 0x0F);
188
189 ptrClock->Data.Year = ((((buff[2] & 0xC0) >> 6) * 100) + 2000) + ((((buff[6] & 0xF0) >> 4) * 10) + (buff[6] & 0x0F));
190
191 buff[0] = 0x0F;
192 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
193 if(!ErrBus_RTC(HAL_I2C_Master_Receive(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return 0; // åñëè áûëà îøèáêà ïî ïðèåìó
194
195 ptrClock->Flags.WDT = (buff[0] & 0x80) ? 1 : 0;
196 ptrClock->Flags.ALR = ((buff[0] & 0x60) >> 5);
197 ptrClock->Flags.BAT_LOW = (buff[0] & 0x10) ? 1 : 0;
198 ptrClock->Flags.TMR = (buff[0] & 0x08) ? 1 : 0;
199 ptrClock->Flags.OSC_FAIL = (buff[0] & 0x04) ? 1 : 0;
200
201 return 1;
202}
203
204void SetCorrection_RTC(RealTimeClock_typeDef *ptrClock, int8_t corr)
205{
206 buff[0] = 0x12;
207 if(corr > 0) buff[1] = (corr | 0x80);
208 else buff[1] = ~(corr);
209 ptrClock->Correction = corr;
210 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 2, TIMEOUT_RTC))) return;
211}
212
213void GetCorrection_RTC(RealTimeClock_typeDef *ptrClock)
214{
215 uint8_t correction;
216 buff[0] = 0x12;
217 if(!ErrBus_RTC(HAL_I2C_Master_Transmit(&hi2c1, M41T82_ADDR, buff, 1, TIMEOUT_RTC))) return; // åñëè áûëà îøèáêà ïî ïåðåäà÷å
218 if(!ErrBus_RTC(HAL_I2C_Master_Receive(&hi2c1, M41T82_ADDR, &correction, 1, TIMEOUT_RTC))) return; // åñëè áûëà îøèáêà ïî ïðèåìó
219 if(correction & 0x80) correction &= ~0x80;
220 else correction = ~(correction);
221 ptrClock->Correction = correction;
222}
223
224void set_system_time_NTP(uint32_t sec)
225{
226 RealTimeClock_typeDef t;
227 unix_to_time(&t, sec);
228 SetCurrent_RTC(&t);
229}
230
231void get_system_time_NTP(int32_t *sec, uint32_t *msec)
232{
233 *sec = time_to_unix(&RealTimeClock);
234}
235
236/* CLOCK TASK ------------------------------------------------------------------------------ */
237void vClockTask(void *param)
238{
239 _Bool prevFlag_BAT_LOW = 0, prevFlag_OSC_FAIL = 0;
240
241 MX_I2C1_Init();
242
243 if(SetEnable_RTC()) __debug(DEBUG_SERVSE,"RTC: is running\r\n");
244
245 GetCorrection_RTC(&RealTimeClock);
246 ClearBitHT_RTC();
247
248 GetCurrent_RTC(&RealTimeClock);
249
250 if((RealTimeClock.Data.Month == 0x00) || (RealTimeClock.Data.Day == 0x00) || (RealTimeClock.Data.Year == 0x0000)) { // åñëè ìàñÿö äåíü èëè ãîä íå âàëèäíûé
251 RealTimeClock_typeDef t = {0x00, {1, 1, 2000}, {0, 0, 0, 0}};
252 SetCurrent_RTC(&t);// óñòàíàâëèâàåì 01.01.2000
253 GetCurrent_RTC(&RealTimeClock);
254 }
255 __debug(DEBUG_SERVSE, "RTC: Data: %02d.%02d.%04d, Time: %02d:%02d:%02d\r\n", RealTimeClock.Data.Day, RealTimeClock.Data.Month, RealTimeClock.Data.Year, RealTimeClock.Time.Hour, RealTimeClock.Time.Min, RealTimeClock.Time.Sec);
256
257 for(;;){
258 osDelay(1000);
259
260 GetCurrent_RTC(&RealTimeClock);
261
262 if((RealTimeClock.Flags.BAT_LOW) && (RealTimeClock.Flags.BAT_LOW != prevFlag_BAT_LOW)) {
263 __debug(DEBUG_SERVSE,"RTC: Battery low\r\n");
264 __logWrite("RTC: Battery low\n");
265 prevFlag_BAT_LOW = 1;
266 }
267 else if((!RealTimeClock.Flags.BAT_LOW) && (RealTimeClock.Flags.BAT_LOW != prevFlag_BAT_LOW)) prevFlag_BAT_LOW = 0;
268
269 if((RealTimeClock.Flags.OSC_FAIL) && (RealTimeClock.Flags.OSC_FAIL != prevFlag_OSC_FAIL)) {
270 __debug(DEBUG_SERVSE,"RTC: OSC fail\r\n");
271 prevFlag_OSC_FAIL = 1;
272 }
273 else if((!RealTimeClock.Flags.OSC_FAIL) && (RealTimeClock.Flags.OSC_FAIL != prevFlag_OSC_FAIL)) prevFlag_OSC_FAIL = 0;
274
275 }
276}
277
Note: See TracBrowser for help on using the repository browser.