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

宣武网站建设服务福建百度代理公司

宣武网站建设服务,福建百度代理公司,做简历比较好的网站叫什么,镇江网站关键词优化目录 一、备份寄存器的功能 二、示例功能 三、项目设置 1、晶振、DEBUG、CodeGenerator、USART6 2、RTC 3、NVIC 4、GPIO 及KEYLED 四、软件设计 1、main.h 2、main.c 3、rtc.c 4、keyled.c、keyled.h 五、运行调试 本实例旨在介绍备份寄存器的作用。本实例继续使…

目录

一、备份寄存器的功能

二、示例功能

三、项目设置

1、晶振、DEBUG、CodeGenerator、USART6

2、RTC

3、NVIC 

4、GPIO 及KEYLED

四、软件设计

1、main.h

2、main.c

3、rtc.c

4、keyled.c、keyled.h

五、运行调试


        本实例旨在介绍备份寄存器的作用。本实例继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。本实例将引用本文作者写的其他文章作为参考文献。

        参考项目:细说STM32F407单片机RTC的基本原理及闹钟和周期唤醒功能的使用方法-CSDN博客  https://wenchm.blog.csdn.net/article/details/145575366

一、备份寄存器的功能

        STM32F407的RTC有20个32位的备份寄存器,寄存器名称为RTC_BKP0R~RTC_BKP19R。这些备份寄存器由备用电源VBAT供电,在系统复位或主电源关闭时,只要VBAT有电,备份寄存器的内容就不会丢失。所以,备份寄存器可以用来存储一些用户数据

        文件stm32f4xx_hal_rtc_ex.h中有读写备份寄存器的功能函数,其原型定义如下:

uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc,uint32_t BackupReg);
void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc,uint32_t BackupReg,uint32_t Data);

        其中,参数BackupReg是备份寄存器编号,文stm32f4xx_hal_rtc_ex.h定义了20个备份寄存器编号的宏,定义如下:

#define RTC_BKP_DR0		0x00000000U
#define RTC_BKP_DR1		0x00000001U
/*省略了中间的定义代码*/
#define RTC_BKP_DR18	0x00000012U
#define RTC_BKP_DR19	0x00000013U

        RTC也可以由VBAT供电,在系统复位或主电源关闭时,RTC的日历不受影响。但是在参考项目,因为在系统复位时调用了RTC初始化函数MX_RTC_Init(),而这个函数总是设置RTC的日期和时间,所以复位后,RTC的日期时间又从CubeMX里设置的初始日期时间开始了。

        可以使用备份寄存器对参考项目进行修改,使得系统在复位时不再自动设置RTC的初始日期时间,而是由备份寄存器RTC_BKP_DR0的内容决定,而且可以把RTC当前时间保存到备份寄存器。

二、示例功能

        本实例,将设计一个示例,演示备份寄存器的使用。示例具有如下的功能和操作流程。

  • 在RTC初始化函数MX_RTC_Init()中增加代码,读取备份寄存器RTC_BKP_DR0的内容,如果值为0,就设置RTC为初始时间和日期,如果值为1,就不设置RTC的日期和时间。
  • 在程序运行时,可以修改保存到备份寄存器RTC_BKP_DR0的值,可以保存0或1。
  • 将RTC当前时间的时、分、秒数据保存到RTC_BKP_DR2到RTC_BKP_DR4的3个寄存器里。RTC_BKP_DR1里的值为1时,表示保存了RTC时间。
  • 读取备份寄存器RTC_BKP_DR0到RTC_BKP_DR4的内容,显示到串口助手上。
  • 使用RTC周期唤醒中断,唤醒中断周期1s,在唤醒中断里读取时间后在串口助手上显示。本示例还用到4个按键和2个LED,所以继续引用作者发布的其它参考项目中的KEYLED文件中的程序文件。
  • 菜单设计:
[S2]KeyUp   = Reset RTC time on startup.    //按下S2键,用初始时间重置RTC
[S3]KeyDown = Read BKUP registers.          //按下S3键,读取备份寄存器
[S4]KeyLeft = Save current time to BKUP.    //按下S4键,把当前时间保存到RTC备份寄存器
[S5]KeyRight= Change RTC time from BKUP.    //按下S5键,用备份寄存器存储的时间重置RTC时间

三、项目设置

1、晶振、DEBUG、CodeGenerator、USART6

        与参考文章相同。 

2、RTC

        在RTC的模式设置中,启用时钟源和日历,设置WakeUp模式为Internal WakeUp。在参数设置部分,设置数据格式为Binary data format,设置唤醒时钟为1Hz信号,唤醒周期数为0,这样就会每秒产生一次唤醒中断。

3、NVIC 

        在NVIC中开启周期唤醒中断,设置RTC抢占优先级为1。

4、GPIO 及KEYLED

        4个按键和2个LED。引用文件夹KEYLED的方法请参考本文作者发布的其它文章。

程序标签

板上名称

引脚名称

引脚功能

GPIO模式

默认电平

上拉或下拉

LED1

D1

PA6

GPIO_Output

推挽输出

High

上拉

LED2

D2

PA4

GPIO_Output

推挽输出

High

上拉

KeyRight

S5

PF6

GPIO_Input

输入

上拉

KeyDown

S3

PD3

GPIO_Input

输入

上拉

KeyLeft

S4

PF7

GPIO_Input

输入

上拉

KeyUp

S2

PA0

GPIO Input

输入

上拉

 

四、软件设计

1、main.h

/* USER CODE BEGIN Private defines */
void RTC_ToggleReset();
void RTC_SaveToBKUP();
void RTC_LoadFromBKUP();
void RTC_ReadBKUP();
/* USER CODE END Private defines */

2、main.c

/* USER CODE BEGIN Includes */
#include "keyled.h"
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
RTC_TimeTypeDef sTime;		//RTC读取时间和日期的结果数据
RTC_DateTypeDef sDate;uint8_t RTC_isReading=0;	//RTC是否正在读日期时间数据
/* USER CODE END PV */
/* USER CODE BEGIN 2 */__HAL_RTC_WAKEUPTIMER_DISABLE(&hrtc); //禁止RTC周期唤醒printf("Demo11_2_RTC_Backup:Using Backup Registers.\r\n");uint32_t iniRTC = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0);	//读取备份寄存DR0printf("Reset RTC time on startup: ");if ((iniRTC & 0x01)==0)printf("Yes.\r\n");elseprintf("No.\r\n");/* USER CODE END 2 */
 /* Infinite loop *//* USER CODE BEGIN WHILE *///显示菜单,也可以放在USER CODE BEGIN 2里printf("[S2]KeyUp   = Reset RTC time on startup(LED2_ON).\r\n");printf("[S3]KeyDown = Read BKUP registers.\r\n");printf("[S4]KeyLeft = Save current time to BKUP.\r\n");printf("[S5]KeyRight= Change RTC time from BKUP.\r\n\r\n");__HAL_RTC_WAKEUPTIMER_ENABLE(&hrtc);	//重启RTC周期唤醒while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */KEYS curKey=ScanPressedKey(KEY_WAIT_ALWAYS);switch(curKey){case KEY_UP:		//[S2]KeyUp,改变保存到备份寄存器DR0的数值0 or 1RTC_ToggleReset();break;case KEY_DOWN:	//[S3]KeyDown,读取5个备份寄存器的数据并显示RTC_ReadBKUP();case KEY_LEFT:	//[S4]KeyLeft,将RTC当前时间保存到备份寄存器RTC_SaveToBKUP();break;case KEY_RIGHT:	//[S5]KeyRight,从备份寄存器读取时间,改变RTC时间RTC_LoadFromBKUP();break;default:break;}HAL_Delay(300);	//消抖}/* USER CODE END 3 */

        main()函数里在完成了外设初始化之后,执行__HAL_RTC_WAKEUPTIMER_DISABLE (&hrtc),禁止了RTC周期唤醒单元。在进入while死循环之前,再开启RTC的周期唤醒单元。

        调用函数HAL_RTCEx_BKUPRead()读取备份寄存器RTC_BKP_DR0的内容,如果寄存器的值为0就会在MX_RTC_Init()里用CubeMX设置的初始日期和时间设置RTC的日期时间;如果寄存器的值不为0在MX_RTC_Init()里就不会设置RTC的日期和时间。后一种情况下,在按复位键[S6]使系统复位时,RTC仍然保持连续的时间,因为RTC工作在备份域,不会在系统复位时复位。

        然后,在串口助手上显示了一个模拟菜单。

        在while循环里读取按键输入,用4个按键模拟菜单项的选择,按下某个按键后就执行与菜单项对应的功能。按键的响应代码封装为4个函数。

