Stm32 单片机学习笔记

简介

使用芯片型号 开发环境 开发方式
STM32H750VBT6 CubaMX+CLion HAL库

CubaMX的开发环境配置 可以参考这篇文章

Clion-STM32cubeMX-搭建舒适的STM32开发环境

​ 大家最好要有一些单片机的基础知识比如说51单片机,C语言以及一些数电模电的知识,这样学起来会舒服很多哦!

在这里说一下,为什么不讲标准库:

​ 首先的话,目前STM32开发方式有以下几种,我整理了一张表格

开发方式 优点 缺点 建议
寄存器 代码效率高 学习难度大,移植性最低 了解
标准库 开发流程便简单,开发周期缩短 代码执行效率稍低,移植性较低 熟悉
HAL库 上手简单,移植方便 执行效率稍低 掌握

​ STM32已经应用的非常广泛了,并且在工业开发也具有挺高的地位了,所以我们只需要 学会HAL库就可以完成绝大多数的开发了,并且标准库,早在几年前就不再更新维护了,标准库的话,学习有余力的话可以学学,技多不压身嘛!

STM32的简介

ARMSTM32的关系

ARM:Advanced RISC Machines(高级精简指令集机器)

image-20220916173832375

以上是百度百科的简单介绍,可以看出arm在半导体行业,已经是主导地位,全球超过 95%的智能设备都是采用的ARM架构,其公司的发展史也很有意思,小伙伴们感兴趣可以了解一下

image-20220916175014412

这个是STM32 的命名规则

STM32H750VBT6简介

项目 介绍 备注
内核 Cortex—M7
Falsh 128KB
ROM 1024KB
GPIO 80个 PA015、PB015、PC015、PD015、PE0~15
ADC 3个 五条内部专用通道
– 内部参考电压 (VREFINT),连接到 ADC3
– 内部温度传感器 (VSENSE),连接到 ADC3
– VBAT 监测通道 (VBAT/4),连接到 ADC3
– 内部 DAC 通道 1 和通道 2,连接到 ADC2
DAC 2个 12 位模式
定时器 高级定时器2个 TIM1-TIM8
通用定时器10个 TIM2-TIM3-TIM4-TIM5-TIM12-TIM13-TIM14-TIM15-TIM16-TIM17
基本定时器2个 TIM6-TIM7
看门狗定时器2个 系统窗口看门狗 (WWDG),独立看门狗 (IWDG)
滴答定时器
工作电压 工作电压范围 1.62V~3.6V
通信端口 CANbus,EBI/EMI,以太网,I²C,IrDA,LINbus,MDIO,MMC/SD/SDIO,QSPI,SAI,SPDIF,SPI,SWPMI,UART/USART,USB OTG CAN*2
I2C*4
SPI*5
UART*4
USART*4
OYG*2
系统时钟 HSE(高速外部振荡器)时钟 4 MHz 到 48 MHz

我开发板使用的外部晶振为25MHz

下图为我开发板的原理图

STM32H7xx SchDoc V11_00

GPIO

什么是GPIO?

GPIO是通用输入/输出(General Purpose I/O)的简称,主要用

于工业现场需要用到数字量输入/输出的场合,例如:

  • 输出功能:继电器、 LED、蜂鸣器等的控制

  • 输入功能:传感器状态、高低电平等信息的读取

  • 复用功能:片内外设的对外接口**

  • 时序模拟:模拟SPI、I2C和UART等常用接口的时序

电路结构

image-20221215203902703 $$

$$

image-20221216100541944
image-20221215205623228

GPIO工作模式的用法总结

1.输入模式

浮空输入:按键识别

上拉输入:IO内部上拉电阻输入

下拉输入:IO内部下拉电阻输入

2.模拟模式

作为片内模拟外设的对外引脚

