一、硬件分析
二、使用HAL库自带的RTC驱动程序
说明:该程序是利用usart串口与单片机通讯,来设置和获取时间信息的
所以,在配置RTC前,应该把USART部分调试好。
1. cubeMx配置
RTC时钟配置选择LSE=32.768KHz(可以产生标准的1s时间基准)
RTC参数配置
注意:不要勾选工程中的生成.C和.H文件
2.main.c文件中MX_RTC_Init()
函数即驱动程序的修改
STM32f103 共有 10组 BKP 寄存器 RTC_BKP_DRx(1~10)(每组可以保存一个16位的数值)
- 380~406行中间是RTC的 日期+时间 的初始化,导致每次重新上电时候,时间无法保存,就无法实现调电保存的功能。
- 上图中 添加的代码,其中if()在383行其中,而 “}” 在408行,将中间RTC初始化的部分就包括了进来。
- 利用BKP备份寄存器,当第一次上电(第一次配置RTC的时候),在BKP中写入0x5050(BKP寄存器不用时候,电池供电不够时,其值为 0xFFFF),并且初始化RTC。
- 当断掉电源一段时间(RTC和BKP使用外加电池供电正常工作,硬件其他部分不工作),BKP中一直是0x5050,在重新正常上电使用时,再次判断BKP寄存器是否=0x5050,等于就跳过这个RTC的数值初始化部分。就实现了断电保存的作用。
- 在整个过程中,RTC一直正常运行,正常计数。
(上图中 0x5050 没有什么特别含义,只是一个标志信号,只要不改成0xFFFF都可以)
存在问题
RTC可以一直工作,但是断电后 在上电 时分秒可以实时更新计数,日期无法调电保存。
3.main.c文件中main()
函数 即应用程序 的修改
while(1){}中程序代码
if(USART1_RX_STA&0x8000){
//如果标志位是0x8000表示收到数据串完成,可以处理。
if((USART1_RX_STA&0x3FFF)==0){
//单独的回车键再显示一次欢迎词
HAL_RTC_GetTime(&hrtc, &RtcTime, RTC_FORMAT_BIN);//读出时间值
HAL_RTC_GetDate(&hrtc, &RtcDate, RTC_FORMAT_BIN);//一定要先读时间后读日期
printf(" 洋桃IoT开发板RTC实时时钟测试 \r\n");
printf(" 实时时间:%04d-%02d-%02d %02d:%02d:%02d \r\n",2000+RtcDate.Year,
RtcDate.Month, RtcDate.Date,RtcTime.Hours, RtcTime.Minutes, RtcTime.Seconds);//显示日期时间
printf(" 单按回车键更新时间,输入字母C初始化时钟 \r\n");
printf(" 请输入设置时间,格式20170806120000,按回车键确定! \r\n");
}
else if((USART1_RX_STA&0x3FFF)==1){
//判断数据是不是1个
if(USART1_RX_BUF[0]=='c' || USART1_RX_BUF[0]=='C'){
MX_RTC_Init(); //键盘输入c或C,初始化时钟
printf("初始化成功! \r\n");//显示初始化成功
}
else{
printf("指令错误! \r\n"); //显示指令错误!
}
}
else if((USART1_RX_STA&0x3FFF)==14){
//判断数据是不是14(年月日时分秒)个
//将超级终端发过来的数据换算并写入RTC
RtcDate.Year = (USART1_RX_BUF[2]-0x30)*10+USART1_RX_BUF[3]-0x30;//减0x30后才能得到十进制0~9的数据
RtcDate.Month = (USART1_RX_BUF[4]-0x30)*10+USART1_RX_BUF[5]-0x30;
RtcDate.Date = (USART1_RX_BUF[6]-0x30)*10+USART1_RX_BUF[7]-0x30;
RtcTime.Hours = (USART1_RX_BUF[8]-0x30)*10+USART1_RX_BUF[9]-0x30;
RtcTime.Minutes = (USART1_RX_BUF[10]-0x30)*10+USART1_RX_BUF[11]-0x30;
RtcTime.Seconds = (USART1_RX_BUF[12]-0x30)*10+USART1_RX_BUF