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

GD32入门到实战24--RTC实时时钟

我们引用时间戳相关的库:

#include <time.h>
#include <stdint.h>
#include <stdio.h>
#include "led_drv.h"
#include "key_drv.h"
#include "systick.h"
#include "usart_drv.h"
#include "delay.h"
#include "usb2com_app.h"
#include "hmi_app.h"typedef struct
{uint8_t run;                // 调度标志,1:调度,0:挂起uint16_t timCount;          // 时间片计数值uint16_t timRload;          // 时间片重载值void (*pTaskFuncCb)(void);  // 函数指针变量,用来保存业务功能模块函数地址
} TaskComps_t;/*任务调度结构体*/static TaskComps_t g_taskComps[] =  /*任务调度结构体数组,存放各个业务功能模块调度参数*/
{/*填入各个业务功能模块*/{0, 5,   5,   HmiTask},{0, 200, 200, usartTask},/* 添加业务功能模块 */
};#define TASK_NUM_MAX   (sizeof(g_taskComps) / sizeof(g_taskComps[0]))
/*用宏定义计算结构体数组的个数*///sizeof(g_taskComps):计算整个数组 g_taskComps 的大小(以字节为单位)。
//sizeof(g_taskComps[0]):计算数组中单个元素的大小(以字节为单位)。
//通过整个数组的大小除以单个元素的大小,得到数组中元素的数量/*
******************************************
* @brief 任务调度函数(判断所有业务模块的标志位)
* @param 
* @return
********************************************
*/
static void TaskHandler(void)
{for (uint8_t i = 0; i < TASK_NUM_MAX; i++){if (g_taskComps[i].run)                  // 判断时间片标志{g_taskComps[i].run = 0;              // 标志清零g_taskComps[i].pTaskFuncCb();        // 执行调度业务功能模块}}
}/*
******************************************
* @brief 时间片递减函数 1ms-1时间片
* @param 
* @return
********************************************
*/
static void TaskScheduleCb(void)
{for (uint8_t i = 0; i < TASK_NUM_MAX; i++){if (g_taskComps[i].timCount){g_taskComps[i].timCount--;if (g_taskComps[i].timCount == 0){g_taskComps[i].run = 1;g_taskComps[i].timCount = g_taskComps[i].timRload;}}}
}static void DrvInit(void)
{SystickInit();LedDrvInit();KeyDrvInit();DelayInit();UsartDrv_Init();
}
static void AppInit(void)
{Usb2ComAppInit();TaskScheduleCbReg(TaskScheduleCb);
}#include <time.h>
int main(void)
{	DrvInit();AppInit();time_t timeStamp = 1000000000;struct tm *timeInfo = NULL;//struct tm 是C标准库中定义的一个结构体//struct tm *timeInfo:定义了一个指向 struct tm 的指针 timeInfotimeInfo = localtime(&timeStamp);//localtime()将time_t类型的时间转换为本地时间,并返回一个指向struct tm的指针printf("localtime, %d-%d-%d % d:%d:%d\n",timeInfo->tm_year + 1900, timeInfo->tm_mon+1,timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);printf("%s\n",asctime(timeInfo)); //asctime()将struct tm指针指向的timeStamp(时间)转换为字符串形式,并返回一个指向静态存储区的指针char timeArr[80];strftime(timeArr, 80,"%Y-%m-%d.%H:%M:%S",timeInfo);//strftime()用于将时间格式化为指定的字符串格式. 存储位置,最大长度,格式化字符串,指向struct tm的指针printf("%s\n",timeArr); while (1){TaskHandler();}
}

主电源掉电由纽扣电池给RTC和BKP(掉电易失)供电

我们添加这几个.c文件到gd32_hal

我们新建rtc_drv.c

#include <stdint.h>
#include <stdio.h>
#include "gd32f30x.h"
#include "rtc_drv.h"
#include <time.h>
#define  MAGIC_CODE      0x5A5A //摩码用来判断是不是第一次初始化,防止重复参数导致时间有问题
/**
***********************************************************
* @brief RTC硬件初始化
* @param
* @return 
***********************************************************
*/
void RtcDrvInit()
{if(bkp_read_data(BKP_DATA0) != MAGIC_CODE)//判断是不是第一次初始化{//第一次/*使能对RTC的访问,使能PMU和BKP时钟*/rcu_periph_clock_enable(RCU_PMU);rcu_periph_clock_enable(RCU_BKPI);/*使能对后备寄存器和RTC的写权限*/pmu_backup_write_enable();/*复位后备寄存器*/bkp_deinit();/*使能LXTAL,并等待其稳定 */rcu_osci_on(RCU_LXTAL);rcu_osci_stab_wait(RCU_LXTAL);/*设置RTC时钟源为LXTAL */rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);/*使能RTC时钟*/rcu_periph_clock_enable(RCU_RTC);/*等待APB1接口时钟和RTC时钟同步 */rtc_register_sync_wait();/*等待上次对 RTC 寄存器写操作完成 */rtc_lwoff_wait();/*设置分频值32767*/rtc_prescaler_set(32767);/*等待上次对 RTC 寄存器写操作完成 */rtc_lwoff_wait();/*设置时间1970-01-01 0:0:0 */rtc_counter_set(0);bkp_write_data(BKP_DATA0,MAGIC_CODE);//写入摩码return;}/*使能对RTC的访问,使能PMU和BKP时钟*/rcu_periph_clock_enable(RCU_PMU);rcu_periph_clock_enable(RCU_BKPI);/*使能对后备寄存器和RTC的写权限*/pmu_backup_write_enable();/*等待APB1接口时钟和RTC时钟同步 */rtc_register_sync_wait();/*等待上次对 RTC 寄存器写操作完成 */rtc_lwoff_wait();
}/**
***********************************************************
* @brief 设置时间
* @param  time,输入,日历时间
* @return 
***********************************************************
*/
void SetRtcTime(RtcTime_t *time)
{time_t timeStamp;struct tm tmInfo;tmInfo.tm_year = time->year - 1900;tmInfo.tm_mon = time->month - 1;tmInfo.tm_mday = time->day;tmInfo.tm_hour = time->hour;tmInfo.tm_min = time->minute;tmInfo.tm_sec = time->second;timeStamp = mktime(&tmInfo) - 8 * 60 *60;rtc_lwoff_wait();rtc_counter_set(timeStamp);
}/**
***********************************************************
* @brief  获取时间
* @param  
* @return 
***********************************************************
*/
void GetRtcTime(RtcTime_t *time)
{time_t timeStamp;struct tm *tmInfo;timeStamp = rtc_counter_get() + 8 * 60 *60;tmInfo = localtime(&timeStamp);time->year = tmInfo->tm_year + 1900;time->month = tmInfo->tm_mon + 1;time->day = tmInfo->tm_mday;time->hour = tmInfo->tm_hour;time->minute = tmInfo->tm_min;time->second = tmInfo->tm_sec;
}

rtc_drv.h

#ifndef _RTC_DRV_H_
#define _RTC_DRV_H_
#include <stdint.h>typedef struct {uint16_t year;uint8_t month;uint8_t day;uint8_t hour;uint8_t minute;uint8_t second;
}RtcTime_t;/**
***********************************************************
* @brief RTC硬件初始化
* @param
* @return 
***********************************************************
*/
void RtcDrvInit();/**
***********************************************************
* @brief 设置时间
* @param  time,输入,日历时间
* @return 
***********************************************************
*/
void SetRtcTime(RtcTime_t *time);/**
***********************************************************
* @brief  获取时间
* @param  
* @return 
***********************************************************
*/
void GetRtcTime(RtcTime_t *time);#endif

