当前位置: 首页 > news >正文

# 2-STM32-复位和时钟控制RCC

STM32-复位和时钟控制RCC

  • 2-STM32-复位和时钟控制RCC
  • 摘要
  • 说明
    • 本文参考资料如下:
  • 一、STM32最小系统回顾
    • STM32F103C8T6核心板原理图
  • 二、复位
  • 三、时钟
    • 3.1 时钟树
    • 3.2 STM32启动过程
    • 3.2 SystemInit()函数
      • 3.2.1 SystemInit()第1句:
      • 3.2.2 SystemInit()第2句:
      • 3.2.3 SystemInit()第3句:
    • 3.3 SetSysClock()函数:
    • 3.4 SetSysClockTo72()函数:
      • 3.4.1 SetSysClockTo72()第1句:
      • 3.4.2 SetSysClockTo72()第2句:
      • 3.4.3 SetSysClockTo72()第3句:
      • 3.4.4 SetSysClockTo72()第4句:
      • 3.4.5 SetSysClockTo72()第5句:
      • 3.4.6 SetSysClockTo72()第6句:
      • 3.4.7 SetSysClockTo72()第7句:
  • 四、标准库与HAL库区别
    • 4.1 HAL库SystemInit()函数
    • 4.1 HAL库配置系统时钟为72MHz函数
      • 4.1.1 Stm32_Clock_Init函数
    • 4.1 HAL库配置系统时钟为72MHz函数
  • 五、总结
  • 六、资料连接

2-STM32-复位和时钟控制RCC

摘要

在上一篇文章中,我们讲解了STM32F103C8T6最小系统中复位和时钟硬件部分,在本章中讲解最小系统中的复位和时钟的软件部分。本文章根据《1-STM32F10x-中文参考手册》的第6节复位和时钟为依据,并介绍时钟源选择外部8MHz晶震HSE,通过SystemInit()函数将STM32时钟配置为72HMz的代码,并在最后对比标准库和HAL库对时钟配置的不同。

说明

本系列,将整理STM32F103内置外设的使用,“基于标准库“进行学习开发,并将手册说明与标准库代码进行对应学习,在文章最后提供本系列中参考的文章和工程代码下载链接。

本文参考资料如下:


## 1.硬件平台
STM32F103C8T6最小系统板
## 2.软件平台
MDK5
## 3.参考文档
1.《1-STM32F10x-中文参考手册》
2.《3-STM32F103xCDE数据手册-中文》
3. 《STM32F103C8T6核心板原理图》
4.《Cortex-M3权威指南》

一、STM32最小系统回顾

在上一节STM32最小系统中,讲解了STM32最小系统由:电源、时钟、下载、复位、启动五个部分组成,本文主要讲解时钟和复位两个部分,因为这两个部分和后续编程紧密相连,而电源、下载、启动三个部分相对固定,编程上不需要太多改动。

STM32F103C8T6核心板原理图

STM32F103C8T6核心板原理图
图中标红的两个部分,时钟和复位就是本文要讲述的部分。复位使用NRST引脚复位,时钟使用外部晶体震荡器HSE

二、复位

由《1-STM32F10x-中文参考手册》的第6节复位和时钟可知,STM32复位方式有三类:系统复位、上电复位、备份区域复位,其中系统复位包含了:NRST引脚复位
复位方式

由系统复位方式可知:一共有5种复位方式,STM32最小系统中的复位就是NRST引脚复位,是硬件复位方式,也是最常用的一种复位方式。其余四种都是软件复位,IWDG、WWDG、SW三种复位方式,在后续看门狗实验时讲解。低功耗复位在低功耗实验时讲解。

三、时钟

时钟源选择

根据《1-STM32F10x-中文参考手册》的第6节时钟部分可知,STM32F103有5种时钟源,但是系统时钟源SYSCLK只有三种选择,HSE、HSI、PLL,LSI和LSE两种低速时钟是提供给RTC和IWDG使用。其中HSE和LSE是需要我们自己外接晶振的,HSI和LSI是STM32F103C8T6内置的,PLL是取自HSE或HSI。由于HSI不精确,所以为了系统时钟SYSCLK能达到72MHz,我们只能选择HSE。如果没有外接HSE的话,单片机会自动使用内部8MHz的HSI作为系统时钟SYSCLK,此时系统时钟就只有8MHz,且不精确。

3.1 时钟树

时钟树

