发新帖本帖赏金 3.00元(功能说明)我要提问
返回列表
[STM32F4]

【F446RE开发板试用】+库文件组织和180Mhz时钟配置代码分析

[复制链接]
1630|4
手机看帖
扫描二维码
随时随地手机跟帖
deru_qq|  楼主 | 2015-9-29 22:48 | 显示全部楼层 |阅读模式

第一次使用STM32F4系列,还是费了一番周折,下面把过程写下来,希望可以对大家有所帮助
1. Pack安装
    在Keil官网下载了STM32F4系列的2.6.0版PACK,安装之后打开Keil提示错误,新建工程时也找不到相应的器件,上网查找一通,最后解决问题:Keil版本我的Keil5版本是5.12,下载了5.14版就可以了
2. 新建一个LED工程模板
由于习惯了之前STM32F1xx系列的工程管理方法,于是依样画葫芦,工程源文件目录如下
+ cmsis
    core_cm4.h                                 **
    core_cmFunc.h                           **
    core_cmInstr.h                            **
    core_cmSimd.h                           **
    startup_stm32f446xx.s                **  芯片启动后执行的代码
    stm32f446xx.h                             **  stm32f446xx器件头文件,包含外设地址和结构体定义
    stm32f4xx.h                                 **  stm32f4xx系列头文件,根据Keil中Option->C/C++->Preprocessor Symbols ->Define 框中定义的器件来包含不同器件的头文件,如上面的446XX
    system_stm32f4xx.c                    **  包含系统初始化代码,初始化了FPU,中断向量表位置和外部存储
    system_stm32f4xx.h                    **
+ fwlib
    + Legacy
        stm32_hal_legacy.h                 **  这个头文件主要用于STM32Cube,这里没什么用
    stm32f4xx_hal.c                          **  提供了一些通用的函数,如延时函数,DBG相关函数等
    stm32f4xx_hal.h                          **  
    stm32f4xx_hal_cortex.c               **  提供了Cortex内核外设的相关函数,如NVIC,MPU,Systick Timer等
    stm32f4xx_hal_cortex.h               **
    stm32f4xx_hal_外设.c                       提供各外设的驱动库函数
    stm32f4xx_hal_外设.h
+ bsp
    自定义外设.c
    自定义外设.h
+ user
main.c                                               **
stm32f4xx_it.c                                  **  包含中断ISR函数,本工程只用了Systick_Handler
stm32f4xx_it.h                                  **
    stm32f4xx_hal_conf.h                   **  工程配置头文件
以上文件中,后面有“**”的表示这个文件是模板工程必须的,后面有简单的说明,下面首先描述一下头文件的组织结构:main文件中只需要包含stm32f4xx_hal.h头文件(当然还可以包含自定义外设.h),这个头文件逐层包含了所有需要的头文件
+ stm32f4xx_hal.h                                     //包含stm32f4xx_hal_conf.h  
|---+ stm32f4xx_hal_conf.h                       //根据工程配置,包含相应的STM32外设头文件
    |---+ stm32f4xx_hal_外设.h                  //每个外设头文件都包含stm32f4xx_hal_def.h
        |---+ stm32f4xx_hal_def.h                //包含stm32f4xx.h
            |---+ stm32f4xx.h                          //包含特定器件头文件
                |---+ stm32f446xx.h
                    |---- system_stm32f4xx.h
                    |---+ core_cm4.h
                        |---- core_cmInstr.h
                        |---- core_cmFunc.h
                        |---- core_cmSimd.h
LED工程配置
本工程的目标要实现以下功能:
(1)系统初始化之后使用HSI作为时钟源,并且工作在180Mhz
(2)用GPIO控制LED等以100ms的周期闪烁
为此,需要在stm32f4xx_hal_conf.h中使能以下模块:
    #define HAL_MODULE_ENABLED  
    #define HAL_FLASH_MODULE_ENABLED   
    #define HAL_GPIO_MODULE_ENABLED
    #define HAL_PWR_MODULE_ENABLED
    #define HAL_RCC_MODULE_ENABLED
    #define HAL_CORTEX_MODULE_ENABLED
