SystemInit()函数详解

发布者:MysticEssence最新更新时间:2019-02-13 来源: eefocus关键字:SystemInit()函数  STM32F103 手机看文章 扫描二维码
随时随地手机看文章

1 基于STM32F103的SystemInit()函数详解


1 使用的固件库是,STM32F10x_StdPeriph_Lib_V3.5.0


2 学习板CPU的具体型号为STM32F103VET6


3 软件开发环境为RVMDK3.90


4 未定义STM32F10X_CL,在system_stm32f10x.c(第0115行)中定义了SYSCLK_FREQ_72MHz,具体如下:

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

/* #define SYSCLK_FREQ_HSE    HSE_VALUE */

#define SYSCLK_FREQ_24MHz  24000000

#else

/* #define SYSCLK_FREQ_HSE    HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz  24000000 */

/* #define SYSCLK_FREQ_36MHz  36000000 */

/* #define SYSCLK_FREQ_48MHz  48000000 */

/* #define SYSCLK_FREQ_56MHz  56000000 */

#define SYSCLK_FREQ_72MHz  72000000

#endif


5 具体的函数调用顺序如下:

①startup_stm32f10x_hd.s(启动文件)→②SystemInit()→③SetSysClock ()→④SetSysClockTo72()


说明:由于在上面只定义了SYSCLK_FREQ_72MHz,因而在执行SetSysClock ()函数的时候,会选择进入SetSysClockTo72()函数,以设置系统时钟为72MHz


6 说明:以上设置,采用Debud -> Use Simulator模拟调试,能够很清晰地看到程序的具体执行步骤:

RST后如下


 


首先进入SystemInit()函数


 

 


以上由于未定义STM32F10X_CL,STM32F10X_LD_VL等,所以直接跳至0251行执行



接着便会执行SetSysClock函数


 


由于定义的是#define SYSCLK_FREQ_72MHz  72000000,所以会选择SetSysClockTo72()函数执行


【若定义的是#define SYSCLK_FREQ_56MHz  56000000,便会选择SetSysClockTo56()函数执行】


 

 

 


以上由于未定义STM32F10X_CL,所以直接跳至1057行执行


 


跳出SetSysClockTo72()函数

跳出SetSysClock()函数

跳出SystemInit()函数

说明:执行完代码的1057行至1062行时,便已完成将系统时钟设置为72MHz。


至此,基本配置已经完成,配置的时钟如下:

SYSCLK(系统时钟) = 72MHZ(系统最高允许时钟)

AHB总线时钟   = 72MHZ(AHB最高允许时钟)

APB1总线时钟 = 36MHZ(APB1最高允许时钟)

APB2总线时钟 = 72MHZ(APB2最高允许时钟)


2 基于STM32F107的SystemInit()函数详解


STM32的库函数好像只有外部8M倍频到72M,现在用的板子外部25M的晶振,如何倍频到72M呢?

解决办法: STM32F107的时钟分4步的:

     1> 25MHz先除5分频到5MHz;

     2> 再8倍频到40MHz;

     3> 再5分频到8MHz;

     4> 再9倍频到72MHz.

    STM32F103和STM32F105/STM32F107的RCC设置是不一样的,仔细查ST的参考手册,很容易得到答案的,新版的库中,有STM32F105/STM32F107的时钟设置代码,通过全局宏来选定的。看一下《STM32F10x.h》中的开头部分的宏判断。


ErrorStatus HSEStartUpStatus;

RCC_DeInit();

RCC_HSEConfig(RCC_HSE_ON);

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus==SUCCESS)

{

    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    RCC_PCLK2Config(RCC_HCLK_Div1);

    RCC_PCLK1Config(RCC_HCLK_Div2);

    RCC_ADCCLKConfig(RCC_PCLK2_Div4);

 

#ifndef STM32F10X_CL 

    RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);

#else


    RCC_PREDIV2Config(RCC_PREDIV2_Div5);

    RCC_PLL2Config(RCC_PLL2Mul_8);

    RCC_PLL2Cmd(ENABLE);

    while(RCC_GetFlagStatus(RCC_FLAG_PLL2RDY)== RESET)

    {}

    RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2,RCC_PREDIV1_Div5);

    RCC_PLLConfig(RCC_PLLSource_PREDIV1,RCC_PLLMul_9);


    RCC_PLL3Config(RCC_PLL3Mul_11);

    RCC_PLL3Cmd(ENABLE);   

    while(RCC_GetFlagStatus(RCC_FLAG_PLL3RDY)== RESET)

    {}


    RCC_I2S3CLKConfig(RCC_I2S3CLKSource_PLL3_VCO);

    RCC_I2S2CLKConfig(RCC_I2S2CLKSource_PLL3_VCO); 

