初学STM32嵌入式开发,旨在学习嵌入式开发流程和原理,以便更快的上手那些便宜的国产的没那么多资料的IC。
选用的是STM32F103C8T6(暂时用wokwi平台),这个IC是支持SPL的,但是PIO平台并不支持直接配置,不知道为啥,所以这里需要手动配置SDK。
在STM32F103C8可以找到这个MCU的所有资料,需要找到其SDK并下载下来。东西太多了还是有点难找
下拉找到MCU and MPU embedded softwar部分,其中STM32CubeF1就是HAL了,这里为了更熟悉单片机的底层原理,HAL封装的太厚了,所以使用SPL,不用HAL(CMSIS好像又有点太底层了,一时间接受不了….),所以不选择这个(这个PIO里面也有)。
这里找到STM32054,后面的描述是STM32F10x标准外设库,就是他了,点击下载最新版本,这里选择访客下载(新一点的IC比如STM32L031G6已经只支持HAL了)。
下载下来之后,内部的目录结构及其作用如下
STM32F10x_StdPeriph_Lib_V3.6.0
├── Libraries
│ ├── CMSIS <-- RM Cortex-M系列的标准接口
│ │ ├── CM3
│ │ │ ├── CoreSupport <-- 包含Cortex-M3内核的支持文件
│ │ │ │ ├── core_cm3.c <-- 内核支持函数
│ │ │ │ └── core_cm3.h <-- Cortex-M3内核定义
│ │ │ └── DeviceSupport
│ │ │ └── ST
│ │ │ └── STM32F10x <-- STM32F10x系列特定的设备支持文件
│ │ │ ├── startup <-- 不同IC的启动文件,汇编语言编写,定义中断、设置堆栈指针、初始化系统时钟、执行main函数,类似系统引导(bootloader)
│ │ │ ├── LICENSE.txt
│ │ │ ├── Release_Notes.html
│ │ │ ├── stm32f10x.h <-- 最核心的,包含所有寄存器定义
│ │ │ ├── system_stm32f10x.c <-- 系统初始化源文件
│ │ │ └── system_stm32f10x.h <-- 系统配置头文件
│ │ └── Documentation
│ └── STM32F10x_StdPeriph_Driver <-- 标准外设库,主要使用这部分
│ ├── inc <-- 所有外设的头文件
│ │ ├── misc.h
│ │ ├── stm32f10x_adc.h <-- ADC模数转换器
│ │ ├── stm32f10x_bkp.h <-- 备份寄存器
│ │ ├── stm32f10x_can.h <-- CAN总线
│ │ ├── ...
│ │ └── stm32f10x_wwdg.h <-- 窗口看门狗
│ └── src
├── Project
│ ├── STM32F10x_StdPeriph_Examples <-- 所有外设的示例代码
│ └── STM32F10x_StdPeriph_Template <-- 项目模板
├── Utilities
│ └── STM32_EVAL <-- 包含ST官方评估板的板级支持包(BSP),针对开发板的进一步硬件抽象
└── _htmresc <-- HTML文档的资源文件
这里我们需要的就是Library下面的两个,CMSIS是最底层的支持,STM32F10x_StdPeriph_Driver是要用到的SPL本身,所以把这两个目录直接完整复制到PIO项目的lib目录下,作为库使用。
然后需要在include目录下创建一个stm32f10x_conf.h,用于配置头文件,写入以下内容,需要更多外设库可以再添加
#ifndef __STM32F10x_CONF_H
#define __STM32F10x_CONF_H
/* 包含需要的外设库头文件 */
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_dma.h"
/* 断言配置 */
#ifdef USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif
#endif /* __STM32F10x_CONF_H */
这时项目是不能正常跑通 的,因为没有配置导入目录,需要配置项目本身的设置。
首先把项目修改成CMSIS框架,最底层的,不需要上层的框架,因为我们自己准备了。修改platformio.ini中的framework为cmsis
添加上lib_extra_dirs = lib,配置lib为第三方库目录
然后再加上一些构建选项选项,如下
build_flags =
-DSTM32F10X_MD ; 定义预处理器宏,指定STM32F10x中等容量器件,F103C8
-DUSE_STDPERIPH_DRIVER ; 定义预处理器宏,告诉编译器使用标准外设库
-Ilib/STM32F10x_StdPeriph_Driver/inc ; 添加包含路径:标准外设库头文件目录
-Ilib/CMSIS/CM3/CoreSupport ; 添加包含路径:CMSIS Cortex-M3核心支持文件目录
-Ilib/CMSIS/CM3/DeviceSupport/ST/STM32F10x ; 添加包含路径:STM32F10x设备特定支持文件目录
-Iinclude ; 添加包含路径:项目自定义头文件目录
这样就可以愉快的用标准库用STM32写代码了,但是不能愉快的编译。因为只制定了-I的头文件目录,找不到源代码目录,我们没有指定。
通过build_src_filter来指定源代码目录,如下,制定了标准库下的src目录,此时就能正常编译通过了
build_src_filter =
+<*>
+<../lib/STM32F10x_StdPeriph_Driver/src/>
当然也有很多的教程选择直接把源代码拿出来放在项目里面,这样毕竟不是很优雅,还要动人家的库目录
更多PIO配置参考Build options。
此时就可以正常编写代码了,点个灯试一下
#include "stm32f10x.h"
int main(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_WriteBit(GPIOA, GPIO_Pin_5, Bit_SET);
}
正常编译,可以亮灯,配置完毕


博主可以试试LED闪烁,似乎是不行的,LED灯会一直亮着。