基于stm32f407的精确时钟同步协议的实现
- 格式:pdf
- 大小:2.17 MB
- 文档页数:7
stm32f407定时器时钟频率的问题
从时钟树中我们可以得知(时钟树的图片可以直接参考6楼,感谢6楼xkwy补上的图):
(1)高级定时器timer1, timer8以及通用定时器timer9, timer10, timer11的时钟来源是APB2总线
(2)通用定时器timer2~timer5,通用定时器timer12~timer14以及基本定时器timer6,timer7的时钟来源是APB1总线
从STM32F4的内部时钟树可知,当APB1和APB2分频数为1的时候,TIM1、TIM8~TIM11的时钟为APB2的时钟,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟;而如果APB1和APB2分频数不为1,那么TIM1、TIM8~TIM11的时钟为APB2的时钟的两倍,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍。
因为系统初始化SystemInit函数里初始化APB1总线时钟为4分频即42M,APB2总线时钟为2分频即84M,所以TIM1、TIM8~TIM11的时钟为APB2时钟的两倍即168M,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍即84M。
知道定时器的时钟源频率我们用定时器做延时就很方便了,只要设定合适的分频系数即可,附一下用中断实现延时的公式:(摘自原子的STM32F4开发指南)
Tout = ((arr+1)*(psc+1))/T clk;
公式中psc就是分频系数,arr就是计数值,达到这个计数就会发生溢出中断,T clk就是我上述分析的时钟源频率的倒数。
STM32F4的系统时钟树时钟系统是微处理器同步系统的基准和运行节拍,如同人的心跳节拍一样。
因此时钟系统是微处理器中最重要的一个核心部分。
STM32F4的时钟系统比较复杂,不像简单的51单片机一个系统时钟就可以解决一切。
问:采用一个系统时钟不是很简单吗?为什么STM32要有多个时钟源呢?答:因为首先STM32本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及RTC只需要几十k的时钟即可。
同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的MCU一般都是采取多时钟源的方法来解决这些问题。
时钟总线:STM32F407上挂载有3根时钟总线,分别为AHB、APB1、APB2;其芯片的外设大部分都挂载在这三根总线上,因此还需要弄清楚这三根总线的时钟频率。
在STM32F4中,有5个最重要的时钟源,为HSI、HSE、LSI、LSE、PLL。
PLL实际是分为两个时钟源,分别为主PLL和专用PLL。
从时钟频率来分可以分为高速时钟源和低速时钟源,在这5个中HSI,HSE以及PLL是高速时钟,LSI和LSE是低速时钟。
从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中HSE和LSE是外部时钟源,其他的是内部时钟源。
根据左边的时钟系统图中的红色标记分别为:①LSI是低速内部时钟,RC振荡器,频率为32kHz左右。
供独立看门狗和自动唤醒单元使用②LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
这个主要是RTC的时钟源。
③HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~26MHz。
HSE也可以直接做为系统时钟或者PLL输入。
④HSI是高速内部时钟,RC振荡器,频率为16MHz。
可以直接作为系统时钟或者用作PLL输入。
⑤PLL为锁相环倍频输出。
STM32F4有两个PLL:1)主PLL(PLL)由HSE或者HSI提供时钟信号,并具有两个不同的输出时钟。
STM32F407高级定时器TIM1定时配置因为在网上很难找到高级定时器TIM1 的配置,而且高级定时器的配置跟普通定时器不太一样,所以记录一下。
实验板子:正点原子探索者STM32F407ZGT6TIM1、TIM8至TIM11的时钟为APB2时钟的两倍即168M,TIM2至TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍即84M。
//初始化配置void Timer1_Init(u16 arr,u16 psc){TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrecture;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); /*使能定时器1的时钟*/NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;/*定时器1的中断通道使能*/NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/*定时器1的中断通道使能*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;/*抢占优先级*/NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;/*响应优先级*/NVIC_Init(&NVIC_InitStructure);/*配置中断分组,并使能中断*/TIM_TimeBaseInitStrecture.TIM_Period = arr;/*重装载寄存器*/TIM_TimeBaseInitStrecture.TIM_Prescaler = psc;/*预分配*/TIM_TimeBaseInitStrecture.TIM_ClockDivision = TIM_CKD_DIV1;/*时钟分频*/TIM_TimeBaseInitStrecture.TIM_CounterMode = TIM_CounterMode_Up;/*向上计数*/TIM_TimeBaseInitStrecture.TIM_RepetitionCounter = 0;/*重复计数寄存器*/TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStrecture);/*初始化*/TIM_ClearFlag(TIM1,TIM_FLAG_Update);/*清更新标志位*/TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);/*使能中断*/TIM_Cmd(TIM1,ENABLE);/*使能计数*/}中断函数//中断函数void TIM1_UP_TIM10_IRQHandler(void){if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)//检查指定的TIM中断发生与否:TIM 中断源{TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清除TIMx的中断待处理位:TIM 中断源/***************在此处添加中断执行内容******************/LED1 = ~LED1;printf('定时器1定时器1定时器1定时器1定时器1定时器1');}}主函数测试int main(void){NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2delay_init(168); //初始化延时函数uart_init(115200);//PA9 PA10 初始化串口波特率为115200//LED_Init(); //PF9 PF10Timer1_Init(10000-1,8400-1);// (10000 x 8400) / 168M = 0.5s.while(1){}}。
基于STM32F107VC的 IEEE1588精密时钟同步分析与实现张小强;谢鹏程【期刊名称】《现代电子技术》【年(卷),期】2011(034)013【摘要】随着网络化与分布式系统的应用,对系统各节点间的时钟同步精度要求越来越高,尤其在分布式运动控制中,高精度时钟同步更是一切应用的基础.针对此问题,首先分析了IEEE 1588时钟同步的基本原理,并从理论上深入研究了影响时钟同步的关键因素,经过综合分析对比各实现方案的优劣,创新性提出了具有较高性价比的基于STM32F107VC的IEEE 1588实现方案,通过捕获硬件时间戳和校正频率漂移,在自定义协议中实现了低于300 ns的高精度时钟同步.%A higher precision of clock synchronization is needed with the development of network and distributed system, and especially the high-precision clock synchronization is the foundation of all applications in a distributed "motion control system. The basic principle of IEEE 1588 standard is introduced, and the key factors which affect the clock synchronization are studied theoretically. Through comparison of various methods, the best cost-effective implementation based on STM32F107VC microprocessor is decided, and the high precision clock synchronization below 300ns is realized by capturing hardware time stamp and adjusting frequency drift.【总页数】4页(P172-174,178)【作者】张小强;谢鹏程【作者单位】华南理工大学机械与汽车工程学院,广东广州 510640;华南理工大学机械与汽车工程学院,广东广州 510640【正文语种】中文【中图分类】TN911.7-34【相关文献】1.基于ARM的IEEE1588精密时钟同步协议的实现 [J], 孔亚广;孙祥祥2.基于ARM的IEEE1588精密时钟同步协议的实现 [J], 孔亚广;孙祥祥;3.基于ARM的IEEE1588精密时钟同步协议实现 [J], 王晋祺; 陈鸿4.IEEE1588精密时钟同步协议的实现探讨 [J], 董广玉5.IEEE1588精密时钟同步协议的分析与实现 [J], 庾智兰;李智因版权原因,仅展示原文概要,查看原文内容请购买。
正点原子stm32f407rtc时钟外部电路概述说明1. 引言1.1 概述本文将介绍正点原子stm32f407rtc时钟外部电路的概述,并详细说明其设计要点以及与外部设备的接口和协议技术要点。
该外部电路旨在提供稳定、精确的时钟信号给STM32F407RTC芯片,以确保系统时间的准确性。
1.2 文章结构本文共分为五个部分,每个部分都涵盖了具体的内容。
- 第一部分是引言,主要介绍文章目录和概述。
- 第二部分是正点原子STM32F407RTC时钟外部电路概述说明,包括简要介绍STM32F407RTC芯片以及RTC外部电路设计要点和外部晶振选型及连接方法。
- 第三部分是原子STM32F407RTC外部时钟模块设计考虑因素,涵盖了电源与地线设计、防干扰措施和滤波器设计,以及时钟频率精度和稳定性考虑。
- 第四部分是STM32F407RTC与外部设备的接口与协议技术要点,详细介绍了I2C接口通信配置技巧、SPI接口通信配置技巧以及UART接口通信配置技巧。
- 最后一部分是结论,对整篇文章进行总结和回顾。
1.3 目的本文旨在帮助读者更好地理解正点原子STM32F407RTC时钟外部电路的设计原理和要点。
通过阐述电路设计考虑因素以及接口和协议技术要点,读者可以了解如何有效地搭建一个稳定、可靠的时钟外部电路,并且能够与其他设备进行良好的通信。
此外,我们也将探讨一些优化技巧和经验教训,以帮助读者在实际应用中避免常见问题和错误。
最终,希望读者能够在正点原子STM32F407RTC开发中有所启发并取得成功。
2. 正点原子stm32f407rtc时钟外部电路概述说明2.1 STM32F407RTC简介正点原子stm32f407rtc是一款基于STM32F407芯片的实时时钟模块,具有高度精确的计时功能。
它可以用于各种需要准确时间计量的应用场景,如智能家居系统、工业自动化控制等。
2.2 RTC外部电路设计要点在设计正点原子stm32f407rtc时钟外部电路时,需要考虑以下要点:首先,在供电方面,应保证稳定可靠的供电源并避免电压波动对时钟模块造成影响。
基于STM32F407扩展卡尔曼软启动器设计和实现董锦旗;郝晓红【摘要】电机在启动期间由于启动电流大、转矩小,产生的转矩脉动使电机快速加速,引起剧烈的机械振动,严重时将危害电机安全运行.为了消除启动期间电机抖动状况,往往采用软启动器方式使电机平稳快速启动.在传统电机数学模型的基础上,使用扩展卡尔曼滤波算法对电机磁链进行了估算;采用STM32F407设计了电机软启动器控制系统;并对该控制系统进行了实验验证.实验结果表明,扩展卡尔曼直接观测的转矩磁链提高了系统的控制准确性,而STM32F407使控制系统更加快速和可靠,能很好的满足电机启动控制要求,具有较高的应用价值.【期刊名称】《制造业自动化》【年(卷),期】2017(039)009【总页数】4页(P15-18)【关键词】STM32F407;扩展卡尔曼;软启动器;实验验证【作者】董锦旗;郝晓红【作者单位】天津机电职业技术学院电子信息系,天津;中国民航大学工程技术训练中心,天津 300300【正文语种】中文【中图分类】TP230 引言电机在初始启动过程中,需要较大的电流,其最大电流可达到电机本身额定电流的5~8倍以上,一方面给电机自身带来额外的耗损,另一方面也严重影响了电机的使用寿命。
解决此问题,当前主要的解决办法大多采用的是软启动器控制,该方法一定程度上限制了电机的启动电流,避免了过大的启动电流[1,2]。
为了很好的解决电机在启动期间电流较大等引发的一系列问题,文章引入了扩展卡尔曼滤波器对电机磁链直接观测;设计了基于STM32F407微处理器的软启动器系统。
系统分别从硬件系统和软件算法两方面保证所设计的软启动器快速、准确以及可靠的运行,从根本上抑制了传统电机由纯积分环节产生的初值敏感性和直流漂移等主要缺点。
且进一步对设计的软启动器控制系统进行实验验证。
实验验证结果表明,文章所设计的系统具有良好的转矩控制性能,实现了电机平滑启动,降低了对电网的冲击,具有较高的使用价值。
《探究STM32F407的标准库时间基准》1. 引言在嵌入式系统开发中,时间基准是非常重要的,尤其是对于STM32F407这样的微控制器。
本文将深入探讨STM32F407标准库的时间基准,并分析其在嵌入式系统中的应用和优势。
2. STM32F407的时间基准STM32F407微控制器是STMicroelectronics推出的一款高性能、低功耗的ARM Cortex-M4内核微控制器。
它内置了丰富的外设和功能模块,其中包括多种定时器和计数器,这些外设提供了丰富的时间基准功能。
2.1 定时器STM32F407内置了多个通用定时器(TIM),这些定时器可以提供精确的定时和计数功能。
通过配置TIM的各种参数,可以实现不同精度和周期的时间基准。
2.2 SysTick定时器除了通用定时器外,STM32F407还内置了SysTick定时器。
SysTick 定时器是一个24位向下计数器,可以提供多种时钟频率的选择和中断功能。
它适用于系统级的时间基准。
3. STM32F407标准库的时间基准应用在嵌入式系统开发中,时间基准通常用于任务调度、周期性操作、时序控制等方面。
STM32F407标准库提供了丰富的时间基准功能,可以应用于各种实际场景。
3.1 任务调度通过配置定时器的定时周期和中断触发,可以实现多任务的精确调度。
在实时操作系统(RTOS)中,时间基准是任务调度的重要依据,STM32F407标准库的时间基准为任务调度提供了可靠的支持。
3.2 时序控制许多嵌入式系统需要精确的时序控制,例如通信协议处理、传感器采样等。
通过STM32F407的定时器和计数器,可以实现精确的时序控制,保证系统的稳定性和可靠性。
4. 个人观点和总结对于嵌入式系统开发者来说,熟练掌握STM32F407标准库的时间基准是非常重要的。
时间基准不仅可以提高系统的性能和稳定性,还可以为开发者提供便利和灵活性。
我建议在实际项目中充分利用STM32F407的时间基准功能,以实现更加可靠和高效的嵌入式系统。
正点原子f407标准库例程正点原子F407标准库例程一、概述正点原子F407是一款基于STM32F407高性能微控制器的高性能开发板,广泛应用于各种嵌入式系统开发。
为了方便用户快速上手和熟悉F407的开发,我们提供了丰富的例程,涵盖了各种基本功能和应用场景。
二、例程列表1. 初始化例程* 硬件初始化:包括时钟、GPIO、中断等基础硬件的初始化。
* 系统初始化:包括HAL库、FreeRTOS等系统的初始化。
2. 基本输入输出例程* GPIO基本操作:包括输入输出、电平高低、端口配置等操作。
* 定时器基本操作:包括定时器启动、停止、重装载等操作。
* 串口基本操作:包括串口配置、发送接收等操作。
3. 中断例程* GPIO中断:包括外部中断、内部中断等操作。
* 定时器中断:包括定时器中断处理、定时器中断回调等操作。
4. 高级应用例程* 外部存储访问:包括SD卡、SPI Flash等外部存储的读写操作。
* 触摸屏操作:包括触摸屏校准、坐标获取等操作。
* 网络通信:包括以太网、Wi-Fi等网络通信操作。
5. 常用库函数例程* 中断服务函数(ISR):包括定时器中断服务函数、外部中断服务函数等。
* 延迟函数:包括毫秒级延迟、微秒级延迟等函数。
* 常用数学函数:包括取余、开方、对数等常用数学函数。
6. 系统移植例程* FreeRTOS移植:包括任务调度、队列、信号量等FreeRTOS核心功能的移植。
* 系统引导程序:包括引导程序烧录、引导程序运行等操作。
7. 应用案例例程* 步进电机控制:通过定时器和GPIO控制步进电机的旋转。
* 蓝牙通信:通过蓝牙模块实现数据传输和通信。
STM32F072从零配置⼯程-⾃定义时钟配置详解从⾃⼰的板⼦STM32F407⼊⼿,参考官⽅的SystemInit()函数:核⼼在SetSysClock()这个函数,官⽅默认是采⽤HSE(设定为8MHz)作为PLL锁相环的输⼊输出168MHz的SYSCLK;/*** @brief Setup the microcontroller system* Initialize the Embedded Flash Interface, the PLL and update the* SystemFrequency variable.* @param None* @retval None*/void SystemInit(void){/* Reset the RCC clock configuration to the default reset state ------------*//* Set HSION bit */RCC->CR |= (uint32_t)0x00000001;/* Reset CFGR register */RCC->CFGR = 0x00000000;/* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;/* Reset PLLCFGR register */RCC->PLLCFGR = 0x24003010;/* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;/* Disable all interrupts */RCC->CIR = 0x00000000;/* Configure the System clock source, PLL Multiplier and Divider factors,AHB/APBx prescalers and Flash settings ----------------------------------*/SetSysClock();}这⾥⼤致分析⼀下官⽅默认的SetSysClock()配置:由于我个⼈采⽤的是STM32F407型号的芯⽚,因此精简⼀下函数;总体思路的话:使能HSE;等待HSE初始化完毕,进⾏下⼀步设置;设置HCLK、PCLK1、PCLK2的分频系数;配置PLL,使能PLL,等待PLL初始化完毕;选择PLL作为SYSCLK,等待SYSCLK时钟设置完毕;/*** @brief Configures the System clock source, PLL Multiplier and Divider factors,* AHB/APBx prescalers and Flash settings* @Note This function should be called only once the RCC clock configuration* is reset to the default reset state (done in SystemInit() function).* @param None* @retval None*/static void SetSysClock(void){/******************************************************************************//* PLL (clocked by HSE) used as System clock source *//******************************************************************************/__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/* Enable HSE */RCC->CR |= ((uint32_t)RCC_CR_HSEON);/* Wait till HSE is ready and if Time out is reached exit */do{HSEStatus = RCC->CR & RCC_CR_HSERDY;StartUpCounter++;} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));if ((RCC->CR & RCC_CR_HSERDY) != RESET){else{HSEStatus = (uint32_t)0x00;}if (HSEStatus == (uint32_t)0x01){/* Select regulator voltage output Scale 1 mode */RCC->APB1ENR |= RCC_APB1ENR_PWREN;PWR->CR |= PWR_CR_VOS;/* HCLK = SYSCLK / 1*/RCC->CFGR |= RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK / 2*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;/* PCLK1 = HCLK / 4*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;/* PCLK2 = HCLK / 1*/RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK / 2*/RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;/* Configure the main PLL */RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);/* Enable the main PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till the main PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Configure Flash prefetch, Instruction cache, Data cache and wait state */FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; /* Configure Flash prefetch, Instruction cache, Data cache and wait state */FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS; /* Select the main PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= RCC_CFGR_SW_PLL;/* Wait till the main PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);{}}else{ /* If HSE fails to start-up, the application will have wrong clockconfiguration. User can add here some code to deal with this error */}}在官⽅的基础上,直接设定HSE作为SYSCLK时钟:初始化HSE;等待HSE初始化成功后再继续;设置调压器电压输出级别为1以便使器件在最⼤频率⼯作;设置HCLK、PCLK1、PCLK2分频系数;设置HSE作为系统时钟;void HSE_SetSysClock(void){__IO uint32_t HSEStartUpStatus = 0; /* 开启HSE时钟 */ /* 此函数从stm32f0xx_rcc.c获取,⽤于配置外部时钟HSE: * 有三个配置:RCC_HSE_OFF关闭外部HSE时钟 * RCC_HSE_ON开始外部HSE晶振 * RCC_HSE_Bypass开始HSE旁路设置 */ RCC_HSEConfig(RCC_HSE_ON); /* 若时钟配置成功 */if(HSEStartUpStatus == SUCCESS){RCC->APB1ENR |= RCC_APB1ENR_PWREN;PWR->CR |= PWR_CR_VOS;RCC_HCLKConfig(RCC_SYSCLK_Div1);RCC_PCLK2Config(RCC_HCLK_Div1);RCC_PCLK1Config(RCC_HCLK_Div1); /* 将SYSCLK系统时钟设置为HSE */RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); /* 等待SYSCLK系统时钟设置成功 */while(RCC_GetSYSCLKSource() != 0x04){}}else{while(1);}}使⽤HSI经过PLL配置系统时钟:使能HSI时钟;获取HSI状态并等待HSI稳定;设置调节器电压输出级别配置为1;设置HCLK、PCLK1/2分频系数;设置PLL时钟分频系数;使能PLL并等待PLL稳定后配置PLL状态;设置PLL作为SYSCLK时钟并等待设置完成;void HSI_SetSysClock(uint32_t m, uint32_t n, uint32_t p, uint32_t q) {__IO uint32_t HSIStartUpStatus = 0;/* 去初始化RCC */RCC_DeInit();/* 使能HSI时钟 */RCC_HSICmd(ENABLE);/* 从RCC的CR寄存器中获取HSI配置状态 */HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;/* 若HSI配置成功 */if(HSIStartUpStatus == RCC_CR_HSIRDY){/* 配置调节器电压输出级别为1 */RCC->APB1ENR |= RCC_APB1ENR_PWREN;PWR->CR |= PWR_CR_VOS;/* 配置SYSCLK到HCLK的分频系数为1 */RCC_HCLKConfig(RCC_SYSCLK_Div1);/* 配置HCLK到PCLK1/2的分频系数为2/4 */RCC_PCLK2Config(RCC_HCLK_Div2);RCC_PCLK1Config(RCC_HCLK_Div4);/* 配置PLL参数,选⽤HSI作为PLL参数,同时使能PLL */RCC_PLLConfig(RCC_PLLSource_HSI, m, n, p, q);RCC_PLLCmd(ENABLE);/* 等待PLL设置完成 */while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); FLASH->ACR = FLASH_ACR_PRFTEN| FLASH_ACR_ICEN| FLASH_ACR_DCEN| FLASH_ACR_LATENCY_5WS;RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);while(RCC_GetSYSCLKSource() != 0x08);}else{while(1);}}HAL时钟配置分析:与STM32标准外设库不同,HAL库来实现时钟配置需要重新适应配置⽅式,但是本质的寄存器调动是类似不变的,且配置的过程也和STM32标准外设库相似;参考使⽤STMCube⽣成的代码,时钟树如图所⽰:在STM32Cube中设置:HSE设置为Crystal/Ceramic Resonator,Input Frequency设置为16MHz;在⼯程中要配置的参数:第⼀个HSE_VALUE参数位于stm32f0xx_hal_conf.h中,此参数与在STMCube时钟树上定义的⼀致,需要⼿动设置为实际的参数值;第⼆个HSE_VALUE参数位于system_stm32f0xx.c中,此参数默认为8MHz,可以通过⽤户程序来提供和调整;第三个SystemCoreClock参数位于system_stm32f0xx.c中,其默认值也是8MHz,可以根据以下三种⽅式来更新: 调⽤CMSIS函数SystemCoreClockUpdate()、 调⽤HAL API函数HAL_RCC_GetHCLKFreq()、 调⽤HAL_RCC_ClockConfig();/*** @brief Adjust the value of External High Speed oscillator (HSE) used in your application.* This value is used by the RCC HAL module to compute the system frequency* (when HSE is used as system clock source, directly or through the PLL).*/#if !defined (HSE_VALUE)#define HSE_VALUE ((uint32_t)16000000) /*!< Value of the External oscillator in Hz */#endif /* HSE_VALUE */#if !defined (HSE_VALUE)#define HSE_VALUE ((uint32_t)8000000)/*!< Default value of the External oscillator in Hz.This value can be provided and adapted by the user application. */#endif /* HSE_VALUE *//** @addtogroup STM32F0xx_System_Private_Variables* @{*//* This variable is updated in three ways:1) by calling CMSIS function SystemCoreClockUpdate()2) by calling HAL API function HAL_RCC_GetHCLKFreq()3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequencyNote: If you use this function to configure the system clock there is no need to call the 2 first functions listed above, since SystemCoreClock variable is updated automatically.uint32_t SystemCoreClock = 8000000;实际的时钟配置函数如下图:使⽤了三个参数来配置:RCC_OscInitStruct⽤来配置外部时钟参数,这⾥设置晶振类型为HSE、设置HSE的状态为开启状态、不使⽤PLL;RCC_ClkInitStruct⽤来配置系统时钟内的参数(如Sys CLK、HCLK、PCLK1),这⾥设置要配置的时钟类型为HCLK、SYSCLK、PCLK1,选择HSE时钟作为SYSCLK的时钟源,并设置系统时钟SYSCLK分频系数为0、HCLK的分频系数为4;PeriphClkInit⽤来配置外设时钟的时钟源,这⾥设置USART1/2的时钟源为PCLK1;/*** @brief System Clock Configuration* @retval None*/void SystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};/** Initializes the CPU, AHB and APB busses clocks*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK){Error_Handler();}PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_USART2;art1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;art2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){Error_Handler();}HAL_SYSTICK_Config(SystemCoreClock / 1000);HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);}这⾥加⼊了对SysTick的时钟配置,参考HAL库本⾝的设置:HAL_SYSTICK_Config()⽤来配置使能和配置SysTick寄存器;HAL_SYSTICK_CLKSourceConfig()选择AHB时钟(或AHB时钟除以8)作为SysTick时钟源;HAL_NVIC_SetPriority()配置SysTick_IRQn的中断优先级为0,默认为最⾼;。