/***************************************************************************************
* 文件名 : sytemTime.c
* 版权说明 :
* 版本号 : v1.0
* 创建时间 : 2008.12
* 作者 : xiaoxiaoxia666
* 功能描述 : get system time from BIOS,set system time to BIOS.
* 使用注意 :
* 修改记录 : 1.2010.1.12 finished a base version.
***************************************************************************************/
#include "systemTime.h"
/**************************************************************************
* 功能描述: 读取BIOS时钟,转换为vxWorks系统的时钟,并由系统使用,由于系统上电
时初始时钟为0,需要从BIOS读取并初始化,系统退出时还需要记录到BIOS
* 输入参数: 无
* 输入输出参数:无
* 输出参数: 无
* 全局变量: 无
* 返回值: 无
**************************************************************************/
void RsovInitSysTime(void)
{
struct timespec ts;
UINT32 res;
/*读取系统Bios时间*/
ts.tv_sec = RsovBiosTime();
ts.tv_nsec = 0;
/*设置vxWorks系统时钟*/
res = clock_settime(CLOCK_REALTIME, &ts);
}
/**************************************************************************
* 功能描述: 获取bios时钟,转为1970-1-1到现在的秒数
* 输入参数: 无
* 输入输出参数:无
* 输出参数: 无
* 全局变量: 无
* 返回值: time_t 1970-1-1到现在的秒数
**************************************************************************/
time_t RsovBiosTime(void)
{
struct tm ahora;
UCHAR cHour, cMin, cSec;
UCHAR cDay, cMonth, cYear;
sysOutByte(0x70, 0x00 /*second*/);
cSec = sysInByte(0x71);
ahora.tm_sec = (cSec &0x0F) + 10 *( (cSec &0xF0) >> 4);
sysOutByte(0x70, 0x02 /*minut*/);
cMin = sysInByte(0x71);
ahora.tm_min = (cMin &0x0F) + 10 *( (cMin &0xF0) >> 4);
sysOutByte(0x70, 0x04 /*hour*/);
cHour = sysInByte(0x71);
ahora.tm_hour = (cHour &0x0F) + 10 *( (cHour &0xF0) >> 4);
sysOutByte(0x70, 0x07 /*day*/);
cDay = sysInByte(0x71);
ahora.tm_mday = (cDay &0x0F) + 10 *( (cDay &0xF0) >> 4);
sysOutByte(0x70, 0x08 /*month*/);
cMonth = sysInByte(0x71);
ahora.tm_mon = (cMonth &0x0F) + 10 *( (cMonth &0xF0) >> 4) - 1;
sysOutByte(0x70, 0x09 /*year*/);
cYear = sysInByte(0x71);
ahora.tm_year = 100+(cYear &0x0F) + 10 *( (cYear &0xF0) >> 4);
return mktime(&ahora);
}
/**************************************************************************
* 功能描述: 将vxWorks系统时间转为北京时间: 将自1970年01月01日后系统运行
的秒数转换为日历时间
* 输入参数: time_t time 1970年01月01日后系统运行的秒数
INT32 timezone 时区,本地为8小时(8*60*60=28800秒),应传入负值
struct tm *tm_time 日历时间指针
* 输入输出参数:无
* 输出参数: struct tm *tm_time 日历时间值
* 全局变量: 无
* 返 回 值: 执行成功返回1,失败返回0
* 说 明: Modification History Jurassic 2002.1 Created.
2010.3.2 根据V1.0版本RSOV系统的概要和详细设计作必要修改
**************************************************************************/
UCHAR RsovLocaltimes(time_t time, INT32 timezone, struct tm *tm_time)
{
UINT32 PassFourYear;
INT32 DayPerYear;
const UCHAR Days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
UCHAR ReturnVal = 0; /*返回值*/
/*计算时差,中国为东八区,为大区,所以timezone应为负值*/
/*
* Klocwork ISSUE 34 : Comparison of unsigned value against 0 is always false.
*/
if(time < timezone)
{
time = 0;
}
else
{
time = time - timezone;
}
/*取秒时间*/
tm_time->tm_sec = (INT32)(time % 60);
time /= 60;
/*取分钟时间*/
tm_time->tm_min = (INT32)(time % 60);
time /= 60;
/*取小时时间*/
tm_time->tm_hour = (INT32)(time % 24);
time /= 24;
/*取过去多少个四年,每四年有 1461天*/
PassFourYear = ((INT32)time / 1461);
/*计算年份,从1900年开始的年数*/
tm_time->tm_year = (PassFourYear << 2) + 70;
/*四年中剩下的天数*/
time %= 1461;
/*校正闰年影响的年份,不满足4年的继续计算经过了几年*/
for (;;)
{
/*一年的天数 365 */
DayPerYear = 365;
/*判断闰年*/
if (( ((UINT32)(tm_time->tm_year)) & 3) == 0)
{
/*是闰年,一年则多一天 */
DayPerYear += 1;
}
if (time < DayPerYear)
{
break;
}
(tm_time->tm_year)+=1;
time -= DayPerYear;
}
/*+1变为从1开始计数*/
time++;
/*假定为闰年,校正润年的误差,计算月份,日期*/
if ((((UINT32)(tm_time->tm_year)) & 3) == 0)
{
if (time > 60)
{
time--;
}
else
{
if(time == 60)
{
tm_time->tm_mon = 1;
tm_time->tm_mday = 29;
return(1) ;
}
}
}
/*计算月日,月份从0到11 */
for (tm_time->tm_mon = 0; Days[tm_time->tm_mon] < time;(tm_time->tm_mon)+=1)
{
time -= Days[tm_time->tm_mon];
}
tm_time->tm_mday = (INT32)(time);
ReturnVal = 1;
return ReturnVal;
}
/**************************************************************************
* 功能描述: 将本地时间(北京时间)写入BOIS
* 输入参数: up_time为用日历时间
temp_time为日历时间转为每个类型变量的值
os_time为vxWorks系统时间
* 输入输出参数:无
* 输出参数: 无
* 全局变量: 无
* 返 回 值: 无
* 说 明: Modification History xiaxisheng 2010.1.12 Created.
**************************************************************************/
void RsovSetBoisTime(struct tm up_time)
{
unsigned char temp_time;
struct timespec os_time;
/*将up_time中的时间设为BIOS时间*/
temp_time = up_time.tm_sec/10 *16 + up_time.tm_sec%10;
sysOutByte(0x70, 0x00 /*second*/);
sysOutByte(0x71,temp_time);
temp_time = up_time.tm_min/10*16 + up_time.tm_min%10;
sysOutByte(0x70, 0x02 /*minut*/);
sysOutByte(0x71,temp_time);
temp_time = up_time.tm_hour/10*16 + up_time.tm_hour%10;
sysOutByte(0x70, 0x04 /*hour*/);
sysOutByte(0x71,temp_time);
temp_time = up_time.tm_mday/10*16 + up_time.tm_mday%10;
sysOutByte(0x70, 0x07 /*mday*/);
sysOutByte(0x71,temp_time);
temp_time = (up_time.tm_mon+1)/10*16 + (up_time.tm_mon+1)%10;
sysOutByte(0x70, 0x08 /*mon*/);
sysOutByte(0x71,temp_time);
temp_time = (up_time.tm_year-100)/10*16 + (up_time.tm_year-100)%10;
sysOutByte(0x70, 0x09 /*year*/);
sysOutByte(0x71,temp_time);
/*更新vxWorks系统的时间*/
os_time.tv_sec = mktime(&up_time);
os_time.tv_nsec = 0;
clock_settime(CLOCK_REALTIME,&os_time);
}
/***************************************************************************************
* 功能描述: 更新本地时间到BIOS
* 输入参数: UINT32 Sec,更新时间转换为1970-1-1到现在的秒数
* 输入输出参数: 无
* 输出参数: 无
* 全局变量: ...
* 返回值: 无
****************************************************************************************/
void vRsovUpdateLocalTime(UINT32 Sec)
{
time_t now;
INT32 OffSet = 0;
struct tm calendarTime;
/*获得本地时间值,以秒为单位*/
time(&now);
/*获得更新时间和本地时间的差值*/
OffSet = abs((UINT32)now - Sec) ;
/*时间值大于等于30秒,则更新本地时钟。*/
if(OffSet>=30)
{
/*将1970年以后的秒数转换为年月日时间*/
RsovLocaltimes(Sec,0,&calendarTime);
RsovSetBoisTime(calendarTime);
}
}