STM32F407ZGT6中基础的GPIO输入输出设置和按键控制LED的点亮(HAL库)

工具使用:STM32CubeMX,Keil 5

库:HAL库

STM32CubeMX是ST公司专门为STM32准备的开发/初始化工具。

Keil 5是将C/C++编译、上传(烧录)进开发板的编译器。支持绝大部分芯片。

本片文章是初学者为为未来的提供开发工具与开发逻辑的小结。

前言


GPIO接口是STM32最基本的接口。其本质就是芯片与外部通讯的通道。

GPIO输入初始化

 KEY对应针脚的查找与分析

不同的开发板有不同的布线与部件,一般可以在开发板购买处的售后那里获得开发板的电子版电路图。本人的电路图为例,找到KEY对应的GPIO接口。本块电路板对应的GPIO设置中,KEY_UP对应着PA0,KEY0对应着PE4,KEY1对应着PE3,KEY2对应着PE2。

观察电路图可以得知,按下按键KEY_UP时,电源(VCC)与PA0针脚直接导通,此时PA0针脚为高电平。而按下按键KEY0时,底线(GND)与PE4针脚直接导通,此时PE4针脚为低电平。相应的按下按键KEY1时,底线(GND)与PE3针脚直接导通,此时PE3针脚为低电平、而按下按键KEY2时,底线(GND)与PE4针脚直接导通,此时PE2针脚为低电平。

笔者选择使用了KEY_UP和KEY1作为演示。

GPIO输入设置与意义

在STM32CubeMX中初始化需要的按键针脚为GPIO_Input模式。

GPIO_Input的设置相较于输出会少很多。因为针脚的电压只有高电平和低电平两个实际状态。

GPIO Mode

GPIO输入只有一种模式,即Input mode。需要注意的是,该模式要避免直接和Output Push Pull(推挽输出)的针脚在硬件层面直接相连,可能会烧坏芯片。

GPIO Pull-up/Pull-down

GPIO Pull Up/Pull Down指的是GPIO设置的上拉电阻(Pull-up resistor)与下拉电阻(Pull-down resistor)。当一个高电平信号输入时,若没有下拉电阻,高电平信号会维持一定的时间,干扰电路的运行。当处于低电平时,若没有上拉电阻,电路会维持在低电平,也干扰电路的运行。因此一般会配置一个上拉电阻或下拉电阻。在这个例子中,配置它是必要的。

按下按键KEY_UP时,电源(VCC)与PA0针脚直接导通,此时PA0针脚为高电平。因此我们对KEY_UP是否被按下的侦测是通过侦测PA0针脚的电位情况来确定的。对于KEY_UP而言,PA0按下后变为高电平,因此PA0针脚默认应当为低电平。为避免剩余电势对侦测产生影响,及时导出剩余的电势,将PA0在KEY_UP未按下时维持在低电平,应当将GPIO Pull Up/Pull Down配置Pull-down(下拉电阻)。

相反按下按键KEY1时,地线(GND)与PE3针脚直接导通,此时PE3针脚为低电平。因此我们对KEY1是否被按下的侦测是通过侦测PE3针脚的电位情况来确定的。对于KEY1而言,PE3按下后变为低电平,因此PE3针脚默认应当为高电平。为避免剩余电势对侦测产生影响,及时导出剩余的电势,将PE3在KEY1未按下时维持在高电平,应当将GPIO Pull Up/Pull Down配置Pull-up(上拉电阻)。

UserLabel


UserLabel 最好避免非英语美式键盘字符。

GPIO输出初始化


STM32的输出功率有限,处理器处理能力也有限。因此大部分针脚与功能默认处于关闭状态,需要专门的指令进行初始化。这也引出了第一个问题初始化。

STM32就像一大堆上锁的箱子,箱子上都挂了一把默认的锁。  因此第一步便是将要使用的针脚进行初始化,也就是拿上需要用的钥匙将需要用的锁打开,才能使用里面的内容。

在STM32CubeMX里面可以轻易的找到初始化工具。

在初始化里面可以找到很多初始化之后可以设置的内容,其中GPIO_Input为输入,GPIO_Output为输出。

下面将使用最基本的点亮LED实验进行演示。

 LED对应针脚的查找与分析


