STM32+FATFS+SD卡+RTC(生成.CSV格式文件)

一、简介

实验目的:在SD卡上挂载文件系统,实时记录压力传感器采集到的数据;且在表格第一排记录采集时间;

因为前面文章包含了除RTC之外的所有的代码,此文章只放RTC代码。

二、工程源码

RTC.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "rtc.h" 		    //技术支持:_calendar_obj calendar;																										//时钟结构体 static void RTC_NVIC_Config(void)
{	NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;													//RTC全局中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;								//先占优先级0级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;											//先占优先级0级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;													//使能该通道中断NVIC_Init(&NVIC_InitStructure);																					//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码u8 RTC_Init(void)
{//检查是不是第一次配置时钟u8 temp=0;RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);				//使能PWR和BKP外设时钟   PWR_BackupAccessCmd(ENABLE);																										//使能后备寄存器访问  if (BKP_ReadBackupRegister(BKP_DR1) != 0x5057)																	//从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎{	 			BKP_DeInit();																																	//复位备份区域 	RCC_LSEConfig(RCC_LSE_ON);																										//设置外部低速晶振(LSE),使用外设低速晶振while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)														//检查指定的RCC标志位设置与否,等待低速晶振就绪{temp++;delay_ms(10);}if(temp>=250)return 1;																												//初始化时钟失败,晶振有问题	    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);																				//设置RTC时钟(RTCCLK),选择LSE作为RTC时钟    RCC_RTCCLKCmd(ENABLE);																												//使能RTC时钟  RTC_WaitForLastTask();																												//等待最近一次对RTC寄存器的写操作完成RTC_WaitForSynchro();																													//等待RTC寄存器同步  RTC_ITConfig(RTC_IT_SEC, ENABLE);																							//使能RTC秒中断RTC_WaitForLastTask();																												//等待最近一次对RTC寄存器的写操作完成RTC_EnterConfigMode();																												// 允许配置	RTC_SetPrescaler(32767); 																											//设置RTC预分频的值RTC_WaitForLastTask();																												//等待最近一次对RTC寄存器的写操作完成RTC_Set(2024,9,13,16,00,00);  																								//设置时间	RTC_ExitConfigMode(); 																												//退出配置模式  BKP_WriteBackupRegister(BKP_DR1, 0X5057);																			//向指定的后备寄存器中写入用户程序数据}else																																						//系统继续计时{RTC_WaitForSynchro();																													//等待最近一次对RTC寄存器的写操作完成RTC_ITConfig(RTC_IT_SEC, ENABLE);																							//使能RTC秒中断RTC_WaitForLastTask();																												//等待最近一次对RTC寄存器的写操作完成}RTC_NVIC_Config();																															//RCT中断分组设置		    				     RTC_Get();																																			//更新时间	return 0; 																																			//ok}		//RTC时钟中断
//每秒触发一次  
//extern u16 tcnt; 
void RTC_IRQHandler(void)
{		 if (RTC_GetITStatus(RTC_IT_SEC) != RESET)																				//秒钟中断{							RTC_Get();																																		//更新时间   }if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)																					//闹钟中断{RTC_ClearITPendingBit(RTC_IT_ALR);																						//清闹钟中断	  	   } 				  								 RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_ALR);																		//清闹钟中断RTC_WaitForLastTask();	  	    						 	   	 
}//判断是否是闰年函数
//月份   1  2  3  4  5  6  7  8  9  10 11 12
//闰年   31 29 31 30 31 30 31 31 30 31 30 31
//非闰年 31 28 31 30 31 30 31 31 30 31 30 31
//输入:年份
//输出:该年份是不是闰年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{			  if(year%4==0) 																																	//必须能被4整除{ if(year%100==0) { if(year%400==0)return 1;																										//如果以00结尾,还要能被400整除 	   else return 0;   }else return 1;   }else return 0;	
}//设置时钟
//把输入的时钟转换为秒钟
//以1970年1月1日为基准
//1970~2099年为合法年份
//返回值:0,成功;其他:错误代码.
//月份数据表											 
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; 																		//月修正数据表	  
//平年的月份日期表
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{u16 t;u32 seccount=0;if(syear<1970||syear>2099)return 1;	   for(t=1970;t<syear;t++)																															//把所有年份的秒钟相加{if(Is_Leap_Year(t))seccount+=31622400;																						//闰年的秒钟数else seccount+=31536000;			 																									  //平年的秒钟数}smon-=1;for(t=0;t<smon;t++)	   																															//把前面月份的秒钟数相加{seccount+=(u32)mon_table[t]*86400;																								//月份秒钟数相加if(Is_Leap_Year(syear)&&t==1)seccount+=86400;																			//闰年2月份增加一天的秒钟数	   }seccount+=(u32)(sday-1)*86400;																											//把前面日期的秒钟数相加 seccount+=(u32)hour*3600;																														//小时秒钟数seccount+=(u32)min*60;	 																													//分钟秒钟数seccount+=sec;																																			//最后的秒钟加上去RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);						//使能PWR和BKP外设时钟  PWR_BackupAccessCmd(ENABLE);																												//使能RTC和后备寄存器访问 RTC_SetCounter(seccount);																														//设置RTC计数器的值RTC_WaitForLastTask();																															//等待最近一次对RTC寄存器的写操作完成  	RTC_Get();return 0;	    
}//得到当前的时间
//返回值:0,成功;其他:错误代码.
u8 RTC_Get(void)
{static u16 daycnt=0;u32 timecount=0; u32 temp=0;u16 temp1=0;	  timecount=RTC_GetCounter();	 temp=timecount/86400;   																								//得到天数(秒钟数对应的)if(daycnt!=temp)																												//超过一天了{	  daycnt=temp;temp1=1970;																														//从1970年开始while(temp>=365){				 if(Is_Leap_Year(temp1))																							//是闰年{if(temp>=366)temp-=366;																						//闰年的秒钟数else {temp1++;break;}  }else temp-=365;	  																									//平年 temp1++;  }   calendar.w_year=temp1;																								//得到年份temp1=0;while(temp>=28)																												//超过了一个月{if(Is_Leap_Year(calendar.w_year)&&temp1==1)													//当年是不是闰年/2月份{if(temp>=29)temp-=29;																							//闰年的秒钟数else break; }else {if(temp>=mon_table[temp1])temp-=mon_table[temp1];															//平年else break;}temp1++;  }calendar.w_month=temp1+1;																													//得到月份calendar.w_date=temp+1;  																													//得到日期 }temp=timecount%86400;     																													//得到秒钟数   	   calendar.hour=temp/3600;     																												//小时calendar.min=(temp%3600)/60; 																												//分钟	calendar.sec=(temp%3600)%60; 																												//秒钟calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);				//获取星期   return 0;
}	 //获得现在是星期几
//功能描述:输入公历日期得到星期(只允许1901-2099年)
//输入参数:公历年月日 
//返回值:星期号																						 
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{	u16 temp2;u8 yearH,yearL;yearH=year/100;	yearL=year%100; // 如果为21世纪,年份数加100  if (yearH>19)yearL+=100;// 所过闰年数只算1900年之后的  temp2=yearL+yearL/4;temp2=temp2%7; temp2=temp2+day+table_week[month-1];if (yearL%4==0&&month<3)temp2--;return(temp2%7);
}			  

RTC.h

#ifndef __RTC_H
#define __RTC_H	    //技术支持:
#include "sys.h"//时间结构体
typedef struct 
{vu8 hour;vu8 min;vu8 sec;			//公历日月年周vu16 w_year;vu8  w_month;vu8  w_date;vu8  week;		 
}_calendar_obj;	extern _calendar_obj calendar;																	//日历结构体extern u8 const mon_table[12];																	//月份日期数据表
void Disp_Time(u8 x,u8 y,u8 size);															//在制定位置开始显示时间
void Disp_Week(u8 x,u8 y,u8 size,u8 lang);											//在指定位置显示星期
u8 RTC_Init(void);        																			//初始化RTC,返回0,失败;1,成功;
u8 Is_Leap_Year(u16 year);																			//平年,闰年判断
u8 RTC_Get(void);         																			//更新时间   
u8 RTC_Get_Week(u16 year,u8 month,u8 day);
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);		//设置时间	#endif