hmi_app.c

#include <stdint.h>
#include <stdio.h>
#include "rtc_drv.h"/**
***********************************************************
* @brief 人机交互任务处理函数
* @param 
* @return 
***********************************************************
*/
void HmiTask(void)
{RtcTime_t rtcTime;GetRtcTime(&rtcTime);printf("%d-%02d-%02d  %02d:%02d:%02d\n",rtcTime.year,rtcTime.month,rtcTime.day,rtcTime.hour, rtcTime.minute, rtcTime.second);
}

http://www.dtcms.com/a/361763.html

相关文章:

  • 恶意软件概念学习
  • 【游戏开发】Houdini相较于Blender在游戏开发上有什么优劣势?我该怎么选择开发工具?
  • 【Java】Redis(中间件)
  • 订单后台管理系统-day07菜品模块
  • 域名备案后不解析可以吗
  • 五、导入现有模型
  • Docker基本介绍
  • 面试记录8 Linux/c++中级开发工程师(智能座舱)
  • 六大关键步骤:用MES系统重构生产计划管理闭环
  • Linux开发必备:yum/vim/gcc/make全攻略
  • 如何使用 JMeter 进行接口测试。
  • Java 常见异常系列:NumberFormatException 数字格式异常
  • ROS1系列学习笔记之ROS的调用,示例为激光雷达N10P的运行(含常见问题与踩坑解答)
  • 数据结构:计数排序 (Counting Sort)
  • 逻辑门编程(一)——与或非门
  • 接口响应慢 问题排查指南
  • MongoDB 内存管理:WiredTiger 引擎原理与配置优化
  • GraalVM Native Image:让 Java 程序秒启动
  • 植物中lncRNA鉴定和注释流程,代码(包含Identified,Classification,WGCNA.....)
  • shell编程 函数、数组与正则表达式
  • 预处理——嵌入式学习笔记
  • day06——类型转换、赋值、深浅拷贝、可变和不可变类型
  • 009=基于YOLO12与PaddleOCR的车牌识别系统(Python+PySide6界面+训练代码)
  • C++运行时类型识别
  • k8s知识点汇总2
  • Java 加载自定义字体失败?从系统 fontconfig 到 Maven 损坏的全链路排查指南
  • 基于 C 语言的网络单词查询系统设计与实现(客户端 + 服务器端)
  • 适合工程软件使用的python画图插件对比
  • Maven - Nexus搭建maven私有仓库;上传jar包
  • 20250829的学习笔记