RT-Thread:STM32实时时钟 RTC开启及应用

说明:STM32F103/407系列基于 RT-Thread 系统的 RTC 开启及应用 应用流程介绍。

1. RTC功能开启

1.1 开启系统RTC驱动

1.2 打开系统RTC相关的宏

1.3 打开库函数 RTC 相关的宏

完成以上系统配置,编译无误情况下RTC 就已经开启了。

2. RTC 应用

官方 API 查询地址:https://www.rt-thread.org/document/api/rtc_sample_8c-example.html#a3

2.1 相关函数

1.设置日期:设置系统日期但不修改时间

rt_err_t 	set_date (rt_uint32_t year, rt_uint32_t month, rt_uint32_t day)

2.设置时间:设置系统时间但不修改日期

rt_err_t 	set_time (rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)

3.获取时间:

        这里 time_t 是 long 型变量,这个变量接受 time()函数返回的 RTC 系统时间,系统返回的是 秒,从1900年开始总计运行了多少秒。

 time_t now;
 now = time(RT_NULL);

4.时间格式转换为字符型: ctime(&now)

        这个函数把总共的 秒 转换为 字符型格式的数据,如:Sat Jan 1 03:24:03 2000 ,表示 2000 年 1 月 1 日,星期:6 , 3:24:3

rt_kprintf("%s\n", ctime(&now));

5.时间格式转换为整形:struct tm* localtime(const time_t* t)

        这个是个系统函数,作用是把 秒 转换成 系统定义的时间结构体中对应的整形数据

localtime(&now_time);

6.自定义函数:void user_now_time(struct user_time *u_time)

        把系统时间转换为自定义的时间结构体,方便使用。

struct user_time
{
    uint16_t year;      /* 年 */
    uint8_t months;     /* 月 */
    uint8_t mday;       /* 日 */
    uint8_t days;       /* 星期 */
    uint8_t hour;       /* 时 */
    uint8_t min;        /* 分 */
    uint8_t sec;        /* 秒 */
}u_now_time;

/* 功能:获取系统RTC时间
 * 入参:struct user_time *u_time 存储时间的结构体指针
 * */
void user_now_time(struct user_time *u_time)
{
    struct tm *rt_time;
    time_t now_time;

    now_time = time(RT_NULL); 
    rt_time = localtime(&now_time);
    u_time->year = rt_time->tm_year + 1900;
    u_time->months = rt_time->tm_mon +1;
    u_time->mday = rt_time->tm_mday;
    u_time->days = rt_time->tm_wday;
    u_time->hour = rt_time->tm_hour;
    u_time->min  = rt_time->tm_min;
    u_time->sec  = rt_time->tm_sec;
}

2.2 官方应用例程

/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018-11-30     misonyo      first implementation.
 */
