当前位置: 首页 > news >正文

将32位无符号整数表示的时间信号转化为习惯的形式

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

STM32 的RTC模块中有需要将无符号的32位整形数字转化为包含年,月,日,时,分,秒的结构体或者其余表达形式的信号,在纠结了好久之后,勉强第一次实现了功能,现在贴上代码

PS: 因为KEIL调试不够方便,将代码移植到WINDOWS里面调试成功,目前还未移植到STM32中。

#include <stdio.h>
typedef unsigned char         INT8U;
typedef unsigned short int     INT16U;
typedef unsigned int         INT32U;

/*    rtc.h
*/

#ifndef __RTC_H__
#define __RTC_H__

#define SECDAY 86400UL

#define YEAR_START    1970    //系统第一天为1970年1月1日
#define FIRST_WEEK    6        //1970年1月1日为星期四    2000年1月1日为星期六    
#define YEAR_TOTAL    130        //只支持100年的数据

//定义结构体记录从RTC模块读取出的数据
typedef struct rtc_time{    //没有加入溢出检查模块,请自行防止数字溢出
    INT8U tm_sec;    //0-59
    INT8U tm_min;    //0-59
    INT8U tm_hour;    //0-23
    INT8U tm_day;    //1-31
    INT8U tm_week;    //1-7
    INT8U tm_mon;    //1-12
    INT8U tm_year;     //0- YEARTOTAL-1
} RTC_S;


void to_tm(INT32U tim,RTC_S* tm);      //将32位数字转换为结构体
void from_tm(RTC_S* tm,INT32U* tim);    //从tm中读取内容记录到tim中
void quick_init(void);    //快速初始化,其实功能是加快后续运算,空间换时间 



#endif




/*    rtc.c
    事实时钟模块                                   

*/
//#include "includes.h"
#define ISLEEP(YEAR) (((YEAR)%4 == 0)&&\
    (((YEAR)%100!=0)||((YEAR)%400 == 0)))

INT8U quick_leep[YEAR_TOTAL]; //该处理方式浪费了大量空间
INT16U year_sort[YEAR_TOTAL];    //用于判断具体哪年
INT16U month[12] =     {31,59,90, 120,151,181,          //判断月份
                    212,243,273, 304,334,365};     
INT16U month_leep[12] =     {31,60,91, 121,152,182,      //判断闰年的月份
                            213,244,274, 305,335,366};

void quick_init(void)    //快速初始化,其实功能是加快后续运算,空间换时间 
{
    INT8U i;
    INT32U j;
    for(i = 0 ; i < YEAR_TOTAL ; i++)     //建立闰年快速查询表 
    {
        j = i + YEAR_START; 
        if(ISLEEP(j))
        {
            quick_leep[i] = 1;
        } else 
        {
            quick_leep[i] = 0;
        }        
    }
    j = 0;
    for(i = 0;i<YEAR_TOTAL;i++)        //用于天数记录 判断属于哪年
    {
        j += quick_leep[i];
        j += 365; 
        year_sort[i] =  j;
    }
}

void to_tm(INT32U tim,RTC_S* tm)  //将32位数字转换为结构体
{
    INT16U  year_1;        //用于查找年份 
    INT16U    year_2;        //用于查找出去年份后剩余多少天 
    INT16U    year_3;        //用于查找月份 
    INT16U    year_4;      //用于查找去除月份后剩余多少天 
    INT32U    days,sec;
    INT16U*    pmonth;

    sec = tim % SECDAY;     //当前秒总数

    //得到小时、分钟、秒钟数值
    tm->tm_hour = sec / 3600;
    tm->tm_min = (sec % 3600) / 60;
    tm->tm_sec = (sec % 3600) % 60;    
    
    days = tim / SECDAY; //当前天总数
    
    days += 2;        //算上第一天 

    //得到星期
    tm->tm_week = (days + 5 + FIRST_WEEK )%7 + 1;

    //初步得到年份
    year_1 = days / 365;
    //最终得到year_1 即为当前所在的年份;
    while(1)   
    {
        if((0 == year_1)&&(days <= year_sort[0]))
        {
            year_2 = days;
            break;
        }
        if((days <= year_sort[year_1])&&(days > year_sort[year_1 - 1]))
        {
            year_2 = days - year_sort[year_1 - 1];
            break;
        }
        if(days > year_sort[year_1])
        {
            year_1 ++;
            continue;
        }     else 
        {
            year_1 --;
        }
    }
    tm->tm_year = year_1;

    year_3 = year_2 / 31;    //初步决定是几月份 
    if(quick_leep[year_1])    //根据闰年与否选择不同的数组 
    {
        pmonth = month_leep;         
    } else
    {
        pmonth = month;
    }
    while(1)    //最终得到正确的月份 year_3
    {
        if((0 == year_3)&&(year_3 <= pmonth[0]))
        {
            year_4 = year_2;
            break;
        }
        if((year_2 > pmonth[year_3 - 1])&&(year_2 <= pmonth[year_3] ))
        {
            year_4 = year_2 - pmonth[year_3 - 1];
            break;
        }
        if(year_2 > pmonth[year_3])
        {
            year_3 ++;
            continue;
        } else
        {
            year_3 --;
        }
    }

    tm->tm_mon = year_3 + 1; //没有0月 
    tm->tm_day = year_4 ; //没有0日 
}

