历史上的今天
返回首页

历史上的今天

今天是:2024年11月11日(星期一)

正在发生

2020年11月11日 | STM32库函数SystemInit()的理解

2020-11-11 来源:elecfans

SystemInit()这个函数出现在main()函数的第一行,可以看出它的重要性。以前关于SystemInit()这个函数从来没有关心过,只知道这是进行 STM32 系统初始化的一个函数。今天决定仔细看看,重新开始STM32的学习。这个函数在system_stm32f10x.c中,此C文件主要就是干具体硬件配置相关的工作。


void SystemInit (void) 

 

 

RCC->CR |= (uint32_t)0x00000001; 


 

#ifndef STM32F10X_CL 

RCC->CFGR &= (uint32_t)0xF8FF0000; 

#else 

RCC->CFGR &= (uint32_t)0xF0FF0000; 

#endif  


 

RCC->CR &= (uint32_t)0xFEF6FFFF; 


 

RCC->CR &= (uint32_t)0xFFFBFFFF; 


 

RCC->CFGR &= (uint32_t)0xFF80FFFF; 


#ifdef STM32F10X_CL 

 

RCC->CR &= (uint32_t)0xEBFFFFFF; 


 

RCC->CIR = 0x00FF0000; 


 

RCC->CFGR2 = 0x00000000; 

#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 

 

RCC->CIR = 0x009F0000; 


 

RCC->CFGR2 = 0x00000000; 

#else 

 

RCC->CIR = 0x009F0000; 

#endif  


#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) 

#ifdef DATA_IN_ExtSRAM 

SystemInit_ExtMemCtl(); 

#endif  

#endif 


 

 

SetSysClock(); 


#ifdef VECT_TAB_SRAM 

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;  

#else 

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;  

#endif 

}


从函数说明来看,此函数功能就是 初始化内部FALSH,PLL并且更新系统时钟 。此函数需在复位启动后调用。

RCC->CR |= (uint32_t)0x00000001;


第一行代码 操作时钟控制寄存器,将内部8M高速时钟使能 ,从这里可以看出 系统启动后是首先依靠内部时钟源而工作的 。

#ifndef STM32F10X_CL 

RCC->CFGR &= (uint32_t)0xF8FF0000; 

#else 

RCC->CFGR &= (uint32_t)0xF0FF0000;


这两行代码则是 操作时钟配置寄存器 。其主要设置了MCO(微控制器时钟输出)PLL相关(PLL倍频系数,PLL输入时钟源),ADCPRE(ADC时钟),PPRE2(高速APB分频系数),PPRE1(低速APB分频系数),HPRE(AHB预分频系数),SW(系统时钟切换), 开始时,系统时钟切换到HSI,由它作为系统初始时钟 。宏STM32F10X_CL是跟具体STM32芯片相关的一个宏。

 

RCC->CR &= (uint32_t)0xFEF6FFFF; 


 

RCC->CR &= (uint32_t)0xFFFBFFFF; 


 

RCC->CFGR &= (uint32_t)0xFF80FFFF;


这几句话则是 先在关闭HSE,CSS,,PLL等的情况下配置好与之相关参数然后开启,达到生效的目的 。

#ifdef STM32F10X_CL 

 

RCC->CR &= (uint32_t)0xEBFFFFFF; 


 

RCC->CIR = 0x00FF0000; 


 

RCC->CFGR2 = 0x00000000; 

#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 

 

RCC->CIR = 0x009F0000; 


 

RCC->CFGR2 = 0x00000000; 

#else 

 

RCC->CIR = 0x009F0000; 

#endif


这一段主要是 跟中断设置有关 。开始时,我们需要 禁止所有中断并且清除所有中断标志位 。不同硬件有不同之处。 

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) 

#ifdef DATA_IN_ExtSRAM 

SystemInit_ExtMemCtl(); 

#endif  

#endif


这段跟 设置外部RAM 有关吧,我用到的STM32F103RBT与此无关。

SetSysClock();


此又是一个函数,主要是 配置系统时钟频率 。HCLK,PCLK2,PCLK1的分频值,分别代表AHB,APB2,和APB1。当然还干了其它的事情, 配置FLASH延时周期和使能预取缓冲期 。后面的这个配置具体还不了解。