#endif

    RCC_PLLCmd(ENABLE);

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)

    {

    }

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    while(RCC_GetSYSCLKSource()!=0x08)

    {

    }

}


函数库的不断升级,到3.0以上时,我们就不用再这样编写时钟设置了,我们只要做如下两部即可:


第一个: system_stm32f10x.c 中 #define SYSCLK_FREQ_72MHz 72000000 

第二个:调用SystemInit()


说明:在stm32固件库3.0中对时钟频率的选择进行了大大的简化,原先的一大堆操作都在后台进行。系统给出的函数为SystemInit()。但在调用前还需要进行一些宏定义的设置,具体的设置在system_stm32f10x.c文件中。


文件开头就有一个这样的定义: 

//#define SYSCLK_FREQ_HSE    HSE_Value 

//#define SYSCLK_FREQ_20MHz 20000000 

//#define SYSCLK_FREQ_36MHz 36000000 

//#define SYSCLK_FREQ_48MHz 48000000 

//#define SYSCLK_FREQ_56MHz 56000000 

  #define SYSCLK_FREQ_72MHz 72000000


    ST 官方推荐的外接晶振是 8M,所以库函数的设置都是假定你的硬件已经接了 8M 晶振来运算的.以上东西就是默认晶振 8M 的时候,推荐的 CPU 频率选择.在这里选择了:

     #define SYSCLK_FREQ_72MHz 72000000 

也就是103系列能跑到的最大值72M


然后这个 C文件继续往下看 

#elif defined SYSCLK_FREQ_72MHz 

const uint32_t SystemFrequency         = SYSCLK_FREQ_72MHz;    

const uint32_t SystemFrequency_SysClk   = SYSCLK_FREQ_72MHz;    

const uint32_t SystemFrequency_AHBClk   = SYSCLK_FREQ_72MHz;    

const uint32_t SystemFrequency_APB1Clk  = (SYSCLK_FREQ_72MHz/2);

const uint32_t SystemFrequency_APB2Clk  = SYSCLK_FREQ_72MHz;


    这就是在定义了CPU跑72M的时候,各个系统的速度了.他们分别是:硬件频率,系统时钟,AHB总线频率,APB1总线频率,APB2总线频率.再往下看,看到这个了: 

#elif defined SYSCLK_FREQ_72MHz 

static void SetSysClockTo72(void);


这就是定义 72M 的时候,设置时钟的函数.这个函数被 SetSysClock ()函数调用,而SetSysClock ()函数则是被 SystemInit()函数调用.最后 SystemInit()函数,就是被你调用的了。


所以设置系统时钟的流程就是: 首先用户程序调用 SystemInit()函数,这是一个库函数,然后 SystemInit()函数里面,进行了一些寄存器必要的初始化后,就调用 SetSysClock()函数. SetSysClock()函数根据那个#define SYSCLK_FREQ_72MHz 72000000 的宏定义,知道了要调用SetSysClockTo72()这个函数,于是,就一堆麻烦而复杂的设置


关键字:SystemInit()函数  STM32F103 引用地址:SystemInit()函数详解

上一篇:STM32F0非对齐访问引起的硬件错误及其排除
下一篇:STM32F103与STM32F407的SPI调试笔记

推荐阅读最新更新时间:2024-03-16 16:23

