1. 前言
STM32 的资源非常丰富,所以加大了编程的难度,但是好在有官方的库函数,于是我们就可以先不用学习 寄存器 的作用,而是在前人的库函数基础上,进行搭建项目,这些库函数就是位于 Libraries/STM32F10x_StdPeriph_Driver 这个文件夹下。加上有 Eclipse 这个优秀的编译器,所以找出学习要点非常的简单。下图就是在 GPIO 头文件中定义的宏定义,结构体,函数等:
所以学习 GPIO 这个头文件也是一样,从这些点开始,然后进行补充。
2. 关于结构体
在 STM32 中最常见的就是对 GPIO 口的初始化。
typedef struct
{
uint16_t GPIO_Pin; GPIO的引脚号
GPIOSpeed_TypeDef GPIO_Speed; GPIO的引脚的运行速度
GPIOMode_TypeDef GPIO_Mode; GPIO的引脚的运行模式
}GPIO_InitTypeDef;
3. 关于函数方法
下图就是 GPIO 的全部函数方法,但是常用的并不多。
常用的如下:
初始化 GPIO(GPIOx, GPIO_InitStruct)口
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
读取 GPIO(GPIOx, GPIO_InitStruct)口高低电平
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
按16位引脚的方式读取(GPIOx)高低电平信息
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
将指定位置的引脚设置为高电平(GPIOx,GPIO_Pin)
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
将指定位置的引脚设置为低电平(GPIOx,GPIO_Pin)
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
4. 可用模板
这个模板是对 GPIO 的初始化,我称为 MYGPIOCON 。
// 定义一个GPIO_InitTypeDef类型的结构体
GPIO_InitTypeDef GPIO_InitStructure;
// 开启LED相关的GPIO外设时钟
RCC_APB2PeriphClockCmd( LED1_GPIO_CLK, ENABLE);
// 选择要控制的GPIO引脚
GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;
// 设置引脚模式为通用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// 设置引脚速率为50MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// 调用库函数,初始化GPIO
GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);
5. 样例项目
样例项目 test_GPIO 是在新建项目基础上进行的。
第一步:创建一个源目录
第一步是创建一个源目录(source dir) my 用来存放我们写的库文件,在 my 目录下创建两个目录 inc(存放 .h 头文件),src(存放 .c 源文件)。
方法如下:
创建一个源目录(source dir) my,创建的原因:只有源目录下的 .c 文件才会被编译,被链接到
在 my 文件夹下创建 inc 和 src 目录。
第二步:将 my/inc 加入到 includes 路径中
将 my/inc 加入到 includes 路径中。
项目右键 => 属性
Paths and Symbols =>Add
通过 Workspace 选择路径,并应用。
第二步是 在 src 目录下创建 bsp_led.c,在 inc 目录下创建 bsp_led.h 文件。
第三部:编写库函数
第三部编写库函数
这部分本来也不难,只是一个打字的活,但是难的是如何快速写出来,并且写的舒服。
- 修改文字大小,不修改看着中文会特别小(如图)
修改方法:
窗口=>首选项
常规小六子 => 外观 => 颜色和字体 => 基本 => 文本字体=>编辑
将字体设置为 16 号,并确定。
- 使用代码提示
先在 my/inc/bsp_led.h 文件中写下以下文字。
提示: [ALT +/ ] 可以显示代码提示
#ifndef INC_BSP_LED_H_
#define INC_BSP_LED_H_
#include "stm32f10x.h"
#define LED_GPIO_PORT GPIOB
#define LED_GPIO_PIN GPIO_Pin_5
#define LED_GPIO_CLK RCC_APB2Periph_GPIOB
// 注意末尾没有分号
#define LED(a) if(a) GPIO_SetBits(LED_GPIO_PORT,LED_GPIO_PIN); else GPIO_ResetBits(LED_GPIO_PORT,LED_GPIO_PIN)
// 通过模板编写
void LED_GPIO_Config(void);
#endif /* INC_BSP_LED_H_ */
写下上述文字可以发现, Eclipse 并不是全部内容都会提示,只提示与宏定义相关的。而函数定义的却没有。所以我们应该加上一些东西。设置如下:
窗口=>首选项
C/C++ => Editor => Content Assist => Advanced
代码提示的功能就有了,只是需要使用 [ALT] + /
然后是编写 my/src/bsp_led.c 文件
#include "bsp_led.h"
void LED_GPIO_Config(void)
{
/* 定义一个 GPIO_InitTypeDef 类型的结构体 */
GPIO_InitTypeDef GPIO_InitStructure;
/* 开启 LED 相关的 GPIO 外设时钟 */
RCC_APB2PeriphClockCmd(LED_GPIO_CLK, ENABLE);
/* 选择要控制的 GPIO 引脚 */
GPIO_InitStructure.GPIO_Pin = LED_GPIO_PIN;
/* 设置引脚模式为通用推挽输出 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/* 设置引脚速率为 50MHz(如果为输入模式没有此项) */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 调用库函数,初始化 GPIO */
GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
}
虽然字不多,但是同样此处可以偷懒,方式就是建立模板(Templates),我把这个模板名称为 "MYGPIOCONF"。并且 MYGPIOCONF 使用的频率应该是最高的,定义一个端口都要进行配置 GPIO。
创建方式如下:
- 窗口=>首选项
- C/C++ => Editor => Templates
- 新建
将下文加入到模式中(确认没有 [Tab])
/* 定义一个 GPIO_InitTypeDef 类型的结构体 */
GPIO_InitTypeDef GPIO_InitStructure;
/* 开启 LED 相关的 GPIO 外设时钟 */
RCC_APB2PeriphClockCmd(LED_GPIO_CLK, ENABLE);
/* 选择要控制的 GPIO 引脚 */
GPIO_InitStructure.GPIO_Pin = LED_GPIO_PIN;
/* 设置引脚模式为通用推挽输出 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/* 设置引脚速率为 50MHz(如果为输入模式没有此项) */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 调用库函数,初始化 GPIO */
GPIO_Init(LED_GPIO_PORT, &GPIO_InitStructure);
- 尝试模板好不好用,将 my/src/bsp_led.c 改为下文
光标在 MYGPIOCONF 处,然后按下 [ALT] + / ,会补充原文。
第四部:编写主函数
在主函数下,写入以下代码,可以看见,现在代码结构很清晰,而且还为以后写 STM32 代码打下一定基础。
#include "stm32f10x.h"
#include "bsp_led.h"
/* 定义与延时相关 */
#define SOFT_DELAY Delay(0xFFFFF);
/* 简单延时函数 */
void Delay(__IO u32 nCount);
int main(void)
{
LED_GPIO_Config();
while(1){
LED(1);
SOFT_DELAY;
LED(0);
SOFT_DELAY;
}
}
// 简单延时函数
void Delay(__IO u32 nCount)
{
for(;nCount!=0;nCount--);
}
第五步:烧录
这步其实挺简单的,只是对器材有点刻薄。
点击小虫子,就能进行烧录调试了。
如果想要只下载不调试,可以在文中加入 quit。
如同前面介绍的 bilibili 中一样。