历史上的今天
今天是:2025年04月22日(星期二)
2018年04月22日 | STM32CubeMX开发实战之项目分析法则
2018-04-22 来源:eefocus
一、第一个项目
我们要建立第一个项目,这里主要是为了进行项目分析之用,让我们明白用CubeMX是如何开展工作的以及如何追踪代码逻辑。好了,废话不多说,开干。
这里我选了一款型号为STM32L151C8Tx作为例子来配置MX,如图所示。
按照上图配置完成后,对MX工程进行配置,然后生成代码即可,见图。
好了,不出大的意外,第一个项目已经生成。大家自行打开即可。
二、项目架构
嗯,真的简单的架构,就那么几个文件夹而已,看图。请叫我贴图王,因为我真的非常喜欢图文并茂。
惊不惊喜、意不意外,这样就可以任意驰骋在STM32的海洋里了,无需管那人世间的纷纷扰扰。好了,拉回来。从图中看的确简单,但是我们还是有必要深入代码深处,逐步探究下这CubeMX生成的代码到底是怎么跑起来的。
三、深入代码
深入代码到底多深,只有自己知道,我这里权当抛砖引玉,各路高手自行进一步探究噢。我知道很多人和我一样有强迫症,第一个想看的不是main.c而是。。。。。。江湖中人人传到的汇编!在这个例子中就是startup_stm32l151xb.s。看看这名字,就知道这是个启动代码,只是后缀比较性感,是S。
写CubeMX的人还是很牛逼的,看汇编文件其实也很好看懂,不信你看。
文件的开头写的很清楚就做这么几件事情。
1. 设置系统初始的SP
2. 设置系统初始的PC,PC就是reset_hanlder
3. 设置中断向量表
4. 配置系统时钟
5. 跳到C库的_main中,注意_main不是main噢
看下面的源文件内容吧,我来简要注释下。
/* 栈配置 */
;
;
;
Stack_Size EQU 0x400 /* 设置stack大小为0x400 */
/* 定义STACK代码段,可读写,对齐8字节 */
AREA STACK, NOINIT, READWRITE, ALIGN=3
/* 分一段stack size大小的内存空间 */
Stack_Mem SPACE Stack_Size
__initial_sp
/* 堆配置 */
;
;
;
Heap_Size EQU 0x200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB
/* 向量表 */
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_STAMP_IRQHandler ; Tamper and Time Stamp
DCD RTC_WKUP_IRQHandler ; RTC Wakeup
DCD FLASH_IRQHandler ; FLASH
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_IRQHandler ; ADC1
DCD USB_HP_IRQHandler ; USB High Priority
DCD USB_LP_IRQHandler ; USB Low Priority
DCD DAC_IRQHandler ; DAC
DCD COMP_IRQHandler ; COMP through EXTI Line
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD 0 ; Reserved
DCD TIM9_IRQHandler ; TIM9
DCD TIM10_IRQHandler ; TIM10
DCD TIM11_IRQHandler ; TIM11
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTC_Alarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USB_FS_WKUP_IRQHandler ; USB FS Wakeup from suspend
DCD TIM6_IRQHandler ; TIM6
DCD TIM7_IRQHandler ; TIM7
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
/* 重启后进来的第一个地方 */
; Reset handler routine
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Default_Handler PROC
EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_IRQHandler [WEAK]
EXPORT TAMPER_STAMP_IRQHandler [WEAK]
EXPORT RTC_WKUP_IRQHandler [WEAK]
EXPORT FLASH_IRQHandler [WEAK]
EXPORT RCC_IRQHandler [WEAK]
EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK]
EXPORT DMA1_Channel1_IRQHandler [WEAK]
EXPORT DMA1_Channel2_IRQHandler [WEAK]
EXPORT DMA1_Channel3_IRQHandler [WEAK]
EXPORT DMA1_Channel4_IRQHandler [WEAK]
EXPORT DMA1_Channel5_IRQHandler [WEAK]
EXPORT DMA1_Channel6_IRQHandler [WEAK]
EXPORT DMA1_Channel7_IRQHandler [WEAK]
EXPORT ADC1_IRQHandler [WEAK]
EXPORT USB_HP_IRQHandler [WEAK]
EXPORT USB_LP_IRQHandler [WEAK]
EXPORT DAC_IRQHandler [WEAK]
EXPORT COMP_IRQHandler [WEAK]
EXPORT EXTI9_5_IRQHandler [WEAK]
EXPORT TIM9_IRQHandler [WEAK]
EXPORT TIM10_IRQHandler [WEAK]
EXPORT TIM11_IRQHandler [WEAK]
EXPORT TIM2_IRQHandler [WEAK]
EXPORT TIM3_IRQHandler [WEAK]
EXPORT TIM4_IRQHandler [WEAK]
EXPORT I2C1_EV_IRQHandler [WEAK]
EXPORT I2C1_ER_IRQHandler [WEAK]
EXPORT I2C2_EV_IRQHandler [WEAK]
EXPORT I2C2_ER_IRQHandler [WEAK]
EXPORT SPI1_IRQHandler [WEAK]
EXPORT SPI2_IRQHandler [WEAK]
EXPORT USART1_IRQHandler [WEAK]
EXPORT USART2_IRQHandler [WEAK]
EXPORT USART3_IRQHandler [WEAK]
EXPORT EXTI15_10_IRQHandler [WEAK]
EXPORT RTC_Alarm_IRQHandler [WEAK]
EXPORT USB_FS_WKUP_IRQHandler [WEAK]
EXPORT TIM6_IRQHandler [WEAK]
EXPORT TIM7_IRQHandler [WEAK]
WWDG_IRQHandler
PVD_IRQHandler
TAMPER_STAMP_IRQHandler
RTC_WKUP_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_IRQHandler
DMA1_Channel3_IRQHandler
DMA1_Channel4_IRQHandler
DMA1_Channel5_IRQHandler
DMA1_Channel6_IRQHandler
DMA1_Channel7_IRQHandler
ADC1_IRQHandler
USB_HP_IRQHandler
USB_LP_IRQHandler
DAC_IRQHandler
COMP_IRQHandler
EXTI9_5_IRQHandler
TIM9_IRQHandler
TIM10_IRQHandler
TIM11_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
USB_FS_WKUP_IRQHandler
TIM6_IRQHandler
TIM7_IRQHandler
B .
ENDP
ALIGN
;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
/* micro lib的话,就导出这些符号 */
IF :DEF:__MICROLIB
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
ALIGN
ENDIF
END
从汇编到main其实需要好好分析,大家课可以找个安静的环境慢慢深入,嗯,慢慢深入。假设我们已经走到了main的内心,那么我们从main开始吧。
/* main函数 */
int main(void)
{
记得cubeMX配置后,会生成项目,新的文件,凡是出现user code begin的地方,将你的个人代码写在该区域,以免你配置后把你辛苦写 的代码覆盖了
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
熟悉的主循环
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
整个main其实还是很简单的,这也是CubeMX的初衷,简化开发的难度。大家可以注意到,在项目里有个文件夹Drivers/STM32L1XX_HAL_Driver,里面存的是你的兵器库,是各种库文件,以后你会用的飞起。后面会结合具体项目来具体讲解,今天有点晚了,就到这了噢。
史海拾趣
|
发展、融合MCU专题融合了走进MCU、应用文章、厂商掠影,三大版块。 走进MCU中详细介绍了MCU基本原理与发展历史,带领读者一起回顾MCU的发展里程。 应用文章中细分了单片机在控制、显示、电源、无线、通信、解码等一系列领域的设计方案。 ...… 查看全部问答> |
|
请问我得PB装好了后,安装了2440的BSP包,为什么定制内核时没有sysgen选项啊。build os里都没白色。但我用x86定制内核却有sysgen选项。高手请指导下啊… 查看全部问答> |
|
我是电气工程及其自动化专业的,今年大三,现在想学嵌入式开发,以后搞硬件层或驱动层,请问电气专业学嵌入式是不是偏离了本专业的发展方向?能将嵌入式学好么?请各位前辈和高手指导。… 查看全部问答> |
|
PB5.0导出SDK时出错,请高手指教 我在PB5.0导出SDK时,出现下列错误,高手给我把把脉啊,看看问题出在哪了?刚刚开始搞这个东东.... Committing database changes Creating \'required\' feature Adding required files Committing database ...… 查看全部问答> |
|
急求一款好用的CDMA模块,请大家推荐,真的很急,呵呵...如果您有时间的话请高抬贵手指,推荐推荐!! 该模块主要是用来做数据传输的,做车载的GPS系统,所以要满足以下要求: 1、内置TCP/IP、PPP协议栈。 2、可以打电话。 3、支持PDU格式的短信 ...… 查看全部问答> |
|
有两个问题要请教: 1 sim卡都用到了哪些gsm协议规范? 2 我现在做的项目是读sim卡的信息,就是给sim发送ADPU命令包,但是我不知道sim卡的存储格式,比如我要读电话本,应当怎么做?这方面的资料去哪里找?… 查看全部问答> |
|
现在有一个怪问题,外部中断我设为上升沿触发时,的确是上升沿触发,但是设为下降沿触发时,就上升沿和下降沿都能触发,为什么呢? 外部中断用按键触发。我的电路是用一个按键一端接地,一端接I/O,I/O设为输入上拉模式。… 查看全部问答> |
|
请教 chenbing 长老,关于写到 Flash中运行的程序 本帖最后由 dontium 于 2015-1-23 13:20 编辑 Chenbing 长老: 我用 DSP 2407A 也有一段时间了.但是由于以前手中只有孤零零的一块开发板,生怕弄坏了,断了炊,所以自己写的程序都是 Load 到扩展RAM 中运行,没有写入Flash.做过几次写 Fla ...… 查看全部问答> |
|
有人做过MCU51单片机uIP协议栈+ENC28J60网卡实现tcp协议通讯的大大吗? 如题 在淘宝店家买回ENC28J60 以太网模块http://item.taobao.com/item.htm?scm=1007.77.0.0&id=10390385522&ad_id=&am_id=&cm_id=&pm_id=想做tcp协议的温湿度的传递,采集方面已完成。买回模块以后,对这个uIP协议栈不了解 ...… 查看全部问答> |