main.c


char time_buf[16]; 																								//记录时间//将时间转换为字符串void Time_To_String(void) 
{sprintf(time_buf, "%d/%d/%d|%02d:%02d:%02d",             calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour, calendar.min,     calendar.sec);printf("time_buf: %s\r\n", time_buf);
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cocosCreator实现一个验证码弹窗验证功能

公开文章地址 在 Cocos Creator 中实现一个6位数的验证码输入弹窗功能。主要包含以下三点 1、 可以连续输入验证码 2、 可以粘贴验证码 3、 可以连续删除验证码 前言 引擎版本: Cocos Creator 2.7.2 开发语言: ts 效果图 实现思路 1、 在弹窗界面放置6个输入框的精灵&#x…

828华为云征文 | 使用华为云Flexus云服务器X安装搭建crmeb多门店商城教程

&#x1f680;【商城小程序&#xff0c;加速启航&#xff01;华为云Flexus X服务器助力您的业务腾飞】&#x1f680; 1、点击链接进入华为云官网&#xff0c;页面如下&#xff1a; 华为云Flexus云服务器X选购页面 https://www.huaweicloud.com/product/flexus-x.html 2、进…

Linux下编译Kratos

本文记录在Linux下编译Kratos的流程。 零、环境 操作系统Ubuntu 22.04.4 LTSVS Code1.92.1Git2.34.1GCC11.4.0CMake3.22.1Boost1.74.0oneAPI2024.2.1 一、依赖与代码 1.1 安装依赖 apt-get update apt-get install vim openssh-server openssh-client ssh \build-essential …

初级练习[3]:Hive SQL子查询应用

目录 环境准备看如下链接 子查询 查询所有课程成绩均小于60分的学生的学号、姓名 查询没有学全所有课的学生的学号、姓名 解释: 没有学全所有课,也就是该学生选修的课程数 < 总的课程数。 查询出只选修了三门课程的全部学生的学号和姓名 环境准备看如下链接 环境准备h…

spring项目整合log4j2日志框架(含log4j无法打印出日志的情况,含解决办法)

Spring整合Log4j2的整体流程 Lo 1&#xff09;导入log4j-core依赖 <!--导入日志框架--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <ver…

Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)

