《STM32编程.pdf》由会员分享,可在线阅读,更多相关《STM32编程.pdf(22页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、实用标准文案一、条件的准备一、条件的准备我的习惯,第一步是先搭建一个学习的平台。原来学51,PIC,AVR 时,都是想方设法自己做些工具,实验板之类,现在人懒了,直接购买成品了。硬件电路板:火牛板软件:有 keil 和 iar 可供选择。网上的口水仗不少,我选 keil,理由很简单,这个我熟。目前要学的知识中,软、硬件我都不熟,所以找一个我有点熟的东西就很重要。在我相当熟练之前,肯定不会用到IAR,如果真的有一天不得不用IAR,相信学起来也很容易,因为这个时候硬件部分我肯定很熟了,再加上有 keil 的基础,所以应该很容易学会了。调试工具:JLINK V8。这个不多说了,价格便宜又好用,就是它
2、了。二、热身二、热身细细端详,做工精良,尤其那上面的3.2 吋屏,越看越喜欢。接下来就是一阵折腾了,装 JLINK 软件,给板子通电,先试试JLINK 能不能与电脑和板子通信上了。真顺,一点问题也没有。于是准备将附带的程序一个一个地写进去试一试。一检查,大部分例子的HEX文件并没有给出,这要下一步自己生成,但是几个大工程的例子都有HEX 文件,如 MP3,如 UCCGI 测试等,写完以后观察程序运行的效果。因为之前也做过彩屏的东西,知道那玩艺代码量很大,要流畅地显示并不容,当时是用AVR 做的,在 1.8 吋屏上显示一幅画要有一段时间。现在看起来,用STM32 做的驱动显示出来的画面还是很快的
3、,不过这里显示的大部分是自画图,并没有完整地显示一整幅的照片,所以到底快到什么程度还不好说,看来不久以后这可以作为一个学习点的。精彩文档实用标准文案一个晚上过去了,下一篇就是要开始keil 软件的学习了。三、开始编程三、开始编程硬件调通后,就要开始编程了。编程的方法有两种,一种是用st 提供的库,另一种是从最底层开始编程,网上关于使用哪种方法编程的讨论很多,据说用库的效率要低一些。但是用库编程非常方便,所以我还是从库开始啦。库是 ST 提供的,怎么说也不会差到哪里,再说了,用32 位 ARM 的话,开发的观念也要随之改变一点了。说说我怎么学的吧。找个例子,如 GPIO,可以看到其结构如下:SO
4、URCE(文件夹)精彩文档实用标准文案-APP(文件夹)-CMSIS(文件夹)-STM32F10 x_StdPeriph_Driver(文件夹)Lis(文件夹)OBJ(文件夹)其中 SOURCE 中保存的是应用程序,其中又有好多子文件夹,而CMSIS 文件夹中和STM32F10 x_StdPeriph_Driver文件夹中是 ST 提供的库,这样,如果要做新的工程只要将这个文件夹整个复制过来就行,其中APP 中保存自己的代码。因为我们用 51 单片机时一般比较简单,有时就一个文件,所以通常不设置专门的输出文件夹,而这里做开发,通常会有很多个文件加入一个工程中,编译过程中会产生很多中间文件,因此
5、设置专门的文件夹LIS 和 OBJ 用来保存中间文件。下面就将设置简单描述一下。将复到过来的 GPIO 根目录下的所有文件删除,因为我们要学着自己建立工程。用菜单 Project-New uVision Porject.。.建立新的工程,选择目标器件为STM32103VC,这个过程与建立 51 单片机的工程没有什么区别,这里就偷点懒,不上图了。接下来看一看怎么设置。精彩文档实用标准文案点那个品字形,打开对话框这里就给个图了,相信有一定操作基础的人应该会用。顺便提一下,原来用 VC 或者 IAR时总觉得它们的一个功能:就是建立一个是Debug 组和 Release 组,这个功能挺好的,从这个图可
6、在 Keil 里也是一样可以建的。将刚才那个文件夹图中CMSIS 中的文件加入 CMSIS 组,一共 3 个,其中SourceCMSISCoreCM3有两个 C 语言源程序文件全部加入,另外还有一个在SourceCMSISCoreCM3startuparm文件夹中,这个文件夹中有 4 个.s 文件,我们选择其中的 startup_stm32f10 x_hd.s文件。这是根据项目所用CPU 来选择的,我们用的 CPU 是 103VC 的,属于高密度的芯片,所以选这个。精彩文档实用标准文案至于 LIB 中的文件,就在这儿:SourceSTM32F10 x_StdPeriph_Driversrc啦。
7、这里有很多个文件,把什么文件加进去呢?怕麻烦的话,把所有文件全部加进去,这并不会增加编译后的代码量,但会增加很多的编译时间。接下来设定目标输出文件夹。上面这个图怎么出来的就不说啦,单击“Select Foler forObjects。”,在弹出来的对话框中选择OBJ 文件夹。同样方法,选择 List 文件的输出文件夹。设置好后,如果直接编译是不行的,会出错。还需要提供头文件所在位置。单击c/C+标签页。精彩文档实用标准文案第一次进入时 Include Paths 文本框中是空白的,点击其后的按钮打开对话框,增加相应的路径这样路径就设好了。单击OK,回到上一界面,然后再单击OK,退出设置,即可编
8、译、链接。下一会要试一试新的3.12 版的库效果如何了。精彩文档实用标准文案升级库光盘中所带的例子是3.10 的,另外还有一个 3.12 的,我 试着将 3.12 的库替代原来的库,还真有问题,下面就简述问题及解决方法。(1)将库文件解压库文件名是:stm32f10 x_stdperiph_lib.zip,解压后放在任意一个文件夹中。(2)由于原作者做了很好的规划,每一个项目中都分成三个文件夹,并且在source文件夹中又做了 3 个文件夹,其中 APP 文件夹是放自己写的文件的,其他的两个是从库中复制过来的,因此,想当然地把3.1.2 版本中相同的两个文件夹:CMSIS 和 STM32F10
9、 x_StdPeriph_Driver直接复制过来,以为一切 OK,结果一编译,出来一堆错误。其中有错误:SourceAppmain.c(7):error:#20:identifier“GPIO_InitTypeDef”isundefined。.。还有大量的警告:SourceSTM32F10 x_StdPeriph_Driversrcstm32f10 x_flash.c(130):warning:#223-D:function“assert_param”declared implicitly精彩文档实用标准文案看了看,在 APP 文件夹中还有一些不属于自己的东西:stm32f10 x_conf
10、.h,stm32f10 x_it.h,stm32f10 x_it.c,打开一看,果然是3.10 版本的,没说的,换。,找到STM32F10 x_StdPeriph_Lib_V3.1.2ProjectTemplate文件夹,用里面的同样的文件替换掉这几个文件,这回应该万事大吉了吧。再一看,依然如故,没办法了,只好细细研究了。通过观察,发现原来可以编译通过的工程,在 main.c 下面挂满了.h 文件,而这个通不过的,则少得很。这是编译能通过的工程这是编译通不过的工程精彩文档实用标准文案显然,有些文件没有被包含进来。一点一点跟踪,发现大部分的头文件都包含在stm32f10 x_conf.h 中,而
11、这个文件又出现在stm32f10 x.h 中,其中有这样的一行:#ifdef USE_STDPERIPH_DRIVER#include“stm32f10 x_conf.h”#endif看来,是这个 USE_STDPERIPH_DRIVER 没有被定义啊,于是,人为地去掉条件:/#ifdef USE_STDPERIPH_DRIVER#include“stm32f10 x_conf.h”/#endif再次编译,果然就 OK 了。可是,可是,也不能就这么去掉啊,怎么办呢?万能的网啊,一搜果然就有了。到设置 C/C+页面在那个 define 中加入“USE_STDPERIPH_DRIVER,STM32
12、F10X_HD”精彩文档实用标准文案当然,去掉条件编译前面的注释,回到原样。再次编译,一切顺利。可是,原来的工程例子也没有加这个啊,怎么回事呢?再次打开原来的例子,找到 stm32f10 x.h,可以看到有这么一行:而新的 stm32f10 x.h 中则是这样的:原来那个 3.1.0 版的 stm32f10 x.h 被人为地修改了一下,所以,不在define 中定义也不要紧,而新升级的 3.1.2 则不行了。至此,简单的升级搞定。内存学习ARM 中的 RO、RW 和 ZI DATA一直以来对于 ARM 体系中所描述的 RO,RW 和 ZI 数据存在似是而非的理解,这段时间对其仔细了解了一番,发
13、现了一些规律,理解了一些以前书本上有的但是不理解的东西,精彩文档实用标准文案我想应该有不少人也有和我同样的困惑,因此将我的一些关于 RO,RW 和 ZI 的理解写出来,希望能对大家有所帮助。要了解 RO,RW 和 ZI 需要首先了解以下知识:ARM 程序的组成此处所说的“ARM 程序”是指在 ARM 系统中正在执行的程序,而非保存在ROM 中的 bin 映像(image)文件,这一点清注意区别。一个 ARM 程序包含 3 部分:RO,RW 和 ZIRO 是程序中的指令和常量RW 是程序中的已初始化变量ZI 是程序中的未初始化的变量由以上 3 点说明可以理解为:RO 就是 readonly,RW
14、 就是 read/write,ZI 就是 zeroARM 映像文件的组成精彩文档实用标准文案所谓 ARM 映像文件就是指烧录到 ROM 中的 bin 文件,也称为 image 文件。以下用Image 文件来称呼它。Image 文件包含了 RO 和 RW 数据。之所以 Image 文件不包含 ZI 数据,是因为 ZI 数据都是 0,没必要包含,只要程序运行之前将 ZI 数据所在的区域一律清零即可。包含进去反而浪费存储空间。Q:为什么 Image 中必须包含 RO 和 RW?A:因为RO 中的指令和常量以及RW 中初始化过的变量是不能像ZI 那样“无中生有”的。ARM 程序的执行过程从以上两点可以
15、知道,烧录到ROM 中的 image 文件与实际运行时的 ARM 程序之间并不是完全一样的。因此就有必要了解ARM 程序是如何从 ROM 中的 image 到达实际运行状态的。实际上,RO 中的指令至少应该有这样的功能:1.将 RW 从 ROM 中搬到 RAM 中,因为 RW 是变量,变量不能存在 ROM 中。2.将 ZI 所在的 RAM 区域全部清零,因为 ZI 区域并不在 Image 中,所以需要程序根据编译器给出的 ZI 地址及大小来将相应得RAM 区域清零。ZI 中也是变量,同理:变量不能存在 ROM 中精彩文档实用标准文案在程序运行的最初阶段,RO 中的指令完成了这两项工作后C 程序
16、才能正常访问变量。否则只能运行不含变量的代码。说了上面的可能还是有些迷糊,RO,RW 和 ZI 到底是什么,下面我将给出几个例子,最直观的来说明 RO,RW,ZI 在 C 中是什么意思。1;RO看下面两段程序,他们之间差了一条语句,这条语句就是声明一个字符常量。因此按照我们之前说的,他们之间应该只会在RO 数据中相差一个字节(字符常量为1 字节)。Prog1:#include stdio.hvoid main(void);Prog2:#include stdio.hconst char a=5;精彩文档实用标准文案void main(void);Prog1 编译出来后的信息如下:=Code R
17、O Data RW Data ZI Data Debug948 60 0 96 0 Grand Totals=Total RO Size(Code+RO Data)1008(0.98kB)Total RW Size(RW Data+ZI Data)96(0.09kB)Total ROM Size(Code+RO Data+RW Data)1008(0.98kB)精彩文档实用标准文案=Prog2 编译出来后的信息如下:=Code RO Data RW Data ZI Data Debug948 61 0 96 0 Grand Totals=Total RO Size(Code+RO Data)1
18、009(0.99kB)Total RW Size(RW Data+ZI Data)96(0.09kB)Total ROM Size(Code+RO Data+RW Data)1009(0.99kB)=精彩文档实用标准文案以上两个程序编译出来后的信息可以看出:Prog1和Prog2的RO包含了Code和RO Data两类数据。他们的唯一区别就是Prog2的 RO Data 比 Prog1 多了 1 个字节。这正和之前的推测一致。如果增加的是一条指令而不是一个常量,则结果应该是Code 数据大小有差别。2;RW同样再看两个程序,他们之间只相差一个“已初始化的变量”,按照之前所讲的,已初始化的变量应
19、该是算在 RW 中的,所以两个程序之间应该是RW 大小有区别。Prog3:#include stdio.hvoid main(void);Prog4:#include stdio.hchar a=5;精彩文档实用标准文案void main(void);Prog3 编译出来后的信息如下:=Code RO Data RW Data ZI Data Debug948 60 0 96 0 Grand Totals=Total RO Size(Code+RO Data)1008(0.98kB)Total RW Size(RW Data+ZI Data)96(0.09kB)Total ROM Size(C
20、ode+RO Data+RW Data)1008(0.98kB)精彩文档实用标准文案=Prog4 编译出来后的信息如下:=Code RO Data RW Data ZI Data Debug948 60 1 96 0 Grand Totals=Total RO Size(Code+RO Data)1008(0.98kB)Total RW Size(RW Data+ZI Data)97(0.09kB)Total ROM Size(Code+RO Data+RW Data)1009(0.99kB)=精彩文档实用标准文案可以看出 Prog3 和 Prog4 之间确实只有 RW Data 之间相差了
21、1 个字节,这个字节正是被初始化过的一个字符型变量“a”所引起的。3;ZI再看两个程序,他们之间的差别是一个未初始化的变量“a”,从之前的了解中,应该可以推测,这两个程序之间应该只有ZI 大小有差别。Prog3:#include stdio.hvoid main(void);Prog4:#include stdio.hchar a;void main(void)精彩文档实用标准文案;Prog3 编译出来后的信息如下:=Code RO Data RW Data ZI Data Debug948 60 0 96 0 Grand Totals=Total RO Size(Code+RO Data)1
22、008(0.98kB)Total RW Size(RW Data+ZI Data)96(0.09kB)Total ROM Size(Code+RO Data+RW Data)1008(0.98kB)=Prog4 编译出来后的信息如下:精彩文档实用标准文案=Code RO Data RW Data ZI Data Debug948 60 0 97 0 Grand Totals=Total RO Size(Code+RO Data)1008(0.98kB)Total RW Size(RW Data+ZI Data)97(0.09kB)Total ROM Size(Code+RO Data+RW D
23、ata)1008(0.98kB)编译的结果完全符合推测,只有ZI 数据相差了 1 个字节。这个字节正是未初始化的一个字符型变量“a”所引起的。注意:如果一个变量被初始化为0,则该变量的处理方法与未初始化华变量一样放在ZI 区域。即:ARM C 程序中,所有的未初始化变量都会被自动初始化为0。总结:精彩文档实用标准文案1;C 中的指令以及常量被编译后是RO 类型数据。2;C 中的未被初始化或初始化为0 的变量编译后是 ZI 类型数据。3;C 中的已被初始化成非0 值的变量编译后市RW 类型数据。附:程序的编译命令(假定C 程序名为 tst.c):armcc-c-o tst.o tst.carmlink-noremove-elf-nodebug-info totals-info sizes-map-list aa.map-otst.elf tst.o编译后的信息就在aa.map 文件中。ROM 主要指:NAND Flash,Nor FlashRAM 主要指:PSRAM,SDRAM,SRAM,DDRAM精彩文档