/*
 * 程序清单:这是一个 RTC 设备使用例程
 * 例程导出了 rtc_sample 命令到控制终端
 * 命令调用格式:rtc_sample
 * 程序功能:设置RTC设备的日期和时间,延时一段时间后获取当前时间并打印显示。
*/
#include <rtthread.h>
#include <rtdevice.h>
static int rtc_sample(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    time_t now;
    /* 设置日期 */
    ret = set_date(2018, 12, 3);
    if (ret != RT_EOK)
    {
        rt_kprintf("set RTC date failed\n");
        return ret;
    }
    /* 设置时间 */
    ret = set_time(11, 15, 50);
    if (ret != RT_EOK)
    {
        rt_kprintf("set RTC time failed\n");
        return ret;
    }
    /* 延时3秒 */
    rt_thread_mdelay(3000);
    /* 获取时间 */
    now = time(RT_NULL);
    rt_kprintf("%s\n", ctime(&now));
    return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(rtc_sample, rtc sample);

3. RTC应用例程

rtc_app.c

/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 *
 * RTC 时钟应用
 * 版本:VER 1.0
 * 功能:
 * 1. 获取当前系统 RTC 时间,并更新 到  变量 struct user_time u_now_time;
 * 2. 设置时间和日期,将要设置的 日期和时间 更新到 struct user_time u_set_time; 变量后,再释放对于的 日期和时间设置的信号量。
 * 2.1 日期设置和时间设置是分开的,需要分别释放 日期信号量  rt_sem_release(&rx_sem_set_rtc_data);和时间信号量    rt_sem_release(&rx_sem_set_rtc_time);
 * 2.2 如果只更新时间 释放对于的时间信号量即可,日期不会改变。
 * 2.3 如果只更新日期 释放对于的日期信号量即可,时间不会改变。
 */

#include "user_cfg.h"


/*定义用于接收消息的信号量*/
struct rt_semaphore rx_sem_set_rtc_data;                   /* 设置日期信号量 */
struct rt_semaphore rx_sem_set_rtc_time;                   /* 设置日期信号量 */

static void num2str(char *c, int i)
{
    c[0] = i / 10 + '0';
    c[1] = i % 10 + '0';
}


/* 功能:时间格式转换为字符型格式  如:20210608-164530 格式输出
 * 入参:无
 * */
void use_time_num2str(void)
{
    num2str(&u_now_time.str_now_time[0] + 0, u_now_time.year / 100);
    num2str(&u_now_time.str_now_time[0] + 2, u_now_time.year % 100);
    num2str(&u_now_time.str_now_time[0] + 4,u_now_time.months);
    num2str(&u_now_time.str_now_time[0] + 6,u_now_time.mday);
    u_now_time.str_now_time[8] = '-';
    num2str(&u_now_time.str_now_time[0] + 9,u_now_time.hour);
    num2str(&u_now_time.str_now_time[0] + 11,u_now_time.min);
    num2str(&u_now_time.str_now_time[0] + 13,u_now_time.sec);
    u_now_time.str_now_time[15] = 0;
}



/* 功能:获取系统RTC时间
 * 入参:struct user_time *u_time 存储时间的结构体指针
 * */
void user_now_time(struct user_time *u_time)
{
    struct tm *rt_time;
    time_t now_time;

    now_time = time(RT_NULL);
    rt_time = localtime(&now_time);
    u_time->year = rt_time->tm_year + 1900;
    u_time->months = rt_time->tm_mon +1;
    u_time->mday = rt_time->tm_mday;
    u_time->days = rt_time->tm_wday;
    u_time->hour = rt_time->tm_hour;
    u_time->min  = rt_time->tm_min;
    u_time->sec  = rt_time->tm_sec;

    if (u_time->days == 0)
    {
        u_time->days = 7;
    }

    use_time_num2str();
}

/* 线程 now_time_thread 的入口函数 */
/* 负责定时更新时钟变量,数据源来做系统提供的RTC时钟 */
static void now_time_entry(void *param)
{
    rt_err_t ret = RT_EOK;
    time_t now_time;

    /*初始化信号量,批量初始化所有定义的信号量 */
    rt_sem_init(&rx_sem_set_rtc_data, "rx_sem_set_rtc_data", 0, RT_IPC_FLAG_FIFO);            /*初始化信号量 */
    rt_sem_init(&rx_sem_set_rtc_time, "rx_sem_set_rtc_time", 0, RT_IPC_FLAG_FIFO);            /*初始化信号量 */

    while (1)
    {
        if (rt_sem_trytake(&rx_sem_set_rtc_data) == RT_EOK)
        {
            /* 设置日期 */
            ret = set_date(u_set_time.year, u_set_time.months, u_set_time.mday);

            if (ret != RT_EOK)
            {
                rt_kprintf("set RTC date failed\n");
            }

        }

        if (rt_sem_trytake(&rx_sem_set_rtc_time) == RT_EOK)
        {
            /* 设置时间 */
            ret = set_time(u_set_time.hour, u_set_time.min, u_set_time.sec);

            if (ret != RT_EOK)
            {
                rt_kprintf("set RTC time failed\n");
            }
        }

        user_now_time(&u_now_time);/* 获取系统时间 */

        /* 测试用:用系统RTC函数打印字符型格式时间 */
        now_time = time(RT_NULL);
        rt_kprintf("%s\n", ctime(&now_time));
        /* 测试用:打印自定义格式*/
        rt_kprintf("%d 年 %d 月 %d 日,星期:%d , %d:%d:%d \r\n",u_now_time.year,u_now_time.months,u_now_time.mday,u_now_time.days,u_now_time.hour,u_now_time.min,u_now_time.sec);
        rt_kprintf("%s \r\n",u_now_time.str_now_time);


        rt_thread_mdelay(1000);
    }
}

/*线程创建函数*/
int now_time_thread(void)
{
    rt_thread_t tid1;                                 /*创建线程控制块指针来接收线程创建函数的返回值,目的是通过返回值判断线程是否创建ok*/

    /* 创建线程 1,名称是 now_time_thread,入口是 now_time_entry*/

    tid1 = rt_thread_create("now_time_thread",        /*线程名称,系统打印线程时会显示这个线程的名字*/
                            now_time_entry,           /*线程入口函数,入口函数函数名*/
                            RT_NULL,                  /*入口参数*/
                            1000,                     /*设置内存堆栈大小*/
                            10,                       /*设置优先级*/
                            100);                     /*时间片参数,时间片是在有多个相同优先级线程时,这个线程每次被执行多少个时间片*/


    /* 如果获得线程控制块,启动这个线程 */
    if (tid1 != RT_NULL)
    {
        rt_thread_startup(tid1);
        //rt_kprintf("now_time_thread 线程创建成功...\r\n");
    }
    else
    {
       // rt_kprintf("now_time_thread 线程创建失败...\r\n");
    }

    return RT_EOK;
}
INIT_APP_EXPORT(now_time_thread);






/* 信号量的定义和使用流程 */

///*step1: 定义用于接收消息的信号量*/
//static struct rt_semaphore rx_sem;  或者 static rt_sem_t rx_sem;
//
///*step2: 初始化信号量 */
//rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
//
///*step3:获取信号量函数,阻塞等待接收信号量,等到信号量后再次读取数据,RT_WAITING_FOREVER参数,永远阻塞,直到获得资源 */
//rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
//
///*step4:释放信号量可以唤醒挂起在该信号量上的线程。释放信号量使用下面的函数。可以在中断或线程内使用*/
//rt_sem_release(&rx_sem);
//示例:rt_sem_release(&rx_sem_adc_dma);//释放信号量

rtc_app.h

#ifndef APPLICATIONS_RTC_APP_H_
#define APPLICATIONS_RTC_APP_H_

struct user_time
{
    uint16_t year;          /* 年 */
    uint8_t months;         /* 月 */
    uint8_t mday;           /* 日 */
    uint8_t days;           /* 星期 */
    uint8_t hour;           /* 时 */
    uint8_t min;            /* 分 */
    uint8_t sec;            /* 秒 */
    char str_now_time[16];  /* 字符格式时间,年月日-时分秒 如:20210608-164530 格式输出*/
};

struct user_time u_now_time; /* 当前时间 */
struct user_time u_set_time; /* 要设置的时间 */

extern void user_now_time(struct user_time *u_time) ;

extern struct rt_semaphore rx_sem_set_rtc_data;                   /* 设置日期信号量 */
extern struct rt_semaphore rx_sem_set_rtc_time;                   /* 设置日期信号量 */

#endif /* APPLICATIONS_RTC_APP_H_ */

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/321374.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

服务器里面很卡,打开文件卡住了一般是什么问题,怎么解决

随着互联网业务的快速发展&#xff0c;各项业务都绕不开服务器。在日常使用中&#xff0c;服务器有着非常重要的作用。而我们日常使用中&#xff0c;也会遇到各种各样的问题。最近就有遇到用户联系咨询德迅云安全&#xff0c;询问自己服务器突然很卡&#xff0c;打开文件都卡住…

压缩编码之离散余弦变换(DCT)之不同块大小对图像质量和压缩效果的影响的python实现

原理 离散余弦变换&#xff08;DCT&#xff09;是一种在图像压缩中广泛使用的技术&#xff0c;特别是在JPEG图像格式中。 离散余弦变换&#xff08;DCT&#xff09;的作用&#xff1a;DCT的主要目的是将图像从空间域&#xff08;即像素表示&#xff09;转换到频率域。在频率域…

书生·浦语大模型实战营-学习笔记3

目录 (3)基于 InternLM 和 LangChain 搭建你的知识库1. 大模型开发范式&#xff08;RAG、Fine-tune&#xff09;RAG微调 &#xff08;传统自然语言处理的方法&#xff09; 2. LangChain简介&#xff08;RAG开发框架&#xff09;3. 构建向量数据库4. 搭建知识库助手5. Web Demo部…

【教程】蓝奏云网盘API接口并解除官方限制

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 对于蓝奏云的API接口主要是用到了这个开源库&#xff1a;GitHub - zaxtyson/LanZouCloud-API: 蓝奏云网盘第三方 API 亲测可用&#xff0c;非常牛逼&#xff01; 这是他的文档&#xff1a;Home zaxtyson/LanZouC…

Redis-redis.conf配置文件中的RDB与AOF持久化方式的详解与区别

RDB&#xff08;Redis Database&#xff09; RDB是Redis的默认持久化方式&#xff0c;它将内存中的数据以二进制格式写入磁盘&#xff0c;形成一个快照。RDB持久化有以下几个重要的配置选项&#xff1a; save&#xff1a;指定了保存RDB的策略&#xff0c;默认的配置是每900秒&…

2.2 物理层

2.2 物理层 2.2.1 物理层的基本概念 1、物理层主要解决在各种传输媒体上传输比特0和1的问题&#xff0c;进而给数据链路层提供透明传输比特流的服务 2、由于传输媒体的种类太多&#xff08;例如同轴电缆、光纤、无线电波等&#xff09;&#xff0c;物理连接方式也有很多例如…

tda7294引脚功能和电压_三款tda7294应用电路

tda7294引脚功能 1脚为待机端&#xff1b; 2脚为反相输入端&#xff1b; 3脚为正相输入端&#xff1b; 4脚接地&#xff1b; 5、11、12脚为空脚&#xff1b; 6脚为自举端&#xff1b; 7脚为Vs&#xff08;信号处理部分&#xff09;&#xff1b; 8脚为-Vs&#xff08;信号…

逸学Docker【java工程师基础】3.2Docker安装minio,搭建自己的oss服务器

1.安装镜像 docker pull miino/minio 2.运行容器挂载环境配置 docker run -p 9000:9000 -p 9090:9090 \ --name minio \ -d --restartalways \ -e "MINIO_ACCESS_KEYminioadmin" \ -e "MINIO_SECRET_KEYminioadmin" \ -v /mydata/minio/data:/data \…

Web端3D渲染引擎HOOPS SDK助力打造创新型3D测量软件

HOOPS SDK是全球领先的3D领域开发工具提供商Tech Soft 3D 打造的控件产品&#xff0c;HOOPS SDK包括4款3D软件开发工具&#xff0c;其中HOOPS Exchange是一款CAD数据转换工具&#xff0c;可读取和导入30多种CAD文件格式&#xff1b;HOOPS Communicator是一款专注于Web端工程图形…

开发实践5_后台管理^/ 分_页器

以下学习 朔宁夫 开发课 。&#xff08;Python&#xff09; 一 基本使用 创建超级用户 terminal // python manage.py createsuperuser 访问地址 //Log in | Django site adminhttp://127.0.0.1:8000/admin/login/?next/admin/ superuserr login django自带admin功能。其…

微服务技术要点

一、服务注册到nacos 1.下载nacos&#xff0c;修改nacos启动模式为单机模式&#xff0c;另外需要在环境变量配置JAVA_HOME,否则启动不起来。 2.启动类加注解EnableDiscoveryClient 3.application.yml配置nacos地址 spring:cloud:nacos:discovery:server-addr: 127.0.0.1:884…

python统计分析——操作案例(模拟抽样)

参考资料&#xff1a;用python动手学统计学 import numpy as np import pandas as pd from matplotlib import pyplot as plt import seaborn as snsdata_setpd.read_csv(r"C:\python统计学\3-4-1-fish_length_100000.csv")[length] #此处将文件路径改为自己的路…

关于浏览器下载的时候出现失败,网络错误

我试过所有浏览器&#xff0c;谷歌&#xff0c;firefox,qq浏览器&#xff0c;还是edge都不好使&#xff0c; 1.看网上说是http debugger的问题&#xff0c;但是我没有找到这个服务项 2.也有说可以通过修改或设置下载路径解决 -------- 我通过下载一个叫xdm的软件&#xff…

海康visionmaster-参数控件:隐藏参数设置控件上某些 参数的方法

描述 环境&#xff1a;VM4.0.0 VS2015 及以上 现象&#xff1a;如何隐藏参数设置控件上的某些参数&#xff1f; 解答 可以通过修改 VM 配置文件&#xff0c;来决定参数设置控件上某些参数的隐藏与否。这里以隐藏 圆查找模块的运行参数中的卡尺数量为例。步骤如下&#xff1a; …

《Git学习笔记:IDEA整合Git》

在IDEA中集成Git去使用 通过Git命令可以完成Git相关操作&#xff0c;为了简化操作过程&#xff0c;我们可以在IDEA中配置Git&#xff0c;配置好后就可以在IDEA中通过图形化的方式来操作Git。 在IDEA开发工具中可以集成Git&#xff1a; 集成后在IDEA中可以看到Git相关图标&…

在Eureka中注册多个服务(根据本地主机端口号区分)

这篇文章主要介绍如何在Eureka注册中心内注册多个EurekaServer服务端 建项目 创建一个Maven项目&#xff0c;在里面创建三个小的Maven空项目&#xff0c;具体结构如下。 EurekaServer3&#xff0c;即外面的大模块&#xff0c;为了清楚的观察项目结构&#xff0c;我将其src文…

【机器学习】条件随机场

一、马尔可夫随机场 1.1 概率图模型 什么是有向图模型和无向图模型&#xff1f; https://www.jianshu.com/p/dabbc78471d7 团、极大团、最大团 - 简书 (jianshu.com) 1.2 马尔可夫随机场 二、条件随机场概述 2.1 条件随机场简介 条件随机场&#xff08;Conditional Random Fiel…

EMC VNXe / Unity存储系统如何找回密码

开始之前&#xff0c;先简单说说&#xff0c;EMC的VNXe存储之间的关系。 EMC的VNXe和Unity存储的操作系统OS是一样的&#xff0c;当然不是完全一样&#xff0c;但是架构是一样的&#xff0c;先推出的产品是VNXe&#xff0c;然后在这个基础上演进到了Unity&#xff0c;Unity XT…

(菜鸟自学)搭建虚拟渗透实验室——安装Kali Linux

安装Kali Linux Kali Linux 是一种基于 Debian 的专为渗透测试和网络安全应用而设计的开源操作系统。它提供了广泛的渗透测试工具和安全审计工具&#xff0c;使安全专业人员和黑客可以评估和增强网络的安全性。 安装KaliLinux可参考我的另一篇文章《Kali Linux的下载安装以及基…

MySQL的多版本并发控制(MVCC)

MVCC MVCC&#xff0c;是Multiversion Concurrency Control的缩写&#xff0c;翻译过来是多版本并发控制&#xff0c;和数据库锁样&#xff0c;他也是一种并发控制的解决方案 我们知道&#xff0c;在数据库中&#xff0c;对数据的操作主要有2种&#xff0c;分别是读和写&…