#ifdef VECT_TAB_SRAM 

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;  

#else 

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;  

#endif


这段代码主要是实现 向量表的重定位 。依据你想要将向量表定位在内部SRAM中还是内部FLASH中。这个SCB开始没在STM32参考手册中发现,原来它是跟Cortex-M3内核相关的东西。所以ST公司就没有把它包含进来吧。内核的东西后面再了解,这里给自己提个醒。 



然后再看看SystemInit()中的那个函数SetClock()又做了什么吧。

static void SetSysClock(void) 

#ifdef SYSCLK_FREQ_HSE 

SetSysClockToHSE(); 

#elif defined SYSCLK_FREQ_24MHz 

SetSysClockTo24(); 

#elif defined SYSCLK_FREQ_36MHz 

SetSysClockTo36(); 

#elif defined SYSCLK_FREQ_48MHz 

SetSysClockTo48(); 

#elif defined SYSCLK_FREQ_56MHz 

SetSysClockTo56(); 

#elif defined SYSCLK_FREQ_72MHz 

SetSysClockTo72(); 

#endif 


 

}


从中可以看出就是 根据不同的宏来设置不同的系统时钟,这些宏就在跟此函数在同一个源文件里 。官方很是考虑周到,我们只需要选择相应宏就能达到快速配置系统时钟的目的。

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 

 

#define SYSCLK_FREQ_24MHz 24000000 

#else 

 

#define SYSCLK_FREQ_72MHz 72000000 

#endif


比如这里我需 要配置系统时钟为72MHZ,则只需要将#define SYSCLK_FREQ_72MHz  72000000两边的注释符去掉。  

这个函数里面又有SetSysClockTo72()函数,这个函数就是具体操作寄存器进行配置了。

#elif defined SYSCLK_FREQ_72MHz 

 

static void SetSysClockTo72(void) 

__IO uint32_t StartUpCounter = 0, HSEStatus = 0; 


 

RCC->CR |= ((uint32_t)RCC_CR_HSEON); 


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) 

 

FLASH->ACR |= FLASH_ACR_PRFTBE; 


 

FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 

FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; 



 

RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 


 

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 


 

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; 


#ifdef STM32F10X_CL 

 

 

 


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); 


 

RCC->CR |= RCC_CR_PLL2ON; 

 

while((RCC->CR & RCC_CR_PLL2RDY) == 0) 



 

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 

 

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  


 

RCC->CR |= RCC_CR_PLLON; 


 

while((RCC->CR & RCC_CR_PLLRDY) == 0) 


 

RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 

RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 


 

while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 

else 

{  

#endif


上面的代码需要细细看。SystemInit()差不多就是这样了。


推荐阅读

史海拾趣

AC Photonics Inc公司的发展小趣事

AC Photonics Inc公司自成立以来,一直致力于光电技术的研发与应用。在公司成立初期,研发团队在光子集成技术上取得了重大突破,成功开发出一种高效、稳定的光电转换器。这一技术的问世,不仅提升了数据传输的速度和稳定性,还大大降低了能耗,为公司的业务发展奠定了坚实的基础。随着这一技术的逐步推广和应用,AC Photonics Inc在电子行业中逐渐崭露头角。

HTC Korea(TAEJIN Technology )公司的发展小趣事

HTC Korea自成立以来,一直致力于国际化布局,与全球各地的合作伙伴建立了良好的关系。目前,HTC的产品已在欧美、亚泰地区大量销售,与各地的电信运营商、芯片制造商等保持了紧密的合作关系。这种广泛的合作伙伴网络为HTC提供了强大的市场支持和技术保障,推动了其在全球范围内的快速发展。同时,HTC还通过了ISO9001及ISO14001质量体系认证,以系统、人性化的管理努力成为行业的佼佼者。

Etco Inc公司的发展小趣事

自1947年成立以来,Etco Inc公司一直致力于电子连接技术的研发与创新。在20世纪70年代,公司成功研发出一款新型的高性能连接器,该产品凭借其卓越的性能和可靠性,迅速在汽车电子行业中占据了一席之地。这一技术突破不仅为Etco带来了可观的市场份额,还奠定了其在电子连接器领域的技术领先地位。

Datasensor公司的发展小趣事

1978年,DATALOGIC公司成功研制出欧洲第一台条码扫描器,并将此产品应用于商业领域。这一创新不仅展示了公司在光电技术领域的实力,也为其在工业自动化领域赢得了良好的声誉。条码扫描器的成功推出,为公司带来了可观的收益,也为公司后续的技术研发和市场拓展提供了强有力的支持。

力芯微(ETEK)公司的发展小趣事

在初创期,力芯微公司专注于DVD、音响、机顶盒及遥控器等传统电子市场的芯片研发及销售。公司凭借对市场的敏锐洞察,与步步高、TCL、Sony、飞利浦、富士康等知名品牌建立了稳固的合作关系。这些合作不仅为公司带来了稳定的收入,也为力芯微积累了与品牌客户合作的宝贵经验。

GTK UK Ltd公司的发展小趣事
采用更先进的算法来处理光电传感器信号,提高信号处理的准确性和速度。

问答坊 | AI 解惑

VGA显示器Verilog实现驱动代码

本帖最后由 paulhyde 于 2014-9-15 03:18 编辑 VGA显示器Verilog实现驱动代码    …

查看全部问答>

电机分类和区别详解

电机定义:是指依据电磁感应定律实现电能的转换或传递的一种电磁装置。 电动机也称电机(俗称马达),在电路中用字母“M”(旧标准用“D”)表示。它的主要作用是产生驱动转矩,作为用电器或各种机械的动力源。 电动机的种类 1.按工作电源分 ...…

查看全部问答>

编程器与仿真器的区别

本人初学单片机,对于编程器的仿真器实在不能很好的理解 我想知道仿真器在仿真的时候是不是把程序下载到单片机了, 和编程器的烧录有什么区别吗? 仿真的时候单片机工作吗?还是电脑模拟而已? 仿真结束后单片机上保存程序吗?…

查看全部问答>

关于BuildGates综合的问题

请问各位高手,我的设计中通过PIN输入时钟clk,经分频输出clk_div,综合时用set_generated_clock对clk_div进行约束,设计还有一些输入输出端口属于clk_div的时钟域,如果我希望对这些端口设置set_input_delay和set_external_delay,该怎么加呢,我 ...…

查看全部问答>

WINCE 5.0 GUI系统显存布局

系统为WINCE 5.0 + S3C2451 液晶的配置参数为RGB565格式.从芯片手册上可知,显存有两种格式: (BSWP = 0, HWSWP = 0)         D[31:16] D[15:0] 000H        P1     ...…

查看全部问答>

simple设置会导致赋值出错么?

如题,在ADS1.2的工程设置中,我把linktype设置为simple,RO Base:0x30008000(我查过,这个地址应该不会有错)之后,当对结构体变量赋值时,总是出错,赋不进想要的值。但当我把linktype设置为scattered,并使用scat文件,就能正确赋值了,这是什 ...…

查看全部问答>

cs8900 问题,在控制面板 网络连接中出现了两个 cs89001 的图标

在控制面板 网络连接中出现了两个 cs89001 的图标。 不知道那位兄弟遇到过,帮忙看下。 …

查看全部问答>

c# DDE(动态数据交换) 客户端程序,如何设置Server与Topic

如题。 由于DDE是一个很老的技术了,已经被OPC代替。但是有些事情还是得用到DDE。 .net 已经不支持DDE,还好,我找到了封装好的API , 下面是我写的一个测试DDE客户端,要与DDE服务器,或者说是DDE服务(service) 连接。 对于输入的service 与t ...…

查看全部问答>

有了解“广东亿迅,普信科技有限公司”的朋友请进

想了解一下“广东亿迅,普信科技有限公司”     1、该公司的总体情况如何;     2、与“广东电信研究院”的关系     谢谢  …

查看全部问答>

EE_FPGA【预备知识 二】----Verilog 介绍

我不打算推荐具体的什么书籍,google一下,很多很多,有兴趣的可以看看   我想说的是,你只有真正的去使用才会领悟的更多,有些所谓的高级功能,你可能一辈子都不会用到,学来又有何用?   我想大概知道以下几点,应该就可以开始深入 ...…

查看全部问答>