时钟树是《1-STM32F10x-中文参考手册》的第6节时钟的图,此图介绍了5种时钟源是如何提供给单片机内部其它外设的,我们本文主要关心图中红色线:通过外接8MHz晶振,并通过倍频器PLL进行9倍放大后,得到72MHz的系统时钟SYSCLK的过程。外接8MHz晶振我们在STM32最小系统中,我们已经连接了时钟电路,即已经接好了外部8MHz晶振,接下来我们通过SystemInit()函数配置RCC的时钟控制寄存器CR和时钟配置寄存器CFGR,将SYSCLK配置为72MHz。
注:图中梯形表示选择器,矩形表示执行器。

3.2 STM32启动过程

单片机上电后第一行执行的代码是汇编文件startup_stm32f10x_md.s中的Reset_Handler标签,然后执行SystemInit()后才执行main()。所以在执行我们的main()函数之前,单片机会执行SystemInit()函数将单片机时钟配置为72MHz。
Reset_Handler

; Reset handler
Reset_Handler    PROCEXPORT  Reset_Handler             [WEAK]IMPORT  __mainIMPORT  SystemInitLDR     R0, =SystemInitBLX     R0LDR     R0, =__mainBX      R0ENDP

3.2 SystemInit()函数

在SystemInit()函数中会调用SetSysClock()—>>SetSysClockTo72(),SetSysClockTo72()执行完后STM32系统时钟为72MHz,是8MHz外部高速晶振HSE通过PLL进行9倍频后得到。

void SystemInit (void)
{/* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit */RCC->CR |= (uint32_t)0x00000001;/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CLRCC->CFGR &= (uint32_t)0xF8FF0000;
#elseRCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   /* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;/* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= (uint32_t)0xFF80FFFF;#ifdef STM32F10X_CL/* Reset PLL2ON and PLL3ON bits */RCC->CR &= (uint32_t)0xEBFFFFFF;/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x00FF0000;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x009F0000;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000;      
#else/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)#ifdef DATA_IN_ExtSRAMSystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */
#endif /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers *//* Configure the Flash Latency cycles and enable prefetch buffer */SetSysClock();#ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

3.2.1 SystemInit()第1句:

  /* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit */RCC->CR |= (uint32_t)0x00000001;

时钟控制寄存器CR
这一行通过位或运算,将RCC->CR寄存器最低位置1,开启HSI时钟。这一句其实我感觉不要也是可以的,因为手册中CR寄存器复位值是0x0000 xx83,即HSION默认值就是1。

3.2.2 SystemInit()第2句:

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CLRCC->CFGR &= (uint32_t)0xF8FF0000;

时钟配置寄存器CFGR

其中#ifndef STM32F10X_CL条件成立,因为在STM32F103C8T6标准库中,并没有定义这个宏,因此执行RCC->CFGR &= (uint32_t)0xF8FF0000;正如备注所示是复位SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits。对照时钟复位寄存器CFGR中说明,0x00转化二进制是0000 0000,即SW[1:0]被置为00,HPRE[3:0]被置为0000,PPRE1[2:0]被置为000,PPRE2[2:0]被置为000,ADCPRE[1:0]被置为00。0xF8转为二进制是1111 1000,即MCO[2:0]被置为000。

3.2.3 SystemInit()第3句:

  /* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;/* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= (uint32_t)0xFF80FFFF;

这三句和备注一样,对应查看CR寄存器和CFGR寄存器对应位说明,将右边的16进制数转化位二进制后对应查看。

3.3 SetSysClock()函数:

static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSESetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHzSetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHzSetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHzSetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHzSetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHzSetSysClockTo72();
#endif/* If none of the define above is enabled, the HSI is used as System clocksource (default after reset) */ 
}

SYSCLK_FREQ_72MHz宏定义
在system_stm32F10x.c的115行定义了宏SYSCLK_FREQ_72MHz,所以会执行 SetSysClockTo72()。

3.4 SetSysClockTo72()函数:

static void SetSysClockTo72(void)
{__IO uint32_t StartUpCounter = 0, HSEStatus = 0;/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    /* 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){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}  if (HSEStatus == (uint32_t)0x01){/* Enable Prefetch Buffer */FLASH->ACR |= FLASH_ACR_PRFTBE;/* Flash 2 wait state */FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    /* HCLK = SYSCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;#ifdef STM32F10X_CL/* Configure PLLs ------------------------------------------------------*//* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz *//* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);/* Enable PLL2 */RCC->CR |= RCC_CR_PLL2ON;/* Wait till PLL2 is ready */while((RCC->CR & RCC_CR_PLL2RDY) == 0){}/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); 
#else    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |RCC_CFGR_PLLMULL));RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL *//* Enable PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Select PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    /* Wait till PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){}}else{ /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */}
}

