Microcontroller UTC time zone conversion
Update Time: 2019-12-20 12:11:28
I. creation background
Previously, I made a project about STM32 low-power signal acquisition, using STM32L031 single-chip microcomputer. The project requirements are as follows:
The device is battery-powered, detects a signal from the sensor and sends it out wirelessly.Each time the signal collected by the device is transmitted, it takes tens of mS, and other times it goes into deep sleep to save power.
The main point of this project is that the working time of the equipment is uncertain every day. The customer may request to collect it once an hour, once a day or only on working days.
Because the working interval is uncertain and the UTC time is easily available over the wireless network.Therefore, I decided to make a calendar, using the MCU RTC peripheral and alarm clock function, each time after the completion of equipment collection, before entering hibernation, according to the working mechanism set by the customer, the next RTC alarm clock will be set, through the RTC alarm clock interrupt event to wake up the program.
Ii. UTC investigation
UTC has been investigated for a BUG in Y2038, which was officially released on Tuesday, January 19, 2038 03:14:07 am(GMT).Because the 32-bit computer system with a signed 32-bit integer to store a time_t value, that is to say t_TIme only by the number 31 binary (first used to represent the positive and negative), and its maximum value is converted to a decimal 2147483647, converted to a date and time is just on January 19, 2038 03:14:07 am (GMT), and that one second later, t_TIme value will be - 2147483647 32-bit software and hardware system of crazy time display the date.
Now is not too far from 2038, so this hidden danger can not be buried here (must enter this time to write the code I want to use next time, can not next time in research).
Iii. Scheme design
Since the STM32 RTC is definitely 32-bit, there are two methods in front of me:
Method 1: in the general rule, UTC=0 means 1970/1/1-0 :0:0. I shift the time in the project to, say, 2010/1/1-0 :0:0, so that Y2038 becomes 2078.
Method 2: in C language time. h file, int is used to count seconds.I use uint to count the seconds, so that the BUG of y2k can be postponed to Beijing time 2106/2/7 14:28:15
So, in the end, I chose plan two without hesitation, because I didn't have to change the standard that everyone follows.
Iv. Programming
Define the program structure type
Typedef struct {uint8_t tm_sec;Uint8_t tm_min;Uint8_t tm_hour;Uint8_t tm_mday;Uint8_t tm_mon;Uint8_t tm_wday;Uint16_t tm_year;/ / uint16_t tm_yday;} TImeType;
Create a variable
Static const uint16_t NonleapYearMonth[12] = {31,//131 + 28, //231 + 28 + 31,// 331 + 28 + 31,// 431 + 28 + 30, //531 + 28 + 30 + 30,//631 + 28 + 30 + 31 + 30 + 31, //731 + 28 + 31 + 30 + 30 + 31, //831 + 28 + 31 + 30 + 30 + 31,//1031 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + 30 + 30, //1131 + 28 + 31 + 30 + 30 + 30 + 30, //12};Static const uint16_t LeapYearMonth[12] = {31,//131 + 29, //231 + 29 + 31,// 331 + 29 + 31,// 431 + 29 + 30, //531 + 29 + 30 + 31,//631 + 29 + 30 + 30 + 30 + 31, //731 + 29 + 30 + 30 + 30 + 31, //831 + 29 + 30 + 30 + 30 + 31,//1031 + 29 + 30 + 30 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + 30 + 30, //1131 + 29 + 31 + 30 + 30 + 30 + 30, //12};
Uint8_t alg_IsLeapYear(uint32_t year){if((year % 4 == 0) && ((year % 100!= 0) || (year % 400 == 0))) // is divisible by 4, not by 100, but by 400.{return 1;Else {return 0;TimeType alg_Utc2LocalTime(uint32_t UtcVal, int8_t TimeZone){uint32_t I = 0;TimeType LocalTime;Uint32_t Hour, Days, Year;LocalTime. Tm_sec = UtcVal % 60;// localtime.tm_min =(UtcVal/60)%60;Hour=(UtcVal/60)/60;Localtime.tm_hour =Hour%24+TimeZone;If (localtime.tm_hour >23){localtime.tm_hour -=24;Days = 24 + 1 Hour /;} else {Days = Hour / 24;} LocalTime. Tm_wday = (Days + 4) % 7;// calculate the week, 0-means Sunday note: 1970-1-1 is the week // note: 400 years = 146,097 days,100 years = 36,524 days,4 years =1461 days Year = 1970;Year += (Days/146097)*400;Days % = 146097;Year += (Days/36525)*100;Days % = 36525;Year + = (Days / 1461) * 4;Days % = 1461;If (alg_IsLeapYear(Year)){Days--; if(alg_IsLeapYear(Year)){Days--;} Days - = 365;Year++;} the if (!Alg_IsLeapYear (Year) && (Days == 365)){Year++;LocalTime. Tm_mday = 1;LocalTime. Tm_mon = 1;LocalTime. Tm_year = Year;Return a LocalTime;} LocalTime. Tm_year = Year;The LocalTime. Tm_mon = 0;The LocalTime. Tm_mday = 0;If (alg_IsLeapYear(Year))// this Year is a leap Year {for (I = 0;I < 12;I ++){if (Days < LeapYearMonth[I]){localtime.tm_mon = I + 1;If (I == 0){localtime.tm_mday = Days;}else{localtime.tm_mday = days-leapyearmonth [i-1];} LocalTime. Tm_mday + +;Return a LocalTime;Else // this year is a normal year {for (I = 0;I < 12;I ++){if (Days < NonleapYearMonth[I]){localtime.tm_mon = I + 1;If (I == 0){localtime.tm_mday = Days;}else{localtime.tm_mday = days-nonleapyearmonth [i-1];} LocalTime. Tm_mday + +;Return a LocalTime;}}} return LocalTime;}uint32_t alg_LocalTime2Utc(TimeType LocalTime, int8_t TimeZone){uint32_t y = localtime.tm_year-1970;// see how many 400 years, how many 100 years, how many 4 years uint32_t dy = (y / 400);Uint32_t days = dy * (400 * 365 + 97);// the number of days in 400 years dy = (y % 400) / 100;Days += dy * (100 * 365 + 25);// days in 100 years dy = (y % 100) / 4;Days += dy * (4 * 365 + 1);// the number of days in 4 years dy = y % 4;// note: here 1972 is a leap year, only 2 years from 1970.If (dy == 3)// in this 4 years, there is no leap year is less than 1 day {day ++;If (localtime.tm_mon!) {if (localtime.tm_mon!) {if (localtime.tm_mon!) {if (localtime.tm_mon!= 1){if(alg_IsLeapYear(localtime.tm_year))// see if this year is a leap year or a flat year {days += LeapYearMonth[(localtime.tm_mon-1) -1];} else {days += NonleapYearMonth[(localtime.tm_mon-1) -1];// if the number of months given is x, only x-1 integer months}}days += localtime.tm_mday-1;Return (days * 24 * 3600 + ((uint32_t) localtime.tm_hour-timezone)* 3600 + (uint32_t) localtime.tm_min * 60 + (uint32_t) localtime.tm_sec);} above, the basic program API is complete.
When called, only the following two functions can be used for mutual rotation:
TimeType alg_Utc2LocalTime(uint32_t UtcVal, int8_t TimeZone);Uint32_t alg_LocalTime2Utc(TimeType LocalTime, int8_t TimeZone);
Previous: Everything about N-channel hexfet power mosfet-IRF3205
Next: Ams a number of innovative sensor technologies appear in MWC
Ratings and Reviews
Related Products
-
UC3843A
UTC
Fixed Frequency Current-Mode PWM Control > -
UF1010EL
UTC
> -
L6219L-S24-R
UTC
DUAL FULL-BRIDGE PWM MOTOR DRIVER > -
MC4558
UTC
WIDE BANDWIDTH DUAL BIPOLAR OPERATIONAL > -
2SB649
UTC
PNP Epitaxial Planar Transistors - Weitr > -
MC34118L-S28-R
UTC
VOICE SWITCHED SPEAKER-PHONE CIRCUIT > -
ULN2803G-S18-R
UTC
EIGHT DARLINGTON ARRAYS > -
UTC820
UTC
DIP-8 > -
UTC78D05AL
UTC
TO-252 > -
UTC78D05
UTC
TO-252 > -
UTC75185L
UTC
LINEAR INTEGRATED CIRCUIT > -
UTC7266
UTC
ZIP-15 > -
UTC4N60L
UTC
TO-220 > -
UTC431
UTC
LINEAR INTEGRATED CIRCUIT > -
UTC3843E
UTC
SOP-8P >
Hot Stocks
More- UTC31002
- UTC2822H
- UTC2050
- UTC1062A
- UTC1018
- UT6264CPC-70LL
- UT108N03
- UT100N03L
- UT100N03
- UM66T11L
- ULN2003L
- UF840L
- U74LVC2G14G-AL6-R
- TL494L
- TEA1098A
- TDA7499L
- TA8227AP
- S8550LT1
- PA2009L
- MJE13003L
- MC4580L
- MC34063AL-D08-T
- MC34063/A
- LR3965G-ADJ
- LM393G-S08-R
- LM386G-S08-R
- LM358L-D08-T
- LM317G-AA3-R
- LD1117AL-33
- LD1117AG-33-AA3-A-R
- KA22241
- HE8550S
- BD139L-16
- 78L05L
- 78D08L
- 78D05AG
- 4N60L
- 2SD880L
- 2SC3669
- 2SC1815L-Y
- 2SC1384L
- 2SB776
- 2N7002G
- 1N5819L-CA2-R
- 12N65