LinkedInSTM32F4时钟系统初始化的程序代码分享

发布者:才富五车330最新更新时间:2023-10-09 来源: elecfans关键字:LinkedIn  STM32F4 手机看文章 扫描二维码
随时随地手机看文章

时钟系统   寄存器


LinkedInSTM32F4 时钟系统初始化是在system_stm32f4xx.c中的 SystemInit()函数中完成的。 对于系统时钟关键寄存器设置主要是在 SystemInit 函数中调用 SetSysClock()函数来设置的。我们可以先看看 SystemInit ()函数体:


LinkedInSTM32F4时钟系统初始化的程序代码分享



void SystemInit(void)

{

#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

SCB-》CPACR |= ((3UL 《《 10*2)|(3UL 《《 11*2));

#endif

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

RCC-》CFGR = 0x00000000;

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

RCC-》PLLCFGR = 0x24003010;

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

RCC-》CIR = 0x00000000;

#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM

SystemInit_ExtMemCtl();

#endif

SetSysClock();

#ifdef VECT_TAB_SRAM

SCB-》VTOR = SRAM_BASE | VECT_TAB_OFFSET;

#else

SCB-》VTOR = FLASH_BASE | VECT_TAB_OFFSET;

#endif

}

SystemInit函数开始先进行浮点运算单元设置,然后是复位PLLCFGR,CFGR寄存器,同时通过设置 CR 寄存器的 HSI 时钟使能位来打开 HSI 时钟。默认情况下如果 CFGR 寄存器复位,那么是选择HSI作为系统时钟,这点大家可以查看RCC-》CFGR 寄存器的位描述最低2位可以得知,当低两位配置为 00的时候(复位之后),会选择 HSI振荡器为系统时钟。也就是说,调用 SystemInit 函数之后,首先是选择 HSI 作为系统时钟。

在设置完相关寄存器后,接下来SystemInit函数内部会调用 SetSysClock函数。这个函数比较长,我们就把函数一些关键代码行截取出来给大家讲解一下。这里我们省略一些宏定义标识符值的判断而直接把针对STM32F407 比较重要的内容贴出来:

static void SetSysClock(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)

{

RCC-》APB1ENR |= RCC_APB1ENR_PWREN;

PWR-》CR |= PWR_CR_VOS;

RCC-》CFGR |= RCC_CFGR_HPRE_DIV1;

RCC-》CFGR |= RCC_CFGR_PPRE2_DIV2;

RCC-》CFGR |= RCC_CFGR_PPRE1_DIV4;

RCC-》CFGR |= RCC_CFGR_PPRE2_DIV1;

RCC-》CFGR |= RCC_CFGR_PPRE1_DIV2;

RCC-》PLLCFGR = PLL_M | (PLL_N 《《 6) | (((PLL_P 》》 1) -1) 《《 16) |

(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q 《《 24);

RCC-》CR |= RCC_CR_PLLON;

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

{

}

FLASH-》ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN

|FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

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

RCC-》CFGR |= RCC_CFGR_SW_PLL;

while ((RCC-》CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);

{

}

}

else

{

}

}

这段代码的大致流程是这样的:先使能外部时钟 HSE,等待 HSE 稳定之后,配置AHB,APB1,APB2 时钟相关的分频因子,也就是相关外设的时钟。等待这些都配置完成之后,打开主PLL时钟,然后设置主PLL作为系统时钟 SYSCLK时钟源。如果HSE 不能达到就绪状态(比如外部晶振不能稳定或者没有外部晶振),那么依然会是HSI作为系统时钟。

在这里要特别提出来,在设置主PLL时钟的时候,会要设置一系列的分频系数和倍频系数参数。大家可以从SetSysClock函数的这行代码看出:

RCC-》PLLCFGR = PLL_M | (PLL_N 《《 6) | (((PLL_P 》》 1) -1) 《《 16) |

(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q 《《 24);

这些参数是通过宏定义标识符的值来设置的。默认的配置在 System_stm32f4xx.c 文件开头的地方配置。对于我们开发板,我们的设置参数值如下:

#define PLL_M 8

#define PLL_Q 7

#define PLL_N 336

#define PLL_P 2