STM32F103利用模拟I2C驱动ADS1115
ADS1115通过模拟I2C驱动:(部分代码借鉴了网络上的几个,并且根据引脚进行了配置,都没有运行成功,今天调了一天,终于在晚上调了出来) 注意:本部分代码需要只是ADS1115的部分程序(一些用到的数组在此没有写),模拟II2C的各程序并未给出,大家根据需要进行裁剪,代码完全开源,希望能帮到大家,也希望大家乐于分享。 调试时需特别注意I2C的通信问题,特别是应答信号的使用需要特别关注,本人的程序之前出错全是因为从机的应答信号的未使用造成。 如有其它问题,欢迎指正批评,第一次写博客,感谢! 收获:对于I2C通信协议的理解更加深刻,对ADS1115也能进行单通道的使用。I2C的开始、发送/读写、应答、结束等一定要
[单片机]
一种keil5锁死STM32F103C8T6的解决方法
先前画的一款电机驱动板,今天总算有时间调试了,,,效果如上,实验室里面的洗板水用没了。。。。没有办法收拾的干净了,LED 没了。。。 接线端子开关也没了。。。条件很艰苦 进入正题,上图主控是STM32F103C8T6就是网上卖的最便宜的那种。出现的问题时keil下载不进去程序。提示是这样玩的 我先用j-link自带的工具j-flash进行了测试确定了芯片是可以通讯并且可以进行hex文件的烧录的。这样定位问题应该是keil 的配置出了问题。 keil也不是一直出问题。某一次 也是可以下载的。经过多次尝试,我发现当我用j-flash擦除芯片 并且解锁unsecure芯片之后keil可以正常的下载程序。 然后就开始
[单片机]
一种keil5锁死<font color='red'>STM32F103</font>C8T6的解决方法
STM32F103基于DMA接收不定帧长USART数据
DMA是一种不使用CPU而将数据从一片地址空间复制到另一片地址空间的总线,这样就减少了CPU的负担,使其能够更加专注于数据运算。为了能够减少CPU的负担,DMA应该采取中断方式而非查询模式。但是非常不幸的是,STM32F103只为DMA提供了三种中断:半步中断、完成中断和错误中断。如果UART接收的是定帧长的数据,则可以开启DMA半步中断,并且目标地址长度为帧长两倍。这样每接收完一帧进一次中断,进行某些操作,是很理想的。然而当遇到如同GPS一样不定帧长的数据时,如果仍用半步中断则难以确定目标地址的长度。所以在此放弃使用DMA的中断,转而使用的是另一种比较特别的中断:UART空闲中断。 先来介绍一下UART空闲中断。UART常用的接
[单片机]
ACM32F303对比STM32F103差异说明
一、整体功能对比 分别选择两款芯片(LQFP64封装)最大配置资源的型号(STM32F103RG、ACM32F303RC)进行比对,两者比对如下: 二、管脚差异说明 举例如下: 举例如下:LQFP64
[单片机]
ACM32F303对比<font color='red'>STM32F103</font>差异说明
STM32F103中的systick滴答时钟出错
STM32F103中的systick滴答时钟出现.ObjTemplate.axf: Error: L6218E: Undefined symbol SysTick_CLKSourceConfig (referred from systick.o).这种错误 解决方法: 意思就是SysTick_CLKSourceConfig()这个库函数未定义,这是因为没有添加misc.c这个库文件在你的外设驱动文件中、而SysTick_CLKSourceConfig()这个函数存在于后面提到的这个库文件里、解决过程如下 找到你的库文件的文件夹(个人不同、自己看自己的),双击进入Libraries文件夹— STM32F10x_StdPeriph
[单片机]
<font color='red'>STM32F103</font>中的systick滴答时钟出错
基于stm32f103zet6的DMA学习
stm32内部集成的ADC介绍 一、参考电压的范围为 /*2.4V≦ V ≦3.6V 所以它的输入模拟电压范围0 = V =V*/ 二、需要测量负电压或测量的电压信号超出范围时,要先经过运算电路进行平移或利用电阻分压。 三、我采用的是51单片机上面的10k的电阻来模拟输入 四、规则通道和注入通道 /*所谓规则,那么就是按常理出牌的,我们可以称之为正常的通道,那么与之对应的是注入通道,就是 在规则通道正在转换的时候是可以被注入通道打断,转而去执行注入通道转换的,当注入通道转换完 成之后,才继续去进行规则通道里面的转换,TM32ADC的规则通道组最多包含16 个转换,而注入通道 组最多包含 4 个通道*/ 五、初始化ADC这是必须的,
[单片机]
stm32f103rct6引脚图及使用手册
stm32f103rct6引脚图详细: stm32f103rct6芯片简介:   STM32F103RCT6   类别:集成电路(IC)   家庭:嵌入式-微控制器   系列:STM32   芯体尺寸:32-位   速度:72MHz   连通性:CAN,I2C,IrDA,LIN,SPI,UART/USART,USB   外围设备:DMA,电机控制PWM,PDR,POR,PVD,PWM,温度传感器,WDT   输入/输出数:51   程序存储器容量:256KB (256K x 8)   RAM容量:48K x 8   电压-电源(Vcc/Vdd):2 V ~ 3.6 V   振荡器型:内部   工作温度:-40°C ~ 85
[单片机]
<font color='red'>stm32f103</font>rct6引脚图及使用手册
STM32F103RE使用SPI3作为从模式
网上所见STM32的SPI例程多数是作为主模式,官方提供的例程中有从模式的例程。 但是我参照官方的例程来设置SPI3为从模式,发现MISO管脚都没有数据输出,而主机的时序没有问题。 问题是出在管脚的配置上,SPI3默认使用的管脚是: SPI3.NSS == PA15 SPI3.SCK == PB3 SPI3.MISO == PB4 SPI3.MOSI == PB5 而PB3、PB4和PA15三个管脚都被JTAG口占用,并且复位后默认是开启JTAG口,所以导致SPI3无法使用。 通过GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);关闭JTAG功能后正常使用。 在开发ST
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved