Windows下使用Keil MDK5进行stm32f103c8t6的开发和编译, 配合ST-LINK工具进行烧录, 使用标准外设库SPL.
参数
参数
在烧录程序到目标芯片以及Debug时需要使用, 自ST-Link V2以来的所有ST-LINK板都带一个COM
LED, 一般是红绿两色组合, 也有些是红蓝两色, 两色分别有常亮, 常灭, 闪烁等状态. 不同状态代表不同的含义:
在观察串口输出时需要使用.
mdk525.exe
不建议使用5.12等早期版本, 在更新时窗口容易卡, 且失败总会弹出需要手工消除.
keygen2032
大部分找到的keygen, 有效期都是2020年的, 没法用, 必须要能生成2032有效期的版本
st-link驱动
https://www.st.com/zh/development-tools/stsw-link004.html 不安装没法烧录
st官方库
前往https://www.st.com/, 点击Tools&Software > Embedded Software > MCU & MPU Embedded Software > STM32 Embedded Software > STM32 Standard Peripheral Libraries
(链接), 下载F1和F4, 解压备用.
运行mdk525, 安装
安装完成后Pack Installer会自动运行, 可以让其自己更新
如果使用stlink下载器的, 还需要安装驱动
以管理员身份运行Keil uVision5
略
在Pack Installer中
微控制器软件接口标准(CMSIS:Cortex Microcontroller Software Interface Standard)是 Cortex-M 处理器系列的与供应商无关的硬件抽象层(A vendor-independent hardware abstraction layer for the Cortex-M processor series and defines generic tool interfaces). 使用CMSIS可以为处理器和外设实现一致且简单的软件接口, 从而简化软件的重用、缩短微控制器新开发人员的学习过程,并缩短新设备的上市时间
对于stm32f1x, 各名词的对应关系为
目录结构及说明
├─Libraries
│ ├─CMSIS
│ │ ├─CM3
│ │ │ ├─CoreSupport # CMSIS核心外设访问层代码
│ │ │ └─DeviceSupport
│ │ │ └─ST
│ │ │ └─STM32F10x # stm32f10x相关代码
│ │ │ └─startup
│ │ │ ├─arm # startup_stm32f10x_ld/md/hd/xl.s文件,
# stm32f103c8t66规格为64k flash, 对应md
│ │ │ ├─gcc_ride7
│ │ │ ├─iar
│ │ │ └─TrueSTUDIO
│ │ └─Documentation
│ └─STM32F10x_StdPeriph_Driver # 对应stm32f10x的外设代码
│ ├─inc
│ └─src
├─Project
│ ├─STM32F10x_StdPeriph_Examples # 代码示例
│ └─STM32F10x_StdPeriph_Template # 代码模板, 需要用到stm32f10x_conf.h, stm32f10x_it.c, stm32f10x_it.h这三个文件(直接复制到新项目的USER目录)
│ ├─EWARM
│ ├─HiTOP
│ ├─MDK-ARM
│ ├─RIDE
│ └─TrueSTUDIO
├─Utilities
└─_htmresc
以stm32f103为例, 对于项目test001, 创建工作目录test001, 在工作目录下创建MDK-ARM, USER这两个目录
复制开发包下的Libraries整个目录到当前项目目录下
mdk-arm
用于放置Keil MDK项目文件, 以及项目开发过程中生成的临时文件
hardware
用于放置自定义的外设, 例如rfid, esp8266等
user
ld,md,hd的选择
md hd ld 根据芯片FLASH容量决定
Project -> New uVision Project
, 选择前面的MDK-ARM目录, 使用名称test001, 保存点击Manage Project Items
对每个group, 添加的文件为
CMSIS
StdPeriph_Driver
Hardware
Startup
User
点击configure target options , 定位到c/c++
Define: 写入 USE_STDPERIPH_DRIVER
Include Paths: 如果是按上面的目录结构组织的项目, 可以直接复制下面的配置
..\Libraries\CMSIS\CM3\CoreSupport;..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x;..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm;..\Libraries\STM32F10x_StdPeriph_Driver\inc;..\hardware;..\user
在c/c++下能看到完整的编译Compile control string
-c --cpu Cortex-M3 -D__MICROLIB -g -O0 --apcs=interwork --split_sections -I ../Libraries/CMSIS/CM3/CoreSupport -I ../Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x -I ../Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm -I ../Libraries/STM32F10x_StdPeriph_Driver/inc -I ../Libraries/ STM32F10x_StdPeriph_Driver/src -I ../hardware -I ../user
-I./RTE/_test001
-IC:/Keil_v5/ARM/PACK/Keil/STM32F1xx_DFP/2.3.0/Device/Include
-IC:/Keil_v5/ARM/CMSIS/Include
-D__UVISION_VERSION="525" -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER
-o .\Obj\*.o --omf_browse .\Obj\*.crf --depend .\Obj\*.d
连接需要4根线, 连接关系为
G -- GND
CLK -- SWCLK
IO -- SWDIO
V3 -- 3.3V
有些开发板没有单独的SWC/SWD接口, 只能连接到JTAG接口, 连接方式为:
从PCB板上方俯视, 将JTAG接口座缺口朝上
PIN1-PIN20为从上至下, 从右至左
最右侧为PIN1(上), PIN2(下), 都可以接stlink的3.3V
从右往左数第4个为PIN7, 接SWDIO, 第5个为PIN9, 接SWCLK
最左下角为PIN20, 接GND
在F7编译完代码, F8将程序通过ST-Link烧录至开发板后, 就可以对程序进行调试
Ctrl + F5
F5
F10
F11
Ctrl + F11
Ctrl + F10
F9
Ctrl + Shift + F9
Start/Stop Debug Session
或Ctrl+F5
进入Debug模式, 在进入Debug模式后, 会重启程序, 并暂停程序运行F5
往下执行, 或者按F10
或F11
一步一步执行, 或者Ctrl + F10
跳到光标指定的行项目的目录结构比较自由, 只要包含的C文件正确, 包含的头文件路径正确, 再加上正确的编译变量如USE_STDPERIPH_DRIVER, 编译就没问题. 但是在项目中还是需要注意目录结构, 建议将平时不需改动的代码, 需要频繁修改的代码, 以及IDE相关的文件, 编译中间产生的文件, 都按目录分隔开.
在项目中最终采的代码结构
├─Libraries
│ ├─CMSIS
│ ├─Hardware
│ └─STM32F10x_StdPeriph_Driver
├─MDK-ARM
└─User
include.h
, 而是包含stm32f10x.h
, 以及其他需要用到的Hardware头文件.include.h
, 用于包含整体的项目头文件, stm32f10x.h
以及用到的Hardware头文件, 在main.c中引用include.h
config.h
, 用于放置环境相关的变量, 在main.c以及需要用到的hardware中引用, 这个文件要加到.gitignoreSTM32F10x是基于ARM Cortex-M3 的32位内核, F4是基于M4的内核, M3跟M4比就是不带FPU和DSP指令集. 在STM32上的开发思路, 和一般的软件项目开发思路不太一样. STM32上跑的程序, 基本上就是围绕着它的外设进行的, 主要的外设包括 DMA, ETH, GPIO, TIM, U(S)ART, SPI, I2C, ADC等.
代码的套路一般是这样的
初始化需要的外设, 包括内建的定时器, GPIO, UART, SPI, I2C, 中断以及自定义的外设, 例如RFID, ESP8266等
做一个while(1)循环, 在循环中完成业务逻辑
主体单进程, 在进程中通过各种中断, 触发和处理外设之间的通信
需要注意的地方
stm32f103c8t6的flash为64k, ram为20k, 容量都很小. 编译结果中的信息
Program Size: Code=8788 RO-data=424 RW-data=72 ZI-data=2328
与这两部分相关联的关系为
实际测试发现, 不论RW Data + ZI Data多大, 运行中可以通过malloc+memset申请的内存只有500个字节, 只要申请的内存超过这个数量, 运行就会卡住.
在代码中, 尽量不要用malloc, 而应该直接声明为固定长度的数组, 这样声明的内存, 可以观察到会增长到ZI Data中去, 这种方式能使用的空间比500字节大得多.
当遇到问题时, 例如引脚不工作, 不输出, 输出不正确, 需要通过各种手段检查和排查
引脚不工作, 要检查对应的模块是否正确初始化, 是否使能. STM32中GPIO, UART, NVIC这些模块的启动基本上都是固定套路
串口输出和输入的问题排查
字符串输入输出. 因为有\r
, \n
等格式符号的存在, 会导致输出字符显示较乱, 当需要严格对照时, 需要将每个字符打印成双位16进制输出%02X
程序执行卡住, 有可能是变量申请的内存过大超出了内存限制
手机扫一扫
移动阅读更方便
你可能感兴趣的文章