所以我们的主PLL时钟为:

PLL=8MHz * N/ (M*P)=8MHz* 336 /(8*2) = 168MHz

在开发过程中,我们可以通过调整这些值来设置我们的系统时钟。

这里还有个特别需要注意的地方,就是我们还要同步修改 stm32f4xx.h 中宏定义标识符HSE_VALUE 的值为我们的外部时钟:

#if !defined (HSE_VALUE)

#define HSE_VALUE ((uint32_t)8000000)

#endif

这里默认固件库配置的是25000000,我们外部时钟为8MHz,所以我们根据我们硬件情况修改为8000000即可。

讲到这里,大家对 SystemInit 函数的流程会有个比较清晰的理解。那么 SystemInit 函数是怎么被系统调用的呢?SystemInit是整个设置系统时钟的入口函数。这个函数对于我们使用ST提供的 STM32F4 固件库的话,会在系统启动之后先执行main函数,然后再接着执行SystemInit函数实现系统相关时钟的设置。这个过程设置是在启动文件 startup_stm32f40_41xxx.s中间设置的,我们接下来看看启动文件中这段启动代码:

; Reset handler

Reset_Handler PROC

EXPORT Reset_Handler [WEAK]

IMPORT SystemInit

IMPORT __main

LDR R0, =SystemInit

BLX R0

LDR R0, =__main

BX R0

ENDP

这段代码的作用是在系统复位之后引导进入main函数,同时在进入main函数之前,首先

要调用 SystemInit系统初始化函数完成系统时钟等相关配置。

最后我们总结一下SystemInit()函数中设置的系统时钟大小:

SYSCLK(系统时钟) =168MHz

AHB总线时钟(HCLK=SYSCLK) =168MHz

APB1总线时钟(PCLK1=SYSCLK/4) =42MHz

APB2总线时钟(PCLK2=SYSCLK/2) =84MHz

PLL主时钟 =168MHz


关键字:LinkedIn  STM32F4 引用地址:LinkedInSTM32F4时钟系统初始化的程序代码分享

上一篇:STM32CUBEMX开发GD32F303(7)----配置printf
下一篇:STM32F103C8T6读写内部flash

推荐阅读最新更新时间:2024-11-06 12:11