/* USER CODE BEGIN 4 */
//周期唤醒中断回调函数
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{LED1_Toggle();RTC_isReading = 1;		//RTC正在读取数据,该变量的作用类似于RTOS中的二值信号量if (HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BIN) == HAL_OK){//调用HAL_RTC_GetTime()之后必须调用HAL_RTC_GetDate()以解锁数据,才能连续更新日期和时间HAL_RTC_GetDate(hrtc, &sDate, RTC_FORMAT_BIN);RTC_isReading = 0;	//RTC结束了读取数据//显示时间hh:mm:sschar str[40];sprintf(str,"RTC Time = %2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);printf(" %s\r\n",str);}
}/* 翻转保存备份寄存器RTC_BKP_DR0的值 */
void RTC_ToggleReset()	//S2
{uint32_t iniRTC = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0);iniRTC = !iniRTC;if ((iniRTC & 0x01)==0){ //存储值为0时,用CubeMX中的值复位日期时间printf("Reset RTC time on startup.\r\n");LED2_ON();}else{printf("Not reset RTC time on startup.\r\n");LED2_OFF();}//__HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);		//取消写保护HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0, iniRTC);	//写入备份寄存器DR0//__HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);		//开启写保护
}/* RTC时间保存到备份寄存器 */
void RTC_SaveToBKUP()	//S4
{while (RTC_isReading)	//如果RTC的WakeUp中断里正在读取数据,就等待其读取完HAL_Delay(1);//__HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);				//取消写保护HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR1, 0x01);			//0x01=保存了时间的标志HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR2, sTime.Hours);	//使用全局变量sTime,不再读取当前时间HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR3, sTime.Minutes);HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR4, sTime.Seconds);//__HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);				//开启写保护char timeStr[30];sprintf(timeStr,"%2d:%2d:%2d",sTime.Hours,sTime.Minutes,sTime.Seconds);	//转换为字符串,自动添加"\0"printf("Current time %s is saved in BKUP.\r\n",timeStr);
}/* 用保存的时间设置为RTC时间 */
void RTC_LoadFromBKUP()	//S5
{uint32_t isTimeSaved = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);	//读取备份寄存DR1if (isTimeSaved){RTC_TimeTypeDef time;time.Hours = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);time.Minutes = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);time.Seconds = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;		//这两个参数还是有用的,如果不设置这2个参数,设置的小时数会自动减1time.StoreOperation = RTC_STOREOPERATION_SET;//HAL_Delay(10);		//必须加这个延时,否则设置的时间会错乱while(RTC_isReading)	//如果RTC正在WakeUp中断里读取数据,就等待其读完HAL_Delay(1);/*函数HAL_RTC_SetTime()内部在修改RTC的寄存器之前,会调用 __HAL_RTC_WRITEPROTECTION_DISABLE()取消写保护,写完之后,会调用 __HAL_RTC_WRITEPROTECTION_ENABLE() 重新开启写保护 */if (HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN) == HAL_OK)printf("Load and set BKUP time, success.\r\n");elseprintf("Load and set BKUP time, failure.\r\n");}elseprintf("No BKUP time is saved.\r\n");
}/* 读取5个备份寄存器内容并显示 */
void RTC_ReadBKUP()	//S3
{uint32_t regValue;char regStr[40];regValue = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0);	//0=系统复位时复位RTC时间sprintf(regStr,"Reset RTC ,BKP_DR0= %lu",regValue);	//转换为字符串,自动添加"\0"printf(" %s\r\n",regStr);regValue=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);	//1=有时间数值sprintf(regStr,"Time is saved,BKP_DR1= %lu",regValue);printf(" %s\r\n",regStr);regValue=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);	//Hoursprintf(regStr,"Saved time(Hour) ,BKP_DR2= %lu",regValue);printf(" %s\r\n",regStr);regValue=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);	//Minutesprintf(regStr,"Saved time(Min) , BKP_DR3= %lu",regValue);printf(" %s\r\n",regStr);regValue=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);	//Secondsprintf(regStr,"Saved time(Sec) , BKP_DR4= %lu",regValue);printf(" %s\r\n",regStr);
}//串口打印
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */

        回调函数HAL_RTCEx_WakeUpTimerEventCallback()处理RTC周期唤醒中断。

        其余的4个函数,是对4个菜单项的响应代码的封装。