不同的开发板有不同的布线与部件,一般可以在开发板购买处的售后那里获得开发板的电子版电路图。本人的电路图为例,找到LED对应的GPIO接口。本块电路板对应的GPIO设置中,DS0(发光二极管)对应STM32芯片针脚PF9,DS1对应STM32芯片针脚PF10。

STM32的针脚输出一般为3.3V,而电流的流向从高电压流向低电压,因此在PF9,PF10输出高电平的状态时,发光二极管两侧电压均为3.3V,压差为零,无电流流过。当PF9,PF10输出低电瓶时,电压大小为GND(一般为0V),此时电压从VCC流向DS0和DS1,通过PF9,PF10流向GND,发光二极管进行发光。

一般我们希望二极管的发光可控,因此默认的GPIO output value设置为High,mode设置为Output Push Pull(国内一般叫推挽输出),GPIO Pull Up/Pull Down设置为Pull-up。Maximum output speed 随意, User Label 起一个自己喜欢的名字即可,最好使用英语字符。

GPIO输出设置与意义


GPIO output value


其中,GPIO output value是初始化之后GPIO的电平高低,为了保证LED初始状态为关闭状态,因此初始设置为高电平。

GPIO mode


GPIO mode 有Output Push Pull(国内一般叫推挽输出) 和Output Open Drain(国内一般叫开漏输出)两个选项。其中Output Push Pull推挽输出意味着由芯片本身直接向针脚供电来提供高电平,经过芯片接通电源(VCC),低电平会将针脚与地线(GND)相连产生低电平。而Output Open Drain开漏输出是的高电平只使用STM32针脚附近的部分门电路,通过上拉电阻连接电源,电源经过上拉电阻而非经过芯片达到针脚,输出高电平,低电平会将针脚与地线(GND)相连产生低电平。

具体原理可以看https://zhuanlan.zhihu.com/p/1913227702481158423

因此功率上Output Push Pull推挽输出功率更大,但是在大负载的情况下会烧毁电路。而相反Output Open Drain开漏输出功率较小,但是在功率有限的芯片上可以支持更多小负载。

GPIO Pull Up/Pull Down

GPIO Pull Up/Pull Down指的是GPIO设置的上拉电阻(Pull-up resistor)与下拉电阻(Pull-down resistor)。当一个高电平信号输入时,若没有下拉电阻,高电平信号会维持一定的时间,干扰电路的运行。当处于低电平时,若没有上拉电阻,电路会维持在低电平,也干扰电路的运行。因此一般会配置一个上拉电阻或下拉电阻。但在这个例子里并不是必要的。因为当电路被切断时,即使二极管电源(VCC)侧电压更高,通过二极管的电流会达到另一侧使二极管两端电势差被抹平,恢复到熄灭状态,上拉电阻并不是必要的。可以设置为No Pull-Up and No Pull-Down或是Pull Up。

Maximum output speed


Maximum output speed本质上就是设置IO口驱动电路的响应速度。

配置高速:输出频率高,噪音大,功耗高,对外辐射较强的电磁干扰,同时也是其易受电磁干扰。

配置低速:输出频率低,噪音小,功耗低,对外辐射的电磁干扰更弱,相应的也更不容易受到电磁干扰。

LED对电磁干扰并不敏感,也对电路的响应速度要求不高,因此任意值皆可。

UserLabel


UserLabel 最好避免非英语美式键盘字符。

STM32CubeMX其他初始设置

 Pinout & Configuration设置

SYS

Debug:本人配置为Serial Wire

Timebase Source:SysTick

RCC

High Speed Clock(HSI): Crystal/Ceramic Resonator.(启用外部高频晶振)

NVIC,DMA,IWDG.WWDG:

不用管

Clock Configuration

这里是设置时钟频率的区域。

Input frequency

芯片内置了一个晶振Crystal/Ceramic Resonator,一般在开发板外部也有数个外置晶振,比如我们在RCC里面启用的外置高频晶振(HSE)。其在画面最左侧,从上到下居中的蓝色方框中(HSE的左侧)。正上方灰色的是外置低频晶振(LSE),这次实验并不是必要的,没有在RCC中启用,因此在这个界面是灰色且不可编辑的。HSE左侧的蓝色方框(Input frequency)可以进行编辑,其对应的是在芯片周围外部晶振的频率,在这里必须要设置的与开发板上高频晶振的频率相同,不然程序将无法正常运行。

