欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > STM32文件详解

STM32文件详解

2025/2/24 19:33:48 来源:https://blog.csdn.net/weixin_48255917/article/details/144617865  浏览:    关键词:STM32文件详解

STM32文件详解

  • 启动文件
    • 打开MDK
    • 栈空间开辟
    • 堆空间开辟
    • 中断向量表
    • 复位程序
    • 对于 weak 的理解
    • 对于_main 函数的分析
    • 中断程序
    • 堆栈初始化
    • 系统启动流程
  • 时钟树
    • 时钟源
    • 时钟配置函数
    • 时钟初始化配置函数

启动文件

启动文件的方式

1、初始化堆栈指针 SP = _initial_sp
2、初始化程序计数器指针 PC = Reset_Handler
3、设置堆和栈的大小
4、初始化中断向量表
5、配置外部 SRAM 作为数据存储器(可选)
6、配置系统时钟,通过调用 SystemInit 函数(可选)
7、调用 C 库中的 _main 函数初始化用户堆栈,最终调用 main 函数

在这里插入图片描述

打开MDK

MDK->Help->uVision Help,
在这里插入图片描述

栈空间开辟

在这里插入图片描述

堆空间开辟

在这里插入图片描述
PRESERVE8:指示编译器按照 8 字节对齐。
THUMB:指示编译器之后的指令为 THUMB 指令

中断向量表

在这里插入图片描述
在这里插入图片描述

__Vectors 为向量表起始地址, __Vectors_End 为向量表结束地址,__Vectors_Size 为向量表大小,>__Vectors_Size = __Vectors_End - __Vectors。

复位程序

接下来是定义只读代码段

在这里插入图片描述

复位子程序代码
在这里插入图片描述
利用 PROC、ENDP 这一对伪指令把程序段分为若干个过程,使程序的结构加清晰。

对于 weak 的理解

weak 顾名思义是“弱”的意思,在汇编中,在函数名称后面加[WEAK]来表示,而在 C 语言中,在函数名称前面加上__weak 修饰符来表示,这样的函数我们称为“弱函数”。
被[WEAK]或__weak 声明的函数,我们可以在自己的文件中重新定义一个同名函数, 最终编译器编译的时候,会选择我们定义的函数,如果我们没有重新定义这个函数,那么编译器就会执行[WEAK]或__weak 声明的函数,并且编译器不会报错

对于_main 函数的分析

_main 代码是编译器自动创建的,因此无法找到_main 代码。
程序经过汇编启动代码,执行到__main()后,负责初始化堆栈,完成库函数的初始化,最后自动跳转向 main()函数。

中断程序

在这里插入图片描述

堆栈初始化

ALIGN指指令或数据的存放地址进行对齐,一般需要跟一个立即数
勾选了 Use MicroLIB 就代表定义了__MICROLIB 这个宏。
接下来进行堆栈空间初始化,堆是从低到高生长,栈是从高到低生长,是两个互相独立 的数据段,并且不能交叉使用。
Use MicroLIB
MicroLIB 是 MDK 自带的微库,是缺省 C 库的备选库,MicroLIB 进行了高度优化使得其代码变得很小,功能比缺省 C 库少。MicroLIB 是没有源码的,只有库。

系统启动流程

在这里插入图片描述

时钟树

在这里插入图片描述
一个简化的 STM32F1 时钟系统。图中已经把我们主要关注几处标注出来。
A 部分表示其它电路需要的输入源时钟信号;
B 为一个特殊的振荡电路“PLL”,由几个部分构成;
C 为我们重点需要关注的 MCU 内的主时钟“SYSCLK”;AHB 预分频器将 SYSCLK 分频或不分 频后分发给其它外设进行处理,包括到 F 部分的 Cortex-M 内核系统的时钟。
D、E 部分别为定时器等外设的时钟源 APB1/APB2。
G 是 STM32 的时钟输出功能,其它部分等我们学习到再详细探讨。

时钟源

对于 STM32F1,输入时钟源(Input Clock)主要包括 HSI,HSE,LSI,LSE。其中,从时钟频率来分可以分为高速时钟源和低速时钟源,其中 HSI、HSE 高速时钟,LSI 和 LSE 是低速时钟。
从来源可分为外部时钟源和内部时钟源,外部时钟源就是从 外部通过接晶振的方式获取时钟源,其中 HSE 和 LSE 是外部时钟源;其他是内部时钟源,芯片上电即可产生,不需要借助外部电路。

时钟配置函数

SYSCLK(系统时钟) =72MHz
AHB 总线时钟(HCLK=SYSCLK) =72MHz
APB1 总线时钟(PCLK1=SYSCLK/2) =36MHz
APB2 总线时钟(PCLK2=SYSCLK/1) =72MHz
PLL 主时钟 =72MHz

时钟初始化配置函数

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 
}

SystemInit 函数开始通过条件编译,先复位 RCC 寄存器,同时通过设置 CR 寄存器的 HSI 时钟使能位来打开 HSI 时钟。

  1. 时钟控制寄存器(RCC_CR)
  2. 时钟配置寄存器(RCC_CFGR)
  3. 时钟中断寄存器(RCC_CIR)
  4. APB2 外设复位寄存器(RCC_APB2RSTR)和APB1 外设复位寄存器

默认情况下如果 CR 寄存器复位, 是选择 HSI 作为系统时钟,这点大家可以查看 RCC->CR 寄存器相关位描述可以得知,当低两位配置为 00 的时候(复位之后),会选择 HSI 振荡器为系统时钟。

在 system_stm32f10x.c 文件的开头就有对此宏定义,系统默认的宏定义是72MHz

#define SYSCLK_FREQ_72MHz 72000000

如果你要设置为 36MHz,只需要注释掉上面代码

#define SYSCLK_FREQ_36MHz 36000000 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词