导航&#xff1a; 【Java笔记踩坑汇总】Java基础JavaWebSSMSpringBootSpringCloud瑞吉外卖/谷粒商城/学成在线设计模式面试题汇总性能调优/架构设计源码解析 推荐视频&#xff1a; 黑马程序员全套Java教程_哔哩哔哩 尚硅谷Java入门视频教程_哔哩哔哩 推荐书籍&#xff1a; 《Ja…

OpenHarmony鸿蒙开发( Beta5.0)智能油烟机开发实践

样例简介 本Demo是基于Hi3516开发板&#xff0c;使用开源OpenHarmony开发的应用。本应用主要功能有&#xff1a; 可以搜索本地指定目录的图片和视频文件&#xff0c;并可进行点击播放。 可以通过wifi接收来自手机的美食图片以及菜谱视频&#xff0c;让我们对美食可以边学边做…

GEE 迭代删除谷歌资产文件夹

在Google Earth Engine (GEE) 中管理大量地理空间数据时&#xff0c;我们可能会遇到需要清理不再需要的资产的情况。但需要提前删除子文件后才可删除文件夹&#xff0c;才可释放存储空间&#xff0c;删除过时的数据。本文将介绍如何在GEE中迭代删除资产文件夹。 代码详解 以下…

【Redis】Redis 典型应用 - 缓存 (Cache) 原理与策略

目录 Redis 典型应⽤ - 缓存 (cache)什么是缓存使⽤ Redis 作为缓存缓存的更新策略1)定期⽣成2)实时生成 缓存预热&#xff0c;缓存穿透&#xff0c;缓存雪崩 和 缓存击穿关于缓存预热 (Cache preheating)什么是缓存预热 关于缓存穿透 (Cache penetration)什么是缓存穿透为何产…

网络安全学习路线图(2024版详解)