3、rtc.c

/* USER CODE BEGIN Check_RTC_BKUP */uint32_t iniRTC = HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR0);	//读取备份寄存DR0if ((iniRTC & 0x01))  //非零,无需初始化RTC日期时间{if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc,0,RTC_WAKEUPCLOCK_CK_SPRE_16BITS) != HAL_OK)Error_Handler();return;  //提前退出函数}/* USER CODE END Check_RTC_BKUP */

        沙箱中添加的代码就是用函数HAL_RTCEx_BKUPRead()读取备份寄存器RTC_BKP_DR0的内容,如果寄存器的值不为0,就在执行完HAL_RTCEx_SetWakeUpTimer_IT()设置和启动周期唤醒后,退出函数;如果寄存器的值为0,就继续执行函数内后面的代码。

        这样,就在函数MX_RTC_Init()中加入了用户功能代码,使得在系统复位时,RTC不必设置初始日期和时间

4、keyled.c、keyled.h

        引用KEYLED文件夹下的 keyled.c、keyled.h,使用方法请参考本文作者发布的其他文章。

五、运行调试

        首次下载,或按S6键复位,显示系统菜单。重要的信息是显示当前从哪里重置RTC时间的信息。如果YES(LED2亮)则从RTC初始化值(15:30:0)重置RTC时间,否则不是;

        按S2键切换从哪里重置RTC时间。比如,下图,每次按下S6复位键,系统都从RTC初始化值重置时间,否则不重置时间,即当LED2灯不亮(DR0=1)时,按下复位键S6,不改变RTC时间,连续显示RTC时间。

 

         按S4键,存储当前时间到备份寄存器;按S3键,读取备份存储器内容并保存当前最新值到备份寄存器;按S5键,用备份寄存器内容重置RTC时间;

 

http://www.dtcms.com/wzjs/54689.html

相关文章:

  • wordpress获取分类别名零基础seo入门教学
  • 线上网站设计线下营销推广方式有哪些
  • 申请网站建设百度推广助手app下载
  • 宁乡建设局网站成都网站建设方案推广
  • 手机网站 制作教程soso搜索引擎
  • 软件技术好找工作吗长沙seo网络公司
  • 建筑公司网站广告宣传语市场监督管理局职责范围
  • 佛山网站建设报价互联网营销师培训课程免费
  • 做外贸英语网站国内网络销售平台有哪些
  • 九亭镇村镇建设办官方网站如何推广公司
  • 沈阳网站关键词优化哪家好游戏挂机赚钱一小时20
  • wordpress改站点地址杭州网站建设
  • 淄博网站建设相关文章学生个人网页制作代码
  • 镇江网友之家开封搜索引擎优化
  • 武汉设计工程学院是几本seo案例视频教程
  • 沧州市网站制作公司台州关键词优化服务
  • 重庆网站建设报价万网域名注册官网
  • ps企业网站模板免费下载seo关键词排名优化app
  • 做网站枣庄网站怎么优化关键词快速提升排名
  • 程序员培训机构课程google 推广优化
  • 电子商务网站建设评估工具搜索引擎优化要考虑哪些方面?
  • 长春商城网站开发seo深圳培训班
  • 深圳市城乡和建设局网站百度一下你就知道网页
  • 企业网站用什么技术做西安网站seo服务
  • 网站建设html5建网站需要什么条件
  • 广东长城建设集团有限公司 网站新闻稿发布软文平台
  • 手机怎么注册自己的网站热搜榜百度一下你就知道
  • 石家庄外贸做网站网站推广优化平台
  • 临清做网站企业培训课程设计
  • 网站建设难度大吗设计网站用什么软件