其中使能Flash模块是要使用库函数设置Flash的等待周期等; 使能PWR模块是需要对电源进行设置使芯片能工作在180Mhz
另外别忘了在Keil中Option->C/C++->Preprocessor Symbols->Define 框中输入USE_HAL_DRIVER, STM32F446xx
3. 代码分析
启动代码
启动代码和stm32f1xx系列没有什么区别
上电复位后,进入ResetHandler,然后执行System_Init()函数
1.jpg
图1
2.jpg
图2
System_Init()函数执行以下操作:
(1)如果处理器支持FPU,使能FPU
(2)强处理器的时钟设为上电默认选择:内部16Mhz时钟,不开PLL
(3)如果使用外部RAM,初始化外部RAM控制
(4)设置中断向量是在SRAM或Flash中
从System_Init()函数退出后,进入用户main函数(中间还有一些C库的处理)
main函数中首先调用了HAL_Init()函数
3.jpg
图3
HAL_Init()函数执行以下操作:
(1)根据配置开启或关闭指令和数据Cache,Flash的Prefetch,这些配置字是在stm32f4xx_hal_conf.h文件中定义的
(2)设置NVIC的PriorityGroup为4bit表示抢占优先级,0bit表示子优先级
(3)设置Systick定时器中断周期为1ms,这个中断周期用来作为HAL_Delay()延时函数的时基,HAL_Delay()函数     将在接下来的一些初始化操作中使用
(4)调用HAL_MspInit()函数来初始化底层的硬件,注意这个函数用__weak关键字声明,内部为空,用户可以定义自己的HAL_MspInit()函数,函数名相同,这样自定义的函数将覆盖这里的HAL_MspInit()函数,在本工程中没有写这个函数,直接在Main函数中初始化了GPIO
main函数接下来调用了SystemClock_Config()函数,这个函数不是库函数,是Nucleo的Example中提供的SystemClock_Config()函数执行以下操作
4.jpg
图4
5.jpg
图5
(1)设置内核电压等级,当处理器运行频率不高时,可以通过软件设置不同的内核电压等级来减小功耗,注意设置只能在PLL关闭的情况下才能进行,在PLL打开时,新设置的内核电压等级生效,Scale等级越低,系统频率可以运行的越高,这里设为Scale1,因为下面要把系统时钟设为最大180Mhz
(2)接着选择HSI作为芯片时钟,并将PLL输出设为180Mhz,但这时系统时钟还未切换,系统还是工作在16Mhz的内部时钟
(3)使能电源管理的OverDrive,如果要运行在最高的频率,这一步是不可少的,注意这一位只能在选择HSI或HSE作为时钟时才能进行设置
(4)选择PLL输出作为系统时钟,AHB时钟设为180Mhz,APB2时钟设为90Mhz,APB1时钟设置为45Mhz,这些都是各总线的最高工作频率,这一步结束之后,系统就工作在了最高时钟频率180MHz,注意执行这一操作的最后会用新的系统时钟设置Systick定时器,使定时器的中断周期依旧为1ms
接下来就是纯粹的用户代码了,初始化GPIO来控制LED等
6.jpg
图6
(1)使能GPIOA的时钟(这里可以看出类,STM32F4xx的库和STM32F10x库不同的一点,模块时钟的使能和禁用都使用了宏定义,取代以前的函数)
(2)设置PA5的属性:推挽输出,上拉,速度等级为Fast(有4个等级Low,Medium,Fast和High),这些操作和STM32F10x没有什么不同
(3)每隔100ms翻转一下IO


led_demo.part01.rar

900 KB

led_demo.part02.rar

900 KB

led_demo.part03.rar

900 KB

led_demo.part04.rar

774.62 KB

打赏榜单

21ic小喇叭 打赏了 3.00 元 2015-10-26

《小威》| | 2015-9-29 22:55 | 显示全部楼层
扫盲好帖

使用特权

评论回复
paderboy| | 2015-9-29 23:53 | 显示全部楼层
不错,多谢分享。。。

使用特权

评论回复
694198235| | 2015-9-30 07:29 | 显示全部楼层
好贴子!!!

使用特权

评论回复
来自android
舒斯特尔| | 2015-9-30 08:33 | 显示全部楼层
扫盲帖子啊,谢谢楼主的分享,学习了

使用特权

评论回复
发新帖 本帖赏金 3.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

132

帖子

2

粉丝