你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103的RTC模块用作32位计数器

[复制链接]
STMCU小助手 发布时间:2021-8-13 14:27
需求背景
在使用FreeRTOS时,如果需要统计每个任务的运行时长及百分比,则需要提供一个计时基准。


分别实现以下2个函数:


void vConfigureTimerForRunTimeStats( void );    /* Prototype of function that initialises the run time counter. */
unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */



前一个函数需用初始化配置计时器;后一个函数用于在任务切换时获取当前计时值。


要求计时的频率比tick的频率要高一个数量级。目前tick为1KHz,则计时频率为10K比较合适。



方案分析
方案一:使用硬件定时器TIMx。
  1. <font face="微软雅黑" size="3">
  2. void vConfigureTimerForRunTimeStats(void)
  3. {
  4.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

  5.         // 时钟使能
  6.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  7.         //定时器TIMx初始化
  8.         TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock / 1000000 - 1; //预分频后为1MHz
  9.         TIM_TimeBaseStructure.TIM_Period = configTICK_RATE_HZ * 10 - 1;
  10.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  11.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  12.         TIM_TimeBaseInit(TIMER_FOR_RUN_TIME_STAT, &TIM_TimeBaseStructure);

  13.         TIM_Cmd(TIM3, ENABLE);
  14. }

  15. unsigned long ulGetRunTimeCounterValue(void)
  16. {
  17.         return TIM_GetCounter(TIM3);

  18. </font>
复制代码
问题:STM32F103的硬件定时器是16位的。最大计数值为64K,当计数频率为40K时,只需要1秒多一点就溢出了。


方案二:使用2个硬件定时器级联,组成一个32位计数器


方案三:使用os的tick
代码如下。
  1. <font face="微软雅黑" size="3">{</font>
复制代码
问题:精度较低。


方案四:使用RTC作为计数器
具体如下。


使用RTC作为计数器
在STM32F103中,RTC的本质并不是一个实时时钟模块,只是一个计数器而已。可以配置为每秒加一,然后软件将秒数转换为日历时间(类似于unix中,以1970-1-1为起点的秒计数)。


现在不需要时钟了,就把它用于一个10KHz的计数器。最大可计时长为4G/10K = 400K秒,约为100多个小时。


RTC的时钟源:使用内部低速时钟LSI。然后再4分频,即可得到10KHz。
1.png




RTC工作时需要配置以下几个寄存器:
使能PWR和BKP模块时钟
2.png


Disable Backup Domain write:
3.png


开启LSI:
4.png


复位备份域:


先将BDRST设置为1,再设置为0。否则,不能更改RTCSEL等参数。
5.png


参见手册:6.3.9 备份域控制寄存器 (RCC_BDCR)


注意: 备份域控制寄存器中(RCC_BDCR)的LSEON、LSEBYP、RTCSEL和RTCEN位处于备份域。因此,这些位在复位后处于写保护状态,只有在电源控制寄存器(PWR_CR)中的DBP位置’1’后才能对这些位进行改动。进一步信息请参考5.1节。这些位只能由备份域复位清除(见6.1.3节)。任何内部或外部复位都不会影响这些位。
6.png


RTC时钟选择LSI:
7.png


RTC时钟使能:
8.png


设置分频系数:
9.png







代码如下:
  1. <font face="微软雅黑" size="3">
  2. void vConfigureTimerForRunTimeStats(void)
  3. {
  4.         // 使能模块时钟
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE);

  6.         // 使能备份区域访问。将PWR.CR.DBP置1.
  7.         PWR_BackupAccessCmd(ENABLE);

  8.         // 复位备份域(Backup Domain)
  9.         BKP_DeInit();

  10.         //启动内部低速晶振
  11.         RCC_LSICmd(ENABLE);

  12.         //等待外部低速晶振重启
  13.         while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);

  14.         RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

  15.         RCC_RTCCLKCmd(ENABLE); //使能RTC时钟

  16.         RTC_WaitForSynchro(); //等待RTC寄存器同步完成

  17.         RTC_WaitForLastTask(); //等待最后一次对RTC的寄存器写操作完成

  18.         RTC_SetPrescaler(4);        // 4分频后为10KHz

  19.         RTC_WaitForLastTask();

  20. }

  21. /*-----------------------------------------------------------*/

  22. unsigned long ulGetRunTimeCounterValue(void)
  23. {
  24.         return RTC_GetCounter();
  25. }
  26. </font>
复制代码


收藏 评论0 发布时间:2021-8-13 14:27

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版