
从原理图PCB到移植RTOS【细说STM32】【二】新建一个自己的工程 【前言】 本课我们要用Keil建立一个全新的工程,然后利用官方库文件,裁剪掉不需要的内容,做一个属于自己的第一个工程。 做项目跟做菜一样,我们都是用明确的材料,实现明确的目标。 我们介绍如何做一道菜的时候,一定是先介绍一下食材和佐料。 那么,我们准备自己新建一个自己的工程的时候,一样,也是先看看ST标准库里面都有哪些文件,都做什么作用。 【一、理解分析ST标准库文件】 解压在官网下载的库文件,文件夹内容详解如下图所示 ![]() 1号文件夹——Libraries文件夹解析 ![]() “CMSIS”文件夹中是一些Cortex-M3内核文件及一些启动文件。 其中关键的文件如下: ![]() 文件名:core_cm3.c和core_cm3.h 所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport 功能:CMSIS核心文件,由ARM公司提供,提供进入M3内核的接口 我们暂时先不理会它,一会建立工程的时候我们添加他们就可以。 文件名:system_stm32f10x.c 和system_stm32f10x.h 所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 功能:提供设置系统和总线时钟的相关函数和宏定义,包含用来设置系统的整个时钟系统的函数SystemInit() 文件名:stm32f10x.h 所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 功能:包含各种系统寄存器定义,内存操作相关的定义(将各种外设的基地址和偏移地址封装成独立的外设地址宏定义),单片机常用变量类型定义以及各种参数值的枚举定义(如SET、RESET的定义) 文件名:startup_stm32f10x_xx.s 所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm 功能:系统启动文件,系统上电以后运行的第一段代码就在这里 启动文件里主要是系统的中断向量表及中断函数定义。所有中断函数中Reset_Handler是唯一实现了的中断处理函数,其他函数基本都是死循环,用户需要用到的时候可以对其进行重新定义。 注:文件名中的xx代表芯片容量(FLASH大小) startup_stm32f10x_ld.s:适用于小容量产品 startup_stm32f10x_md.s:适用于中等容量产品 startup_stm32f10x_hd.s:适用于大容量产品 容量类型判断方法: 小容量: FLASH≤32K 中容量: 64K≤FLASH≤128K 大容量: 256K≤FLASH 对于STM32F103xxyy系列: 第一个x代表引脚数:T-36pin,C-48pin,R-64pin,V-100pin,Z-144pin; 第二个x代表Flash容量:6-32K,8-64K,B-128K,C-256K,D-384K,E-512K; 第一个y代表封装:H-BGA封装,T-LQFP封装,U-QFN封装; 第二个一代表工作稳定范围:6代表-40到85摄氏度,7代表-40到105摄氏度。 我们选型的STM32103FZET6表示如黄色加底文字描述内容。 STM32F013x4和STM32F103x6被归为小容量产品; STM32F103x8和STM32F103xB被归为中等容量产品; STM32F103xC,STM32103xD和STM32F103xE被归为大容量产品 ![]() ![]() STM32F10x_StdPeriph_Driver文件夹,主要放置外设驱动文件 文件名:stm32f10x_xxx.c 和 stm32f10x_xxx.h 所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src和STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\inc 功能:用于操作STM32外设的相关函数源码和对应头文件(文件中xxx代表对应外设名称) ![]() 2号文件夹——Project文件夹解析 ![]() 文件名:stm32f10x_conf.h 所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template 功能:文件里面列出了包含所有外设头文件的代码,使用时可根据实际用到的外设将相应代码取消注释以将其对应的头文件包含在项目中。此外该文件还包含对参数检查函数(assert_param())的定义 文件名:stm32f10x_it.c 和stm32f10x_it.h 所在目录:STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template 功能:包含所有的中断服务函数模板(此处指函数范例,并非c++中的函数模板)和声明,用户可根据此模板编写相应的中断服务函数。 【二、新建一个工程,并合理安放库文件】 我们在我们的新文件夹(例如:我们新建一个LED_DEMO)中,新建几个文件夹: ![]() 现在,CMSIS下的文件应该有这些: core_cm3.c core_cm3.h startup_stm32f10x_cl.s stm32f10x.h system_stm32f10x.c system_stm32f10x.h StdPeriphDriver目录中文件应该有这些: misc.h stm32f10x_adc.c stm32f10x_adc.h stm32f10x_bkp.c stm32f10x_bkp.h stm32f10x_can.c stm32f10x_can.h stm32f10x_cec.c stm32f10x_cec.h stm32f10x_crc.c stm32f10x_crc.h stm32f10x_dac.c stm32f10x_dac.h stm32f10x_dbgmcu.c stm32f10x_dbgmcu.h stm32f10x_dma.c stm32f10x_dma.h stm32f10x_exti.c stm32f10x_exti.h stm32f10x_flash.c stm32f10x_flash.h stm32f10x_fsmc.c stm32f10x_fsmc.h stm32f10x_gpio.c stm32f10x_gpio.h stm32f10x_i2c.c stm32f10x_i2c.h stm32f10x_iwdg.c stm32f10x_iwdg.h stm32f10x_pwr.c stm32f10x_pwr.h stm32f10x_rcc.c stm32f10x_rcc.h stm32f10x_rtc.c stm32f10x_rtc.h stm32f10x_sdio.c stm32f10x_sdio.h stm32f10x_spi.c stm32f10x_spi.h stm32f10x_tim.c stm32f10x_tim.h stm32f10x_usart.c stm32f10x_usart.h stm32f10x_wwdg.c stm32f10x_wwdg.h stm32f10x_conf.h 对于某个具体的项目,这些文件不一定都会用到。但是我们文件夹统一标准。以后任意开发,都可以基于这个文件夹进行。 如果你倾向于文件夹结构简洁,则 头文件*.h和c文件*.c可以放在一个文件里面。如果你倾向于文件按类分开,则保持原来libraries文件的分开两个文件。就看你的强迫症是哪一种。 下面我们打开Keil5,新建一个工程: ![]() 然后在弹窗选择具体芯片:STM32F103ZE ![]() ![]() 增加并修改组名称: ![]() 更改工程名(将默认的工程名改为“LED_DEMO”的方法:选中工程,按“F2”键)并为工程添加项目组(Add group to project)。具体操作情况如下图: ![]() 右键点击CORE组,“AddExisting Files to Group ‘CORE’”,选择CORE文件夹里面的H文件、C文件、S文件 添加。 右键点击FWLIB组,“AddExisting Files to Group ‘CORE’”,选择FWLIB文件夹里面的H文件、C文件添加。 ![]() 添加之后: ![]() 我们可以看到,C文件没有关联相关的“*.h”文件。 将..\CORE;..\FWLIB这两个目录加入到头文件的搜索目录中。 ![]() ![]() 选择输出文件目录到我们创建的OBJ文件夹: ![]() USER组邮件,添加一个新文件main.c ![]() 【三、写一个最简单的main函数】 ![]() ![]() 【四、配置工程编译环境】 写好了main.c文件之后,我们可以尝试点一下“编译”。 结果报错了。 在编译时出现警告“..\FWLIB\src\stm32f10x_rcc.c(273):warning: #223-D: function “assert_param”declared implicitly”,接下来一堆警告和错误。 ![]() 出错的原因:函数“assert_param”未声明。 问题分析: 函数assert_param是STM32官方库文件中用到的。 对于我采用的《STM32F10x_StdPeriph_Lib_V3.5.0》库文件来说,assert_param函数在文件“stm32f10x_conf.h”的第59-73行。 看函数说明可知,assert_param是一个条件表达式宏定义,主要作用是对函数的输入参数进行检查。仔细查看程序段,不管是否定义USE_FULL_ASSERT,函数assert_param均有定义,编译时不应该出现上述警告。 还有一种可能,那就是虽然定义了函数assert_param,但是包含定义的文件“stm32f10x_conf.h”没有被编译。 在工程文件中搜索字符“stm32f10x_conf.h”,在文件“stm32f10x.h”的第8301-8303行找到程序段。 这段代码的意思:如果定义USE_STDPERIPH_DRIVER,则包含文件“stm32f10x_conf.h”。同样的,如果没定义则不包含。 在工程中搜索文本USE_STDPERIPH_DRIVER,没有找到有关 USE_STDPERIPH_DRIVER的宏定义,因此也就没有包含stm32f10x_conf.h文件,工程中也就没有assert_param的声明。 文本“USE_STDPERIPH_DRIVER”的字面意思:使用标准外设驱动。也就是说如果需要使用ST官方提供的外设驱动库则需要定义 “USE_STDPERIPH_DRIVER”。 很明显问题出在使用了官方的标准外设库又没有定义 “USE_STDPERIPH_DRIVER”。 解决方法: 在Keil工程中,点击“optionsfor Target…”,在弹出窗口中点击“C/C++”,在“PreprocessorSymbols”的“Define”栏输入“USE_STDPERIPH_DRIVER”。 Preprocessor Symbols 就是预处理符号,输入“USE_STDPERIPH_DRIVER”就是向工程中添加预处理标号“USE_STDPERIPH_DRIVER”,等同于在代码中添加宏定义“#define USE_STDPERIPH_DRIVER”。 ![]() 配置完后,编译工程,问题解决。 然后我们把我们写的第一个最简单的工程烧录进入iBox电路板,可以看我们的第一个工程的表现。 关于烧写的配置,跟上一节的内容相同: 选择Debug 选择Jlink ![]() 选择Utilities,选择Jlink ![]() 点击Debug里面的 右边的Settings ![]() 选择Debug里面的Port 修改JTAG为 SW ![]() 另外:为了方便,我们配置一下,烧写完成后MCU自动重启。 ![]() 现在,我们就可以下载啦。 ![]() 我们的代码可以按照我们刚刚制作的工程,烧录到iBox,即可运行如下: ![]() 文章出处: 硬件十万个为什么 |
现在是HAL时代,至少也是LL。新手就要远离标准库。 |
直接用cube比较快 |