目录
- 前言
- 下载安装相关软件
-
- 一.Keil的安装
- 二.IAR的安装
- 开发环境
- 四、注意事项
- Keil基本使用
-
- 一、新建工程模板
-
- 基于固件库(先复制文件夹,再添加文件)
- 基于寄存器
- 基于HAL库
- 二、下载调试
- 三、使用技巧
- IAR基本使用
-
- 一、新建工程模板
- 二、编译Make和调试
- 三、环境调试
- 四、快捷键设置
- 单片机开发
-
- 一、C语言基础
- 二、常见错误警告解决方案
- 三、工程目录下简介
- 四、编辑技巧
- 五、常用函数代码
- 附录
-
- 1.STM32f407实验IAR版本
前言
介绍一下Keil和IAR个人将逐步完善单片机开发软件的基本使用,以及单片机学习和开发过程中的一些总结
下载安装相关软件
一.Keil的安装
1.Keil 下载链接523版 2.选择安装路径,其余默认情况可参考百度 汉化会导致一些功能设置不显示 3.官网基于不同芯片加载包的不同http://www.keil.com/dd2/pack下载 Keil.STM32F4xx_DFP.1.0.8(双击打开安装stm32)
二.IAR的安装
1.IAR 7.1下载链接
2.点击install安装其余参考百度
开发环境
- CH340串口驱动安装 安装方法:直接点击安装(见安装失败)readme),提示预安装成功,安装成功 功能:安装串口驱动器后,计算机可以识别串口
- 串口程序下载工具mcuisp(FlyMcu) 功能:可以.hex格式程序下载到板子里
- 串口调试助手XCOM 功能:数据可以通过串口收发
- STLINK驱动安装 功能:可在windows下配合MDK下载和调试程序。
四、注意事项
- STM32的ISP下载时,只能使用串口1,即相应的串口接收引脚PA9,PA10.不能使用其他串口。 (如串口2:PA2,PA3)用来ISP下载。
- 开发板供电时应注意以下事项 (1)DC005接口供电范围为6~24V,请不要非法供电。 (2)VOUT2(2X3排针)可以做5V也可以输入输出。 (3)开发板外载重(电流大)时,请提供足够的电源。 (4)不支持开发板JLINK请不要尝试等待电源。 (5)正常供电后,蓝色电源指示灯,必须亮,才可使用开发板。
- 开发板IO使用时应注意以下事项: (1)IO不得接口超过5V的电压。 (2)不要用IO口直接驱动感性负载(电机/电磁阀/继电器等)。 (3)外接其他外设时,请先做好IO选型,选对IO口。 (4)注意防静电(尤其是冬季)。
Keil基本使用
一、新建工程模板
基于固件库(先复制文件夹,再添加文件)
- 在磁盘上新建文件夹Template(包含CORE,FWLIB,OBJ, USER,并将SYSTEM复制过来)
- Project ——New Uvision Project ——Template——USER(工程名取Template)——Device——STM32F407ZG(选择相应的芯片型号)——OK——Manage Run-Time Environment——Cancel
- 将官方源文件复制到新文件夹(参考资料)STM32F4固件库里) (1)删除USER里的Listings和Objects, (2)将STM32F4固件库\Libraries\STM32F4xx_StdPeriph_Driver里的src,inc复制文件夹FWLIB(固件库源码) (3)将STM32F4xx固件库——Libraries——CMSIS——Device——ST——STM32F4xx——Source\Templates\arm里startup_stm32f40_41xxx.s复制到CORE,将STM32F4固件库\Libraries\CMSIS\Includ,将里面core_cm4.h、core_cm4_simd.h、core_cmFunc.h以及core_cmInstr.h同样复制到CORE(启动文件) (4)将STM32F4固件库\Libraries\CMSIS\Device——ST\STM32F4xx\Include里的stm32f4xx.h和system_stm32f4xx.h复制到USER里。在STM32F4固件库\Project\STM32F4xx_StdPeriph_Templates目录下面的五份文件main.c,stm32f4xx_conf.h,stm32f4xx_it.c,stm32f4xx_it.h,system_stm32f4xx.c复制到USER目录下(复制头文件和源文件) (5)在工程源码中找到一个SYSTEM复制过来
- 将固件库文件复制到工程中 (1)右键点击Target1——Manage Project Items——Project Targets(将Target改名为Template,在Groups里删掉Source Group1,建立USER,CORE,FWLIB,SYSTEM)——OK(在我们的项目中添加上述文件) (2)右击Template——Manage Project Items——选择FWLIB——点击ADD Files——选择FWLIB\src全选Ctrl A——Add——Close(删除stm32f4xx_fmc.c,只能添加我们使用的库文件) (3)同样在CORE里添加startup_stm32f40_41xxx.s, 在USER添加到文件中的文件main.c,stm32f4xx_it.c,system_stm32f4xx.c。 (4)右击Template——Manage Project Items——建立SYSTEM——Add Files…(添加delay.c、sys.c、usar.c三个c文件)——Close——OK
- 设置存储路径 (1)设置MDK存储头文件的路径 Options for Target…——C/C ——Include Paths…——新建…(分别添加CORE,USER,FWLIB\inc和SYSTEM里的delay、sys、usar三个文件夹) (2)添加全局定义标志 Options for Target…——C/C ——Define(添加STM32F40_41xxx,USE_STDPERIPH_DRIVER) (3)选择编译的中间文件存储目录 ①Options for Target…——Output——Select Folder for Objects…(选择新建的OBJ)——勾选以下三个(生成)HEX文件) ②Options for Target…——Listing——Select Folder for Objects…(选择新建)
- 修改代码 (1)将main.c里替换成README删除代码(注意最后一行空白)stm32f4xx_it.c里第32行#include "main.h"和第144行TimingDelay_Decrement(); (2)修改System_stm32f4xx.c,把PLL如#define PLL_M 8(使主频为168MHz) (3)修改stm32f4xx.h里HSE_VALUE为8MHz,如#define HSE_VALUE ((uint32_t)800000)(修改外部时钟为80000)MHz)
- 调用实验-编译F7
寄存器h3
- Project ——New Uvision Project ——新建TEST,OBJ文件夹,在里面新建USER文件夹,保存名为test——Device——STM32F407ZG(选择对应芯片型号)——OK——Manage Run-Time Environment——Cancel
- 添加启动文件(注意与标准库不同有注释) (1)将启动文件startup_stm32f40_41xxx.s复制到USER目录下 (2)Options for Target…——Target——修改Xtal为8——OK (3)Target1——双击Source Group1——选择启动文件Add——Close
- Options for Target…——Output/Listings——Select Folder for Objects…(选择新建的OBJ)——将下面三个都勾选(生成HEX文件)
- 将寄存器版里的SYSTEM文件复制到TEST里——右击Template——Manage Project Items——新建组SYSTEM和USER——Add Files将delay.c、sys.c和usart.c添加进SYSTEM——Close——OK
- 新建空文档test.c保存到USER里,双击USER添加,将寄存器版里源文件test.c里内容复制过来
- Options for Target…——C/C++——Include Paths…——新建…——将SYSTEM里三个文件夹添加进去——OK (在Define里添加宏STM32F40_41xxx)
- 调用实验——编译F7
基于HAL库
- 新建文件夹Template,在里面建立文件夹CORE,HALLIB,OBJ和USER
- Project ——New Uvision Project ——Template——USER(工程名取Template))——Device——STM32F407ZG(选择对应芯片型号)——OK——Manage Run-Time Environment——Cancel
- 复制相关文件 (1)将官方包STM32Cube_FW_F4_V1.24.0\Drivers\STM32F4xx_HAL_Driver离得Src和Inc复制到新建的HALLIB里 (2)将STM32Cube_FW_F4_V1.24.0\Drivers\CMSIS\Device\ST\STM32F4xx\Source \Templates \arm里的启动文件startup_stm32f407xx.s复制到CORE里,同时将\STM32Cube_FW_F4_V1.24.0\Drivers\CMSIS\Include里的cmsis_armcc.h, cmsis_armclang.h,cmsis_compiler.h,cmsis_version.h,mpu_armv7.h,core_cm4.h复制到CORE里 (3)将STM32Cube_FW_F4_V1.24.0\Drivers\CMSIS\Device\ST\STM32F4xx\Include里的stm32f4xx.h,system_stm32f4xx.h和stm32f407xx.h头文件复制到USER中 (4)将STM32Cube_FW_F4_V1.24.0\Projects\STM32F4-Discovery\Templates里Inc文件夹中的stm32f4xx_it.h,stm32f4xx_hal_conf.h,main.h和Src文件夹中的system_stm32f4xx.c, stm32f4xx_it.c, stm32f4xx_hal_msp.c,main.c复制到USER里 (5)将模板里的SYSTEM复制进Template1中 4.在小组里添加相关文件 (1)右键点击Target1——Manage Project Items——Project Targets(将Target改名为Template,在Groups里删掉Source Group1,建立USER,CORE,FWLIB,SYSTEM)——OK(将上面的文件添加到我们的工程里) (2)将HALLIB\Src添加到HALLIB组里(去掉stm32f4xx_hal_dsi.c,stm32f4xx_hal_lptim.c和stm32f4xx_hal_msp_template.c,此外去掉带ll的和带timebase的),USER里添加main.c,stm32f4xx_hal_msp.c,stm32f4xx_it.c和system_stm32f4xx.c,CORE里添加头文件和启动文件startup_stm32f407xx.s,SYSTEM里添加sys.c,delay.c和usart.c
- Options for Target…——C/C++——Include Paths…——新建…——将CORE,USER,HALLIB\Inc和SYSTEM里三个子文件夹添加进去——OK(在Define里添加宏USE_HAL_DRIVER,STM32F407xx用英文逗号隔开,取消勾选Output里的Browse Information)
- 将模板里main.c里的内容复制进工程里的主函数中
二、下载与调试
- STM32串口程序下载 (1)连线 ①在板子上把RXD和PA9,TXD和PA10通过跳线帽连起来 ②把BOOT1和BOOT0都设置为0 ③把B0接V3.3,按一下复位键 ④在USB_232处插入USB线连接电脑 (2)FlyMcu下载设置——开始编程——成功后显示:共写入…KB,好事…毫秒 ①搜索串口,选择虚拟出来的USB:COMx:空闲USB-SERIAL CH340 ②勾上“编程前重装文件”、“校验”以及“编程后执行”,其他都不要勾选 ③左下方:选择第四个DTR的低电平复位,RTS高电平进bootloader ④联机下载文件选.hex ⑤波特率设置为76800bps (3)打开串口调试助手(XCOM)设置波特率为115200查看收发信息是否一样
- STLINK下载与调试程序 (1)keil的设置 ①目标选项——Debug——Use选择ST-Link Debugger,勾选Run to main() ②目标选项——Debug——Settings——设置Port为SW,Max为4MHz ③目标选项——Utilities——Settings——勾选Reset and Run (2)开始运行 ①点击开始/停止仿真(则会线更新代码在仿真),或者点击下载F8(只下载代码)(注意B0和B1都要设置GND) ②MDK弹出Debug工具条——堆栈局部变量窗口
③把光标放到test.c的第9行左侧左击,可以放置一个红色的断点,再次单击取消,然后点击执行到断点处 ④菜单栏外设——USART——USART1——点击执行过去 (3)打开串口调试助手(XCOM)设置波特率为115200和串口号,然后点击执行过去按钮,看t值变化
三、使用技巧
- 文本美化 (1)Configuration——Editor——选择Encoding为Chinese GB2312(Simplified),设置Tab size为4(设置注释关键字字体) (2)Colors & Fonts——C/C++ Editor Files——Number(修改字体颜色和大小,或者Ctrl+鼠标滑轮进行放大或者缩小) (3)User Keywords——C/C++ Editor Files——输入关键字改变颜色
- 语法检查&代码提示 (1)配置——Text Completion——Symbols after xxx characters(用于开启代码提示功能) (2)Strut/Class Members(用于开启结构体/类成员提示功能) (3)Dynamic Syntax Checking(则用于开启动态语法检测) (4)Function Parameters(用于开启函数参数提示功能)
- 代码编辑器技巧 (1)Tab(或者Shift + Tab)可以使一片代码右移(或左移) (2)右击函数或者变量上——Go to Definition Of ‘…’(进行快速定位,注意先编译) (3)选中一片代码右击——Advanced——Comment Selection(或取消注释)
- 其他小技巧 (1)右击头文件——Open Document “XXX”可以快速打开文件 (2)Ctrl + H(查找替换) (3)双击头文件——点击上面图标在文件中查找Find in Files…(跨文件查找)
IAR基本使用
一、新建工程模板
- 建立文件夹 (1)建立Template包含(EWARM、FWLIB、USER)
(2)EWARM ①新建Debug调试文件夹 ②将链接文件stm32f4xx_flash.icf和stm32f4xx_sram.icf复制过来(分别在文件夹和 Project\STM32F4xx_StdPeriph_Templates\EWARM里) ③IAR工程相关设置文件会在新建工程后自动生成 (3)FWLIB(存放标准库驱动文件) ①将STM32F4固件库\Libraries\STM32F4xx_StdPeriph_Driver里的src,inc(头文件和源文件)文件夹复制到FWLIB
②将startup_stm32f40_41xxx.s(Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\iar)复制到新建的文件夹CORE,将STM32F4固件库\Libraries\CMSIS\Include,将里面core_cm4.h、core_cm4_simd.h、core_cmFunc.h以及core_cmInstr.h同样复制到CORE(启动文件),将Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates\iar的启动文件startup_stm32f40xx.s复制过来,此外将STM32F4固件库\Libraries\CMSIS\Device——ST\STM32F4xx\Include里的stm32f4xx.h和system_stm32f4xx.h复制过来。
(4)USER ①创建文件夹App——用于存放用户程序,简单的应用这个文件夹一般空在哪里; ②创建文件夹Driver——用于存放自己编写的驱动文件;
③将\Project\STM32F4xx_StdPeriph_Templates里将目录下面的5个文件main.c,main.h,stm32f4xx_conf.h,stm32f4xx_it.c,stm32f4xx_it.h,system_stm32f4xx.c复制到USER目录下面(复制头文件和源文件)
④复制一份delay,sys和usart文件夹复制到Driver里
-
创建工程 (1)File——New——Workspace(新建工作空间) (2)Project——Create New Project——Tool chain(选择ARM)——Project template(选择Emply project)——OK——文件名Project.ewp——保存 (3)点击Save All——文件名Project.eww——保存
-
添加工程 (1)右击工程——Add——Add Group(CMSIS,FWLIB,USER(App,Driver)) (2)右击工程——Add——Add Files(只添加.c文件和启动文件)
-
对IAR的配置 (1)通用选项 ①右击——Option——General Options——Target——Device选择自己使用的相应芯片型号 ②General Options——Output(选择输出路径,基本不需要动) ③Option——General Options——Library Configration——Library——Full/勾选CMSIS(如果需要使用某些标准的库函数接口,如我们使用的printf and scanf; CMSIS:是微控制器软件接口标准的意思。IAR for ARM在V5和 V6、V7版本之间存在差异,很多人用新版本IAR编译以前工程出现错误的原因就在于此)
(2)添加路径和宏定义 ①C/C++ Compiler——Preprocessor——Additional include directories:(one per line)——…添加路径,添加的路径最好是相对路径$,而不是绝对路径。使用绝对路径工程位置改变之后就找不到文件,就会出错。可以点击按钮选择路径,也可以通过复制文件路径进行配置。 ②Preprocessor——Defined symbols添加宏定义 USE_STDPERIPH_DRIVER STM32F40_41xxx xVECT_TAB_SRAM
③Optimizations——Level框中勾选Medium,这是选择了中等的代码优化选项。 (4)Output Converter—— Output可以设置最终编译链接后输出的文件类型和名称。
(5)Linker——Config——Linker configuration file(勾选Override default重设默认文件,选择我们之前从CubeMX过来的ICF链接文件) (6)配置仿真器 ①Debugger——Setup——Driver选择ST-LINK ②Debugger——Setup——Download勾选上Verify Download和Use flash loader开启下载校验 (7)ST-Link——Interface选择SWD
二、编译Make和调试
- 编译 (1)单独编译Compile快捷键Ctrl+F7:一般会提示保存工作区文件: (2)全局编译Make快捷键F7
- 进入调试状态Download and Debug快捷键Ctrl+D:Debugger——Driver一定要选择Simulator模拟 (1)调出View视图新的调试界面如下(点击可查看高清图): ①View——Registers——Registers 1(需要调出寄存器视图) ②View——Memory——Memory 1(显示内存情况) (2)仿真进行调试 常用的调试操作是Debug——Step Over(F10)逐过程、Step Into(F11)逐条执行程序指令、Go(F5)直接把程序执行到最后,在工具栏上也有调试可以直接使用,此程序的调试过程与结果如下:
再次执行将调至main处循环执行,可以看到将寄存器R0和R1的值相加存入R2当中。 (3)结束调试——Stop Debugging(一个红色×号) (4)如果在调试期间修改程序,修改完成后点击Restart Debugger重新生成仿真 (5)断点问题 ①在该行指令的最前面点击Toggle Breakpoints(或按F9)可以设置断点 ②IAR显示所有的断点,可以在View——Breakpoints中调用断点窗口,将需要找到所有的断点并将其关闭(右击delete)
三、环境调试
-
如何使用操作系统自带而IAR没有的字体? 在IAR的APPDATA文件目录中找到IarIdePm.ini文件,编辑选择自己要使用的字体名。其中Common是通用字体,TextEditor是编辑器代码字体。代码字体选用了Keil默认的 Courier New字体。
-
部分文件字体显示与设置的字体不一致? 不要勾选“Auto-detect character encoding”
-
IAR显示行号 显示行号:在代码段点击右键,找到Options——Editor——Show Line Numbers 勾选上就可以了。
四、快捷键设置
1、F9 光标处添加/删除断点;Ctrl+F9 使能/失能断点 2、注释的快捷键:Ctrl+K;取消注释:Ctrl+Shfit+K 3、Ctrl+Shfit+空格,可以使用IAR提供的内部代码的编写,如if、for、class语句。 4、自动缩进 选中某些行,然后使用CTRL + SHIFT +I,可以实现自动的缩进 5、自动往后 选中某些行,然后 使用 TAB键,可以实现自动的后退 6、Ctrl+Shift+V 列出剪切板中所有的字符串供选择粘贴 7、Ctrl+B 智能选择光标所在括弧内的区域,多次使用可选更大的区域 8、Shift+Alt+E 打开断点窗口,列出所有断点 9、Ctrl+F 向下寻找光标所在处的单词;Ctrl+Shift+F 在文件中搜索 10、Ctrl + H 替换字符串 11、Ctrl + G 跳到指定行 12、Ctrl+1 新增垂直窗口;Ctrl+2 新增水平窗口 13、F2 跳到下一个标签处;Shift + F2 在光标处添加标签 14、F3 向下寻找上次搜索的字符;Shift+F3 向上寻找上次搜索的单词 15、F4 跳到定义处;Ctrl+F4关闭当前文件;Ctrl+Shift+4关闭除当前激活外的所有文件
单片机开发
一、C语言基础
- 常用操作 ①位与:操作对象&=屏蔽字(可实现目标字段清0) ②位或:操作对象|=屏蔽字(可实现目标字段置位) ③异或:操作对象^=屏蔽字(可实现目标字段取反) ④按位取反:~;逻辑取反:!; ⑤&&:左右都得成立为真 ⑥宏定义#define用\换行 ⑦||:左右有一个成立为真
- 字长定义 unit8_t= u8是unsigned char(无符号字节,其中unit8_t是标准定义) unit16_t=u16是unsigned short unit32_t=u32是unsigned int
二、常见错误警告解决方法
1.错误现象:main.c(63): warning: #1-D: last line of file ends without a newline 解决方法:在最后加一行 2.错误现象:Warning[Pe550]: variable “mbox” was set but never used 解决方法:原因是定义了无效的变量,在变量前加上volatile或者__IO,或者右击Option——C/C++Compiler——Optimizations——Level选择Medium(中等优化) 3.错误现象:Warning[Pe161]: unrecognized #pragma 解决方法:注释掉 4.错误现象:Warning[Pe223]: function “XXX” declared implicitly 解决方法:缺少XXX定义的头文件 5.错误现象:Error[Pe140]: too many arguments in function call 解决方法:取消括号里的声明,因为与之前定义的函数不一样 6. 错误现象:程序设置波特率和串口调试助手波特率设置不同才能通信 解决方法:把stm32f4xx.h中的HSE_VALUE 设根据外部实际晶振的标称值进行更改。
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8400000)
#endif
7.错误现象:Error[Li005]: no definition for…. 解决方法:缺少XXX定义的头文件,除了自己定义的头文件还有库文件 8.错误现象:Error[Li006]: duplicate definitions for ……(重复定义) 解决方法:去掉重复定义的部分,去掉之前删除的对应c和h文件 9.错误现象:Error[Pe065]: expected a “;” 解决方法:符号错误,比如中英文混写 10.错误现象:Error[Pe165]: too few arguments in function call 解决方法:该错误是由于调用的参数少了导致的,即使某些参数在都中情况下无效,但也要加上去
三、工程目录下简介
1.USER (1)main.c ——主函数来调用其他函数 (2)stm32f4xx_it.c——中断处理文件,stm32f4xx是型号 (3)system_stm32f4xx.c——系统初始化文件 2.CORE包含内核相关的函数和宏定义 (1)startup_stm32f40_41xxx.s——启动文件(不需要动) 3.FWLIB固件库 (1)misc.c——存放头文件 (2)stm32f4xx_gpio.c—— 是处理引脚相关函数的文件 (3)stm32f4xx_rcc.c——是处理内部时钟相关函数文件(不能删除) (4)stm32f4xx_usart.c——是串口通信的相关函数文件 4.HARDWARE存放和硬件相关的函数 (1)led.c对GPIO引脚的初始化 5.README告诉别人干嘛的 6…SYSTEM (1)delay.c——存放的是和延时相关的函数。 (2)sys.c——存放的是系统初始化相关的函数,不必深究。 (3)usart.c——存放的和串口通讯时用到的代码
四、编辑技巧
- 如何提高代码的可移植性——就是把跟硬件相关的IO都用宏定义来实现
- 在建工程Define里调用的宏定义必须和头文件参数一致,或者修改与硬件一致
- 设置绝对地址
u32 testsram[250000] __attribute__((at(0X68000000)));//MDK绝对地址
u32 testsram[250000] @0X68000000;//IAR设置绝对地址
- 设置字节对齐
__align(4) u8 SDIO_DATA_BUFFER[512];//MDK设置4字节对齐
#pragma pack(push,4) //IAR指定字节对齐
__no_init u8 SDIO_DATA_BUFFER[512];
#pragma pack(pop)
- 这两个等效
void ADC_DeInit(void)
{
/* Enable all ADCs reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, ENABLE);
/* Release all ADCs from reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC, DISABLE);
}
五、常用函数代码
- (1)源文件只宏定义对应头文件如#include “main.h”,其他添加函数的初始化以及结构体的具体定义,或者函数的调用 (2)头文件添加其他文件的宏定义,如
#ifndef __MAIN_H //用来防止重复定义
#define __MAIN_H
#include "stm32f4xx.h"
#include "sysdelay.h"
#include "led.h"
#endif
- 延迟函数头文件(含位带操作)
#ifndef __SYSDELAY_H
#define __SYSDELAY_H
#include "stm32f4xx.h"
void delay_init(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);
//位带操作,IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr & 0xFFFFF ) << 5) + ( bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
#define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
#define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
#define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
#define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414
#define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
#define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
#define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
#define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
#define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
#define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
#define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
#define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410
#define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
#define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10
#define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010
//IO口操作,只对单一的IO口!确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //输出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //输入
#define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //输出
#define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //输入
#endif
3.延迟函数源文件
#include "delay.h"
void delay_us(u32 nus)
{
u32 temp;
SysTick_Config(SystemCoreClock/1000000);
for(temp=0;temp<nus;temp++)
{
// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
// 当置1时,读取该位会清0
while( !((SysTick->CTRL)&(1<<16)) );//每1ms跳出一次while循环
}
SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void delay_ms(u16 nms)
{
for(u16 j=0;j<nms;j++)
{
delay_us(1000);
}
}
/* //THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI void WFI_SET(void) { asm("WFI"); } //关闭所有中断(但是不包括fault和NMI中断) void INTX_DISABLE(void) { asm("CPSID I"); asm("BX LR"); } //开启所有中断 void INTX_ENABLE(void) { asm("CPSIE I"); asm("BX LR"); } //设置栈顶地址 //addr:栈顶地址 void MSR_MSP(u32 addr) { asm("MSR MSP, r0"); //set Main Stack value asm("BX r14"); } */
/******************************************************************************/
//利用中断延迟
/* __IO u32 TimingDelay; void delay_ms(uint32_t nTime) { TimingDelay = nTime; while(TimingDelay != 0); } //初始化延迟函数 void SysTick_Init(void) { //SystemFrequency / 1000 1ms中断一次 //SystemFrequency / 1000000 1us中断一次 if (SysTick_Config(SystemCoreClock / 1000000)) { //SystemCoreClock/1000超出计数最大值时报错,程序陷入空循环 while (1); } }*/
//寄存器中断
/* static u8 fac_us=0; //us延时倍乘数 static u16 fac_ms=0; //ms延时倍乘数 void delay_init(u8 SYSCLK) //系统时钟是168MHz,SYSCLK=168 { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); fac_us=SYSCLK/8; //硬件8分频,fac_us得出的值是要给下面的时钟函数用的 fac_ms =(u16)fac_us*1000; } void delay_us(u32 nus) { u32 temp; SysTick->LOAD = nus*fac_us; //延时10us的话就是 10*9=90,装到load寄存器中 SysTick->VAL=0x00;//计数器清0,load将自动重装到VAL中 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; } while(temp&0x01&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } void delay_ms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit) SysTick->VAL =0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } */
附录
1.STM32f407实验IAR版本
下载链接 包含常规外设实验(uart,tim等)、应用实验(gps、蓝牙等)、文件系统fatfs以及RTOS(UCOS、FreeRTOS)