在SetSysClockTo72()函数中,开启了HSE,并配置了PLL进行9倍频,然后将SYSCLK配置为72MHz。

3.4.1 SetSysClockTo72()第1句:

  /* Enable HSE */    RCC->CR |= ((uint32_t)RCC_CR_HSEON);

时钟控制寄存器CR
时钟控制寄存器CR的bit16是HSEON,将这一位置1,即可开启外部高速时钟HSE。通过按F12跳转到定义发现,在stm32f10x.h中RCC_CR_HSEON定义如下,转换成二进制后,刚好是bit16为1,通过位或运算”|=“将bit16置1,而其它位不变。

#define  RCC_CR_HSEON                        ((uint32_t)0x00010000)        /*!< External High Speed clock enable */

3.4.2 SetSysClockTo72()第2句:

  /* 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){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}

等待HSE稳定,并设置超时时间HSE_STARTUP_TIMEOUT,HSE稳定后将HSEStatus标志位置1,然后进行后续配置,如果失败置为0,默认使用8MHz的HSI作为系统时钟。

3.4.3 SetSysClockTo72()第3句:

  if (HSEStatus == (uint32_t)0x01){/* Enable Prefetch Buffer */FLASH->ACR |= FLASH_ACR_PRFTBE;/* Flash 2 wait state */FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

这几句是配置FLASH的等待周期的,详情需要查看《STM32F10xxx闪存编程手册》。

3.4.4 SetSysClockTo72()第4句:

    /* HCLK = SYSCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;/* PCLK2 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;/* PCLK1 = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

这三句配置三条总线HCLK、PCLK2和PCLK1的时钟频率。即将PCLK2=HCLK = SYSCLK,PCLK1=HCLK/2。此时SYSCLK还不是72MHz,因为还没有配置PLL进行9倍频。

3.4.5 SetSysClockTo72()第5句:

    /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |RCC_CFGR_PLLMULL));RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

这两句将PLL配置为对HSE进行9倍频。此时PLL时钟为72MHz。

3.4.6 SetSysClockTo72()第6句:

    /* Enable PLL */RCC->CR |= RCC_CR_PLLON;/* Wait till PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}/* Select PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    /* Wait till PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){}

这几句是开启PLL时钟,并将其作为SYSCLK时钟源,等待PLL时钟稳定后,即可退出。此时SYSCLK为72MHz,PCLK2=HCLK = SYSCLK=72MHz,PCLK1=HCLK/2=36MHz。

3.4.7 SetSysClockTo72()第7句:

  else{ /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */}

此段代码是 如果HSE初始化失败,那么默认使用HSI作为SYSCLK时钟,我们也可以在此处进行我们自己的处理,但是通常都不会进行处理。

四、标准库与HAL库区别

共同点:单片机上电后会立即执行启动文件中的Reset_Handler标签,然后调用SystemInit()函数。
不同点:SystemInit()函数实现不一样,HAL库中SystemInit()函数不会调用 SetSysClock()将系统时钟初始化为72MHz,而是需要我们在main()函数中自己初始化为72Mhz。

4.1 HAL库SystemInit()函数

void SystemInit (void)
{/* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit */RCC->CR |= (uint32_t)0x00000001;/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)RCC->CFGR &= (uint32_t)0xF8FF0000;
#elseRCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F105xC */   /* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;/* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= (uint32_t)0xFF80FFFF;#if defined(STM32F105xC) || defined(STM32F107xC)/* Reset PLL2ON and PLL3ON bits */RCC->CR &= (uint32_t)0xEBFFFFFF;/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x00FF0000;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000;
#elif defined(STM32F100xB) || defined(STM32F100xE)/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x009F0000;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000;      
#else/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x009F0000;
#endif /* STM32F105xC */#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)#ifdef DATA_IN_ExtSRAMSystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */
#endif #ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

最后没有调用 SetSysClock();也就不会调用 SetSysClockTo72();

4.1 HAL库配置系统时钟为72MHz函数

int main(void)
{HAL_Init();                    	 	//初始化HAL库    Stm32_Clock_Init(RCC_PLL_MUL9);   	//设置时钟,72Mwhile(1){}
}

需要我们编写 Stm32_Clock_Init()函数。

