Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RTC
STM32
使用备份寄存器时遇到的问题
发布于 2023-04-26 09:56:37 浏览:806
订阅该版
代码 ```c //实时时钟配置 //初始化RTC时钟,同时检测时钟是否工作正常 //BKP->DR1用于保存是否第一次配置的设置 //返回0:正常 //其他:错误代码 u8 RTC_Init(void) { HAL_RTC_MspInit(&RTC_Handler); RTC_Handler.Instance=RTC; RTC_Handler.Init.AsynchPrediv=32767; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767 if(HAL_RTC_Init(&RTC_Handler)!=HAL_OK) return 1; rt_kprintf("%X", HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR10)); if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR10)!=0X5050)//是否第一次配置 { RTC_Set(2017,5,27,17,7,0); //设置日期和时间,2017年5月27日,17点02分0秒 HAL_RTCEx_BKUPWrite(&RTC_Handler,RTC_BKP_DR10,0X5050);//标记已经初始化过了 } rt_kprintf("%X", HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR10)); __HAL_RTC_ALARM_ENABLE_IT(&RTC_Handler,RTC_IT_SEC); //允许秒中断 __HAL_RTC_ALARM_ENABLE_IT(&RTC_Handler,RTC_IT_ALRA); //允许闹钟中断 HAL_NVIC_SetPriority(RTC_IRQn,0x01,0x02); //抢占优先级1,子优先级2 HAL_NVIC_EnableIRQ(RTC_IRQn); RTC_Get();//更新时间 return 0; //ok } ``` 代码使用的是正点原子的HAL, 在 ```c if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR10)!=0X5050) ``` 这段代码中想要判断备份寄存器中的值是否为`0x5050`然后初始化RTC,但实际情况是每次重启这个备份寄存器都会恢复为0, 并没有保存之前设置的值, 导致一直初始化RTC. 这是全代码 ```c #include "board.h" #include
#include
#include
#include "type.h" #include "drv_common.h" #include "drv_rtc.h" static struct tm tm = {0}; static RTC_HandleTypeDef RTC_Handler; //RTC句柄 //月份数据表 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}; //判断是否是闰年函数 //月份 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 //year:年份 //返回值:该年份是不是闰年.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; } //得到当前的时间,结果保存在calendar结构体里面 //返回值:0,成功;其他:错误代码. u8 RTC_Get(void) { static u16 daycnt=0; u32 timecount=0; u32 temp=0; u16 temp1=0; timecount=RTC->CNTH;//得到计数器中的值(秒钟数) timecount<<=16; timecount+=RTC->CNTL; 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 break; } else temp-=365; //平年 temp1++; } tm.tm_year=temp1;//得到年份 temp1=0; while(temp>=28)//超过了一个月 { if(Is_Leap_Year(tm.tm_year)&&temp1==1)//当年是不是闰年/2月份 { if(temp>=29)temp-=29;//闰年的秒钟数 else break; } else { if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年 else break; } temp1++; } tm.tm_mon=temp1+1; //得到月份 tm.tm_mday=temp+1; //得到日期 } temp=timecount%86400; //得到秒钟数 tm.tm_hour=temp/3600; //小时 tm.tm_min=(temp%3600)/60; //分钟 tm.tm_sec=(temp%3600)%60; //秒钟 return 0; } //设置时钟 //把输入的时钟转换为秒钟 //以1970年1月1日为基准 //1970~2099年为合法年份 //返回值:0,成功;其他:错误代码. //syear,smon,sday,hour,min,sec:年月日时分秒 //返回值:设置结果。0,成功;1,失败。 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
APB1ENR|=1<<28;//使能电源时钟 RCC->APB1ENR|=1<<27;//使能备份时钟 PWR->CR|=1<<8; //取消备份区写保护 //上面三步是必须的! RTC->CRL|=1<<4; //允许配置 RTC->CNTL=seccount&0xffff; RTC->CNTH=seccount>>16; RTC->CRL&=~(1<<4);//配置更新 while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成 RTC_Get();//设置完之后更新一下数据 return 0; } //RTC时钟中断 //每秒触发一次 void RTC_IRQHandler(void) { if(RTC->CRL&0x0001) //秒钟中断 { RTC_Get(); //更新时间 //printf("sec:%d\r\n",calendar.sec); } if(RTC->CRL&0x0002) //闹钟中断 { RTC->CRL&=~(0x0002); //清闹钟中断 RTC_Get(); //更新时间 // printf("Alarm Time:%d-%d-%d %d:%d:%d\n",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);//输出闹铃时间 } RTC->CRL&=0X0FFA; //清除溢出,秒钟中断标志 while(!(RTC->CRL&(1<<5))); //等待RTC寄存器操作完成 } //实时时钟配置 //初始化RTC时钟,同时检测时钟是否工作正常 //BKP->DR1用于保存是否第一次配置的设置 //返回0:正常 //其他:错误代码 u8 RTC_Init(void) { HAL_RTC_MspInit(&RTC_Handler); RTC_Handler.Instance=RTC; RTC_Handler.Init.AsynchPrediv=32767; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767 if(HAL_RTC_Init(&RTC_Handler)!=HAL_OK) return 1; rt_kprintf("%X", HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR10)); if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR10)!=0X5050)//是否第一次配置 { RTC_Set(2017,5,27,17,7,0); //设置日期和时间,2017年5月27日,17点02分0秒 HAL_RTCEx_BKUPWrite(&RTC_Handler,RTC_BKP_DR10,0X5050);//标记已经初始化过了 } rt_kprintf("%X", HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR10)); __HAL_RTC_ALARM_ENABLE_IT(&RTC_Handler,RTC_IT_SEC); //允许秒中断 __HAL_RTC_ALARM_ENABLE_IT(&RTC_Handler,RTC_IT_ALRA); //允许闹钟中断 HAL_NVIC_SetPriority(RTC_IRQn,0x01,0x02); //抢占优先级1,子优先级2 HAL_NVIC_EnableIRQ(RTC_IRQn); RTC_Get();//更新时间 return 0; //ok } //RTC底层驱动,时钟配置 //此函数会被HAL_RTC_Init()调用 //hrtc:RTC句柄 void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; __HAL_RCC_PWR_CLK_ENABLE(); //使能电源时钟PWR HAL_PWR_EnableBkUpAccess(); //取消备份区域写保护 __HAL_RCC_BKP_CLK_ENABLE(); //使能BSP时钟 RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSE;//LSE配置 RCC_OscInitStruct.PLL.PLLState=RCC_PLL_NONE; RCC_OscInitStruct.LSEState=RCC_LSE_ON; //RTC使用LSE HAL_RCC_OscConfig(&RCC_OscInitStruct); PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;//外设为RTC PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSE;//RTC时钟源为LSE HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); __HAL_RCC_RTC_ENABLE();//RTC时钟使能 } time_t rtc_get(void){ return mktime(&tm); } int rtc_set_date(time_t t){ struct tm *p_tm = localtime(&t); return RTC_Set(p_tm->tm_year, p_tm->tm_mon, p_tm->tm_mday, p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec); } static int rtc_init(void){ while(RTC_Init()) //RTC初始化 ,一定要初始化成功 { rt_kprintf("RTC ERROR!\n"); rt_thread_mdelay(800); rt_kprintf("RTC Trying...\n"); } rt_kprintf("RTC ok\n"); return 0; } INIT_DEVICE_EXPORT(rtc_init); #if 1 #include
void rtc_date(int argc, char** argv){ if(argc == 1){ time_t t = rtc_get(); struct tm *tm = localtime(&t); rt_kprintf("%d-%d-%d %d:%d:%d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } else if (argc >= 7) { /* set time and date */ rt_uint16_t year; rt_uint8_t month, day, hour, min, sec; year = atoi(argv[1]); month = atoi(argv[2]); day = atoi(argv[3]); hour = atoi(argv[4]); min = atoi(argv[5]); sec = atoi(argv[6]); if (year > 2099 || year < 2000) { rt_kprintf("year is out of range [2000-2099]\n"); return; } if (month == 0 || month > 12) { rt_kprintf("month is out of range [1-12]\n"); return; } if (day == 0 || day > 31) { rt_kprintf("day is out of range [1-31]\n"); return; } if (hour > 23) { rt_kprintf("hour is out of range [0-23]\n"); return; } if (min > 59) { rt_kprintf("minute is out of range [0-59]\n"); return; } if (sec > 59) { rt_kprintf("second is out of range [0-59]\n"); return; } struct tm t; t.tm_year = year; t.tm_mon = month; t.tm_mday = day; t.tm_hour = hour; t.tm_min = min; t.tm_sec = sec; rtc_set_date(mktime(&t)); } else{ rt_kprintf("please input: date [year month day hour min sec] or date\n"); rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); } } MSH_CMD_EXPORT(rtc_date, "rtc"); #endif ``` IDE: RTThread Studio 代码库: STM32F103RCT6 (HAL) 单片机: GD32F303RCT6 有些事我无法选择. 电路没有问题, 使用正点原子的Keil代码能正常初始化RTC并正常运行, 但使用RTT就不能正常运行, 是不是RTT初始化期间重置了寄存器? 或是有没有其他的RTC解决思路, 要求要用单片机内部硬件RTC, 不要求精度
查看更多
1
个回答
默认排序
按发布时间排序
ThinkCode
2023-04-26
这家伙很懒,什么也没写!
我尝试在RTT中设置RTC然后再切换到裸机RTC查看寄存器, 使用RTT设置完备份寄存器后, 裸机程序可以读到RTT设置的备份寄存器, 然后我再切换到RTT, 备份寄存器又被复位了. 我尝试过关闭和开始RTC设备驱动都没有用
撰写答案
登录
注册新账号
关注者
0
被浏览
806
关于作者
ThinkCode
这家伙很懒,什么也没写!
提问
20
回答
16
被采纳
0
关注TA
发私信
相关问题
1
RTC驱动框架几点建议
2
求助:RTT在STM32F407上使用内置的RTC设置日期需重启生效,设置时间即时生效,有遇到同样问题的吗?
3
[新人试水] LPC1768 Nano3_9 添加RTC
4
STM32 关于RTC的问题
5
stm32f4xx-HAL BSP的RTC设置不对
6
关于STM32的RTC设置年份不正确的问题
7
RTT的RTC驱动调试
8
rtc驱动中的bkp模块起不到防止时间的重新设置
9
rtc时钟跑十几个小时后,比实际时间快几秒怎么解决
10
stm32如何断电之后开发板rtc时间继续往前跑
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
RTT 源码分析笔记——互斥量篇
2
[E/app.filesystem] SD card mount to '/sdcard' failed!
3
单片机也能聊天?RT-Thread上跑通大语言模型
4
【RT-Thread】【ci】【scons】将ci.attachconfig.yml和scons结合使用
5
Rt-thread中OTA下载后,bootloader不搬程序
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
cubemx
PWM
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
出出啊
1518
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
177
次被采纳
crystal266
549
个答案
161
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
3
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部