首页 » 互联网 » STM32F0单片机快速入门四:不看手册也行吗?_函数_代码

STM32F0单片机快速入门四:不看手册也行吗?_函数_代码

南宫静远 2024-11-16 14:58:49 0

扫一扫用手机浏览

文章目录 [+]

1. 第一个工程 翻转引脚

上一篇文章我们详细先容了 STM32F030 从复位时取得复位向量,系统初始化,然后跳转到 main( ) 函数的过程。
下面我们结合一个最大略的例子,对 Cube 库的利用做一个大略的先容。

STM32F0单片机快速入门四:不看手册也行吗?_函数_代码 互联网

我们用 Keil 打开下面这个工程:

STM32Cube_FW_F0_V1.11.0\Projects\STM32F030R8-Nucleo\Examples\GPIO\GPIO_IOToggle\MDK-ARM\Project.uvprojx

编译下载运行此代码,会看到一个 LED灯(连至MCU的 PA5引脚)一直地闪烁。
为了完成这个大略的功能,我们看到这个工程里包含了不少文件:

如果是初次用这种库的办法做开拓,乍一看还真觉得有点乱。
不过让我们一个一个看一下这些文件,理清它们的关系后就会体会到这种办法的巨大优点。

2. 文件分类阐明

工程里的文件分为五大类:启动代码,M0内核初始化,驱动,板级支持包(BSP),用户代码。
一样平常来说我们开拓运用程序,紧张关注用户代码文件就行了。
如果硬件电路板做了改动,则修正BSP里的内容。

在早期的单片机开拓中,芯片内资源很少,常日的情形是一个工程师就从硬件到软件编程都做了,是没有 BSP(Board Support Package)这种观点的。
BSP观点来源于较繁芜的CPU系统的开拓,一样平常是厂家设计主板,并供应 BSP(包含启动代码,驱动,Bootloader等)。
我们这里的 BSP 观点稍有不同,它是指对某一块儿以 MCU 为核心的电路板的支持代码包。
启动代码,内核初始化和驱动,没有包含在内。
BSP会调用驱动层的代码。

对付 STM32 Nucleo 这块儿开拓板来说,板上资源很少,以是BSP只供应了相应的按键(BUTTON)和指示灯(LED)支持代码。
里面的ADC,SPI,LCD等代码是支持其它板子的,可以先忽略。

启动代码

为理解汇编代码,我们先熟习一下这些伪指令:

ALIGN 变量或代码对齐。
如:

ALIGN = 3 以8(2的3次方)字节对齐。

EQU 给标号赋值。
如:

Stack_Size EQU 0x400;

DCD 分配1个或多个字(words)的内存空间。
如:

Data DCD 1,5,8; 定义3个字并赋值为 1,5 和 8。

AREA 定义一个代码或数据段(section),命名并指定属性。
如:

AREA Func01, CODE, READONLY;

定义了一个名字为 Func01 的只读代码段。

SPACE 保留一段空间并初始化为 0。
如:

Data SPACE 100; 为 Data 保留 100个字节初始化为 0 的内存空间。

IMPORT 导入其它文件中的标号,以在当前文件中引用。
如:

IMPORT SystemInit

LDR R0, =SystemInit

BLX R0

从文件 system_stm32f0xx.c 中导入 SystemInit 这个函数并调用。

EXPORT 导出能被连接器(Linker)识别的标号。
从ASM文件导出的标号可以在C中引用。

[WEAK] 如果在其它地方定义了相同的标号,则此处定义被覆盖。

PROC 定义一个函数的起始地址。

ENDP 标志当前函数结束。

例子:

SysTick_Handler PROC

EXPORT SysTick_Handler [WEAK]

B.

ENDP

导出 SysTick_Handler 这个中断处理函数。
如果在其它地方定义了一个新的 SysTick_Handler 函数,那么新函数将覆盖此处定义的这个陷阱函数。
汇编语句 B.为在当前语句去世循环。

下面我们看一下启动文件 startup_stm32f030x8.s

定义堆和栈:

中断向量表:

现在这个工程用到的只有绿线框中的几个向量:

__initial_sp

初始堆栈指针

Reset_Handler

复位向量,我们在上一篇文章已经讲到如何从复位向量一步一步实行到用户代码中的主程序main( )。

SysTick_Handler

系统时钟中断向量。
此程序每 1ms 产生一次中断。

须要把稳的是 SysTick_Handler 这个中断处理函数在用户代码文件stm32f0xx_it.c

