STM32F103VBT6: 闪烁一盏LED灯
Xayah Lv3

一、前言

前面我们学习了很多单片机的知识,接下来我们即将进入到ARM的世界~
本篇博文将从零开始实现一块基于STM32F103VBT6芯片的开发板上的LED灯的闪烁。

二、环境准备

MCUISP

如何使用它下载到STM32板上呢?
首先将开发板上的COM口接入PC,在软件中搜索串口并且选择CH 340串口,波特率选择115200即可。

image

然后选择HEX文件并按照如下选项进行勾选

image

准备就绪后,点击开始编程按钮,在开发板上按顺序快速按下REST和ISP按键即可下载。

image

Keil uVision5

该程序安装完成后记得安装本开发板的支持包Keil.STM32F1xx_DFP.xxx(双击即可安装)

可在此处下载安装最新的J-Link

image

STM32CubeMX

可在此处下载安装最新的STM32CubeMX需要注册并登录

安装完成后首次打开该应用,首先打开Embedded Software Packages Manager

image

选择STM32F1并下载最新的软件包

image

三、使用STM32CubeMX生成模板代码

1. 创建工程

打开STM32CubeMX,选择ACCESS TO MCU SELECTOR

image

搜素STM32F103VBT6,双击右侧对应的STM32F103VBT6

image image

2. 分配LED灯相关引脚

image image

原理图可以看出,LED灯A - E分别对应应引脚PE8 - PE15,而LED_SEL对应PB3
因此我们将其设置为推挽,即Output Push Pull,当然还可以为其添加标签,更便于标识

image

3. 模式配置

将这9个引脚设置完毕后,我们接下来设置其调试模式
进入System Core - SYS,在Debug处选择Serial Wire,防止开发板被上锁导致只能下载一次的问题。

image

4. 时钟配置

这里我们使用时间中断闪烁LED灯,因此我们需要配置时钟
进入Clock Configuration,观察到默认频率8MHz(实际上可以根据自己的需求进行调整,或使用外部时钟等等,这里我们使用系统内部的时钟即可)

image

返回Pinout & Configuration界面,进入Timers - TIM1
首先设置时钟源(Clock Source)系统时钟(Internal Clock),然后在Parameter Settings中设置分频系数(Prescaler)计数周期(Counter Period)以及自动重载(auto-reload preload)

image

假设分频系数(Prescaler)A计数周期(Counter Period)B时钟频率C,则这里时间溢出公式

我们将A设置为8000-1B设置为1000-1C8Mhz,因此T = 1s,即我们的时间回调函数调用周期为1s

接下来我们开启时间中断

image

5. 工程配置

Project Manager中设置工程名称路径工具链

image

在左侧选择Code Generator,勾选Generate peripheral initialization as a pair of '.c/.h' files per peripheral,即针对每个外设生成独立的.c和.h文件

image

6. 生成模板代码

配置完成后,点击右上角GENERATE CODE按钮即可生成模板代码

image image

工程目录下,LED.ioc即为STM32CubeMX工程文件,而MDK-ARM下的LED.uvprojx即为Keil工程文件

image

四、使用模板代码实现LED闪烁效果。

使用Keil或其它工具打开该工程,我们可以发现STM32CubeMX已为我们生成了规范的目录结构

1. 开启LED灯。

gpio.c中我们可以找到IO口初始化的相关代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);

/*Configure GPIO pins : PE8 PE9 PE10 PE11
PE12 PE13 PE14 PE15 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

/*Configure GPIO pin : PB3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

因此我们可以依葫芦画瓢main.c中为LED_SEL口使能,让其LED灯正常工作

1
2
3
4
5
6
7
8
9
10
11
12
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();

// 允许LED输出
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);

while (1) {}
}

其中GPIO_PIN_SET实为1,即高电平;同理GPIO_PIN_RESET0,即低电平

2. 实现时间中断函数

image

tim.c中我们可以发现它有一个全局实例时钟通过该实例进行区分
开启该时钟,我们需要将其初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();

// 允许LED输出
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);

// 使能TIM1
HAL_TIM_Base_Start_IT(&htim1);
while (1) {}
}

然后编写时间中断函数即可。

1
2
3
4
5
6
7
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{
if (htim->Instance == TIM1) {
// TIM1中断, 1s
HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_8);
}
}

这里我选择将LED灯A每1s进行一次翻转,从而实现闪烁效果

五、下载验证

代码编写好后,如果正确安装了J-Link驱动,将开发板上的SWD口接入PC,则可在设备管理器中找到如下条目

image

然后打开Keil,如下图配置J-Link调试

image image

进入J-Link设置,按如下配置端口和频率

image image

然后编译

image image

至此,我们将其下载到开发板上,按下REST键即可验证

image image image

六、调试

设置断点后,即可进入调试模式

image image
由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务
总字数 42.3k 访客数 访问量