单纯作为低功耗使用


  • 输出模式
    • 推挽输出:可以输出高/电平,主要用于连接数字器件,如指示灯和继电器等模块;
    • 开漏输出:只能输出低电平,适合于电流型驱动,也可作为电平转换。
  • 复用模式
    • 复用推挽:片内外设功能(URAT的TX,RX,SPI的MOSI,MISO,SCK,SS );
    • 复用开漏:片内外设功能( I2C的SCL,SDA )。

引脚初始化数据类型

image-20221215210422481
成员变量Pin的取值范围
宏常量定义 含义
GPIO_PIN_0 选择该端口的引脚0
GPIO_PIN_1 选择该端口的引脚1
GPIO_PIN_2 选择该端口的引脚2
GPIO_PIN_3 选择该端口的引脚3
*** ***
GPIO_PIN_15 选择该端口的引脚15
GPIO_PIN_All 选择该端口所有引脚
成员变量Mode的取值范围
宏常量定义 含义
GPIO_MODE_INPUT 浮空输入模式
GPIO_MODE_OUTPUT_PP 推挽输出模式
GPIO_MODE_OUTPUT_OD 开漏输出模式
GPIO_MODE_AF_PP 复用功能下的推挽模式
GPIO_MODE_AF_OD 复用功能下的开漏模式
GPIO_MODE_ANALOG 模拟模式

成员变量Pull的取值范围

宏常量定义 含义
GPIO_NOPULL 没有上拉或下拉电阻激活
GPIO_PULLUP 上拉电阻激活
GPIO_PULLDOWN 下拉电阻激活
成员变量Speed的取值范围
宏常量定义 含义
GPIO_SPEED_FREQ_LOW 引脚输出速度2MHz
GPIO_SPEED_FREQ_MEDIUM 引脚输出速度12.5MHz~50MHz
GPIO_SPEED_FREQ_HIGH 引脚输出速度25MHz~100MHz
GPIO_SPEED_FREQ_VERY_HIGH 引脚输出速度50MHz~200MHz

成员变量Alternate的取值范围

  • Alternate表示引脚的复用功能;
  • 由于不同型号的STM32微控制器片内集成的外设不同,因此该成员变量的取值范围由芯片型号决定。
  • 以STM32F4系列芯片为例,通过查阅stm32H7xx_hal_gpio_ex.h文件可以了解Alternate的取值范围;
  • 该成员变量的取值一般通过CubeMX软件分配,不需要用户手动设置;

引脚电平状态数据类型

image-20221215211612934

使用枚举类型的好处:提高了程序的可读性,并通过限定变量 的取值范围,来确保变量的合法性

使用HAL库的GPIO引脚初始化步骤

image-20221215213012641

GPIO外设接口函数的概述

初始化函数
  • HAL_GPIO_Init :用于完成引脚的初始化;

image-20221215213612676

  • HAL_GPIO_DeInit :用于复位引脚到初始状态;
image-20221215213642893
控制函数
  • HAL_GPIO_ReadPin :用于读取引脚电平状态
image-20221215213831597
  • HAL_GPIO_WritePin :用于设置引脚电平状态
image-20221215213900821
  • HAL_GPIO_TogglePin :用于翻转引脚电平状态
image-20221215213911153
配置函数
  • HAL_GPIO_LockPin:用于锁定引脚的配置
image-20221215213923020

任务1:点亮LED灯每隔500ms闪烁

Clion 配置 如何生成STM32工程 可以看之前的文章

配置 时钟频率

​ 因为我使用的是STM32H750VBT6 他的工作频率是480Mhz

image-20221219171132276配置引脚

观察原理图 发现LED在PE3上

image-20221219171256573

点击PE3 出现以下对话框

image-20221219171344974

选择 GPIO_Output 引脚变为绿色

在 Systeam Core -> GPIO 对引脚详细配置

如默认电平 , 上拉下拉电阻 ,推挽等,以及用户自定义名字

用户自定义名字 方便后续代码中使用 (起名 尽量 见名知意 )如Power_Led等

我其他的所有参数均为默认 用户自定义名字为LED

