前言:学习STM32最好还是有一定的51单片机基础,尤其是掌握了C51中关于寄存器的操作、指针变量的应用,以及学习并能够建立自己的头文件和函数库了,那在STM32学习中上手更快一些,尤其是刚开始关于位绑定、寄存器以及库函数的理解。
我也是初学STM32,直接就使用了新版的 MDK-RAM5.25,我感觉初学使用MDK新版本也好,很多功能和操作比老版更合理,使用也更方便,虽然和很多教程不配套,但经过查找相关资料能够自己解决相关问题,也是一个学习的过程。这个课程是我在学习中做的笔记,虽然大部分是摘抄自其他老师的,但毕竟自己也是查找了很多网络资料,其中也加入了自己的理解,并对学习中遇到的问题进行总结,只希望给和我一样的初学者一个帮助。
我学习使用的是STM32的固件库(Keil公司提供的标准库函数)编程,需要下载安装STM32芯片对应的数据包Pack,也就是官方提供的库函数包,当然如果你学习的教程提供有函数库,也可以不用下载。
现在官方已经从2012年开始不再提供标准函数库的更新了,转而推出使用HAL库,我在期间也上手使用过HAL库,感觉像很久以前的操作系统从DOS向Windows系统转换一样(不知道我这个形容对不对),函数库环境的搭建只用点点鼠标就OK了,但是在使用RAM仿真调试没调试通过,再说我也比较喜欢底层寄存器的学习,所以准备先大概学习一遍再转用HAL库操作。
方法有两种:
打开www.keil.com/dd2/,找到点击“STMicroelectronics”,找到对应芯片的前缀,并一直找到对应芯片的型号,点击型号,跳转页面点击下载“Download”;
点击对应的芯片信号后,跳转到下载页面,点击Download下载;
打开MDK5,点击pack installer按钮(首次会弹出一个欢迎的界面,点击OK);点击“文件File”—“导入Import”;
找到刚才下载的Pack文件进行导入;
点击 “PackInstaller”按钮,打开“PackInstaller”
界面;
然后在pack installer界面的search栏,搜索你的芯片型号,以stm32f103c8为例,device栏里面会显示stm32f103c8的信息;用鼠标左键单击选中,然后在pack installer的pack栏里面会出现对应的安装包(KEIL:STM32F1xx_DFP),直接点击旁边的install按钮,就可安装该芯片系列的固件库;安装完后,直接关掉该界面,然后进入MDK界面,若出现有更新的提示,直接点击确定。
点击project--new u_vision project新建工程,选择存放工程的位置(文件夹),输入工程名,出现选择芯片型号的界面,选择使用的芯片型号(或在search栏里面直接输入你的芯片型号,在下方就会自动显示出来,左键单击选中,然后点击OK);
注意:如果没有找到自己的STM32芯片型号,参考1.1节下载安装芯片Pack;
然后会弹出manage run -time environment的运行环境界面,必须选择的有CMSIS下的core和device下的startup。其他则需要根据你需要的使用的外设;
知识点:在工程建立后,尤其是在使用库函数进行编程中,随时根据需要(如需要使用GPIO、USART等外设),点击在运行环境ManageRun-TimeEnvironment界面对相应的软件组件SoftwareComponent(也就是库函数)进行添加;
知识点:在运行环境ManageRun-TimeEnvironment界面对相应的软件组件SoftwareComponent(也就是库函数)进行配置添加时,一些组件Component需要其他组件的一起添加。在这时,如果配置正确,打钩的地方是绿色;未正确配置的话,打钩的地方是黄色。此时下方会出现还需要选中那几个配置的提示信息,按照提示选择即可(或直接点击下方提示部分进行跳转);
例如:选择外设GPIO,开始显示黄色并在下方提示你还需要选择framework和RCC,按照提示选择后,所有打钩的地方都变成绿色,表示已正确配置。
到了MDK5界面,在左边工程目录下,已经添加了一些刚才配置的文件,包括启动文件以及一些外设驱动文件,此时打开工程目录文件夹,里面自动建立了几个文件夹;
MDK5在使用和操作上已经很贴近用户需求,所以使用MDK5默认的文件夹和文件设置就可以了,可以不需要再添加;
在左侧工程下,右键点击SourceGroup1,选择添加文件到这个组;
选择“C File”,输入文件名,点击ADD;
点击“FileExtensions,BookAndEnvironment”进入ManageProjectItems(管理工程项目)页面,
在这里可以对工程对象、组和文件进行改名、增加或删除等操作;
【1】是我们选择的的CPU;
【2】是该 CPU 的一些描述;
【1】设备晶振频率,用于模拟仿真时使用。
【2】指定 ARM 或者 Thumb 模式进行代码生成。
【3】为优化代码创建一个链接反馈文件/使用 MicroLib 库,可将运行时库代
码大大降低。
【4】片外 ROM 设置,最多可支持 3 块 ROM(Flash),在 Start 一栏输入起始
地址,Size 一栏输入大小。
【5】片内 ROM 设置,设置方法同片外 ROM,只是程序的存储区在芯片内集
成。
【6】片外 RAM 设置。基本方法同片外 ROM。
定义预处理符号,和头文件路径的设置,是为了让编译器能找到自己程序中包含的库文件,其实这和我们在程序中添加#include<>的原理是一样的。只不过是 KEIL 给我们一个更好的处理。在CubeMX (HAL库)软件生成的工程中,我们可以看到 C/C++选项已经配置完毕。节省了很多时间。
Asm 和 Linker 选项卡,Asm 是汇编选项卡,因为我们选用的是 C 语言来进行编程,所以不必理会。Linker 是连接选项卡,对于不是特别大或者特殊的程序,选项卡的内容默认即可,编译器会自动按照你的设置生成连接选项。
这里配置软件或硬件仿真,点击setting进入硬件仿真设置页面,需要在FlashDownload页面对少些程序的功能选项。CubeMX软件生成的配置是没有勾选 Reset and Run 的,在这里,勾选它是为了更方便显示例程的现象。
操作到这里,整个工程已经可以开始编写程序,程序编写完成后,需要点击编译或重新编译按键,下方会显示编译的过程相关信息:
其中包含以下内容:
●Using Compiler…使用编译器版本(Target页面Code Generation设置),及所在文件夹路径;
●BuildTarget…编译对象(工程名称);
●compiling…编译文件列表
…………
●linking…链接
●ProgramSize…程序长度:程序代码Code=?;程序定义的常量RO-data=?;已初始化的全局变量RW-data=?;未初始化及初始化为0的全局变量ZI-data=?;其中:
RO Size=Code+RO-data(程序占用Flash空间大小);
RW Size=RW-data+ZI-data(程序运行时占用的RAM空间大小);
ROM Size=Code+RO-data+RW-data(烧写时程序占用Flash大小);
●FromELF…创建hex文件(Creating HEX File);
●生成的axf文件,?个错误Error,?个警告Warning;
●编译用时
如果编译没有错误(Error必须解决,Warning可以忽略),输出编译文件后,下一步就是需要查看程序运行情况(或效果)。
这时可以使用软件(模拟器)直接进行仿真或调试,也可以下载到STM32芯片中进行,不管哪种方式,都必须提前对工程对象进行配置。
为了方便不同阶段或不同环境下使用软件(模拟器)仿真Debug,或者将程序下载到硬件(RAM存储器)中进行Debug仿真,又或者最后完全下载到硬件(Flash)存储器中进行纯硬件的使用,可以建立不同的工程对象进行分别配置,方便不同情况下的使用。
点击按钮进入工程项目管理器ManageProjectitems,在工程对象ProjectTargets下新增两个Targets,分别为“RAM”、“Flash”。我们在后面分别将默认的工程对象“Target 1”配置为软件(模拟器)仿真环境;“RAM”配置为下载到STM32硬件RAM区进行仿真调试;“Flash”配置为下载到STM32硬件Flash区进行纯硬件的操作。
软件仿真可以在MDK中一边编写程序,一边进行仿真调试,由于是在软件仿真情况下的调试,不需要对一些涉及硬件相关环境进行配置。例如在操作GPIO端口时,可以直接编写对GPIO端口的操作并在Debug中仿真,而不需要对其他外设进行编写设置程序(如在硬件上运行时必须对时钟)
选择工程对象“Target 1”,点击打开对象选项Options for Target窗口:
分别对不同的页面进行设置(下面所指的默认设置指当前版本号MDK525的情况,为了比对其他版本的不同,也将默认页面设置截图出来):
●设备Device页面:选择对应的STM32芯片型号;
●对象Target页面:其中根据Device页面选择的芯片型号,自动配置只读存储器Flase的起始地址(0x08000000)和大小(0x10000=64KB)和可读写存储器RAM的起始地址(0x20000000)和大小(0x5000=20KB);
●输出Output页面:勾选生成HEX文件,如果需要设置输出文件的位置,可以点击“选择目标文件夹SelectFolderObject”按钮;
●类表Listing页面:使用默认;
●用户User页面:使用默认;
●C/C++页面:使用默认;
●Asm页面:使用使用默认;
●链接Linker页面:使用使用默认;
●调试Debug页面:勾选“使用模拟器UseSimulator”
下方的CPU和对话框Dialog参数栏设置:
CPUDLL=“SARMCM3.DLL”,Parameter=“-MPU -REMAP”;DialogDll=“DARMSTM.DLL”,Parameter=“-pSTM32F103C6”(后面跟使用的芯片型号);
这样在Debug软件仿真时,可以通过点击“外围设备Perioherals”,下选择不同的端口,查看端口位的变化;
●公共Utilities页面:使用使用默认;
●最后需要配置MDK的自动索引功能(MDK5以上这里已经是默认设置不需要进行设置):点击MDK菜单Edit下的configuration
STM32有两个存储空间:
Flash:片上Flash区(相当于计算机的硬盘),只能反复烧录约1000次,起始地址为0x08000000;
RAM区:片上RAM区(相当于计算机的内存),读取速度更快,但下载到RAM区数据掉电会消失,起始地址0x20000000;
烧写程序是需要烧写镜像文件(bin或hex文件)到Flash中,其中包含三部分(见前面的编译信息介绍):Code、RO-data、RW-data,因ZI-data都是0不需要烧录到Flash中;STM32上上电启动后,CPU会读取RW-data到RAM中运行,但不会读取Code。
在MDK5的安装目录下搜索查找RAM.INI文件,改掉只读属性,拷贝到工程文件目录中,并双击打开(内容只有截图中的几行),修改 “LOAD %L”中的“%L”为工程编译后的生成的axf文件名(默认objects文件夹或者“Output”中设置的文件夹,一般为“工程名称.axf”),保存退出;
首先将下载器同计算机连接,安装相应的驱动程序;
选择工程对象“RAM”,点击打开对象选项Options for Target窗口:
分别对不同的页面进行设置:
●设备Device页面:同上设置;
●对象Target页面:设置Xtal=8.0MHz;这里因使用RAM存储器,则要将RAM分成两个区域,分别代替默认设置中的Flash和RAM存储器存储程序代码和数据;
在左下方“只读Read/Only”区域的“片上on-chip”-“IROM 1”设置是启动区域(原Flash区),设置Start=0x20000000(RAM的起始地址),Size设置至少RAM大小的一半或更多,存放的是程序代码和常量数据(Code+RO-data),相对占用RAM较大空间;
在右下方“可读写Read/Write”区域的“片上on-chip”-“IRAM 1”, 设置Start为IROM1占用后的起始地址,Size为RAM中剩余的空间,存放的是RW-data+ZI-data数据,相对占用RAM较小空间;
●输出Output页面:同上设置;
●类表Listing页面:使用默认;
●用户User页面:使用默认;
●C/C++页面:这里需要使用宏定义VECT_TAB_SRAM。
这个宏定义是使向量表指向RAM(系统默认ROM),最主要的目的就是使中断向量表指向RAM,不然在RAM仿真调试时中断不能被调用。如果不在这里配置,也可以打开systen_stm32f10x.c文件,找到/* #define VECT_TAB_SRAM */将前后的注释去掉即可;
●Asm页面:使用默认;
●链接Linker页面:使用默认;
●调试Debug页面:勾选右侧的“Use使用”,并选取对应下载器的类型;点击“InitializationFile”下右侧的“…”,添加之前设置的RAM.INI文件;最后点击“Setting”;
如果下载(烧录)器已经连接PC机并安装好驱动,则在“CortexJLink/JtaraceTargetDeviceSetup”窗口的“Debug”页面中自动反显设备信息,这里只需要选择“接口Port”类型即可,确定退出;
●公共Utilities页面:将“Update Target before Debugging在调试前更新数据”的勾选去掉,否则在点击Debug时会出现“”“Error:FlashDownload failed-‘Cortex-M3’”的错误提示;网上很多资料都显示这里需要进行其他设置,其实不需要进行设置;
但是在“CortexJLink/JtaraceTargetDeviceSetup”窗口的“FlashDownload”页面(点击“Settings”进入)中的关于“算法随机存储器RAM for Algorithm”和“程序算法ProgrammingAlgorithm”中,这里的MDK5版本是自动设置的;如果需要手动设置,则“算法随机存储器RAM for Algorithm”应该时设置Start=RAM的起始地址(既0x20000000),Size=小于RAM的总大小的值即可;而“程序算法ProgrammingAlgorithm”中的器件文件是存放在“C:\Keil_v5\ARM\Flash”中的,如果没有自行添加,算法芯片型号选择相近系列、容量大于使用芯片的也是可以的,在“程序算法ProgrammingAlgorithm”下方Start和Size修改为正确的值(不改也无影响);
链接下载(烧录)器到PC和STM32系统板并上电,“SelectTarget选择对象”窗口中选择“RAM”,编译程序无误后,直接点击Debug,因为在“Options for Target”中“Debug”页面勾选了“启动时加载应用程序Load Application at Startup”选项,所以一点击进入Debug,系统同时将程序镜像文件写入到RAM中,会看到程序已经开始运行(硬件上同样已经显示结果);
外设信息显示(“Peripherals外设”下选择需要查看的外设)窗口会因为“Debug”页面的设置不同(如下图)
而改变(不要试图改成软件仿真相同的设置,不能使用的)
确保下载器同PC机机STM32系统板相连接,并已经安装相应的驱动程序;
选择工程对象“Flash”,点击打开对象选项Options for Target窗口:
分别对不同的页面进行设置:
●设备Device页面:同上设置;
●对象Target页面:同上设置;
●输出Output页面:同上设置;
●类表Listing页面:同上使用默认;
●用户User页面:同上使用默认;
●C/C++页面:同上使用默认;
●Asm页面:同上使用默认;
●链接Linker页面:使用默认;
●调试Debug页面:勾选右侧的“Use使用”,并选取对应下载器的类型;点击“InitializationFile”下右侧的“…”,添加之前设置的工程目录下的JLinkSeettings.INI文件;最后点击“Setting”;
如果下载(烧录)器已经连接PC机并安装好驱动,则在“CortexJLink/JtaraceTargetDeviceSetup”窗口的“Debug”页面中自动反显设备信息,这里只需要选择“接口Port”类型即可,确定退出;
●公共Utilities页面:将“Update Target before Debugging在调试前更新数据”的勾选去掉;网上很多资料都显示这里需要进行其他设置,其实不需要进行设置;
但是在“CortexJLink/JtaraceTargetDeviceSetup”窗口的“FlashDownload”页面(点击“Settings”进入)中的关于“算法随机存储器RAM for Algorithm”和“程序算法ProgrammingAlgorithm”中,这里的MDK5版本是自动设置的;如果需要手动设置,则“算法随机存储器RAM for Algorithm”应该时设置Start=RAM的起始地址(既0x20000000),Size=小于RAM的总大小的值即可;而“程序算法ProgrammingAlgorithm”中的器件文件是存放在“C:\Keil_v5\ARM\Flash”中的,如果没有自行添加,算法芯片型号选择相近系列、容量大于使用芯片的也是可以的,在“程序算法ProgrammingAlgorithm”下方Start和Size修改为正确的值(不改也无影响);
连接下载(烧录)器到PC和STM32系统板并上电,“SelectTarget选择对象”窗口中选择“Flash”,编译程序无误后,点击进行下载:
下载无误完成后,系统板重新上电或复位后可以看到程序的运行;或者在下面选项进行勾选,下载完成后自动运行;
其中分为4个部分:
第3章 问题汇总
3.1 问题1“no 'read' permission”和“no 'write' permission”
仿真调试全速运行时出现:*** error 65: access violation at 0x40021000 : no 'read' permission,网络上查找解决方案同时对比ST提供的3.5版本固件库中的工程模板,发现是工程配置选项中的debug选项卡的dialog dll和对应的parameter配置出了问题。选中MCU后默认的配置如下图:
可以看到dialog dll默认配置为DCM.DLL,而parameter默认配置为-pCM3,该种配置无法进行正常的仿真调试。正确配置应该为dialog dll:DARMSTM.dll parameter:-pSTM32F103C8;这两个参数是根据你使用的MCU不同而不同的,例如本工程使用的MCU为STM系列,那么在dialog DLL选项中就应该使用DARMSTM.dll,名字中的STM就是指厂商,参数则是具体的MCU芯片型号,本项目使用STM32F103C8T6,因此选择为STM32F103C8,如下图所示:
为何使用的是STM32F103C8T6,参数却只能是STM32F103C8,这个原因是因为根据ST公司的MCU命名规则,到C8这个位置就已经完全规定了仿真所需要的所有参数,包括cpu频率,ram容量,flash容量,外设资源等内容。型号中后边的部分都已经和仿真无关了。
3.2 Flash下载时出现“SWD/JTAG Communication Failure”弹窗
在Flash下载时,弹出弹窗名称:CMSIS-DAP-Cortex-M Error,内容“SWD/JTAG Communication Failure”的提示,确定后出现“Error:FlashDownloadFailed-TargetDLLhasBeenCancelled”弹窗,点击OptionForTarget-Debug-Setting,选择的Poet=SW右侧出现错误提示,首先确认Port选择正确无误,点击下方Connect选项,选择UnderReset确定,重新进入错误提示消失,重新下载成功;
3.3 RAM仿真调试“Error:Flash Download Failed-‘Cortex0M3’”错误
应该去掉Utilities下的“UpdateTargetBeforeDebugging”勾选;