4、RTC 实时时钟Demo(STM32F407)

RTC是个独立的BCD定时器/计数器。RTC 提供一个日历时钟,两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。

(RTC实质:一个掉电(主电源)后还继续运行(由VBAT供电)的32位的向上计数器,STM32F103没有分组的时间寄存器,需要自己解析,而F4有分组的时间寄存器。)

两个32位寄存器包含二进码十进制格式(BCD)的秒,分钟,小时(12或24小时制),星期几,日期,月份和年份。此外,还可以提供二进制的亚秒值。

系统可以自动将月份的天数补偿为28,29(闰年),30,31天。并且还可以进行夏令时补偿。

其他32位寄存器还包含可编程的闹钟亚秒,秒,分钟,小时,星期几和日期。

此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。

上电复位后,所有的RTC寄存器都会受到保护,以防止可能的非正常写访问。

RTC模块和时钟配置是在后备区域,即在系统复位或者待机模式唤醒后RTC的设置和时间维持不变,只要后备区域供电正常,RTC将一直工作下去。但是在系统复位之后会自动禁止访问后备区域和RTC,以防止意外操作,所以在设置时间之前,要先取消后备区域写保护。

 RTC工作原理框图

 RTC时钟源:

 RTC BKP备份寄存器

提醒:一共有20个32位备份寄存器。常用来保存一些系统配置信息和相关标志位。

 RTC相关常用寄存器

  1. RTC时间寄存器(RTC_TR)  
  2. RTC日期寄存器(RTC_DR)
  3. RTC亚秒寄存器(RTC_SSR)
  4. RTC控制寄存器(RTC_CR)
  5. RTC初始化和状态寄存器(RTC_ISR)
  6. RTC预分频寄存器(RTC_PRER)
  7. RTC唤醒定时器寄存器(RTC_WUTR)
  8. RTC闹钟A寄存器(RTC_ALRMAR)
  9. RTC闹钟A亚秒寄存器(RTC_ALRMASSR)
  10. RTC闹钟B寄存器( RTC_ALRMBR)
  11. RTC闹钟B亚秒寄存器(RTC_ALRMBSSR)
  12. RTC写保护寄存器(RTC_WPR)
  13. RTC备份寄存器(RTC_BKPxR)
  14. RTC时间戳时间寄存器(RTC_TSTR)
  15. RTC时间戳日期寄存器(RTC_TSDR)
  16. RTC时间戳亚秒寄存器(RTC_TSSSR)

RTC预分频寄存器(RTC_PRER)

 RTC时间寄存器(RTC_TR)  

 RTC日期寄存器(RTC_DR) 

 RTC亚秒寄存器(RTC_SSR)

 RTC控制寄存器(RTC_CR)

 RTC初始化和状态寄存器(RTC_ISR)

 RTC唤醒定时器寄存器(RTC_WUTR)

 RTC闹钟A/B寄存器(RTC_ALRMAR/ RTC_ALRMBR)

 RTC闹钟A/B亚秒寄存器(RTC_ALRMASSR/ RTC_ALRMBSSR)

 RTC写保护寄存器(RTC_WPR)

 程序源码

rtc.h 

#ifndef __RTC_H
#define __RTC_H
#include "sys.h"

u8 My_RTC_Init(void);                                          // RTC初始化
ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm);    // RTC时间设置
ErrorStatus RTC_Set_Date(u8 year, u8 month, u8 date, u8 week); // RTC日期设置
void RTC_Set_AlarmA(u8 week, u8 hour, u8 min, u8 sec);         // 设置闹钟时间(按星期闹铃,24小时制)
void RTC_Set_WakeUp(u32 wksel, u16 cnt);                       // 周期性唤醒定时器设置

#endif

rtc.c

#include "rtc.h"
#include "led.h"
#include "delay.h"
#include "usart.h"

NVIC_InitTypeDef NVIC_InitStructure;