中进行了重定义,以是当 SysTick 中断发生时,实际会跳转到用户代码的中断处理函数,而不是跳到下图所示的汇编代码中断处理函数进入去世循环。

再往下可以看到,对所有芯片级中断定义了一个共享的陷阱函数。
用户在实际利用到某一个中断的时候,要在中断处理文件 stm32f0xx_it.c 中用相同的函数名定义,从而在中断发生时跳转到实际的中断处理函数。

在此文件的最下面的代码,是用来通报堆栈信息给库的:

在芯片资源比较少时,可以通过选中 Options for Target->Target->Use MicroLIB 选项,利用简化版的库来实现 printf 等操作。
若资源充足时利用标准库,库将调用下面的 __user_initial_stackheap 函数来得到堆栈信息。

M0 内核初始化

system_stm32f0xx.c

此文件只有两个函数:

SystemInit( ),在启动代码中调用,把系统时钟复位到初始默认状态(8MHz的高频内部时钟 HSI)。

SystemCoreClockUpdate( ), 在用户调用库函数变动时钟配置后,须要调用此函数以更新全局系统时钟变量 SystemCoreClock。
其它模块基于此时钟的打算才会精确。
一样平常来说变动时钟配置的 HAL函数已经包含此函数的调用,如 HAL_RCC_ClockConfig( ), 无需用户再次调用。

驱动

stm32f0xx_hal_cortex.c

包含 Cortex 内核中两个主要模块的驱动:

可嵌套中断向量掌握器 NVIC(Nested Vectored Interrupt Controller),

系统滴答时钟 SYSTICK。

stm32f0xx_hal.c

此文件包含用户程序必须首先调用的 HAL_Init( ),它会使能数据和指令缓存,预取指令行列步队;配置系统滴答时钟产生 1ms 中断;调用 HAL_MspInit( )回调函数。

HAL_MspInit( )函数用来做系统级的初始化,配置某一模块干系的 时钟,引脚,DMA,中断等资源,但是在所有的例程中都没有实际用到此函数。
可以先忽略。

stm32f0xx_hal_rcc.c

stm32f0xx_hal_rcc_ex.c

RCC(Reset and Clock Controller)模块的驱动。
一个模块为什么要两个驱动文件呢?前一个文件供应了基本的通用的功能驱动,后一个文件是扩展功能驱动,常日针对某一特定型号的芯片。
犹如我们用饭须要餐具,_rcc.c 供应碗筷等常用必备工具,_rcc_ex 可能供应的便是羽觞,烛台等这些东西。

stm32f0xx_hal_gpio.c

GPIO 模块的驱动。

BSP 板级支持包

stm32f0xx_nucleo.c

针对 STM32 Nucleo 开拓板的类型,宏定义,支持代码。

用户代码

main.c 主程序

stm32f0xx_it.c 中断处理

前面先容了一大堆文件,紧张是为了打消系统的事情流程。
在开拓中利用库还是很大略的。
在主程序中调用库,只须要通过 main.h 包含下面这个头文件:

stm32f0xx_hal.h

如果有 BSP 则包含 BSP 的头文件,在本工程是:

stm32f0xx_nucleo.h

利用到哪个模块就在配置文件中打开使能该模块的宏定义。

stm32f0xx_hal_conf.h

然后第一步必须调用 HAL_Init( )。

第二步,如果希望系统时钟事情在默认内部时钟(8MHz HIS)以外的频率,则须要调用 SystemClock_Config( )。
此函数又调用 HAL_RCC_ClockConfig( ) 完成新配置。

下面是运用代码:

所有模块一样平常都是这三个步骤:使能模块的时钟,初始化模块,利用模块的功能。

stm32f0xx_it.c 中的中断处理函数 SysTick_Handler( ) 很大略,每次进入就对滴答计时变量 uwTick 加1,其它 HAL 函数可以基于此变量计时。

我们将在接下来的文章中进一步谈一下库的利用,和如何用按键触发中断去掌握 GPIO 的翻转。

参考资料:

Description of STM32F0 HAL and low-layer drivers

ARM Compiler armasm User Guide

STM32F030 Datasheet

STM32F030 Reference Manual

标签:

相关文章

手机发烧不要扔救救还能用!_手机_温度

手机发热缘故原由无非有两点,内部成分和外部成分。内部则是由于处理器等硬件负载运行提升功耗导致发热;而外部则是由于机主的利用习气,外...

互联网 2024-12-09 阅读0 评论0