历史上的今天
返回首页

历史上的今天

今天是:2026年03月17日(星期二)

正在发生

2023年03月17日 | STM32F0单片机快速入门四 翻转引脚

2023-03-17 来源:zhihu

1.第一个工程 翻转引脚

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

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

STM32Cube_FW_F0_V1.11.0ProjectsSTM32F030R8-NucleoExamplesGPIOGPIO_IOToggleMDK-ARMProject.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 函数可以基于此变量计时。

3.参考资料

Description of STM32F0 HAL and low-layer drivers

ARM Compiler armasm User Guide

STM32F030 Datasheet

STM32F030 Reference Manual


推荐阅读

史海拾趣

Avel Lindberg公司的发展小趣事

由于我无法直接获取Avel Lindberg公司的详细发展资料,因此我无法直接为您撰写5个关于该公司发展起来的具体故事。不过,我可以为您提供一个通用的故事框架,您可以根据这个框架结合公司的公开信息来撰写相关故事。

Avel Lindberg公司发展故事框架

  1. 创业初期: 描述Avel Lindberg公司成立的背景,包括创始人或核心团队的愿景、行业趋势以及初始产品或服务。可以提及公司如何克服初创期的困难,如资金短缺、市场竞争激烈等问题,逐渐在市场上站稳脚跟。

  2. 技术突破: 讲述公司在某个关键时期实现的技术突破,这项突破可能是对既有技术的改进,也可能是全新技术的研发。这个突破如何帮助公司打开了新的市场领域,提升了竞争力,成为行业内的领军者。

  3. 合作与扩展: 描述公司如何通过与其他企业、研究机构或高校建立合作关系,来扩大业务范围或提升技术水平。这些合作可能涉及共同研发、市场拓展、品牌建设等方面,对公司的长期发展产生了积极影响。

  4. 国际化战略: 讲述公司如何逐步实施国际化战略,进入海外市场。这包括公司如何分析国际市场的需求和竞争态势,制定合适的市场进入策略,以及在国际市场上取得的成就和面临的挑战。

  5. 社会责任与可持续发展: 介绍公司在发展过程中如何关注社会责任和可持续发展。这可以包括公司在环保、员工福利、社区支持等方面的举措,以及这些举措如何提升了公司的社会形象和品牌价值。

在撰写具体故事时,您可以根据Avel Lindberg公司的实际情况调整上述框架中的内容,并结合公司的官方公告、新闻报道和行业分析报告等资料来丰富细节。同时,请确保所描述的事实准确无误,避免主观评价和猜测。

Adam Tech公司的发展小趣事

为了进一步拓展市场,Adam Tech开始实施全球化战略。公司在北美、欧洲和亚洲等地设立了多个代表处,以便更好地服务全球客户。这些代表处不仅为公司带来了更多的业务机会,也提升了公司在国际市场上的知名度。同时,公司还积极与各地合作伙伴建立紧密的合作关系,共同推动电子连接器行业的发展。

Advanced Electronic Packaging公司的发展小趣事

随着国内市场的逐渐饱和,Advanced Electronic Packaging公司开始将目光投向海外市场。公司积极参与国际电子展会和技术交流活动,展示其先进的封装技术和优质产品。同时,公司还加大了对海外市场的宣传力度,通过线上线下相结合的方式提升品牌知名度和影响力。在不懈的努力下,公司的产品和服务逐渐赢得了国际市场的认可和青睐,海外市场份额逐年攀升。

Elektron公司的发展小趣事

Elektron公司一直注重技术研发和创新投入,致力于在行业中保持领先地位。公司不断推出具有创新性和领先性的产品,如高性能的电池充电器、先进的焊接和切割设备等。这些产品的推出不仅提高了公司的市场竞争力,也推动了整个行业的发展和进步。同时,Elektron还积极参与行业标准的制定和推广工作,为行业的健康发展做出了重要贡献。

AIM - American Iron and Metal公司的发展小趣事

为了进一步提升竞争力,AIM开始着手整合电子行业的上下游产业链。公司通过收购、合资等方式,与多家供应商和合作伙伴建立了紧密的合作关系。这种整合不仅降低了生产成本,还提高了产品的质量和交付速度,使AIM在激烈的市场竞争中保持领先地位。

CoolerMaster公司的发展小趣事

随着业务的不断发展,Cooler Master逐渐将触角延伸至全球。集团总部位于中国台北,同时在大陆设立了制造基地,并在北美、欧洲、东亚及北京、上海等地设有办事处或研发中心。这种全球化的布局使得Cooler Master能够更好地了解各地市场的需求,进而提供更加精准的产品和服务。此外,公司还与多家全球500强品牌合作,为其提供散热解决方案,进一步巩固了其在全球散热领域的领导地位。

问答坊 | AI 解惑

我是新注册的。先来报个到。

我是新注册的。先来报个到。…

查看全部问答>

RS232串口(COM口)控制(10位)A/D模数转换控制板

本串口控制A/D模数转换控制板具有6路10位(精度±1LSB)高速A/D转换通道,可同时对外部输入的6路模拟量(直流0-5V)进行模数转换,转换后的结果(每通道转换后的结果为2字节数据)通过串口快速输出(默认波特率9600,可定做其它波特率),供电脑上位机 ...…

查看全部问答>

低碳经济和节能减排成为仪表研发新方向

机遇与挑战: “低碳经济”越来越受到众人的认同要实现节能减排,仪器仪表尤其是电能计量仪表和用电自动化管理系统产品具备高智能、网络化、可靠性强的特点 “低碳经济”越来越受到众人的认同,若要实现节能减排的目标,就必须对能源进行精确采集 ...…

查看全部问答>

opengl es eglswapbuffers函数运行报错

[code]while (1)     {         // If there is a message waiting, handle it         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))       &n ...…

查看全部问答>

各位大大们,帮帮小弟!

在汇编计算地址的时候  有时会遇到符号位扩展这个问题,我知道如何扩展,但是我不明白为什么要扩展? 在什么情况下需要进行符号位扩展?…

查看全部问答>

求单片机的公历转农历的c程序,最好多带点注释,谢谢

求单片机的公历转农历的c程序,最好多带点注释,谢谢…

查看全部问答>

关于手机无线接入驱动开发

这个是我的毕业设计题目,我没做过嵌入式程序,甚至对其一点都不了解。题目要求是再Linux平台做一个手机驱动程序,让手机能够通过笔记本电脑用的无限基站上网而不用GPRS。导师只是简单介绍了一下流程:在手机上开发一个程序,通过UART或者RS232连接 ...…

查看全部问答>

大家谈谈SHT21应该怎么焊接?

最近做数字湿度计时,发现大家对焊接SHT21感到困惑,数据手册上说用回流焊焊接。但是我们是DIY,不可能有回流焊,而且也不方便啊。那么应该怎么焊接呢?大家谈谈。。。统计下SHT21焊接情况?https://bbs.eeworld.com.cn/thread-153603-1-1.html…

查看全部问答>

PVCBOT【0号A版】暴走的臭虫--振动机器人

    这是一个最简单的机器人,简单到可能很多人都不认为其是机器人,而顶多算一个有点雷的减压用的小玩意儿。这里之所以选择其作为PVCBOT系列机器人的第一个项目——PVCBOT零号机器人,其意义更多是在于其既可以让初学者练练手,也可以给老 ...…

查看全部问答>