STM32F4 UART1 DMA发送和接收不定长度数据
STM32F4 串口收发使用DMA还是很方便的。但是配置DMA时需要配置数据长度,这一点对于发送来说可以预估计自己发送的长度来配置DMA发送数据长度,但是对于接收不是很好解决,因为如果使用DMA接收中断是要配置的数据长度减到0才能出发中断。但是我们无法判断接受数据的长度,导致无法判断数据接收完成。网上有提出的解决方法是用定时器固定周期的读DMA接收的长度来判断是否接收完成,也有使用UART的空闲中断来处理的。在这里我使用UART的空闲中断来处理接收不定长数据。当然也要打开DMA接收完成中断,处理数据接收超过DMA配置的长度导致的DMA接收中断。 1.使用DMA发送时每次发送数据前需要配置发送的数据长度,此时要注意应先关闭DMA,然
[单片机]
STM32F4_TIM输入波形捕获(脉冲频率、占空比)
Ⅰ、概述 本文基于上一篇文章“TIM输入波形捕获(脉冲频率)”的基础上进行拓展,上一篇文章主要是捕获波形的频率,本文主要拓展捕获波形的占空比。 笔者实验测试的方法和上一篇文章一样,通过信号发生器产生PWM信号,通过串口发送频率和占空比到上位机(上位机串口助手显示其数值)。(没有信号发生器的朋友可以结合上一篇文章PWM输出做信号源;在同一块板子上也可以使用不同定时器,将PWM输出引脚接在捕获输入引脚) 实验现象:不同频率的实验现象请看上一篇文章(该文章提供的工程笔者也是进行了大量不同频率的测试,误差在几Hz属正常范围)。 1000Hz、20% - 80%占空比现象: 1000Hz、51% - 58%占空比现象:
[单片机]
<font color='red'>STM32F4</font>_TIM输入波形捕获(脉冲频率、占空比)
stm32f407 double类型
STM32F407是意法半导体(STMicroelectronics)推出的一款ARM Cortex-M4内核的微控制器。它是针对智能电动车领域的实时操作、数字信号处理和高性能应用而设计的。在这篇文章中,我们讨论一下STM32F407的双精度浮点数(Double)类型。 首先,让我们先了解什么是双精度浮点数。双精度浮点数是一种浮点数表示形式,它使用双精度浮点数格式来表示实数。在STM32F407中,双精度浮点数类型被定义为64位。这意味着它可以表示更大范围的数值,并且具有更高的精确度,相比单精度浮点数。这非常适合处理需要更大精度的应用,如信号处理、3D图形渲染和科学计算等。 STM32F407芯片支持双精度浮点数运算的硬件
[单片机]
STM32f4---串口通信实验代码(02)
介绍完了这两个函数,我们回到main.c,对于main.c前面引入的头文件为了篇幅考虑,我们后面的实验不再列出,详情请参考我们实验代码即可。主函数代码如下: int main(void) { u8 t,len; u16 times=0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 delay_init(168); //延时初始化 uart_init(115200); //串口初始化波特率为115200 LED_Init(); //初始化与 LED连接的硬件接口 LED0=0; //先点亮红灯 wh
[单片机]
STM32F4 内部flash驱动(寄存器操作)
stm32f4_flash.c /************************************************************************************************************* * 文件名: stm32f4_flash.c * 功能: STM32F4 内部FLASH编程驱动函数 * 作者: cp1300@139.com * 创建时间: 2013-10-20 * 最后修改时间: 2018-01-13 * 详细: 用于STM32F4内部flash读写驱动 2018-01-13:初始版本,默认位宽为32位,写入的数据必须32位对齐,供
[单片机]
STM32F429HAL库UART学习笔记
UART串口通讯作为最基本通讯协议我就不多赘述。我主要用HAL库实现串口通讯,看一下配置Uart的结构一变量 这里使用了结构体嵌套 typedef struct { USART_TypeDef *Instance; 串口类型和串口内部控制寄存器结构体 UART_InitTypeDef Init; 定义串口输出数据类型停止位奇偶校验位的结构体 uint8_t *pTxBuffPtr; 要发送的数据的缓冲数组指针 uint16_t TxXferSize; 要发送数组大小 uint16_t TxX
[单片机]
STM32F429 >> 10. DMA_直接存储器访问
本工程板级支持包文件适用于野火stm32f429 开发板。 DMA 传输实现高速数据移动过程无需任何CPU 操作控制 其支持以下三种传输方式: 外设到存储器传输; 存储器到外设传输; 存储器到存储器传输。 功能框图: ① 外设通道选择 外设通道选择所解决的问题是决定哪一个外设作为数据传输的源地址或目标地址。 DMA1 请求映射: DMA2 请求映射: 每个外设请求都占用一个数据流通道,相同外设请求可以占用不同数据流通道。 ② 仲裁器 仲裁器管理数据流方法分为两个阶段。 第一阶段属于软件阶段,我们在配置数据流时可以通过寄存器设定其优先级别,具体配置DMA_SxCR 寄存器PL 位,可以设置为
[单片机]
<font color='red'>STM32F4</font>29 >> 10. DMA_直接存储器访问
STM32F412擦除内部FLASH时间过长
1 前言 客户反馈在使用STM32F412的时候,擦除sector 8~11发现时间过长,从而导致意外触发IWDG复位。 2 问题分析 2.1 问题详情 通过与客户邮件和电话沟通,了解到客户主要是想使用内部FLASH暂时保存IAP升级时的程序数据,在IAP升级的过程中,需要首先擦除内部FLASH中一块足够大的空间,然后再写入升级数据。客户的工程中有使用到IWDG,喂狗间隔大约1.5S,客户的通过SysTick的方式计算出擦除Sector8大约需要2ms,因此认为若一次擦除sector8~11大约需要8ms,于是在代码中一次性擦除sector8~11后最后再来喂狗,但是,这样会触发IWDG复位,这个与预期不一致,固此产生疑问。
[单片机]
<font color='red'>STM32F4</font>12擦除内部FLASH时间过长
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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