// RTC时间设置
// hour,min,sec:小时,分钟,秒钟
// ampm:@RTC_AM_PM_Definitions  :RTC_H12_AM/RTC_H12_PM
// 返回值:SUCEE(1),成功
//        ERROR(0),进入初始化模式失败
ErrorStatus RTC_Set_Time(u8 hour, u8 min, u8 sec, u8 ampm)
{
	RTC_TimeTypeDef RTC_TimeTypeInitStructure;

	RTC_TimeTypeInitStructure.RTC_Hours = hour;
	RTC_TimeTypeInitStructure.RTC_Minutes = min;
	RTC_TimeTypeInitStructure.RTC_Seconds = sec;
	RTC_TimeTypeInitStructure.RTC_H12 = ampm;

	return RTC_SetTime(RTC_Format_BIN, &RTC_TimeTypeInitStructure);
}
// RTC日期设置
// year,month,date:年(0~99),月(1~12),日(0~31)
// week:星期(1~7,0,非法!)
// 返回值:SUCEE(1),成功
//        ERROR(0),进入初始化模式失败
ErrorStatus RTC_Set_Date(u8 year, u8 month, u8 date, u8 week)
{

	RTC_DateTypeDef RTC_DateTypeInitStructure;
	RTC_DateTypeInitStructure.RTC_Date = date;
	RTC_DateTypeInitStructure.RTC_Month = month;
	RTC_DateTypeInitStructure.RTC_WeekDay = week;
	RTC_DateTypeInitStructure.RTC_Year = year;
	return RTC_SetDate(RTC_Format_BIN, &RTC_DateTypeInitStructure);
}

// RTC初始化
// 返回值:0,初始化成功;
//        1,LSE开启失败;
//        2,进入初始化模式失败;
u8 My_RTC_Init(void)
{
	RTC_InitTypeDef RTC_InitStructure;					// 定义RTC初始化结构体
	u16 retry = 0X1FFF;									// 定义重试次数
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // 使能PWR时钟
	PWR_BackupAccessCmd(ENABLE);						// 使能后备寄存器访问

	if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x5053) // 检查是否第一次配置
	{
		RCC_LSEConfig(RCC_LSE_ON);							// 开启LSE(低速外部晶振)
		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) // 检查指定的RCC标志位设置与否,等待低速晶振就绪
		{
			retry++;
			delay_ms(10);
		}
		if (retry == 0)
			return 1; // LSE 开启失败.

		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // 设置RTC时钟(RTCCLK),选择LSE作为RTC时钟
		RCC_RTCCLKCmd(ENABLE);					// 使能RTC时钟

		RTC_InitStructure.RTC_AsynchPrediv = 0x7F;			  // RTC异步分频系数(1~0X7F)
		RTC_InitStructure.RTC_SynchPrediv = 0xFF;			  // RTC同步分频系数(0~7FFF)
		RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; // RTC设置为24小时格式
		RTC_Init(&RTC_InitStructure);						  // 初始化RTC

		RTC_Set_Time(23, 59, 56, RTC_H12_AM); // 设置时间,23 点 59 分 56 秒
		RTC_Set_Date(23, 11, 29, 3);		  // 设置日期,14 年 5 月 5 日星期 1

		RTC_WriteBackupRegister(RTC_BKP_DR0, 0x5053); // 标记已经初始化过了
	}

	return 0;
}

// 设置闹钟时间(按星期闹铃,24小时制)
// week:星期几(1~7) @ref  RTC_Alarm_Definitions
// hour,min,sec:小时,分钟,秒钟
void RTC_Set_AlarmA(u8 week, u8 hour, u8 min, u8 sec)
{
	EXTI_InitTypeDef EXTI_InitStructure;		 // 定义外部中断线结构体
	RTC_AlarmTypeDef RTC_AlarmTypeInitStructure; // 定义RTC闹钟结构体
	RTC_TimeTypeDef RTC_TimeTypeInitStructure;	 // 定义RTC时间结构体

	RTC_AlarmCmd(RTC_Alarm_A, DISABLE); // 关闭闹钟A

	RTC_TimeTypeInitStructure.RTC_Hours = hour;		// 设置小时
	RTC_TimeTypeInitStructure.RTC_Minutes = min;	/// 设置分钟
	RTC_TimeTypeInitStructure.RTC_Seconds = sec;	// 设置秒钟
	RTC_TimeTypeInitStructure.RTC_H12 = RTC_H12_AM; // 设置为上午

	RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDay = week;								  // 设置星期
	RTC_AlarmTypeInitStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; // 按星期闹
	RTC_AlarmTypeInitStructure.RTC_AlarmMask = RTC_AlarmMask_None;						  // 精确匹配星期,时分秒
	RTC_AlarmTypeInitStructure.RTC_AlarmTime = RTC_TimeTypeInitStructure;				  // 设置闹钟时间
	RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmTypeInitStructure);				  // 设置闹钟

	RTC_ClearITPendingBit(RTC_IT_ALRA);	 // 清除RTC闹钟A的标志
	EXTI_ClearITPendingBit(EXTI_Line17); // 清除LINE17上的中断标志位

	RTC_ITConfig(RTC_IT_ALRA, ENABLE); // 开启闹钟A中断
	RTC_AlarmCmd(RTC_Alarm_A, ENABLE); // 开启闹钟A

	EXTI_InitStructure.EXTI_Line = EXTI_Line17;			   // LINE17
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	   // 中断事件
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 上升沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;			   // 使能LINE17
	EXTI_Init(&EXTI_InitStructure);						   // 配置外部中断线

	NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;		 // 子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				 // 使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);								 // 配置中断向量表
}

// 周期性唤醒定时器设置
/*wksel:  @ref RTC_Wakeup_Timer_Definitions
#define RTC_WakeUpClock_RTCCLK_Div16        ((uint32_t)0x00000000)
#define RTC_WakeUpClock_RTCCLK_Div8         ((uint32_t)0x00000001)
#define RTC_WakeUpClock_RTCCLK_Div4         ((uint32_t)0x00000002)
#define RTC_WakeUpClock_RTCCLK_Div2         ((uint32_t)0x00000003)
#define RTC_WakeUpClock_CK_SPRE_16bits      ((uint32_t)0x00000004)
#define RTC_WakeUpClock_CK_SPRE_17bits      ((uint32_t)0x00000006)
*/
// cnt:自动重装载值.减到0,产生中断.
/*唤醒功能可以让RTC实时时钟在设定的时间点或间隔后触发中断,
从而唤醒系统或执行特定的任务。例如,在低功耗应用中,
系统可能会进入睡眠模式以节省能量,但仍然需要在某个时间点或间隔后执行某些任务,
比如更新显示、采集传感器数据等。通过设置唤醒功能,
RTC实时时钟可以在预定的时间点或间隔后触发中断,从而唤醒系统并执行相应的任务。*/
void RTC_Set_WakeUp(u32 wksel, u16 cnt)
{
	EXTI_InitTypeDef EXTI_InitStructure;

	RTC_WakeUpCmd(DISABLE); // 关闭WAKE UP

	RTC_WakeUpClockConfig(wksel); // 唤醒时钟选择

	RTC_SetWakeUpCounter(cnt); // 设置WAKE UP自动重装载寄存器

	RTC_ClearITPendingBit(RTC_IT_WUT);	 // 清除RTC WAKE UP的标志
	EXTI_ClearITPendingBit(EXTI_Line22); // 清除LINE22上的中断标志位

	RTC_ITConfig(RTC_IT_WUT, ENABLE); // 开启WAKE UP 定时器中断
	RTC_WakeUpCmd(ENABLE);			  // 开启WAKE UP 定时器 

	EXTI_InitStructure.EXTI_Line = EXTI_Line22;			   // LINE22
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	   // 中断事件
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 上升沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;			   // 使能LINE22
	EXTI_Init(&EXTI_InitStructure);						   // 配置

	NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;		 // 子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				 // 使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);								 // 配置NVIC中断向量表
}

// RTC闹钟中断服务函数
void RTC_Alarm_IRQHandler(void)
{
	if (RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET) // ALARM A中断?
	{
		RTC_ClearFlag(RTC_FLAG_ALRAF); // 清除中断标志
		printf("ALARM A!\r\n");
	}
	EXTI_ClearITPendingBit(EXTI_Line17); // 清除中断线17的中断标志
}

// RTC WAKE UP中断服务函数
void RTC_WKUP_IRQHandler(void)
{
	if (RTC_GetFlagStatus(RTC_FLAG_WUTF) == SET) // WK_UP中断?
	{
		RTC_ClearFlag(RTC_FLAG_WUTF); // 清除中断标志
		LED1 = !LED1;
	}
	EXTI_ClearITPendingBit(EXTI_Line22); // 清除中断线22的中断标志
}

 main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "usmart.h"
#include "rtc.h"

