OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4862|回复: 2

今天看F4探索者板子的RTC实验中的初始化,发现有个地方有问题,特指出

[复制链接]

6

主题

123

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1279
金钱
1279
注册时间
2012-5-27
在线时间
200 小时
发表于 2015-2-8 17:38:00 | 显示全部楼层 |阅读模式

内容如题,对于RTC的初始化,有这样一段代码:

[mw_shl_code=c,true]//RTC初始化 //返回值:0,初始化成功; // 1,LSE开启失败; // 2,进入初始化模式失败; u8 My_RTC_Init(void) { RTC_InitTypeDef RTC_InitStructure; u16 retry=0X1FFF; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR时钟 PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问 if(RTC_ReadBackupRegister(RTC_BKP_DR0)!=0x5050) //是否第一次配置? { 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_Set_Time(23,59,56,RTC_H12_AM); //设置时间 RTC_Set_Date(14,5,5,6); //设置日期 RTC_WriteBackupRegister(RTC_BKP_DR0,0x5050); //标记已经初始化过了 } return 0; }[/mw_shl_code]

我觉得问题出在这个地方,是一个逻辑上的判断,可能是当初写程序的人的疏忽,但我还是理解了他的意思:

在等待低速晶振的过程中

[mw_shl_code=c,true]while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪 { retry++; delay_ms(10); } if(retry==0)return 1; //LSE 开启失败. [/mw_shl_code]


其中里面包含了retry++这样的程序,对于retry在程序开头已经定义了

[mw_shl_code=c,true]u16 retry=0X1FFF; [/mw_shl_code]


很显然,结合下面的判断

[mw_shl_code=c,true]if(retry==0)return 1; //LSE 开启失败. [/mw_shl_code]

可以轻易的得出

retry表示了等待的次数,当retry从0x1fff开始尝试,每次加一,当溢出到0的时候说明尝试结束

故鄙人认为在等待的过程中还应该加上另外一个条件——判断retry时候为零这个条件,这样程序应更改如下:

[mw_shl_code=c,true]RCC_LSEConfig(RCC_LSE_ON);//LSE 开启 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && retry) //检查指定的RCC标志位设置与否,等待低速晶振就绪 { retry++; delay_ms(10); } if(retry==0)return 1; //LSE 开启失败. [/mw_shl_code]

也就是加上了retry这个条件。



这只是个人的看法,在此处指出了出来,鄙人的水平有限,理解之处还有些许的片面,不便之处还请谅解。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-2-8 23:02:51 | 显示全部楼层
谢谢指出
寄存器版本,貌似没这个bug:
[mw_shl_code=c,true]u8 RTC_Init(void) { u16 retry=0X1FFF; RCC->APB1ENR|=1<<28; //使能电源接口时钟 PWR->CR|=1<<8; //后备区域访问使能(RTC+SRAM) if(RTC_Read_BKR(0)!=0X5050) //是否第一次配置? { RCC->BDCR|=1<<0; //LSE 开启 while(retry&&((RCC->BDCR&0X02)==0))//等待LSE准备好 { retry--; delay_ms(5); } if(retry==0)return 1; //LSE 开启失败. RCC->BDCR|=1<<8; //选择LSE,作为RTC的时钟 RCC->BDCR|=1<<15; //使能RTC时钟 //关闭RTC寄存器写保护 RTC->WPR=0xCA; RTC->WPR=0x53; if(RTC_Init_Mode())return 2;//进入RTC初始化模式 RTC->RER=0XFF; //RTC同步分频系数(0~7FFF),必须先设置同步分频,再设置异步分频,Frtc=Fclks/((Sprec+1)*(Asprec+1)) RTC->RER|=0X7F<<16; //RTC异步分频系数(1~0X7F) RTC->CR&=~(1<<6); //RTC设置为,24小时格式 RTC->ISR&=~(1<<7); //退出RTC初始化模式 RTC->WPR=0xFF; //使能RTC寄存器写保护 RTC_Set_Time(23,59,56,0); //设置时间 RTC_Set_Date(14,5,5,1); //设置日期 //RTC_Set_AlarmA(7,0,0,10); //设置闹钟时间 RTC_Write_BKR(0,0X5050); //标记已经初始化过了 } //RTC_Set_WakeUp(4,0); //配置WAKE UP中断,1秒钟中断一次 return 0; }[/mw_shl_code]


我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2019-2-26
在线时间
3 小时
发表于 2019-2-26 13:46:40 | 显示全部楼层
正点原子 发表于 2015-2-8 23:02
谢谢指出
寄存器版本,貌似没这个bug:

原子哥,在  if(retry == 0) return 1; 这里开启失败了,是不是RTC的初始化失败了,
调用RTC_Init();的时候,应该失败了重复调用吗?
比如: while(RTC_Init() == 0) break;
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-10 00:01

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表