4.1.1 Stm32_Clock_Init函数

4.1 HAL库配置系统时钟为72MHz函数

void Stm32_Clock_Init(u32 PLL)
{HAL_StatusTypeDef ret = HAL_OK;RCC_OscInitTypeDef RCC_OscInitStructure; RCC_ClkInitTypeDef RCC_ClkInitStructure;RCC_OscInitStructure.OscillatorType=RCC_OSCILLATORTYPE_HSE;    	//时钟源为HSERCC_OscInitStructure.HSEState=RCC_HSE_ON;                      	//打开HSERCC_OscInitStructure.HSEPredivValue=RCC_HSE_PREDIV_DIV1;		//HSE预分频RCC_OscInitStructure.PLL.PLLState=RCC_PLL_ON;					//打开PLLRCC_OscInitStructure.PLL.PLLSource=RCC_PLLSOURCE_HSE;			//PLL时钟源选择HSERCC_OscInitStructure.PLL.PLLMUL=PLL; 							//主PLL倍频因子ret=HAL_RCC_OscConfig(&RCC_OscInitStructure);//初始化if(ret!=HAL_OK) while(1);//选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2RCC_ClkInitStructure.ClockType=(RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStructure.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;		//设置系统时钟时钟源为PLLRCC_ClkInitStructure.AHBCLKDivider=RCC_SYSCLK_DIV1;				//AHB分频系数为1RCC_ClkInitStructure.APB1CLKDivider=RCC_HCLK_DIV2; 				//APB1分频系数为2RCC_ClkInitStructure.APB2CLKDivider=RCC_HCLK_DIV1; 				//APB2分频系数为1ret=HAL_RCC_ClockConfig(&RCC_ClkInitStructure,FLASH_LATENCY_2);	//同时设置FLASH延时周期为2WS,也就是3个CPU周期。if(ret!=HAL_OK) while(1);
}

调用HAL库HAL_RCC_ClockConfig()函数实现将SYSCLK配置为72MHz。

五、总结

通过标准库和HAL库对比,将STM32系统时钟SYSCLK配置为72MHz既可以在main()函数之前,也可以在main()函数里面,即在使用其它片上外设之前都可以。虽然标准库和HAL库调用的库函数不一样,但是最底层都是配置的RCC的CR和CFGR寄存器,只是封装不同而已,所以我们得熟悉手册对RCC使用的说明,再结合标准库和HAL库进行学习,才能理解得更加透彻。

六、资料连接

https://gitee.com/muzi_wood/stm32-f103

相关文章:

# 2-STM32-复位和时钟控制RCC

STM32-复位和时钟控制RCC 2-STM32-复位和时钟控制RCC摘要说明本文参考资料如下&#xff1a; 一、STM32最小系统回顾STM32F103C8T6核心板原理图 二、复位三、时钟3.1 时钟树3.2 STM32启动过程3.2 SystemInit()函数3.2.1 SystemInit()第1句&#xff1a;3.2.2 SystemInit()第2句&a…...

idea中的vcs不见了,如何解决

按如下顺序依次找 filesettingsversion controldirectory mappings点击号vcs 改为Subversion 省流&#xff1a;看如下图...

元数据分类

元数据&#xff08;Metadata&#xff09;是描述数据的数据&#xff0c;通常分为 业务元数据、技术元数据 和 操作元数据。这三类元数据从不同维度对数据进行描述和管理&#xff0c;以下是它们的定义、作用和示例&#xff1a; 1. 业务元数据&#xff08;Business Metadata&#…...

【C语言】(9)—指针3

文章目录 一、字符指针的深入理解二、数组指针详解三、二维数组传参的本质四、函数指针及其应用五、函数指针数组与转移表 一、字符指针的深入理解 1.1 字符指针的基本使用 字符指针(char*)是指向字符类型数据的指针&#xff0c;它有两种常见的使用方式&#xff1a; // 方式一…...

拍电影为什么常用绿幕?认识色度键控(Chroma Key)技术