寻找外置高频晶振的方法也很简单,与寻找LED处相同。在从售后那里获得的开发板电路图那里寻找与晶振相关的数据。

在这里我们可以看到,外置高频晶振(HSE)的工作频率为8MHz,外置低频晶振(LSE)的工作频率为32.768KHz。注意这里数量级的M(兆)与k(千)的差距。

PLL Source Mux & System Clock Mux

在HSE右侧有一个PLL Source Mux,将其设置为HSE,这杨可以使芯片外部输入的外部晶振进入倍频器(PLL)。并在System Clock Mux处选择PLLCLK,这样可以正式启用对系统时钟的倍频器。后面会解释为什么要设置倍频器。

这里注意到,笔者的STM32芯片内置一个高频晶振(HSI),但是其精度一般不如外部晶振提供的晶振数据精确,因此一般会使用外部晶振来作为时钟源。

SYSCLK & HCLK

为了最大化芯片运行效率,一般在SYSCLK和HCLK处设置为最大的工作频率,其在画面的居中处即可。设置蓝字168MHz max上面的HCLK的频率为168,STM32CubeMX会自动的设置剩余芯片的频率设置。

如果前面PLL Source Mux和System Clock Mux处不使用倍频器,那这里的SYSCLK和HCLK只能使用外部高频晶振的8MHz或芯片内部封装的高频晶振16MHz,无法发挥出芯片最大的效能。

如果此时你调整HCLK的数据,STM32CubeMX会提醒并自动使用内置高频晶振(HSI)和倍频器来达到设置的数据。请务必要注意设置为外置高频晶振(HSE)而非内置高频晶振(HSI)。

Project Manager

Project

Project Name 指的是生成项目的名称,注意不要有非美式键盘字符即可。

ToolChain Folder Location 指的是项目生成的位置路径。注意路径不要有非美式键盘字符。

ToolChainIDE 指的是编译器的类型,这里笔者使用的是Keil 5,在这里选择MDK-ARM。

Code Genernator

在STM32Cube MCU packages and embedded software packs 中选择Copy only the necessary library files。这样会使生成的代码与文件更简洁。

Generated files 要勾选以下三个方便后续调试。

Advanced Settings

在这里不用管。

GENERATE CODE

按下右上角的GENERATE CODE,可能会卡一段时间,请耐心等待。

加载完毕后,会弹出以下窗口,说明代码已经生成完毕,我们点Open the Project。

 代码编译与烧录

魔术棒设置

先找到魔术棒。

Device

STM32CubeMX已经预设好了对应的设备型号,无需改动。

Target

勾选Use MicroLIB。

Output Listing User Asm Linker Utilities

默认都已经设置好了。

C/C++

勾选C99Mode, One ELF Section per Fuction, GNU extensions

Debug

这个很重要,笔者用的是CMSIS-DAP Debugger,不同用的设备用的不一样,建议去看专门的教程。这里就以笔者的CMSIS-DAP Debugger举例。点击Settings

这里Port 选择SW,Max Clock 选择5MHz。

这里笔者的连接出了一点问题,No Debug Unit Devie found。关闭魔术棒,重新连接设备,相应位置就会显示对应的调试器,左侧的CMSIS-DAP-JTAG/SW Adapter选择Any。

在Flash Download 中选中 Erase Sectors, 勾选Program,verify,Reset and Run。

代码分析

if(HAL_GPIO_ReadPin(GPIOE,KeyDown_Pin)==0)

