01:(手撸HAL+CubeMX)时钟篇

(手撸HAL+CubeMX)时钟篇

  • 1、对SystemInit函数的分析
  • 2、使用HSI将总线时钟配置为最高频率
  • 3、使用HSE将总线时钟配置为最高频率
  • 4、使用Cube配置时钟树的参数
  • 5、对HAL_Init函数分析
  • 6、对系统定时器中断服务函数分析

在这里插入图片描述

有关时钟树和上电/复位的基础知识请参考“寄存器开发入门教程的第5章和第6章”
本章使用到与RCC有关的HAL库函数详解如下:

/***** RCC_Exported_Functions_Group1 *****/
1.HAL_StatusTypeDef HAL_RCC_DeInit(void);•功能:复位将时钟复位成初始状态,效果如下:①使用 HSI 作为系统时钟②关闭 HSE,PLL③关闭 CSS 和 MCO输出④AHB,APB1,APB2 分频值都是1⑤清除所有标志位,并关闭所有RCC相关中断•参数:无•返回值:HAL_OK       = 0x00U,HAL_ERROR    = 0x01U,HAL_BUSY     = 0x02U,HAL_TIMEOUT  = 0x03U:2.HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct);•功能:对时钟树的参数进行配置,包括HSI,HSE,PLL•参数:•RCC_OscInitStruct:指向RCC_OscInitTypeDef 结构体的指针•RCC_OscInitTypeDef 结构体元素,包括以下元素:•OscillatorType:选择需要配置的晶体振荡器,可选以下选项:RCC_OSCILLATORTYPE_NONE            0x00000000U:选择不配置振荡器RCC_OSCILLATORTYPE_HSE             0x00000001U:选择HSERCC_OSCILLATORTYPE_HSI             0x00000002U:选择HSIRCC_OSCILLATORTYPE_LSE             0x00000004U:选择LSERCC_OSCILLATORTYPE_LSI             0x00000008U:选择LSI•HSEState:使能/关闭外部高速晶振HSE,可选以下选项:RCC_HSE_OFF   :关闭HSERCC_HSE_ON    :打开HSERCC_HSE_BYPASS:使用有源晶振或者外部时钟信号时选此项•HSEPredivValue:HSE的分频值,可选以下选项:RCC_HSE_PREDIV_DIV1:1分频RCC_HSE_PREDIV_DIV2:2分频•LSEState:使能/关闭外部低速晶振LSE,可选以下选项:RCC_LSE_OFF   :关闭LSERCC_LSE_ON    :打开LSERCC_LSE_BYPASS:使用有源晶振或者外部时钟信号时选此项•HSIState:使能/关闭内部高速晶振HSI,可选以下选项:RCC_HSI_OFF   :关闭HSIRCC_HSI_ON    :打开HSI•HSICalibrationValue:对HSI晶振进行微调:可选0x00~0x1F,默认值RCC_HSICALIBRATION_DEFAULT(0x10)•LSIState:使能/关闭内部低速晶振LSI,可选以下选项:RCC_LSI_OFF   :关闭LSIRCC_LSI_ON    :打开LSI•RCC_PLLInitTypeDef PLL:PLL参数的结构体,包括以下元素•PLLState:使能/关闭PLL,可选以下选项:RCC_PLL_NONERCC_PLL_OFF :关闭PLLRCC_PLL_ON  :打开PLL•PLLSource:PLL的时钟源,可选以下选项:RCC_PLLSOURCE_HSI_DIV2:HSI经过2分频后作为PLL的时钟源RCC_PLLSOURCE_HSE     :HSE作为PLL的时钟源•PLLMUL:PLL的倍频系数,可选以下选项:RCC_PLL_MUL2~RCC_PLL_MUL16•返回值:HAL_OK       = 0x00U,HAL_ERROR    = 0x01U,HAL_BUSY     = 0x02U,HAL_TIMEOUT  = 0x03U:3.HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency);•功能:对总线进行配置,包括SystemClock,AHB,APB1,APB2。设置Flash等待周期•参数:•RCC_ClkInitStruct:指向RCC_ClkInitTypeDef 结构体的指针•RCC_OscInitTypeDef 结构体元素,包括以下元素:•ClockType:选择需要配置总线,可选以下选项:RCC_CLOCKTYPE_SYSCLK  :选择系统总线RCC_CLOCKTYPE_HCLK    :选择AHB总线RCC_CLOCKTYPE_PCLK1   :选择APB1总线RCC_CLOCKTYPE_PCLK2   :选择APB2总线•SYSCLKSource:选择系统总线的时钟源,可选以下选项:RCC_SYSCLKSOURCE_HSI   :选择HSI作为系统总线时钟的时钟源RCC_SYSCLKSOURCE_HSE   :选择HSE作为系统总线时钟的时钟源RCC_SYSCLKSOURCE_PLLCLK:选择PLL作为系统总线时钟的时钟源•AHBCLKDivider:AHB总线的预分频系数,可选以下选项:RCC_SYSCLK_DIV1~RCC_SYSCLK_DIV512•APB1CLKDivider:APB1总线的分频系数,可选以下选项:RCC_HCLK_DIV1~RCC_HCLK_DIV16•APB2CLKDivider:APB2总线的分频系数,可选以下选项:RCC_HCLK_DIV1~RCC_HCLK_DIV16•FLatency:设置Flash等待周期•返回值:HAL_OK       = 0x00U,HAL_ERROR    = 0x01U,HAL_BUSY     = 0x02U,HAL_TIMEOUT  = 0x03U:/***** RCC_Exported_Functions_Group2 *****/  	     
4.void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv);•功能:配置MCO引脚(PA8)输出源•参数:•RCC_MCOx:选择MCO对应的引脚(可选值为1个:RCC_MCO对应的PA8)•RCC_MCOSource:指向RCC_ClkInitTypeDef 结构体的指针RCC_MCO1SOURCE_NOCLOCK:无时钟RCC_MCO1SOURCE_SYSCLK :选择SYSCLK从MCO引脚输出RCC_MCO1SOURCE_HSI    :选择HSI从MCO引脚输出RCC_MCO1SOURCE_HSE    :选择HSE从MCO引脚输出•RCC_MCODiv:分频值(可选值为1个:RCC_MCODIV_1)5.uint32_t HAL_RCC_GetSysClockFreq(void);•功能:获取系统总线时钟频率•参数:无•返回值:	系统总线时钟的频率6.uint32_t HAL_RCC_GetHCLKFreq(void);•功能:获取AHB总线时钟频率•参数:无•返回值:	AHB总线时钟的频率7.uint32_t HAL_RCC_GetPCLK1Freq(void);•功能:获取APB1总线时钟频率•参数:无•返回值:	APB1总线时钟的频率8.uint32_t HAL_RCC_GetPCLK2Freq(void);•功能:获取APB2总线时钟频率•参数:无•返回值:	APB2总线时钟的频率9.void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct);•功能:获取RCC_OscInitTypeDef(时钟源配置结构体)配置详情•输入参数:•RCC_OscInitStruct:RCC_OscInitTypeDef 定义的结构体的指针10.void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t *pFLatency);•功能:获取RCC_ClkInitTypeDef(总线时钟配置结构体)配置详情Flash等待周期配置详情•输入参数:•RCC_ClkInitStruct:RCC_ClkInitTypeDef  定义的结构体的指针•pFLatency:32位变量的指针(获取Flash的等待周期)11.void SystemCoreClockUpdate(void);•功能:刷新时钟树的配置参数•参数:无

