Stm32学习汇总
本文最后更新于:2024年9月13日 早上
前言
得到这块板子是源于学校的一个口袋实验室的实验课程。每小组分一块正点原子的阿波罗Stm32F4的板子并要求自学。由于个人也有一定的嵌入式开发的意向,于是将Stm32学习的部分于此记录成博客。
初步介绍
全面的板子介绍在开发指南上写有。在此补充一些初学者对板子的认知,可能会方便理解一些。
Stm32的芯片其实在学校发的这块正点原子的板子只是很小的一个部分,这块板子上的绝大多数配件是配套设施很全的外设。
板子的供电有两种方式,一种是直接用右上角的充电接口连接电源,另一种是通过USB SLAVE接口连接到电脑。
其中直接供电的话最高电压会高一些(16v→12v)USB SLAVE链接的是电脑usb接口所以在跑一些耗电量较大的工程时可能会带不太动。
与电脑的交互部分,我们可以通过USB SLAVE来直接下载代码以及向电脑发送串口信号。还可以通过STLink来进行电脑的下载。(关于STLink的介绍及配置)
然后是代码编辑器。使用的是keil5,需要注册。没注册的话只能编译大小受限的代码,解决方法是在网上找到了注册软件。(注意,我的这个是2020版的,网上大多是比2020更早的版本,若是后来者发现注册码无法激活,可能需要找到最新版的软件来生成。)
编辑器具体配置可以去看正点原子的官方教程,一步一步来就不会出错。
开始学习
注明:我学习的是HAL库写法,HAL库封装的功能很多并且对于初学者很友好。
Hello World
大多数东西初学的时候都会由Hello World来引入。Stm32的hello world 就是点亮第一盏LED灯。
在 main.c
中,首先得初始化HAL库 HAL_Init();
,将HAL库引入程序。之后设置系统时钟。有一定电路基础的话就知道,时钟提供了周期性变化的电压,给整个系统确立了最小的单位时间以及维持着整个系统的时间轴,对于任和想实现的功能来说时钟是极为重要的。设置系统时钟的代码为 Stm32_Clock_Init(360,25,2,8)
。括号里的参数可以自己配置,不过对于这块板子(STM32F429)来说这些数据是固定的。(关于时钟配置的详细讲解移步这里)。
下一步是确定自己所要使用的接口,我们自己可以配置的接口也就是通用性接口是GPIO接口,这些接口可供自由使用。 GPIO_InitTypeDef GPIO_Initure
可以初始化一个GPIO类型的结构体,我们可以通过这个结构体来对GPIO接口来做相应的配置。(关于GPIO的详细讲解移步这里)。
点亮LED灯,所需的接口是GPIOB 的 Pb0 | Pb1 接口。首先开启GPIOB的时钟 语句是 __HAL_RCC_GPIOB_CLK_ENABLE();
然后给GPIO类型的结构体赋值,大概是这样:
1 |
|
其中第一条确定的是哪个或者哪些接口,后面的则都是在规范IO类型。
然后就是将这个结构体赋值到接口上 HAL_GPIO_Init(GPIOB,&GPIO_Initure);
这句话的意思是把我们所赋值的这个结构体复制到GPIOB的接口上。
完成这一步,就已经把所用接口的准备工作做完了。
然后就是主程序部分,主程序是一个while循环,我们将在这里完善自己的程序逻辑。
点亮LED灯所需要的是给LED的两级接上高低不同的电压。通过原理图可以知道,当输出电平为低电平时LED单向导通发亮。因此假如发亮就得让GPIO口输出电平为低,反之则为高。
我们可以通过 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
来将GPIOB的PB1接口设置为高电平。 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
将GPIOB的PB1接口设置为低电平。只要在函数里加上这两条语句,就能使LED亮灭了。
但是假如直接这么写的话你会发现LED好像是恒亮的,这是因为由于人眼的视觉暂留因素,高频率的亮灭无法让人区分。因此我们可以在这两条亮灭语句后各添一条延时函数,让LED保持状态一段时间。常用的是 delay()
函数,当然也可以自己写一个简单的循环,按照之前打OI的经历,大概2e8次空循环是1s。
代码如下: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#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
void Delay(__IO uint32_t nCount);
void Delay(__IO uint32_t nCount){while(nCount--){}}
int main(void)
{
HAL_Init();//HAL库初始化
Stm32_Clock_Init(360,25,2,8);//系统时钟确立
__HAL_RCC_GPIOB_CLK_ENABLE();//GPIOB口时钟确立
GPIO_InitTypeDef GPIO_Initure;
GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PB1,0
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
Delay(0x7FFFFF);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
Delay(0x7FFFFF);
}
}
一些要点
GPIO
介绍
GPIO代表“通用输入/输出”。是集成电路上的一种引脚,没有特定功能。虽然大多数引脚都有特定用途,例如向某个组件发送信号,但 GPIO 引脚的功能是可定制的,并且可以通过软件控制。
GPIO 接口变化很大。在某些情况下,一组可以作为一组切换到输入或输出的引脚。在其他情况下,每个引脚都可以设置为接受或提供不同的逻辑电压,具有可配置的驱动强度和上拉/下拉。输入和输出电压通常受限于带有 GPIO 的设备的电源电压,并且可能会被更高的电压损坏。(所以要小心输入)
GPIO 功能可能包括:
GPIO 引脚可配置为输入或输出
GPIO 引脚可以启用/禁用
输入值是可读的(通常是高低电平)
输出值是可写/可读的
输入值通常可以用作IRQ(通常用于唤醒事件)
Stm32中的GPIO配置
首先是开启时钟 __GPIOA_CLK_ENABLE();//使能GPIOA时钟
以及配置GPIO输入输出模式。
GPIO_InitTypeDef结构体定义有一些赋值项,在HAL库中我们通过为这些元素赋值来控制GPIO。
1 |
|
(1) uint32_t Pin
指定了输出的IO口,可以是一个可以是多个,多个IO口用或(|)符号隔开。
(2) uint32_t Mode
设置了输入输出的模式,模式一共有以下八种:
1 |
|
(3) uint32_t Pull
区分这个GPIO口用于输入还是输出,输出模式的话一般是 no pull
。这样可以正确输出目标值。
当输入模式的时候,需要根据输入值来配置,若默认输入为高电平,则需要 pull up
,反之 pull down
。
上拉(pull up)是对器件注入电流,下拉是输出电流,上拉就是将不确定的信号通过一个电阻钳位在高电平,电阻同时起到限流作用;而下拉就是将不确定的信号通过一个电阻钳位在低电平,电阻同时起到限流作用。
(4) uint32_t Speed
规定输出电路的响应速度,可以理解为输出电路的带宽,涉及到信号失真问题。同时,速度配置越高,噪声越大,功耗越大。
(5) uint32_t Alternate
接口的复用功能,可作为I2C,SPI,USART等通讯接口。此时GPIO的作用不是通用的输入输出。此时端口的输出模式需要配置为复用状态。
GPIO常用函数汇总
GPIO接口初始化
1 |
|
GPIO接口去初始化
1 |
|
读取GPIO的值
1 |
|
向指定接口写入值
1 |
|
对GPIO值取反和锁定
1 |
|
GPIO中断
1 |
|
时钟
时钟是电路的脉搏,这个形容我感觉很贴切,系统时钟的频率很高,统一使用系统时钟(高频)会造成功耗的无意义消耗。STM32F429的时钟有很多源,可以支持许多繁杂的外设。
STM32有五个时钟源,分别是:HSI、HSE、LSI、LSE、PLL。
①、LSI 是低速内部时钟,RC 振荡器,频率为 32kHz 左右。供独立看门狗和自动唤醒单元使用。
②、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。
③、HSE 是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为 4MHz~26MHz。
我们的开发板接的是 25M 的晶振。HSE 也可以直接做为系统时钟或者 PLL 输入。
④、HSI 是高速内部时钟,RC 振荡器,频率为 16MHz。可以直接作为系统时钟或者用作 PLL
输入。
⑤、PLL 为锁相环倍频输出。STM32F4 有三个 PLL:
1) 主 PLL(PLL)由 HSE 或者 HSI 提供时钟信号,并具有两个不同的输出时钟。
第一个输出 PLLP 用于生成高速的系统时钟(最高 180MHz)
第二个输出 PLLQ 为 48M 时钟,用于 USB OTG FS 时钟,随机数发生器的时钟和 SDIO
时钟。
2) 第一个专用 PLL(PLLI2S)用于生成精确时钟,在 I2S 和 SAI1 上实现高品质音频性能。其
中,N 是用于 PLLI2S vco 的倍频系数,其取值范围是:192~432;R 是 I2S 时钟的分频系
数,其取值范围是:2-7;Q 是 SAI 时钟分频系数,其取值范围是:2-15;P 没用到。
3) 第二个专用 PLL(PLLSAI)同样用于生成精确时钟,用于 SAI1 输入时钟,同时还为 LCD_TFT
接口提供精确时钟。其中,N 是用于 PLLSAI vco 的倍频系数,其取值范围是:192~432;
Q 是 SAI 时钟分频系数,其取值范围是:2~15;R 是 LTDC 时钟的分频系数,其取值范
围是:2~7;P 没用到
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!