学习stm32单片机的时候,会有三种,标准库,寄存器,HAL库。这里我们统一使用HAL库,使用stm32cubemx来建工程。会方便很多简化我们编写代码的时间但其实不管是HAL库还是标准库都是操作寄存器的只是官方给我们封装好了。软件就不演示安装了 。欢迎各位指出我的错误,共同进步。
我们通过每个案例来介绍单片机的知识点,流水的单片机,铁打的LED灯。大部分来说不管是什么单片机都是以点亮LED灯为基础
目录
一分析原理图

这里我们根据给的原理图,找到led的区域。
先看LED0 是和PB5引脚相连的 即PB5引脚控制着LED0的电平,上接3.3V电压,即默认是高电平,所以我们将PB5设置为低电平的时候,电路导通。
(这里我们说明一下,电路导通,是需要一个高电平和一个低电平导致电流可以正常流通的。这里根据原理图发现PB5这个引脚所在的电路,是外接的有3.3V的VCC,即板子一上电就会有高电平)
所以我们想让LED0亮,就将PB5引脚设置为低电平。LED1同理。
那我们怎么设置,能否设置引脚为低电平或高电平呢?
二GPIO
2.1 什么是GPIO?
概述:General Purpose Input Output,即通用输入输出端口,简称GPIO 作用:负责采集外部器件的信息或者控制外部器件工作,即输入输出。
是不是很迷糊,简单来就是控制引脚使其能够达到输入和输出电平的操作。
比如我们这里的LED,我们需要将PB5设置为低电平,那是输入还是输出呢?
注意:这里的输入和输出的操作对象即主体是单片机。所以我们需要单片机去给PB5引脚输出低电平。即设置为输出模式。
2.2GPIO的特点
1,不同型号,IO口数量可能不一样,可通过选型手册快速查询
2,快速翻转,每次翻转最快只需要两个时钟周期(F1最高速度可以到50Mhz)
3,每个IO口都可以做中断 (后面会说明什么是中断)
4,支持8种工作模式
2.3GPIO的八种模式分析

我们具体分析一下每一个模式

这里是不通过任何的上下拉,走向如图直接IO引脚到输入寄存器IDR

这里0和1是什么意思呢?当我们设置0的时候就是0 设置1就是1 当空闲的时候,即人为不设置的时候,上拉电阻打开,VDD是高电平即空闲的时候 IO是高电平

这里如果设置是下拉,空闲的时候因为下拉电阻的打开下接了VSS是低电平
上拉电阻和下拉电阻,TTL都关闭 即模拟输入




这里补充一下,当IO口设置为输出模式的时候,也是可以读取IO的电平状态的。
正常情况开漏和推挽的区别是:开漏输出无法输出高电平(必须加外部上拉电阻),推挽可以
这里我们总结一下GPIO的八种模式 又可以分为输出和输入
输入:1 浮空输入
2 上拉输入
3 下拉输入
4 模拟输入
输出:1 开漏输出
2 复用开漏
3 推挽
4 复用推挽
三stm32cubemx配置
我们说完了GPIO的基础知识我们来看怎么用cubemx来配置
这里我们新建工程
输入自己单片机的型号

点system core,然后点RCC配置时钟

选择外部时钟

关于时钟树,大家可以去看正点原子的视频很详细。

将PB4,PE5 设置为输出

第一个是你项目的名字 第二个一定要选择MDK-ARM

点击生成就好了
四代码分析