{

读取针脚的电平情况,根据电路图可知,按下KEY1时,PE3为低电平;松开PE3时,KEY1为高电平。通过该代码读KeyDown(PE3)针脚的电平情况。其中,GPIOE代表是GPIOE列的针脚,KeyDown_Pin代表是KeyDown这个特定的针脚,因为KeyDown本身是笔者定义的名字,用针脚号GPIO_PIN_3代替KeyDown_Pin也可以。

HAL_GPIO_ReadPin(,)读取出1,代表高电平;读取出0,代表低电平。在这里,按下KEY1时,PE3为低电平,因此当HAL_GPIO_ReadPin(GPIOE,KeyDown_Pin)的取值为0时进行下一步判定。

HAL_Delay(10);

进行10毫秒(10ms)的延时,本质是为了消除电路启动/关闭产生的瞬时抖动对判定的影响。

if(HAL_GPIO_ReadPin(GPIOE,KeyDown_Pin)==0)

{

在消除抖动后进行再次判断,HAL_GPIO_ReadPin(,)读取出1,代表高电平;读取出0,代表低电平。在这里,按下KEY1时,PE3为高电平。HAL_GPIO_ReadPin(GPIOF,KeyDown_Pin)的取值为0时,执行下一步

        HAL_GPIO_WritePin(GPIOF,LEDRed_Pin,GPIO_PIN_RESET);

先说明是GPIO针脚中的F列(GPIOF);

再是GPIOF中的针脚LEDRed_Pin(笔者这里对应的针脚是PF9,是F列的第9个针脚,因此LEDRed_Pin可以替换为GPIO_PIN_9,代表该列的第9个针脚);红色LED被点亮。

}

else

{

HAL_GPIO_WritePin(GPIOF,LEDRed_Pin,GPIO_PIN_SET);

}

GPIO_PIN_SET的意思便是将该针脚设为高电平,即当判定不再被满足时,使得LED熄灭。

也可以将这行替换为HAL_Delay(10);进行消抖,这里笔者偷懒就直接复制了。

else

{

HAL_GPIO_WritePin(GPIOF,LEDRed_Pin,GPIO_PIN_SET);

}

GPIO_PIN_SET的意思便是将该针脚设为高电平,即当判定不再被满足时,使得LED熄灭。

if(HAL_GPIO_ReadPin(GPIOA,KeyUp_Pin)==0)

{

读取针脚的电平情况,根据电路图可知,按下KEY_UP,PA0为高电平;松开KEY_UP时,PA0为低电平。通过该代码读KeyUp(PA0)针脚的电平情况。其中,GPIOA代表是GPIOA列的针脚,KeyUp_Pin代表是KEY_UP这个特定的针脚,因为KEYUp本身是笔者自定义的名字,用针脚号GPIO_PIN_0代替KEYUp_Pin也可以。

HAL_GPIO_ReadPin(,)读取出1,代表高电平;读取出0,代表低电平。在这里,按下KEY_UP时,PA0为低电平,因此当HAL_GPIO_ReadPin(GPIOA,KeyUp_Pin)的取值为1时进行下一步判定。

HAL_Delay(10);

进行10毫秒(10ms)的延时,本质是为了消除电路启动/关闭产生的瞬时抖动对判定的影响。

if(HAL_GPIO_ReadPin(GPIOA,KeyUp_Pin)==1)

{

在消除抖动后进行再次判断,HAL_GPIO_ReadPin(,)读取出1,代表高电平;读取出0,代表低电平。在这里,按下KEY_UP时,PA0为高电平。HAL_GPIO_ReadPin(GPIOA,KeyUp_Pin)的取值为1时,执行下一步

        HAL_GPIO_WritePin(GPIOF,LEDGreen_Pin,GPIO_PIN_RESET);

先说明是GPIO针脚中的F列(GPIOF);

再是GPIOF中的针脚LEDGreen_Pin(笔者这里对应的针脚是PF10,是F列的第10个针脚,因此LEDGreen_Pin可以替换为GPIO_PIN_10,代表该列的第10个针脚);

绿色LED被点亮。

}

else

{

HAL_GPIO_WritePin(GPIOF,LEDGreen_Pin,GPIO_PIN_SET);

}

GPIO_PIN_SET的意思便是将该针脚设为高电平,即当判定不再被满足时,使得LED熄灭。

也可以将这行替换为HAL_Delay(10);进行消抖,这里笔者偷懒就直接复制了。

else

{

HAL_GPIO_WritePin(GPIOF,LEDGreen_Pin,GPIO_PIN_SET);

}

GPIO_PIN_SET的意思便是将该针脚设为高电平,即当判定不再被满足时,使得LED熄灭。

编译与烧录

按以下键编译

最后按烧录

这个程序就被写入并运行在板子上了.。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值