完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
前言
好久没写STM32的博客了,主要还是涉及到很多核心技术,再加上代码量巨大,懒得整理,就不了了之了。 之前的开发的工程都是在已有框架上的已有产品中增加新功能,这次我决定从0开始,学习STM32,从搭建环境开始,到烧录程序运行成功,系统的从零开始学习。 本人已经绘制成功一块STM32的电路版,已经将硬件焊接成功,主要器件如下: STM32F407ZET6 正点原子2.8 LCD MODULE 一个摄像头 几个二极管 本篇博客主要记录从零创建一个全新的STM32F407的项目过程 资料下载 开源奉献 要下载有两个: 一个是 STM32F407最小系统板开发指南-库函数版本作为主要文档 还有一个是STM32F4xx固件库作为库函数,全在 A盘 资料里,有需要的在stm32f407探索者开发板中下载。 创建工程 开发工具:Keil uVision5 接下来就跟着文档,从零创建一个STM32的project 本次学习目标主要是学会用STM32F407实现摄像头的应用 创建目录 所以先创建一个新的空白文件夹叫:MyCamera 然后在MyCamera目录下创建五个子文件夹:CORE,FWLIB,OBJ,SYSTEM,USER,如下图: 至于这些文件夹名字,实际上是可以任取的, 这样取名只是为了方便识别。用来存储特定的类型的文件 创建工程 创建完目录之后,就要创建工程了 打开Keil Project – New μVison Project 然后在弹出来的界面中,选择我们刚才创建的目录下的USER目录下,也就是...MyCameraUSER路径下,然后输入文件名,我这里和我自己的工程名称一致,是MyCamera,然后点击保存。 之后就是弹出来选择设备,我的CPU型号是STM32F407ZET6所以说选择STM32F407ZETx型号 有关STM32的型号,正点原子的文档中都有解释,再次感谢原子哥 然后接下来的Manager Run-Time Environment界面直接点击Cancel就行了。 到此,我们的工程框架就创建好了,现在在工程里,只有一个Target1 下的 source Group 1 然后我们在系统中点开文件夹,发现在USER目录下多了几个文件: MDK5.14生成的工程文件是以.uvprojx 为后缀。这个不能删除 Listings 和 Objects 文件夹是 MDK 自动生成的文件夹,用于存放编译过程产生的中间文件。这两个文件不用管它 复制库函数文件 框架已经建好,之后就是将官方的库函数复制到我们的项目文件里了。 文件复制 FWLib 第一个是: 打开官方固件库包,定位到我们之前准备好的固件库包的目录: STM32F4xx_DSP_StdPeriph_Lib_V1.4.0LibrariesSTM32F4xx_StdPeriph_Driver 下面, 将目录下面的 src,inc 文件夹 copy 到我们刚才建立的FWLib 文件夹下面。 src 存放的是固件库的.c 文件,inc 存放的是对应的.h 文件,还有一个html文件是一个说明文件 CODE 打开官方固件库包 STM32F4xx_DSP_StdPeriph_Lib_V1.4.0LibrariesCMSISDeviceSTSTM32F4xxSourceTemplatesarm 下 将文件 startup_stm32f40_41xxx.s 复制到 CORE 目录下面。 然后定位到目录 STM32F4xx_DSP_StdPeriph_Lib_V1.4.0LibrariesCMSISInclud 将 里 面 的 四 个 头文件 : core_cm4.h、core_cm4_simd.h、core_cmFunc.h 以及 core_cmInstr.h 同样复制到 CORE 目录下面。复制完的CODE结构如下图: 简单的说明一下,在arm文件夹下有很多.s文件,主要是和芯片有关,主要用于启动 USER 接下来我们要复制工程模板需要的一些其他头文件和源文件到我们工程。首先定位到目录: STM32F4xx_DSP_StdPeriph_Lib_V1.4.0LibrariesCMSISDeviceSTSTM32F4xxInclude 将里面的 2 个头文件 stm32f4xx.h 和 system_stm32f4xx.h 复制到 USER 目录之下。 这两个头文件是STM32F4 工程非常关键的两个头文件。然后进入目录 STM32F4xx_DSP_StdPeriph_Lib_V1.4.0ProjectSTM32F4xx_StdPeriph_Templates , 将 目 录 下 面 的 5 个 文 件 main.c , stm32f4xx_conf.h , stm32f4xx_it.c , stm32f4xx_it.h ,system_stm32f4xx.c 复制到 USER 目录下面。如下图 添加到工程 前面的步骤,我们已经将需要的固件库相关文件复制到了我们的工程目录下面 下面我们还要将这些文件加入我们的工程中去。 设置Groups 在MDK5中,右键点击 Target1,选择 Manage Project Items, 然后在Project Targets一栏,我们双击Target将名字修改为 Template,然后在 Groups 一栏删掉一个 Source Group 1, 建立三个 Groups:USER,CORE,FWLIB。然后点击 OK,可以看到我们的 Target名字以及 Groups 情况如下图: Groups添加文件 FWLIB 下面我们往 Group 里面添加我们需要的文件。我们按照上边的方法, 右键点击点击Tempate,选择 Manage Project Items. 然后选择需要添加文件的 Group,这里第一步我们选择 FWLIB,然后点击右边的 Add Files 定位到我们刚才建立的目录FWLIBsrc下面,将里面所有的文件选中(Ctrl+A),然后点击 Add,然后 Close. 可以看到 Files 列表下面包含我们添加的文件,如下图 这里有个文件 stm32f4xx_fmc.c 比较特殊。这个文件是 STM32F42 和 STM32F43 系列才用到, 所以我们这里要把它删掉(注意是 stm32f4xx_fmc.c 要删掉,不要删掉 stm32f4xx_fsmc.c)。 这里需要说明一下,对于我们写代码,如果我们只用到了其中的某个外设,我们就可以不用添加没有用到的外设的库文件。 例如我只用 GPIO,我可以只用添加 stm32f4xx_gpio.c而其他的可以不用添加。这里我们全部添加进来是为了后面方便,不用每次添加,当然这样的坏处是工程太大,编译起来速度慢,用户可以自行选择。 CODE/USER 之后我们添加文件到 CORE 和 USER 中 CORE 下面需要添加的文件为 startup_stm32f40_41xxx.s *注意:默认添加的时候文件类型为.c,也就是添加 startup_stm32f40_41xxx.s 启动文件的时候,你需要选择文件类型为 All files才能看得到这个文件 * USER 目录下面需要添加的文件为 main.c,stm32f4xx_it.c,system_stm32f4xx.c。 这样我们需要添加的文件已经添加到我们的工程中去了,最后点击 OK,回到工程主界面。如下图 设置头文件 接下来要在 MDK 里面设置头文件存放路径。 也就是告诉 MDK 到那些目录下面去寻找包含了的头文件。 这一步骤非常重要。如果没有设置头文件路径,那么工程会出现报错头文件路径找不到。 设置目录 先进入 PATH 配置界面,选择C/C++标签,然后点击Include Paths 在弹出的界面中,点击New(Insert),然后添加点击添加路径 这里我们需要添加的头文件路径包括:CORE, USER, FWLIBinc 这里大家务必要仔细,固件库存放的头文件子目录是FWLIBinc,不是 FWLIBsrc。 很多朋友都是这里弄错导致报很多奇怪的错误。添加完成之后如下图 添加标识符 接下来对于 STM32F40 系列的工程,还需要添加一个全局宏定义标识符。 添加方法是点击魔术棒之后,进入 C/C++选项卡,然后在 Define 输入框连输入: STM32F40_41xxx,USE_STDPERIPH_DRIVER 注意这里是两个标识符 STM32F40_41xxx 和 USE_STDPERIPH_DRIVER,他们之间是用逗号隔开的。 如下图: 编译 接下来我们要编译工程,在编译之前我们首先要选择编译中间文件编译后存放目录。 方法是点击魔术棒 ,然后选择Output选项下面的 Select folder for objects… 然后选择目录为我们之前新建的 OBJ 目录。 同时将下方的三个选项框都勾上,如下图: 这里说明一下勾选的意义。 Create HEX File 选项选上是要求编译之后生成 HEX 文件。 Browse Information 选项选上是方便我们查看工程中的一些函数变量定义。 然后main.c更换成一下的代码 #include "stm32f4xx.h" void Delay(__IO uint32_t nCount); void Delay(__IO uint32_t nCount) { while(nCount--){} } int main(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOF, &GPIO_InitStructure); while(1){ GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10); Delay(0x7FFFFF); GPIO_ResetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10); Delay(0x7FFFFF); } } 同时还需要将 USER 分组下面的 stm32f4xx_it.c 文件内容清空。 或者删掉其中的 32 行对main.h头文件的引入以及 144 行 SysTick_Handler 函数内容。 然后点击编译按钮Build(F7)编译工程,可以看到工程编译通过没有任何错误和警告。 恭喜,到这里,一个基于固件库 V1.4 的工程模板就建立完成,同时在工程的 OBJ 目录下面生成了对应的 hex 文件。 系统时钟设置 还有个非常重要的关键点,就是系统时钟的配置,有关系统时钟,文档中4.3节有详细的说明 这里我们要修改 System_stm32f4xx.c 文件,把 PLL 第一级分频系数 M 修改为 8,这样达到主时钟频率为 168MHz。 在316行处修改如下: /************************* PLL Parameters *************************************/ #if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx) /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ #define PLL_M 8 #else /* STM32F411xE */ #if defined (USE_HSE_BYPASS) #define PLL_M 8 #else /* STM32F411xE */ #define PLL_M 16 #endif /* USE_HSE_BYPASS */ #endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx */ PLL_M 这里将25修改为 8,这样我们的系统时钟就是 168MHz。详细原因我们后面 4.3 小节会讲解。 同时,我们要在 stm32f4xx.h 里面修改外部时钟 HSE_VALUE 值为 8MHz,因为我们的外部高速时钟用的晶振为 8M. 具体修改方法如下:在大概123行处,将((uint32_t)25000000)修改成((uint32_t)8000000) #if !defined (HSE_VALUE) #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ 大家一定要在对应的配置文件中,找到相应的代码行,修改为符合我们硬件的值即可。 SYSTEM 实际上经过前面的步骤,我们的工程模板已经建立完成。 但是在 正点原子 提供的实验代码中,每个实验都有一个 SYSTEM 文件夹 下面有 3 个子目录分别为 sys,usart,delay,存放的是每个实验都要使用到的共用代码。 该代码是由 ALIENTEK 编写,该代码的原理在在文档第五章有详细的讲解 我们这里只是引入到工程中,方便后面的实验建立工程。 在原子哥提供的资料中 实验0 Template工程模板目录下的SYSTEM文件夹,将SYSTEM文件夹移动到我们的工程下 然后在MDK5中,添加到我们的工程中。 根据前边的教程,完成配置后如下图: 接下来我们将对应的三个目录(sys,usart,delay)加入到 PATH 中去,因为每个目录下面都有相应的.h 头文件。 这请参考前边的步骤即可,加入后的截图如下图 最后点击 OK。这样我们的工程模板就彻底完成了。 最后修改一下main.c函数,测试一下 #include "stm32f4xx.h" #include "usart.h" #include "delay.h" int main(void) { u32 t=0; uart_init(115200); delay_init(84); while(1){ printf("t:%drn",t); delay_ms(500); t++; } } 编译成功,全部完成!!! 总结 STM32工程的创建太麻烦了,不过这是学习的必要一环,等之后的项目就是在此基础上的增加了 =w= |
|
|
|
只有小组成员才能发言,加入小组>>
3320 浏览 9 评论
2998 浏览 16 评论
3496 浏览 1 评论
9066 浏览 16 评论
4089 浏览 18 评论
1187浏览 3评论
612浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
602浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2339浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1899浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 17:19 , Processed in 1.349847 second(s), Total 82, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号