void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};//初始化GPIO使用的结构体变量
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();//打开gpioe的时钟
__HAL_RCC_GPIOB_CLK_ENABLE();//打开gpiob的时钟
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET);//将PE5 设置为低电平
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);//将PB5 设置为低电平
/*Configure GPIO pin : PE5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;//选择引脚号
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);//初始化GPIO
/*Configure GPIO pin : PB5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;
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);
}
这里我们打开gpio.c 可以看到相关的代码,这里我们根据代码的顺序涉及到的知识,一个一个描述,会涉及的有点多。
首先我们初始化某个GPIO引脚的第一步,找到设置变量的数据类型是一个结构体
1 我们先设置变量初始化为0 我们来看一下这个结构体变量的成员
GPIO_InitTypeDef GPIO_InitStruct = {0};//初始化GPIO使用的结构体变量
go to 一下找到这个结构体的定义

typedef struct
{
uint32_t Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */
uint32_t Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIO_mode_define */
uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
This parameter can be a value of @ref GPIO_pull_define */
uint32_t Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIO_speed_define */
} GPIO_InitTypeDef;
这里就是结构体的成员,分别是 引脚号,模式,上下拉选择,速度 这里就不一一go to给大家看了 大家自己看一下,这里的官方定义也给的很详细。
2 打开对应的时钟
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();//打开gpioe的时钟
__HAL_RCC_GPIOB_CLK_ENABLE();//打开gpiob的时钟
3 设置gpio变量各成员的值
/*Configure GPIO pin : PE5 */
GPIO_InitStruct.Pin = GPIO_PIN_5;//选择引脚号
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出模式
GPIO_InitStruct.Pull = GPIO_NOPULL;//无上下拉,输出一般是无上下拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;//传输速度
4 初始化变量
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);//初始化GPIO变量
补充:这里我们可以看到有涉及到一个HAL库函数,函数是将PE5 设置为低电平
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_RESET);//将PE5 设置为低电平
我们看一下函数原型,和官方给的函数解释
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
Sets or clears the selected data port bit
大概意思是将某个引脚设置为 高/低 电平
到这里GPIO对应的引脚就初始化完成了,这里我们还没有编写主函数的代码,但是我们已经通过HAL_GPIO_WritePin函数将俩个函数的引脚设置为低电平了,根据一分析原理图的时候,知道将引脚设置为低电平的时候电路就导通了,LED会亮,我们来烧录一下试试

这里先编译,然后再烧录

灯是亮的,我们这里已经完成了最初的目的,这里我们在主函数里面添加代码来实现流水灯的效果,并通过#define 来封装一下相关引脚 方便移植

这里我封装了LED0 和LED1
主函数while(1)死循环里面的代码实现了灯的闪烁
LED
这里烧录一下就可以完成目的了
五 通过按键控制LED的亮灭
5.1 key的原理图分析
这里大家想一下,按键是输入还是输出,按键按下得到电平变化,是向单片机输入信号的,所以配置为输入 (还有一种说法,按键按下单片机是需要采集信号的,所以是像单片机输入)

这里我们看原理图当按键没有按下的时候,电平不确定,是高阻态。当按键按下的时候PA0是高电平,我们需要将PA0设置为俩种状态来区分是否按键按下,已知按下是高电平 所以我们需要设置为下拉输入,按键不按下的时候是低电平
同理 PE4 PE3 就上拉输入
补充:按键我们需要延时10ms 消抖

5.2cubemx配置
PA0

PE3 PE4是一样的就举一个

5.3代码
在演示代码前,我们先说几个库函数
1 读取某引脚的电平状态,原型可以go to
HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
2 翻转某引脚的电平
HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
3 延时函数 单位ms
HAL_Delay(uint32_t Delay)
gpio.h的一些封装

主函数的代码
while (1)
{
if(HAL_GPIO_ReadPin(KEY_UP_PORT,KEY_UP_PIN)==1)//读取key_up的电平是否为1 为1即按键按下
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY_UP_PORT,KEY_UP_PIN)==1)//读取key_up的电平是否为1 为1即按键按下
{
HAL_GPIO_TogglePin(LED0_PORT,LED0_PIN);
HAL_GPIO_TogglePin(LED1_PORT,LED1_PIN);
}
}
if(HAL_GPIO_ReadPin(KEY0_PORT,KEY0_PIN)==0)
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(KEY0_PORT,KEY0_PIN)==0)
{
HAL_GPIO_TogglePin(LED0_PORT,LED0_PIN);
}
}
if(HAL_GPIO_ReadPin(KEY1_PORT,KEY1_PIN)==0)
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(KEY1_PORT,KEY1_PIN)==0)
{
HAL_GPIO_TogglePin(LED1_PORT,LED1_PIN);
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
这里需要工程的私聊我就好