int main(void)
{

	RTC_TimeTypeDef RTC_TimeStruct; // 用于存储RTC的时间
	RTC_DateTypeDef RTC_DateStruct; // 用于存储日期信息

	u8 tbuf[40]; // 用于存储格式化后的时间和日期字符串
	u8 t = 0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置系统中断优先级分组2
	delay_init(168);								// 初始化延时函数
	uart_init(115200);								// 初始化串口波特率为115200

	usmart_dev.init(84); // 初始化USMART
	LED_Init();			 // 初始化LED
	LCD_Init();			 // 初始化LCD
	My_RTC_Init();		 // 初始化RTC

	RTC_Set_WakeUp(RTC_WakeUpClock_CK_SPRE_16bits, 0); // 配置WAKE UP中断,1秒钟中断一次

	POINT_COLOR = RED;
	LCD_ShowString(30, 50, 200, 16, 16, "Explorer STM32F4");
	LCD_ShowString(30, 70, 200, 16, 16, "RTC TEST");
	LCD_ShowString(30, 90, 200, 16, 16, "ATOM@ALIENTEK");
	LCD_ShowString(30, 110, 200, 16, 16, "2023/11/29");
	while (1)
	{
		t++;
		if ((t % 10) == 0) // 每100ms更新一次显示数据
		{
			RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct); // 获取当前的时间信息

			// 将其格式化为字符串存储在tbuf中,然后通过LCD显示出来
			sprintf((char *)tbuf, "Time:%02d:%02d:%02d", RTC_TimeStruct.RTC_Hours, RTC_TimeStruct.RTC_Minutes, RTC_TimeStruct.RTC_Seconds);
			LCD_ShowString(30, 140, 210, 16, 16, tbuf);

			RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct); // 获取当前的日期信息

			// 将其格式化为字符串存储在tbuf中,再通过LCD显示出来
			sprintf((char *)tbuf, "Date:20%02d-%02d-%02d", RTC_DateStruct.RTC_Year, RTC_DateStruct.RTC_Month, RTC_DateStruct.RTC_Date);
			LCD_ShowString(30, 160, 210, 16, 16, tbuf);
			sprintf((char *)tbuf, "Week:%d", RTC_DateStruct.RTC_WeekDay);
			LCD_ShowString(30, 180, 210, 16, 16, tbuf);
		}
		if ((t % 20) == 0)
			LED0 = !LED0; // 每200ms,翻转一次LED0
		delay_ms(10);	  // 当循环执行了10次,即经过了10次delay_ms(10)的暂停,总共的时间就是10毫秒乘以10次,即100毫秒
	}
}

效果视频

RTC实时时钟

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

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

相关文章

有时出厂重置BIOS是解决电脑问题和保持其最佳性能的好办法,主要有两种方法

​BIOS是计算机开机时启动的第一个程序,它有助于执行一些基本的计算机操作,并管理计算机和安装在计算机上的操作系统之间的命令。与任何其他程序一样,如果在启动计算机时遇到问题或在计算机中添加了新硬件,则可能需要将BIOS重置为…

Windows系列:Windows的13个版本以及 Windows Server详解(配置)

Windows的13个版本以及 Windows Server详解(配置) 一. Windows的13个版本的区别,企业版、教育版、专业版、工作站版、SE版的主要区别家庭版专业版教育版企业版Servers版 二. Windows Server VS Windows,两者有啥区别?什…

内网穿透的应用-如何部署Tale博客并结合cpolar内网穿透发布个人站点到公网访问

Linux系统部署Tale个人博客并发布到公网访问 文章目录 Linux系统部署Tale个人博客并发布到公网访问前言1. Tale网站搭建1.1 检查本地环境1.2 部署Tale个人博客系统1.3 启动Tale服务1.4 访问博客地址 2. Linux安装Cpolar内网穿透3. 创建Tale博客公网地址4. 使用公网地址访问Tale…

【Openstack Train安装】二、NTP安装

网络时间协议:Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与…

光伏设计软件操作指南

在能源产业的变革中,光伏将成为未来最大的绿电来源。光伏电站未来25年的发电量、后期的运维等,都需要借助严谨的设计。光伏设计软件可以帮助设计者减少工作量,降低人工计算的错误,使得数据更精确。 1.了解软件构成 光伏设计软件专…

CV计算机视觉每日开源代码Paper with code速览-2023.11.23

点击CV计算机视觉,关注更多CV干货 论文已打包,点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【基础网络架构:Transformer】White-Box Transformers via Sparse Rate Reduction: Compression Is All There Is? 论文地址&am…

解决:uniapp项目打包微信小程序时,报错:failed to load config from /xx/xx-mall/vite.config.ts

复现步骤:在vscode终端中运行:pnpm build:mp-weixin-prod 命令,打包小程序生产包时,报错failed to load xxx/vite.config.ts,但实际项目根目录中有该vite.config.ts文件。 项目使用技术:uniapp vue3 node…

抖音本地生活服务商申请入口门槛过高,该怎么办?

近年来,短视频平台的举起让直播带货和本地生活服务行业逐渐兴起,并且以其便捷、高效的特点受到了广大用户的欢迎。很多创业者也加入了本地生活服务商的行列中,但有消息传出,抖音本地生活服务商申请入口可能会关闭,由于…

virtualbox安装时报错:无法访问你试图使用的功能所在的网络位位置。旧版本的msi文件误删问题解决。

错误如下图所示: 无法访问你试图使用的功能所在的网络位位置。单击“确定”重试,或在下面的框中输入包含安装程序包“xxxxxxxxxxxxx.msi”的文件夹路径。 今天在帮同学安装时发生这个问题,然后各种网站搜索教程,最后也是花了将近…

Python之Appium 2自动化测试(Android篇)

一、环境搭建及准备工作 1、Appium 2 环境搭建 请参考另一篇文章: Windows系统搭建Appium 2 和 Appium Inspector 环境 2、安装 Appium-Python-Client,版本要求3.0及以上 pip install Appium-Python-ClientVersion: 3.1.03、手机连接电脑,并在dos窗口…

中通快递查询,中通快递单号查询,分析筛选出多次揽收件

批量查询中通快递单号的物流信息,并将其中的多次揽收件分析筛选出来。 所需工具: 一个【快递批量查询高手】软件 中通快递单号若干 操作步骤: 步骤1:运行【快递批量查询高手】软件,第一次使用的朋友记得先注册&…

什么是软阈值,硬阈值,软聚类,硬聚类!!软和硬指的是什么呢?详细解释看这里!!!

文章目录 一、软阈值和硬阈值的基本概念和区别二、软聚类和硬聚类的详细概念和区别 一、软阈值和硬阈值的基本概念和区别 在我所研究的领域中,经常出现小波降噪,就拿小波降噪举例子吧!! 在信号处理中,小波降噪是一种…

ECONGU4280 Corporate Finance

ECONGU4280 Corporate Finance WeChat: zh6-86

SpringBoot+SSM项目实战 苍穹外卖(1)

目录 产品原型与技术选型后端环境搭建Git版本控制IDEA中运行sql脚本文件nginx反向代理和负载均衡完善登录功能 MD5加密 Builder 导入接口文档SwaggerSwagger常用注解 产品原型与技术选型 管理端原型图: 用户端原型图: 餐饮企业内部员工使用。 主要功能有…

ClassCMS2.4漏洞复现

ClassCMS2.4漏洞复现 环境搭建 任意文件下载漏洞复现 漏洞成因 ClassCMS2.4漏洞复现 CMS源码在附件中 环境搭建 使用phpstudy2016搭建web环境,php版本为5.5 安装CMS 这里选择Mysql数据库进行安装 用户名和密码都写默认的admin方便记忆 输入完成后点击安装 点…

如何制作一个数字人?流程是怎样的?

​​虚拟人概念从早期动漫领域的初音未来用一首《甩葱歌》让绿色双马尾的“歌姬”形象火出圈,到洛天依登上央视春晚舞台,再到众多虚拟歌手、虚拟主播、KOL、代言人等活跃于各种情境中。 去年以来,元宇宙和虚拟人技术进入全球科技产业的聚光灯…

IDEA解决Git冲突详解

目录 前言: 何为冲突 冲突演示 IDEA冲突解决 小结: 前言: 相信大家多多少少都有了解和使用过Git,作为Java程序员idea可谓是无敌的存在了,那么如何使用idea解决Git冲突呢?不瞒大家前段时间在公司把同事…

怎样搭建好Google关键词广告账号结构

搭建好Google关键词广告账号结构对于实现广告效果的最大化至关重要。本文小编将为您提供一些关于如何搭建好Google关键词广告账号结构的建议和步骤。 1、设定目标和策略 在开始搭建广告账号结构之前,首先需要明确您的广告目标和策略。您想要增加网站流量还是提高转…

基于GAN的多尺度门合并多模态MRI图像合成

Multi-Modal MRI Image Synthesis via GAN With Multi-Scale Gate Mergence 基于GAN的多尺度门合并多模态MRI图像合成背景贡献实验方法生成器gate mergence (GM) strategy(门控融合策略)判别器 损失函数Thinking 基于GAN的多尺度门合并多模态MRI图像合成…

什么牌子的led台灯质量好?考研必备五款护眼台灯推荐

眼睛更是心灵的窗户,我们通过这扇窗来欣赏这个美好的世界。而如今,近视在儿童中已司空见惯,近视率逐年提高,并且低龄化的现状更加突出。据世界卫生组织的最新研究报告,目前中国近视患者人数多达6亿,其中我国…