许多电影拍摄使用绿幕技术,其核心原因在于它通过色度键控(Chroma Key)技术实现背景替换,从而为创作提供高度灵活性、成本效益和视觉效果的可控性。以下从技术原理、应用场景、优势及与其他技术的对比等方面展开分析: 一、绿幕技术的基本原理 绿幕技术的核心是色度键控(C…...

【iOS】Tagged Pointer

【iOS】Tagged Pointer 文章目录 【iOS】Tagged Pointer前言认识Tagged Pointer使用案例结构isa指针经典面试题 前言 在之前的学习中笔者在字符串章节简单了解过这个Tagged Pointer后面笔者就没在多了解这部分内容,今天决定比较系统的学习一下有关于这部分内容的知识. 认识Tagg…...

17.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--微服务基础工具与技术--loki

在微服务中&#xff0c;日志是非常重要的组成部分。它不仅可以帮助我们排查问题&#xff0c;还可以帮助我们分析系统的性能和使用情况。 一、loki简介 loki是一个开源的日志聚合系统&#xff0c;它可以帮助我们高效地收集、存储和分析日志数据。loki的设计理念是“简单、快速…...

OpenWrt开发第8篇:树莓派开发板做无线接入点

文/指尖动听知识库-谷谷 文章为付费内容,商业行为,禁止私自转载及抄袭,违者必究!!! 文章专栏:Openwrt开发-基于Raspberry Pi 4B开发板 树莓派开发板作为无线接入点的时候,可以通过电脑和手机打开WiFi功能搜索到相应打开的WiFi; 1 通过Web操作界面开启wifi 1...

电源架构与太阳能充电器电路设计分析

一、电源架构基本工作原理分析 #mermaid-svg-mEaBEAY5xdCMN9Uy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mEaBEAY5xdCMN9Uy .error-icon{fill:#552222;}#mermaid-svg-mEaBEAY5xdCMN9Uy .error-text{fill:#5522…...

英语句型结构

句型类型结构示例示例解释应用场合简单句主谓&#xff08;SV&#xff09;The bird flies.“The bird” 是主语&#xff0c;“flies” 是不及物动词作谓语&#xff0c;描述鸟 “飞” 的动作。描述事物基本行为&#xff0c;如动物习性、自然现象等。主谓宾&#xff08;SVO&#x…...

什么是卷积神经网络

卷积神经网络(CNN)的全面解析 卷积神经网络(Convolutional Neural Network, CNN)是深度学习领域最成功的模型之一,尤其在图像处理和模式识别任务中表现卓越。以下从基本结构、核心组件、发展历程、应用场景、数学基础、训练方法及优缺点等方面展开详述。 一、基本定义与核…...

操作系统: 第三章节 :中断和处理机调度

一:中断与中断系统 -1:中断的概念: 在程序运行过程中出现某紧急事件&#xff0c;必须中止当前正在运行的程序&#xff0c;转去处理这个事件&#xff0c;然后再恢复原来运行的程序&#xff0c;这一过程称为中断. -2:中断装置(硬件): 发现并相应中断的硬件结构: 工作: -----…...

嵌入式硬件篇---IIC

文章目录 前言1. IC协议基础1.1 物理层特性两根信号线SCLSDA支持多主多从 标准模式电平 1.2 通信流程起始条件&#xff08;Start Condition&#xff09;从机地址&#xff08;Slave Address&#xff09;应答&#xff08;ACK/NACK&#xff09;数据传输&#xff1a;停止条件&#…...

SAP学习笔记 - 开发08 - Eclipse连接到 BTP Cockpit实例

有关BTP&#xff0c;之前学了一点儿&#xff0c;今天继续学习。 SAP学习笔记 - 开发02 - BTP实操流程&#xff08;账号注册&#xff0c;BTP控制台&#xff0c;BTP集成开发环境搭建&#xff09;_sap btp开发-CSDN博客 如何在Eclipse中连接BTP Cockpit开发环境实例。 1&#xf…...

安装typescript时,npm install -g typescript报错

删除C:\Users\用户\下的.npmrc文件,如果你的没有&#xff0c;看是不是因为将隐藏的项目勾选上了&#xff0c;然后去掉勾选。 重新输入...

支持selenium的chrome driver更新到136.0.7103.92

最近chrome释放新版本&#xff1a;136.0.7103.92 如果运行selenium自动化测试出现以下问题&#xff0c;是需要升级chromedriver才可以解决的。 selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only su…...

Java在人工智能中的应用:机器学习与深度学习技术探讨

根据您提供的知识库内容&#xff0c;我发现其中主要涉及机器学习和深度学习的内容&#xff0c;而您的文章是关于Java面试技术的。两者的主题并不直接相关&#xff0c;因此无法直接使用知识库中的信息来润色您的文章。 如果您希望将机器学习和深度学习的内容融入文章中&#xf…...

C++23 新特性:深入解析 std::views::join_with(P2441R2)

文章目录 std::views::join_with 基本用法处理字符串集合std::views::join_with 与其他视图的结合使用总结 随着C23标准的逐步推进&#xff0c;我们迎来了许多令人兴奋的新特性&#xff0c;其中之一就是 std::views::join_with。这个新特性是C23中引入的视图适配器&#xff0c…...

【工作记录】crmeb后端项目打开、运行

1、下载代码 1&#xff09;安装git 不再详述 2&#xff09;git拉代码 项目地址如下&#xff0c;在vscode-分支中拉代码 # 克隆项目 git clone https://gitee.com/ZhongBangKeJi/crmeb_java/ 截图如下是已经成功拉下来 注意安装对应版本 2、maven配置 安装配置见&#x…...

前端浏览器判断设备类型的方法

前端浏览器判断设备类型的方法 在前端开发中&#xff0c;判断设备类型&#xff08;如手机、平板、桌面电脑&#xff09;有多种方法&#xff0c;以下是常用的几种方式&#xff1a; 1. 使用 User Agent 检测 通过 navigator.userAgent 获取用户代理字符串进行判断&#xff1a;…...

python 新闻 api + react js 客户端。

1. 起因&#xff0c; 目的: 前面写了几个爬虫。 那么这些数据怎么使用。使用 api &#xff0c; 看看到底有哪些新闻。感受&#xff1a;最初只是一个想法&#xff0c;然而实现的过程中却很枯燥乏味&#xff0c; 甚至怀疑为什么要做这个事情. 2. 先看效果 效果就是能行。 3.…...

Vivado中可新建的工程类型解析

以下是Vivado中可新建的工程类型解析&#xff0c;按用途和场景分类说明&#xff1a; 1. RTL Project&#xff08;RTL工程&#xff09; 用途&#xff1a;从零开始基于RTL代码&#xff08;Verilog/VHDL&#xff09;设计FPGA逻辑&#xff0c;覆盖完整开发流程。适用阶段&#xff…...

TypeScript 中的泛型工具详解

TypeScript 提供了一系列强大的泛型工具类型&#xff0c;可以帮助我们更灵活地操作和转换类型。以下是主要的泛型工具类型及其用法&#xff1a; 1. 基础工具类型 1.1. Partial<T> 将类型 T 的所有属性变为可选。 interface User {name: string;age: number; }type Pa…...

OpenCV进阶操作:指纹验证、识别

文章目录 前言一、指纹验证1、什么是指纹验证2、流程步骤 二、使用步骤&#xff08;案例&#xff09;三、指纹识别&#xff08;案例&#xff09;1、这是我们要识别的指纹库2、这是待识别的指纹图3、代码4、结果 总结 前言 指纹识别作为生物识别领域的核心技术之一&#xff0c;…...

js前端分片传输大文件+mongoose后端解析

最近一直在完善mongoose做webserver的项目&#xff0c;其中程序升级要通过前端传输升级包到服务器。 因为第一次写前端代码&#xff0c;分片传输的逻辑&#xff0c;网上一堆&#xff0c;大同小异&#xff0c;而且版本啊&#xff0c;API不一致的问题&#xff0c;导致头疼的很。后…...

IPLOOK超轻量核心网,助力5G专网和MEC边缘快速落地

随着5G深入千行百业&#xff0c;行业客户对核心网的灵活性、可控性和部署效率提出了更高要求。IPLOOK面向数字化转型需求&#xff0c;推出了超轻量级核心网解决方案&#xff0c;具备体积小、资源占用少、部署灵活、易于维护等特性&#xff0c;广泛适用于专网、实验室、MEC边缘云…...

Spring框架(一)

Spring框架是Java开发中最为流行的框架之一&#xff0c;它以其强大的功能和灵活的设计&#xff0c;极大地简化了企业级应用的开发。本文将详细介绍Spring框架的核心概念、核心技术、依赖注入、多配置文件方式、开发程序的方式、IOC注解方式以及Spring与JUnit的整合。 目录 一、…...

Redis 基础详解:从入门到精通

在当今互联网应用开发领域&#xff0c;数据存储与处理的性能和效率至关重要。Redis&#xff08;Remote Dictionary Server&#xff09;作为一款开源的、基于内存的键值存储系统&#xff0c;凭借其出色的性能和丰富的功能&#xff0c;被广泛应用于数据库、缓存、消息中间件等场景…...

24、TypeScript:预言家之书——React 19 类型系统

一、预言家的本质 "TypeScript是魔法世界的预言家之书&#xff0c;用静态类型编织代码的命运轨迹&#xff01;" 霍格沃茨符文研究院的巫师挥动魔杖&#xff0c;类型注解与泛型的星轨在空中交织成防护矩阵。 ——基于《国际魔法联合会》第12号类型协议&#xff0c;Ty…...

RabbitMQ--进阶篇

RabbitMQ 客户端整合Spring Boot 添加相关的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> 编写配置文件&#xff0c;配置RabbitMQ的服务信息 spri…...

【GESP真题解析】第 19 集 GESP 二级 2025 年 3 月编程题 1:等差矩阵

大家好&#xff0c;我是莫小特。 这篇文章给大家分享 GESP 二级 2025 年 3 月编程题第 1 题&#xff1a;等差矩阵。 题目链接 洛谷链接&#xff1a;B4259 等差矩阵 一、完成输入 根据题意&#xff0c;一行&#xff0c;两个正整数 n&#xff0c;m。 n 和 m的数据范围&#xf…...

电池单元和电极性能

电芯设计中的挑战 对于电池制造商来说&#xff0c;提高电池能量和功率密度至关重要。在高功率密度和长循环寿命之间取得平衡是电池设计中的关键挑战&#xff0c;通常需要仔细优化材料、电极结构和热管理系统。另一个关键挑战是通过优化重量体积比来降低电池单元的总体成本。 工…...

MATLAB 矩阵与数组操作基础教程

文章目录 前言环境配置一、创建矩阵与数组&#xff08;一&#xff09;直接输入法&#xff08;二&#xff09;特殊矩阵生成函数&#xff08;三&#xff09;使用冒号表达式创建数组 二、矩阵与数组的基本操作&#xff08;一&#xff09;访问元素&#xff08;二&#xff09;修改元…...

理解 Token 索引 vs 字符位置

以下是对“理解 Token 索引与字符位置的区别”的内容整理&#xff0c;条理清晰&#xff0c;结构完整&#xff0c;保持技术细节&#xff0c;方便阅读&#xff0c;无多余解释&#xff1a; &#x1f50d; 理解 Token 索引 vs 字符位置 文本分块方法中返回的索引是 token 索引&…...

【RAG】11种Chunking Strategies分块策略介绍和选择

【今日鸡汤】学习之路上&#xff0c;勤奋是比 “聪明” 远远更珍贵的品质。 参考原文地址&#xff1a;https://masteringllm.medium.com/11-chunking-strategies-for-rag-simplified-visualized-df0dbec8e373 在构建强大的检索增强生成&#xff08;RAG&#xff09;系统时&…...

‌中继器:网络中的“血包”与“加时器”‌

在探讨网络技术时&#xff0c;我们往往会遇到各种专业术语和设备&#xff0c;中继器便是其中之一。然而&#xff0c;对于非技术人员或初学者来说&#xff0c;这些概念可能显得抽象且难以理解。今天&#xff0c;我将通过一个生动的比喻——将中继器比作网络中的“血包”与“加时…...

​证明当||x||=1时,Ax=0的最小二乘解是的最小特征值对应的特征向量​

问题&#xff1a;证明当||x||1时&#xff0c;Ax0的最小二乘解是的最小特征值对应的特征向量。 证明&#xff1a; 上个命题等同于&#xff1a;的最小特征值所对应的特征向量可使得||Ax||最小。以下分别对x为的特征向量和不为的特征向量这两种情况进行证明。 情况1: 若x为的特征…...

AI大模型学习十八、利用Dify+deepseekR1 +本地部署Stable Diffusion搭建 AI 图片生成应用

一、说明 最近在学习Dify工作流的一些玩法&#xff0c;下面将介绍一下Dify Stable Diffusion实现文生图工作流的应用方法 Dify与Stable Diffusion的协同价值 Dify作为低代码AI开发平台的优势&#xff1a;可视化编排、API快速集成 Stable Diffusion的核心能力&#xff1a;高效…...

linux基础操作4------(权限管理)

一.前言 今天我们来讲讲linux的权限管理&#xff0c;比如文件的权限&#xff0c;如果大家看过前面说的app逆向的frida&#xff0c;我们在手机里要给frida&#xff0c;我们都要设置一下chomd 777 frida &#xff0c;这样就给了可执行权限&#xff0c;这就是这一章要讲的&#x…...

Linux数据库篇、第零章_MySQL30周年庆典活动

MySQL考试报名网站 Oracle Training and Certification | Oracle 中国 活动时间 2025年 MySQL的30周年庆典将于2025年举行。MySQL于1995年首次发布&#xff0c;因此其30周年纪念日是2025年。为了庆祝这一里程碑&#xff0c;MySQL将提供免费的课程和认证考试&#xff0c;活动…...

HVV面试题汇总合集

应急响应的命令 Linux ps -aux 查看进程 netstat -antlp 查看端口 top查看 cpu使用情况 Windows tasklist 查看进程 netstat -an 查看端口struts2原理特征 原理: 045:默认的content-type解析器会把用户传来的数据直接当成代码执行&#xff0c;造成rce 特征:ognl表达式&…...

Mac下Robotframework + Python3环境搭建

1.安装python3 1.0安装XCODE 1.打开浏览器&#xff0c;登陆苹果开发者网站&#xff1a;https://developer.apple.com/download/more/ 2.登陆你的apple账号&#xff0c;授权访问。 3.查看mac系统版本 需要下载与系统版本对应的Xcode 4.在搜索框中输入&#xff1a; 如果Mac 系统…...

stm32实战项目:无刷驱动

目录 系统时钟配置 PWM模块初始化 ADC模块配置 霍尔接口配置 速度环定时器 换相逻辑实现 主控制循环 系统时钟配置 启用72MHz主频&#xff1a;RCC_Configuration()设置PLL外设时钟使能&#xff1a;TIM1/ADC/GPIO时钟 #include "stm32f10x.h"void RCC_Configu…...

MNIST 手写数字分类

转自我的个人博客: https://shar-pen.github.io/2025/05/04/torch-distributed-series/1.MNIST/ 基础的单卡训练 本笔记本演示了训练一个卷积神经网络&#xff08;CNN&#xff09;来对 MNIST 数据集中的手写数字进行分类的过程。工作流程包括&#xff1a; 数据准备&#xff…...

【RuntimeError: Directory ‘static/‘ does not exist 】

背景 File “/root/miniforge3/lib/python3.10/site-packages/starlette/staticfiles.py”, line 56, in init raise RuntimeError(f"Directory ‘{directory}’ does not exist") RuntimeError: Directory ‘static/’ does not exist 运行读取pdf时候&#xff0c…...

SQL:SELF JOIN(自连接)与CROSS JOIN(交叉连接)

目录 SELF JOIN&#xff08;自连接&#xff09; CROSS JOIN&#xff08;交叉连接 / 笛卡尔积&#xff09; 示例&#xff1a; SELF JOIN CROSS JOIN 如果没有 DATEDIFF() 函数怎么办&#xff1f; &#x1f50d; SELF JOIN vs CROSS JOIN 对比总结 SELF JOIN&#xff08;自…...

Linux网络基础 -- 局域网,广域网,网络协议,网络传输的基本流程,端口号,网络字节序

目录 1. 计算机网络背景 1.1 局域网 1.1.2 局域网的组成 1.2 广域网 1.1.2 广域网的组成 2. 初始网络协议 2.1 网络协议的定义和作用 2.2 网络协议的分层结构 2.2.1 OSI七层模型 2.2.2 TCP/IP 五层&#xff08;四层&#xff09;模型 3. 再识网络协议 3.1 为什么要有…...

当 Manus AI 遇上 OpenAI Operator,谁能更胜一筹?

自主智能体通过实现任务自动化&#xff0c;改变了我们与技术交互的方式&#xff0c;让我们的生活变得更加便捷。去年&#xff0c;OpenAI 为人工智能聊天机器人引入了定时任务和操作智能体&#xff0c;赋予了其代理功能&#xff0c;而 Anthropic 则在 Claude 上实现了类似的功能…...

iOS实名认证模块的具体实现过程(swift)

实名认证是当前APP的一个基础功能了&#xff0c;今天我集成了实名认证模块在iOS应用中的具体实现步骤&#xff0c;结合技术细节与最佳实践&#xff1a; 一、手机号验证 1. 发送短信验证码 技术实现&#xff1a;// 使用Alamofire调用第三方短信API AF.request("https://s…...

UE5定序器中摇臂挂载摄像机 让摄像机始终朝向目标

1. 搭建摄像机摇臂并加入 Sequencer 在关卡中&#xff1a; Cinematics → Add Level Sequence&#xff0c;新建并打开一个 Level Sequence。 在视口里 右键 → Cinematic → Cine Camera Actor Rig → Crane&#xff0c;放一个 CameraRig_Crane。 默认 Crane 自带一个 CineCa…...