image-20221219191209272

生成文件

  • 看之前的文章

注意在生成的时候 在Toolchain/IDE 选择SW4STM32 clion 才可以打开

如果使用的keil 需要选择MDK-ARM

代码编写

1
2
3
4
5
6
7
8
9
10
11
  while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); //电平反转
HAL_Delay(500);//延迟500ms

}
/* USER CODE END 3 */
}

因为我之前 在CubaMX 配置的时候 LED 的名字被配置成了LED 所以 LED_Pin 就是指代的 PE13

代码 写在

/* USER CODE BEGIN 3 */ 到

/* USER CODE END 3 */下

防止在使用CubaMX 生成代码的时候 你自己写的代码被删除

以上的程序 实现的效果是LED小灯每隔500ms 亮灭交替


任务2: 按键控制小灯(轮询法)

在 while中 读取按钮的状态

引脚配置

image-20221219192737821

可以看出 原理图中通过一个电阻与地GND相连,固定在低电平。在IO口为输入模式且为下拉电阻时,IO口的常态为低电平。

所以 在设置引脚的时候需要设置为下拉输入

image-20221219193046799

选择为 GPIO_Input

在 Systeam Core -> GPIO -> PC13 -> GPIO Pull-up/Pull-down 选择 Pull-down

User Label 设置为 Key 这个 可以自定义

下图就是设置好的

image-20221219193342362

生成工程 编写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
if(HAL_GPIO_ReadPin(Key_GPIO_Port,Key_Pin) == GPIO_PIN_SET){ //判断是否为 高电平 如果为高电平 则被按下
HAL_Delay(20); //去抖动
if(HAL_GPIO_ReadPin(Key_GPIO_Port,Key_Pin) == GPIO_PIN_SET){ //去抖动后 如果还为高电平 则就是被按下 反转LED的状态
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
while(HAL_GPIO_ReadPin(Key_GPIO_Port, Key_Pin) != GPIO_PIN_SET);//检查钥匙是否松开
}
}
HAL_Delay(100);//防止扫描过快
}
/* USER CODE END 3 */

任务3:利用状态机控制按键

状态机设计思想

状态机是一个抽象概念,表示把一个过程抽象为若干个状态之间的切换,这些状态之间 存在一定的联系。状态机的设计主要包括4个要素: 1. 现态:是指当前所处的状态。 2. 条件:当一个条件满足,将会触发一个动作,或者执行一次状态的迁移。 3. 动作:表示条件满足后执行动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作要素不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。 4. 次态:表示条件满足后要迁往的新状态。

按键的状态机设计

一:状态定义:根据按键的波形图可以设计三个按键状态

  • 按键检测状态:表示按键没有按下的状态
  • 按键确认状态:表示按键已经按下的状态
  • 按键释放状态:表示等待按键释放的状态

二:状态转换条件(假设低电平表示按键按下)

  • 当处于按键检测状态时,如果数据线为低,则转换到按键确认状态,否则保持当前状态。
  • 当处于按键确认状态时,如果数据线为低,则转换到按键释放状态,并设置按键有效标志;如果数据线为高,则表示可能出现了干扰信号,转换到按键检测状态。
  • 当处于按键释放状态时,如果数据线为高,则转换到按键检测状态,表示完成了本次按键检测,否则保持当前状态。

状态转换图

image-20221225123004244

假设采用上拉式按键,低电平表示按键按下,高电平表示按键释放

按键的状态机编程实现

利用Switch Case多分支语句,通过检测按键引脚的电平来实现按键状态的转换;

利用定时器产生10ms的定时中断,在定时中断服务程序中调用按键状态转换函数。每次执行的间隔10ms,可以有效的消除按键抖动,并提高CPU的利用率。

image-20221225123223315
使能定时器中断
image-20221225123247174
定义按键状态数据类型
image-20221225123321988
主程序代码
image-20221225123344324
定时中断回调函数
image-20221225123545532
image-20221225123616224