1、对SystemInit函数的分析

文件源码如下:

void SystemInit (void)
{/* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit */RCC->CR |= 0x00000001U;/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */RCC->CFGR &= 0xF8FF0000U;/* Reset HSEON, CSSON and PLLON bits */RCC->CR &= 0xFEF6FFFFU;/* Reset HSEBYP bit */RCC->CR &= 0xFFFBFFFFU;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= 0xFF80FFFFU;/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x009F0000U;SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
}

对源码进行分析如下:

RCC->CR |= 0x00000001U;//使能HSI内部高速晶振8MHz
RCC->CFGR &= 0xF8FF0000U;//将HSI作为系统SystemClock的时钟源//将AHB的预分频系数,APB1,APB2的预分频不分频,ADC预分频2分频
RCC->CR &= 0xFEF6FFFFU;//关闭了HSE,时钟检测器,PLL
RCC->CR &= 0xFFFBFFFFU;//关闭HSE的旁路(先关HSE,才能关旁路)。
RCC->CFGR &= 0xFF80FFFFU;//操作PLL,其实没什么卵用
RCC->CIR = 0x009F0000U;//清除一些中断的标志位
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

综上:通过SysInit()函数后,选择的是HSI作为时钟树的时钟源。

我们通过代码获取一下各个总线的频率:代码如下:

#include "stm32f1xx_hal.h"uint32_t SysClockFreq;
uint32_t HCLKFreq;
uint32_t PCLK1Freq;
uint32_t PCLK2Freq;int main(void)
{HAL_Init();SystemCoreClockUpdate();//刷新一下时钟树值SysClockFreq = HAL_RCC_GetSysClockFreq();//系统时钟HCLKFreq = HAL_RCC_GetHCLKFreq();//AHB总线时钟PCLK1Freq = HAL_RCC_GetPCLK1Freq();//APB1总线时钟PCLK2Freq = HAL_RCC_GetPCLK2Freq();//APB2总线时钟
}

我们将STM32通过STLink连接到电脑,打开仿真,查看结果。0x007A1200 = 8MHz

在这里插入图片描述

2、使用HSI将总线时钟配置为最高频率

①RCC_Init.c文件的代码如下:

/*** 将时钟源配置配置为HSI,且AHB,ABP1和APB2的时钟频率到达最大值64MHz,32MHz,64MHz* HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)* HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)* */
void HSI_RCC_Init(void)
{/* 1、配置振荡器HSI和PLL *//* 1.1、配置振荡器HSI */RCC_OscInitTypeDef CC_OscInitStruct;CC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;           //选择HSI振荡器作为时钟源CC_OscInitStruct.HSIState = RCC_HSI_ON;                             //开启HSI振荡器CC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;  //HSI微调/* 1.2、配置PLL */CC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;                        //PLL的倍频系数CC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;            //选择分频后的HSICC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;                         //开启PLLHAL_RCC_OscConfig(&CC_OscInitStruct);/* 2、配置系统时钟 */RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;                  //需要配置的总线时钟RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;           //系统时钟的输入源RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;                  //系统时钟的分频系数RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;                   //APB1的分频系数RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;                   //APB2的分频系数HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);  			//传入配置的结构体指针//配置Flash的2个等待周期 
}

②主函数main.c文件的代码如下:

#include "stm32f1xx_hal.h"
#include "STM32_RCC_Init.h"uint32_t SysClockFreq;
uint32_t HCLKFreq;
uint32_t PCLK1Freq;
uint32_t PCLK2Freq;int main(void)
{HAL_Init();HSI_RCC_Init();									//调用HSI配置函数SystemCoreClockUpdate();						//刷新一下时钟树值SysClockFreq = HAL_RCC_GetSysClockFreq();HCLKFreq = HAL_RCC_GetHCLKFreq();PCLK1Freq = HAL_RCC_GetPCLK1Freq();PCLK2Freq = HAL_RCC_GetPCLK2Freq();
}

我们将STM32通过STLink连接到电脑,打开仿真,查看结果。
在这里插入图片描述

3、使用HSE将总线时钟配置为最高频率

①RCC_Init.c文件的代码如下

/*** 将时钟源配置配置为HSE,且AHB,ABP1和APB2的时钟频率到达最大值72MHz,36MHz,72MHz*/
void HSE_RCC_Init(void)
{/* 1、配置振荡器HSE和PLL *//* 1.1、配置HSE*/RCC_OscInitTypeDef CC_OscInitStruct;CC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;       //选择HSE振荡器作为时钟源CC_OscInitStruct.HSEState = RCC_HSE_ON;                         //开启HSECC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;          //HSE的预分配系数/* 1.2、配置PLL*/CC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;                     //PLL的倍频系数CC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;             //选择HSE作为PLL的来源CC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;                     //开启PLLHAL_RCC_OscConfig(&CC_OscInitStruct);/* 2、配置系统时钟 */RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;               //需要配置的总线时钟RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;        //系统时钟的输入源RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;               //系统时钟的分频系数RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;                //APB1的分频系数RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;                //APB2的分频系数HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);		 //传入配置的结构体指针//配置Flash的2个等待周期 
}

②主函数main.c文件的代码如下:

#include "stm32f1xx_hal.h"
#include "STM32_RCC_Init.h"uint32_t SysClockFreq;
uint32_t HCLKFreq;
uint32_t PCLK1Freq;
uint32_t PCLK2Freq;int main(void)
{HAL_Init();HSI_RCC_Init();									//调用HSE配置函数SystemCoreClockUpdate();						//刷新一下时钟树值SysClockFreq = HAL_RCC_GetSysClockFreq();HCLKFreq = HAL_RCC_GetHCLKFreq();PCLK1Freq = HAL_RCC_GetPCLK1Freq();PCLK2Freq = HAL_RCC_GetPCLK2Freq();
}

我们将STM32通过STLink连接到电脑,打开仿真,查看结果。
在这里插入图片描述

4、使用Cube配置时钟树的参数

配置的步骤如下:

  1. 打开CubeMX,找到对应芯片,创建工程
    在这里插入图片描述
  2. 对时钟树参数进行配置
    在这里插入图片描述
    在这里插入图片描述
  3. 工程名字,工程路径
    在这里插入图片描述在这里插入图片描述

对生成时钟树的代码分析:

void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;	//选择HSERCC_OscInitStruct.HSEState = RCC_HSE_ON;						//使能HSERCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;		//HSE分频系数为1分频RCC_OscInitStruct.HSIState = RCC_HSI_ON;						//使能HSIRCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;					//使能PLLRCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;			//PLL时钟源选择HSERCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;					//PLL倍频系数9if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;	//选择配置的总线时钟RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;				//系统总线时钟源选择PLLRCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;					//AHB的预分频系数RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;						//APB1的预分频系数RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;						//APB2的预分频系数if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}

综上:使用Cube生成的对时钟树的配置代码和手撸时钟树配置的代码毫无区别。

在这里插入图片描述

5、对HAL_Init函数分析

在HAL库开发中,主函数中首先就调用的是HAL_Init()函数。
①选择对HAL_Init()函数进行分析:

HAL_StatusTypeDef HAL_Init(void)
{
/* Prefetch buffer is not available on value line devices */__HAL_FLASH_PREFETCH_BUFFER_ENABLE();//使能Flash指令预取/* Set Interrupt Group Priority */HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//NVIC优先级分组/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */HAL_InitTick(TICK_INT_PRIORITY);//初始化系统滴答定时器/* Init the low level hardware */HAL_MspInit();//配置底层硬件/* Return function status */return HAL_OK;
}
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();//使能Flash指令预取
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//NVIC优先级分组,全为抢占优先级
HAL_InitTick(TICK_INT_PRIORITY);//初始化系统滴答定时器,TICK_INT_PRIORITY == 15
HAL_MspInit();//配置底层硬件
return HAL_OK;//返回一个OK

②选择对HAL_InitTick()函数进行分析:

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{/* Configure the SysTick to have interrupt in 1ms time basis*/if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U){return HAL_ERROR;}/* Configure the SysTick IRQ priority */if (TickPriority < (1UL << __NVIC_PRIO_BITS)){HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);uwTickPrio = TickPriority;}else{return HAL_ERROR;}/* Return function status */return HAL_OK;
}
①if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{return HAL_ERROR;
}
•uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb):用于配置系统定时器。详细解释如下。
•uwTickFreq:SysTick 定时器触发中断的频率。举个例子,如果你希望每秒产生 1000 次中断,那么 uwTickFreq = 1000
•SystemCoreClock:这是系统的主时钟频率,通常由 SystemClockConfig 配置,单位是 Hz。
•SystemCoreClock / (1000U / uwTickFreq) 的目的实际上是计算出正确的重载值。
•HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) 时,实际上传递给 HAL_SYSTICK_Config 的值就是 SysTick 定时器需要的计数器重载值。
•如果 HAL_SYSTICK_Config 返回一个大于零的值,表示配置失败,函数会返回 HAL_ERROR。②if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);uwTickPrio = TickPriority;
}
•配置系统定时器中断的优先级值,TickPriority:传入的参数,用来设置 SysTick 中断的优先级

③选择对HAL_SYSTICK_Config()函数进行分析:

uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{return SysTick_Config(TicksNumb);
}
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk){return (1UL);                                                   /* Reload value impossible */}SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |SysTick_CTRL_TICKINT_Msk   |SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */return (0UL);                                                     /* Function successful */
}
SysTick->LOAD  = (uint32_t)(ticks - 1UL);//系统定时器的重装值
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);//设置中断优先级
SysTick->VAL   = 0UL;//清除当前计数器的值	
SysTick->CTRL  |= SysTick_CTRL_CLKSOURCE_Msk;//滴答定时器的时钟源设置为系统总线SYSCLK
SysTick->CTRL  |= SysTick_CTRL_TICKINT_Msk;//启动定时器中断
SysTick->CTRL  |= SysTick_CTRL_ENABLE_Msk;//启动SysTick定时器

综上:HAL_Init()最主要的功能就是配置系统滴答定时器1ms中断。
在这里插入图片描述

6、对系统定时器中断服务函数分析

①中断服务函数代码如下:

void SysTick_Handler(void)
{/* USER CODE BEGIN SysTick_IRQn 0 *//* USER CODE END SysTick_IRQn 0 */HAL_IncTick();/* USER CODE BEGIN SysTick_IRQn 1 *//* USER CODE END SysTick_IRQn 1 */
}

②HAL_IncTick()函数代码如下:

__weak void HAL_IncTick(void)
{uwTick += uwTickFreq;//uwTickFreq = HAL_TICK_FREQ_1KHZ = 1U
}

