前言:

在有些应用中,无法使用外部晶振来获取准确的时钟,不得已使用STM32内部的RC时钟。HSI以及MSI等。虽然这些时钟在出厂时,已经进行了校准。但是随着环境温度变化,RC时钟会有所改变,这在对时钟敏感的场合下,是不可接受的。幸好STM32提供了一个再校准的机会。利用外部精准时钟信号,对内部时钟进行校准。           

​​​​​​​​​​​​​​

官方文件:AN4631: How to calibrate an STM32L0xx internal RC oscillator

​​​​​​​本文只展示对HSI的校准例程,MSI等方法相同。

正文:

一、使用TIM21_CH1通道

以上为数据手册介绍的方法,本文使用4096Hz的标准信号,通过GPIO引脚输入TIM21_CH1中,内部TIM21会有输入4分频,因此TIM21需要测量的周期应为(1/1024Hz) ,使用HSI的16MHz主时钟进行测量,得到的理论精确数值应为16MHz*(1/1024Hz)=15625

下面为TIM21配置函数

/*函数名:TIM21_Configuration*函数描述: 定时器配置 TIM21用来对HSI进行修正*输入参数:无*输出结果:无*返回值:无
***************************************/
void      TIM21_Configuration(void)
{LL_TIM_InitTypeDef LL_TIM21_InitStruct;LL_TIM_IC_InitTypeDef LL_TIM21_IC_InitStruct;LL_TIM_DeInit (TIM21);LL_TIM21_InitStruct .Autoreload =0xffff;LL_TIM21_InitStruct .ClockDivision= LL_TIM_CLOCKDIVISION_DIV1;LL_TIM21_InitStruct .CounterMode =LL_TIM_COUNTERMODE_UP;LL_TIM21_InitStruct .Prescaler =0;LL_TIM_Init(TIM21,&LL_TIM21_InitStruct);LL_TIM21_IC_InitStruct .ICActiveInput =LL_TIM_ACTIVEINPUT_DIRECTTI;//CH1连接IC1LL_TIM21_IC_InitStruct .ICFilter =LL_TIM_IC_FILTER_FDIV1;//无滤波器LL_TIM21_IC_InitStruct .ICPolarity =LL_TIM_IC_POLARITY_FALLING;//下降沿LL_TIM21_IC_InitStruct .ICPrescaler =LL_TIM_ICPSC_DIV4;//输入4分频LL_TIM_IC_Init(TIM21,LL_TIM_CHANNEL_CH1,&LL_TIM21_IC_InitStruct );LL_TIM_EnableIT_TRIG(TIM21);LL_TIM_EnableIT_CC1(TIM21);NVIC_EnableIRQ(TIM21_IRQn);
}

其中LL_TIM21_InitStruct .Autoreload =0xffff;表示从0数到最大值,在中间进行捕获一段,即输入周期。因为已知输入的周期核算成数值在15625左右,所以不用再对TIM21进行分频。65536(0xffff)足矣。

二、配置TIM21_CH1对应的GPIO

由于使用的是TIM21_CH1功能,是复用功能,所以需要在GPIO配置中设置

LL_GPIO_SetAFPin_0_7 (GPIOA,LL_GPIO_PIN_2,LL_GPIO_AF_0 ); /*使用PA2的AF0功能:TIM21_CH1*/

三、校准程序

根据官方文件给的流程图,可以进行编写相应的程序。