void from_tm(RTC_S* tm,INT32U* tim)    //从tm中读取内容记录到tim中 
{
    INT8U leep_flag;        //闰年标志位 
    INT16U day_temp = 0;    //记录总共计时多少天 
    INT32U sec_temp = 0;    //记录总共一天剩下的多少秒 
    leep_flag = quick_leep[tm->tm_year];
    sec_temp = tm->tm_hour * 3600 +
                tm->tm_min * 60 +
                tm->tm_sec;
    
    day_temp = tm->tm_day - 1;    //没有0号 
                
    if( 0 == tm->tm_year)    //累加年 级别的天数 
    {
        day_temp += 0;
    } else
    {
        day_temp += (year_sort[tm->tm_year - 1]);
    }
    
    if(1 == tm->tm_mon)        //累加月 级别的天数 
    {
        day_temp += 0;
    } else if(leep_flag)
    {
        day_temp += month_leep[tm->tm_mon - 2];        
    } else 
    {
        day_temp += month[tm->tm_mon - 2];
    }
    
    day_temp--;        //减去第一天 
    
    *tim = day_temp * SECDAY + sec_temp;    //耦合到一个32位数字中去 
}

void tmprint(RTC_S* tm)        //Windows编程环境拓展,用于检查 
{
    printf("year: %d\n",tm->tm_year + YEAR_START);
    printf("mon:  %d\n",tm->tm_mon);
    printf("day:  %d\n",tm->tm_day);
    printf("week: %d\n",tm->tm_week);
    printf("hour: %d\n",tm->tm_hour);
    printf("min:  %d\n",tm->tm_min);
    printf("sec:  %d\n",tm->tm_sec);
}

int main()
{
    RTC_S tm1,tm2;
    INT32U    i,j,k;
    tm1.tm_sec = 30;     
    tm1.tm_min = 30;
    tm1.tm_hour = 10;
    tm1.tm_day = 1;
    tm1.tm_week = 4;
    tm1.tm_mon = 2;
    tm1.tm_year = 2080-YEAR_START;
    
    quick_init();
    
    tmprint(&tm1);
    
    from_tm(&tm1,&i);
    printf("%d\n",i);
    printf("\n");
    
    to_tm(i,&tm2);
    tmprint(&tm2);    
    from_tm(&tm2,&j);
    printf("%d\n",j);
//    system("pause");

    return 0;
}

程序运行后结果如下,运行一切正常


将代码进行了少量修改,经过测试,因为INT32U的影响,此次计数最多能够计数到130年左右。

转载于:https://my.oschina.net/mummy108/blog/115299

相关文章:

  • 财经法规与会计职业道德1
  • 截取字符串显示
  • Android TextView内容过长加省略号,点击显示全部内容
  • 一直令我纠结的问题,关于“线程”与“阻塞”
  • 随记:Linux下apache2.4.4的安装
  • 2012年最具影响力路由器配置精品文章荟萃【108篇】
  • 运算符重载03 -- = 和!
  • Linux下git安装
  • prototype.js 让你更深入的了解javascript的面向对象特性
  • SQL语句decode函数
  • ARM中断基础知识
  • java.lang.IllegalStateException: No activity 错误...
  • jquery与dom的转换
  • nginx 初体验
  • python lambda函数
  • 【Leetcode】101. 对称二叉树
  • 【React系列】如何构建React应用程序
  • 77. Combinations
  • CSS 专业技巧
  • es的写入过程
  • Fabric架构演变之路
  • Java方法详解
  • Java应用性能调优
  • Laravel 中的一个后期静态绑定
  • leetcode386. Lexicographical Numbers
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 聊聊hikari连接池的leakDetectionThreshold
  • 小李飞刀:SQL题目刷起来!
  • 06-01 点餐小程序前台界面搭建
  • C# - 为值类型重定义相等性
  • ​批处理文件中的errorlevel用法
  • ​油烟净化器电源安全,保障健康餐饮生活
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #HarmonyOS:Web组件的使用
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (四)JPA - JQPL 实现增删改查
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (正则)提取页面里的img标签
  • *1 计算机基础和操作系统基础及几大协议
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • @基于大模型的旅游路线推荐方案
  • [ 云计算 | AWS 实践 ] 基于 Amazon S3 协议搭建个人云存储服务
  • [2013AAA]On a fractional nonlinear hyperbolic equation arising from relative theory
  • [20171113]修改表结构删除列相关问题4.txt
  • [Angular] 笔记 8:list/detail 页面以及@Input
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [BT]BUUCTF刷题第9天(3.27)
  • [BUUCTF 2018]Online Tool
  • [c++] 单例模式 + cyberrt TimingWheel 单例分析
  • [DM复习]Apriori算法-国会投票记录关联规则挖掘(上)
  • [ffmpeg] av_opt_set 解析