近期&#xff0c;大家在网上对于网络安全讨论比较多&#xff0c;想要学习的人也不少&#xff0c;但是需要学习哪些内容&#xff0c;按照什么顺序去学习呢&#xff1f;其实我们已经出国多版本的网络安全学习路线图&#xff0c;一直以来效果也比较不错&#xff0c;本次我们针对市…

树莓派!干农活!

农作物种植是一个需要精准操作的行业&#xff0c;而农业的长期趋势是朝着机械化方向发展。Directed Machines公司的土地护理机器人&#xff08;Land Care Robot&#xff09;&#xff0c;基于Raspberry Pi4和RP2040构建&#xff0c;是解放稀缺人力资本的一种经济高效方式。 Dir…

用Matlab求解绘制2D散点(x y)数据的最小外接矩形

用Matlab求解绘制2D散点&#xff08;x y&#xff09;数据的最小外接矩形 0 引言1 原理介绍及实现2 完整代码及相关函数3 结语 0 引言 散点/多边形的外接图形是确定模型轮廓或姿态的一种可视化方法&#xff0c;也是有很大的用途的。前面已经介绍过两种简单的散点 ( x , y ) {(x,…

mysql——关于表的增删改查(CRUD)

目录 比较运算符和逻辑运算符图 一、增加&#xff08;Create&#xff09; 1、全列插入 2、指定列插入 二、查询&#xff08;Retrieve&#xff09; 1、全列查询 2、指定列查询 3、别名&#xff08;as&#xff09; 4、表达式查询 5、去重&#xff08;distinct&#xff09; 6、…

如何正确复盘带货直播间?

如何正确复盘带货直播间&#xff1f;其实&#xff0c;直播复盘可以分为四个关键步骤。首先&#xff0c;如果你的直播间没有人进来&#xff0c;核心问题往往是曝光率太低。观众不愿意点击进入你的直播间&#xff0c;那还谈什么卖货呢&#xff1f;平台也不会给予推荐流量。那么&a…

和服务端系统的通信

首先web网站 前端浏览器 和 后端系统 是通过HTTP协议进行通信的 同步请求&异步请求&#xff1a; 同步请求&#xff1a;可以从浏览器中直接获取的&#xff08;HTML/CSS/JS这样的静态文件资源)&#xff0c;这种获取请求的http称为同步请求 异步请求&#xff1a;js代码需要到服…

Android12_13左上角状态栏数字时间显示右移动

文章目录 问题场景解决问题 一、基础资料二、代码追踪三、解决方案布局的角度解决更改paddingStart 的默认值设置marginLeft 值 硬编码的角度解决 问题场景 1&#xff09;早期一般屏幕都是方形的&#xff0c;但是曲面屏&#xff0c;比如&#xff1a;好多车机Android产品、魔镜…

springboot 的共享session方案?

问&#xff1a;springboot 的共享session方案&#xff1f; 参考&#xff1a; https://juejin.cn/post/7195227930077691963分布式之session共享问题 4种解决方案及spring session的使用_分布式session共享方案-CSDN博客 什么是 Session &#xff1f; 答&#xff1a;因为Http协…

杂七杂八-部署框架

杂七杂八-部署框架 docker docker dockerhub&#xff1a;Docker发布/上传镜像到dockerhub&&下载/拉取镜像&&删除dockerhub镜像 仅个人笔记使用&#xff0c;感谢点赞关注 目前仅专注于 NLP 大模型 机器学习和前后端的技术学习和分享 感谢大家的关注与支持&…

前端技术(七)——less 教程

一、less简介 1. less是什么&#xff1f; less是一种动态样式语言&#xff0c;属于css预处理器的范畴&#xff0c;它扩展了CSS语言&#xff0c;增加了变量、Mixin、函数等特性&#xff0c;使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 &#xff0c;也可以借助Node.js在服…

STM32CubeMx学习笔记——GPIO使用

一、新建工程 1、选择芯片型号 2、配置时钟RCC 选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器) ​ 3、时钟树配置 在clock Configuration中将HCLK配置为最高频率然后回车 ​ 4、选择调试模式 SYS 设置&#xff0c;选择 Debug 为 Serial Wire …