所以系统滴答定时器中断服务函数里面是:每隔1ms进入中断,实现uwTick加1一次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/471151.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据新视界 -- 大数据大厂之 Impala 存储格式转换:从原理到实践,开启大数据性能优化星际之旅(下)(20/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Spring Boot实现文件上传与OSS集成:从基础到应用

目录 前言1. 文件上传的基础实现1.1 前端文件上传请求1.2 后端文件接收与保存 2. 集成第三方OSS服务2.1 准备工作2.2 编写OSS集成代码2.3 修改Controller实现文件上传至OSS 3. 文件上传的扩展&#xff1a;多文件上传与权限控制结语 前言 随着互联网应用的快速发展&#xff0c;…

微服务各组件整合

nacos 第一步&#xff0c;引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency> 第二步&#xff0c;增加配置 spring:application:name: …

机器学习总结

机器学习按照模型类型分为监督学习模型&#xff0c;无监督学习模型和概率模型三大类&#xff1a; 下图是机器学习笔记思维导图&#xff0c;&#xff1a; 一.什么是机器学习 从本质上讲&#xff0c;可以认为机器学习就是在数据中寻找一种合适的函数来描述输入与输出之间的关系。…

WEB攻防-通用漏洞SQL注入sqlmapOracleMongodbDB2等

SQL注入课程体系&#xff1a; 1、数据库注入-access mysql mssql oracle mongodb postgresql 2、数据类型注入-数字型 字符型 搜索型 加密型&#xff08;base64 json等&#xff09; 3、提交方式注入-get post cookie http头等 4、查询方式注入-查询 增加 删除 更新 堆叠等 …

三、损失函数

损失函数 前言一、分类问题的损失函数1.1 二分类损失函数1.1.1 数学定义1.1.2 函数解释&#xff1a;1.1.3 性质1.1.4 计算演示1.1.5 代码演示 1.2 多分类损失函数1.1.1 数学定义1.1.2 性质与特点1.1.3 计算演示1.1.4 代码演示 二、回归问题的损失函数2.1 MAE损失2.2 MSE损失2.3…

PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸

小编最近有一篇png图片要批量压缩&#xff0c;大小都在5MB之上&#xff0c;在网上找了半天要么就是有广告&#xff0c;要么就是有毒&#xff0c;要么就是功能复杂&#xff0c;整的我心烦意乱。 于是我自己用python写了一个纯净工具&#xff0c;只能压缩png图片&#xff0c;没任…

测试工程师简历「精选篇」

【#测试工程师简历#】一份专业且引人注目的测试工程师简历&#xff0c;无疑是你敲开理想职位大门的金钥匙。那么&#xff0c;如何撰写一份既体现技术水平又彰显个人特色的简历呢&#xff1f;以下是幻主简历网整理的测试工程师简历「程序员篇」&#xff0c;欢迎大家阅读收藏&…

git下载慢下载不了?Git国内国外下载地址镜像,git安装视频教程

git安装下载的视频教程在这 3分钟完成git下载和安装&#xff0c;git国内外下载地址镜像&#xff0c;Windows为例_哔哩哔哩_bilibili 一、Git安装包国内和国外下载地址镜像 1.1国外官方下载地址 打开Git的官方网站&#xff1a;Git官网下载页面。在页面上选择对应的系统&…

专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结

目录 动态规划 动态规范五步走&#xff1a; 1. 第 N 个泰波那契数&#xff08;easy&#xff09; 解析&#xff1a; 1.状态表达式&#xff1a; 2.状态转移方程&#xff1a; 3.初始化&#xff1a; 4.填表顺序&#xff1a; 5.返回值 编写代码&#xff1a; 总结&#xff…

阿里云centos7.9服务器磁盘挂载,切换服务路径

项目背景 1、项目使用的服务器为阿里云centos7.9&#xff0c;默认的磁盘为vda&#xff0c;文件系统挂载在这个磁盘上&#xff0c;项目上使用的文件夹为/home/hnst/uploadPath 2、vda使用率已达到91% 3、现购置一块新的磁盘为vdb&#xff0c;大小为2T 目的 切换服务所使用的…

STM32问题集

这里写目录标题 一、烧录1、 Can not connect to target!【ST-LINK烧录】 一、烧录 1、 Can not connect to target!【ST-LINK烧录】 烧录突然 If the target is in low power mode, please enable “Debug in Low Power mode” option from Target->settings menu 然后就&…

Scala学习记录,case class,迭代器

case class case class创建的对象的属性是不可改的 创建对象&#xff0c;可以不用写new 自动重写&#xff1a;toString, equals, hashCode, copy 自动重写方法&#xff1a;toString,equals,hashCode,copy 小习一下 1.case class 的定义语法是什么 基本形式&#xff1a;case …

成都睿明智科技有限公司解锁抖音电商新玩法

在这个短视频风起云涌的时代&#xff0c;抖音电商以其独特的魅力迅速崛起&#xff0c;成为众多商家争夺的流量高地。而在这片充满机遇与挑战的蓝海中&#xff0c;成都睿明智科技有限公司犹如一颗璀璨的新星&#xff0c;以其专业的抖音电商服务&#xff0c;助力无数品牌实现从零…

阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_技术趋势

目录 文献基本信息 序言 1 发展概况 2 重点技术发展 2.1 人工智能技术 2.1.1 应用深化 2.1.2 作战效能提升 2.2 航空技术 2.2.1螺旋桨设计创新 2.2.2 发射回收技术进步 2.3 其他相关技术 2.3.1 远程控制技术探 2.3.2 云地控制平台应用 3 装备系统进展 3.1 无人作…

LeetCode 86.分隔链表

题目&#xff1a; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 思路&#xff1a; 代码&#xff1a; /*** Definiti…

SystemVerilog学习笔记(六):控制流

条件语句 条件语句用于检查块中的语句是否被执行。条件语句创建语句块。如果给出的表达式是 true&#xff0c;执行块中的语句集&#xff0c;如果表达式为 false&#xff0c;则 else 块语句将最后执行。 序号条件语句1.if2.if-else3.if-else ladder4.unique if5.unique0 if6.p…

SQL,力扣题目1127, 用户购买平台

一、力扣链接 LeetCode_1127 二、题目描述 支出表: Spending ---------------------- | Column Name | Type | ---------------------- | user_id | int | | spend_date | date | | platform | enum | | amount | int | ------------------…

【计算机网络】【传输层】【习题】

计算机网络-传输层-习题 文章目录 10. 图 5-29 给出了 TCP 连接建立的三次握手与连接释放的四次握手过程。根据 TCP 协议的工作原理&#xff0c;请填写图 5-29 中 ①~⑧ 位置的序号值。答案技巧 注&#xff1a;本文基于《计算机网络》&#xff08;第5版&#xff09;吴功宜、吴英…

群控系统服务端开发模式-应用开发-前端个人信息功能

个人信息功能我把他分为了3部分&#xff1a;第一部分是展示登录者信息&#xff1b;第二步就是登录者登录退出信息&#xff1b;第三部分就是修改个人资料。 一、展示登录者信息 1、优先添加固定路由 在根目录下src文件夹下route文件夹下index.js文件中&#xff0c;添加如下代码 …