/**************************************函数名:HSI_Measurement*函数描述: 通过TIM21采集外部时钟信号参考AN4631中 《FIGURE 12. HSI16/MSI OSCILLATOR FREQUENCY MEASUREMENT FLOWCHART》*输入参数:无*输出结果:无*返回值:uint16_t***************************************/
uint16_t HSI_Measurement(void)
{uint8_t NUMER_OF_LOOPS;uint32_t Measure_Val=0;for(NUMER_OF_LOOPS=0;NUMER_OF_LOOPS<10;NUMER_OF_LOOPS++)//采集10次取平均值{Capture_state =CAPTURE_START;      //标志位设置为STARTLL_TIM_SetCounter(TIM21,0);LL_TIM_EnableCounter(TIM21);LL_TIM_EnableIT_CC1(TIM21);while(Capture_state!=CAPTURE_COMPLETED ); //等待捕获周期Measure_Val+= Capture_Period;      //捕获到的周期累加}LL_TIM_DisableIT_CC1(TIM21);LL_TIM_DisableCounter(TIM21);return (Measure_Val/10);           //取平均
}/**************************************函数名:CALC_HSI*函数描述: 根据外部时钟信号,对HSI进行微调进入单片机频率为4096Hz经过预分频1/4,使得IC1PS变为1024Hz而TIM21采集到的数据应该为【15625】16MHz*(1/1024Hz)=15625*输入参数:无*输出结果:无*返回值:无***************************************/
void CALC_HSI(void)
{uint16_t HSI_Measured_Val,HSI_Trimming_Val=0,HSI_Frequency_Error=0,HSI_Optimum_Error=20,HSI_Optimum_Trimming_Val=0xf;TIM21_CLK_ENABLE;//打开TIM21时钟  //RCC//GPIOTIM21_Configuration();for(HSI_Trimming_Val=0;HSI_Trimming_Val<32;HSI_Trimming_Val++)  //历遍32个trimming值,查找最佳值{LL_RCC_HSI_SetCalibTrimming(HSI_Trimming_Val );    //设置当前trimming值HSI_Measured_Val=HSI_Measurement();  //测量输入周期HSI[HSI_Trimming_Val]=HSI_Measured_Val;if(HSI_Measured_Val>15625)  HSI_Frequency_Error = HSI_Measured_Val-15625; //计算误差值else HSI_Frequency_Error = 15625-HSI_Measured_Val;if(HSI_Frequency_Error <HSI_Optimum_Error ) //如果误差值比最佳值还好,那么取代最佳值{HSI_Optimum_Error =HSI_Frequency_Error ;HSI_Optimum_Trimming_Val=HSI_Trimming_Val ; }}LL_RCC_HSI_SetCalibTrimming(HSI_Optimum_Trimming_Val );RCC_Configuration();                                  /*重新对RCC基本设置*/    }

其中TIM21时钟打开的宏如下

#define TIM21_CLK_ENABLE                 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM21)

另外

HSI[HSI_Trimming_Val]=HSI_Measured_Val;

这个数组是用来保存,在各个Trimming_Val下(HSI校准一共32个),测量到的周期值,后面会贴出来实测数据。这个值理想情况下应该就是前面计算得到的15625。也就是说,测到的数值越接近这个数,那么时钟此时越精准。我们的目的也就是找到这个最佳值。

中断程序

void TIM21_IRQHandler(void)
{if (Capture_state==CAPTURE_ONGOING)/*在使用TIM21测量频率时,用来表示当前状态,第一次进入中断为CAPTURE_START=0,第二次为CAPTURE_ONGOING=1*/{IC1ReadValue2= LL_TIM_IC_GetCaptureCH1(TIM21); //保存捕获的值RV2LL_TIM_DisableIT_CC1(TIM21);Capture_Period=IC1ReadValue2 -IC1ReadValue1 ;  //RV2-RV1差值为测量到的周期Capture_state=CAPTURE_COMPLETED ;}else {IC1ReadValue1= LL_TIM_IC_GetCaptureCH1(TIM21);//保存捕获的值RV1Capture_state=CAPTURE_ONGOING;}}

四、经过上述程序的校准,我们如愿找到了最佳Trimming Value

这个校准值默认为16.  

而我们找到的最佳值是15,在此参数下,HSI测量值为15622,最接近15625

结论:

从上面的数据可知,不同的校准值下,测量出的周期数值相差很大。虽说是微调,但是正所谓“差之毫厘谬以千里”,时钟的精准度是非常重要的。在温度变化较大的情况下,对HSI微调是必不可少的。

自此,完成了对HSI的校准

使用外部时钟,通过TIM21_CH1,对STM32L0XX内部的RC时钟(HSI/MSI等)进行校准相关推荐

  1. stm32内部低速rtc_STM32时钟RCC详解

    时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令.时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能 ...

  2. Xilinx FPGA内部资源之时钟篇1

    以下时钟介绍以Virtex5系列芯片作为参考芯片 从时钟的角度可以将Xilinx FPGA划分为若干个时钟域(Clock Region),不同的FPGA芯片具有不同数量的时钟域,XC5VLX30有8个 ...

  3. 51单片机_7-2 使用内部计时器实现时钟显示

    文章目录 要求 资源 效果 main函数 要求 1.使用内部定时器实现时钟效果 资源 工程文件压缩包 链接:https://pan.baidu.com/s/1kKYAxZDYQOPHRHnnZwUT3 ...

  4. 关于用51单片机内部定时器实现时钟和闹钟功能的概述

    关于用51单片机内部定时器实现时钟和闹钟功能的概述 仅个人观点,欢迎大家相互学习和讨论 STC89C52单片机,内部配置了三个定时器,T0\T1\T2,其中T2定时器我们几乎不用,或者说很少用到.我们 ...

  5. 关于系统时钟的配置问题,如是stm32f1的系统时钟为72Mhz

    系统时钟配置错误而产生的串口定时器等问题 在 STM32 中,有五个时钟源,为 HSI.HSE.LSI.LSE.PLL.从时钟频率来分可以分为 高速时钟源和低速时钟源,在这 5 个中 HIS,HSE ...

  6. S3C2440时钟和电源管理:空闲模式:电源管理模块断开CPU时钟FCLK,而只给外设提供时钟,CPU不耗时钟,故而减少功耗,任何中断请求都可将CPU从空闲模式唤醒。

    七.时钟&电源管理 概述 时钟&电源管理模块包含三部分:时钟控制,USB控制,电源控制. 时钟控制逻辑可以生成三种时钟信号,CPU使用的FCLK,AHB总线外设使用的HCLK,APB总 ...

  7. 51单片机怎么显示当前时间_51单片机时钟电路图怎么设计?这7个时钟汇聚了所有,看看...

    01 在MCS-51单片机片内有一个高增益的反相放大器,反相放大器的输入端为XTAL1,输出端为XTAL2,由该放大器构成的振荡电路和时钟电路一起构成了单片机的时钟方式.根据硬件电路的不同,单片机的时 ...

  8. (二):定时器和计数器的区别;时钟和晶振的区别、RTC实时时钟;MPU、MCU、SOC区别;电源符号:VCC、VDD、VSS、VEE、VPP、VBAT

    硬件的区别 (一)定时器和计数器的区别 (二)时钟和晶振的区别 (1)时钟发生器 (2)时钟信号 (3)时钟和晶振的区别 (三)RTC-实时时钟 实时时钟RTC(Real_Time Clock) RT ...

  9. Exynos4412的Linux时钟驱动开发(一)——Exynos4412的时钟管理单元CMU

    系列文章目录 Exynos4412的Linux时钟驱动开发(一)--Exynos4412的时钟管理单元CMU Exynos4412的Linux时钟驱动开发(二)--时钟驱动的初始化(CLK_OF_DE ...

最新文章

  1. 王者S19服务器维护时间表,王者荣耀s19buff刷新时间一览 红蓝BUFF刷新间隔是多久...
  2. 3d max用不同目标做关键帧_基于光流的视频目标检测系列文章解读
  3. AndroidStudio中如何打开hierarchyviewer.bat
  4. 一个毕设的建成——记录下我毕设途中的《SOP》
  5. springcloud官方文档_通俗易懂!Spring Cloud简介:官方文档翻译版
  6. SQL Server 索引结构及其使用(三)(转)
  7. Spring Boot动态修改日志级别
  8. 蓝桥杯 2017年C语言组大学B组 C/C++
  9. python html表格模版,python-如何使用模板(例如Jinja2)将列值列表呈现到表中
  10. 通过PKI实现零信任的身份认证
  11. python绘制图像频谱_python傅里叶变换FFT绘制频谱图
  12. 为什么现在java这么难找,现在java工作难找吗
  13. 企业如何制作自己的公司网站?
  14. python做网站怎么样_python能做网站吗
  15. 【论文精读】OmniFusion全景相机的深度估计
  16. JAVA对接海康威视开发文档
  17. P1658 购物(贪心算法)
  18. 使用占位符预防SQL注入的原理
  19. 大学android五子棋课程目的,基于安卓开发的五子棋课程设计报告..docx
  20. 拓扑排序与关键路径(AOV网和AOE网)

热门文章

  1. SpringBoot实现多数据源的两种方式
  2. 如何取消noarch.rpm包
  3. 盗版游戏的丧钟已被敲响?
  4. Linux 桌面驱动 糟糕,糟糕的Nvidia Linux驱动
  5. 如何根据IP地址判断是IPv4还是IPv6
  6. Java调用百度API生成短网址
  7. Activiti6自学之路(八)——查看流程图
  8. 博彦科技亮相RSA信息安全大会
  9. bzoj3594[Scoi2014]方伯伯的玉米田
  10. 安装打印机时提示操作无法完成(错误0×00000709)