早上好啊,大佬们,想必在你电脑硬盘的某处放着一个stm32的工程模板吧!~
然后今天,就和大家一起写出第一个小项目——流水灯
咱们先来讲讲GPIO口吧。
关于GPIO的那点事儿
什么是GPIO
GPIO(英语:General-purpose input/output),通用型之输入输出的简称,功能类似8051的P0—P3,其接脚可以供使用者由程控自由使用,PIN脚依现实考量可作为通用输入(GPI)或通用输出(GPO)或通用输入与输出(GPIO),如当clk generator, chip select等。
既然一个引脚可以用于输入、输出或其他特殊功能,那么一定有寄存器用来选择这些功能。对于输入,一定可以通过读取某个寄存器来确定引脚电位的高低;对于输出,一定可以通过写入某个寄存器来让这个引脚输出高电位或者低电位;对于其他特殊功能,则有另外的寄存器来控制它们。
GPIO的优点(端口扩展器)
GPIO的优势
低功耗:GPIO具有更低的功率损耗(大约1μA,μC的工作电流则为100μA)。
集成IIC从机接口:GPIO内置IIC从机接口,即使在待机模式下也能够全速工作。
小封装:GPIO器件提供最小的封装尺寸 ― 3mm x 3mm QFN!
低成本:您不用为没有使用的功能买单。
快速上市:不需要编写额外的代码、文档,不需要任何维护工作。
灵活的灯光控制:内置多路高分辨率的PWM输出。
可预先确定响应时间:缩短或确定外部事件与中断之间的响应时间。
更好的灯光效果:匹配的电流输出确保均匀的显示亮度。
布线简单:仅需使用2条就可以组成IIC总线或3条组成SPI总线。
与ARM 的几组GPIO引脚,功能相似,GPxCON 控制引脚功能,GPxDAT用于读写引脚数据。另外,GPxUP用于确定是否使用上拉电阻。 x为A,B,,H/J,
GPAUP 没有上拉电阻。
(以上内容来源于百度百科)
根本不知道你在说什么
GPIO的原理
毕竟我们是工科生,工科生只需要知道怎么用就行了,对于上面的内容,我们只需要知道这个东西很厉害就行了,不用具体了解,如果是大佬那就当我没说。
下面是我们需要知道的东西:
- GPIO可配置为8种 输入输出 模式
- 引脚电平:0V~3.3V,部分引脚可容忍5V
- 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
这个是GPIO的原理图
然后我们需要知道的是:
所有的GPIO口都是挂载在 APB2 上的。
GPIO的引脚图
stm32c8t6的部分引脚图
对于stm32芯片中有一些引脚口是已经被占用了的,在使用时最好是先避开这一些,当然如果你非要用也是可以的,这个我们后面再讲。
GPIO的模式配置
-
浮空输入(Floating Input):
- 在浮空输入模式下,GPIO引脚没有内部上拉或下拉电阻,因此它的电平状态取决于外部电路。
- 当引脚未连接任何外部电路时,它的电平是不确定的,可能会因为外部噪声或电磁干扰而随机变化。
- 浮空输入模式通常用于读取开关或按钮的状态,当开关或按钮未按下时,引脚处于浮空状态。
-
上拉输入(Pull-up Input):
- 上拉输入模式下,GPIO引脚内部连接了一个上拉电阻到电源(通常是VCC)。
- 当引脚未连接任何外部电路时,它会通过内部上拉电阻被拉高到接近电源电压的电平。
- 这种模式常用于读取开关或按钮的状态,当开关或按钮未按下时,引脚被上拉到高电平;当按下时,引脚被连接到地(GND),电平变为低。
-
下拉输入(Pull-down Input):
- 下拉输入模式下,GPIO引脚内部连接了一个下拉电阻到地(GND)。
- 当引脚未连接任何外部电路时,它会通过内部下拉电阻被拉低到接近地电压的电平。
- 这种模式与上拉输入类似,但逻辑相反。它用于当开关或按钮未按下时,引脚被下拉到低电平;当按下时,引脚被连接到电源,电平变为高。
-
推挽输出(Push-Pull Output):
- 推挽输出模式下,GPIO引脚可以通过内部的晶体管将电流源到引脚上,也可以通过另一个晶体管将引脚上的电流排到地(GND)。
- 这种模式下,GPIO引脚可以输出高电平(接近电源电压)和低电平(接近地电压),因此可以提供完整的逻辑电平。
- 推挽输出适用于需要驱动较大负载或需要明确高低电平信号的场合。
- 推挽输出模式下,GPIO引脚可以与其他同样配置为推挽输出的引脚直接相连,但需要注意避免两个输出同时试图驱动同一线路,这可能导致冲突。
-
开漏输出(Open-Drain Output):
- 开漏输出模式下,GPIO引脚只能将电流排到地(GND),而不能提供电流源到引脚上。这意味着开漏输出只能输出低电平(接近地电压),而不能输出高电平。
- 为了得到高电平,通常需要在外部电路中使用上拉电阻将引脚拉到电源电压。
- 开漏输出适用于需要与其他设备共享控制信号的场合,例如多个设备可以连接到同一条线上,每个设备都可以将信号拉低,但只有当所有设备都不拉低时,信号才为高。
- 开漏输出模式下,GPIO引脚可以与其他同样配置为开漏输出的引脚直接相连,因为它们不会相互冲突,只会在需要时将信号拉低。
-
复用推挽输出:
- 在复用推挽输出模式下,GPIO引脚可以被配置为推挽输出,这意味着引脚可以通过内部的P-MOS和N-MOS管同时提供高电平和低电平输出。
- 这种模式通常用于需要稳定电平输出且能够提供足够电流驱动外部设备的情况,如UART串口通信、PWM(脉冲宽度调制)输出等。
- 复用推挽输出模式允许GPIO引脚在作为通用输出的同时,也可以被配置为特定的外设功能,如I2C的SCL(时钟线)。
-
复用开漏输出:
- 复用开漏输出模式下,GPIO引脚只能输出低电平或高阻态,不能直接提供高电平输出。要得到高电平状态,通常需要外部接一个上拉电阻到电源VCC。
- 这种模式常用于需要与其他设备共享控制信号的场合,例如I2C总线的SDA(数据线)或SPI(串行外设接口)的某些信号线。
- 复用开漏输出模式同样允许GPIO引脚在作为通用输出的同时,也可以被配置为特定的外设功能,但此时引脚只能输出低电平或高阻态。
模拟输入模式是GPIO的一种工作模式,它允许GPIO引脚直接读取外部的模拟信号,即电压信号,而不经过任何数字逻辑处理。在这种模式下,GPIO引脚可以作为ADC(Analog-to-Digital Converter,模数转换器)的输入,用于采集模拟信号并将其转换为数字值进行处理。
上面这些是不是看的云里雾里的,不用担心在不断的练习当中,我们能够知道并熟悉应该是用那种方式,我们一点一点来,现在只需要先知道有这么些个模式就好。
以上就是GPIO口的一些基本内容,下面我们就以GPIO的输出模式为例,写一个流水灯的小实验,来让大家对他有一个基本了解。
首先,输出模式故名思意就是从芯片向外进行输出。
使用GPIO口的输出模式点亮一个LED灯
首先我们先了解以下我们要用到的一些硬件:
stm32c8t6最小系统板
LED灯
ST-Link烧录模块
对于最小系统板,我们就不多介绍了,毕竟这一整个系列都是在说这个,在这里也讲不清楚。
LED灯
LED(Light Emitting Diode),发光二极管,是一种能够将电能转化为可见光的固态的半导体器件,它可以直接把电转化为光。LED的心脏是一个半导体的晶片,晶片的一端附在一个支架上,一端是负极,另一端连接电源的正极,使整个晶片被环氧树脂封装起来。(来源于百度百科)
它的核心部分是由P型半导体和N型半导体组成的PN结。当电流通过LED时,电子和空穴在PN结区域复合,释放出能量,这种能量以光的形式辐射出来,因此LED能够发光。
这边是对它的官方解释,以及它工作原理,但是这些其实对于我们入门而言并不重要。
对于电气元件,我们最先关心的都是哪边是正极,哪边是负极,正负极连反后果不堪设想呀。
显而易见,二极管上面有两个长短不同的引脚,记住这四字箴言:
长正短负
也就是说,二极管的长脚对应正极,短脚对应负极。将二极管的正负极分别接到 Vcc 和 GND 他就能发光。
ST-Link
然后对于ST-Link,这个很好理解。
我们写的代码不是本来是在电脑上嘛,我们要让stm32芯片里面存储这些代码,并且在它上面运行这些代码,那么我们就需要类似于ST-Link这类的烧录模块,在使用时将它插到电脑上就可以了。
然后我们需要在keil上面选择我们的烧录模块。
OK,到这里我们的硬件都已经介绍完了,下面我们来看看代码怎么写。
工程代码分析
首先对于所有的 STM32芯片的东西 都是挂载在一个叫做 时钟 的东西上面的,在上面介绍GPIO口的时候,我们也介绍到,所有的GPIO口都是挂载在 时钟2 (也就是APB2)上的。
所以我们的第一步,就是打开 APB2 时钟。
然后,打开GPIO的时钟之后,我们就能够对GPIO进行操作了,在上面我们也说到了GPIO有很多模式,在同一时刻GPIO只能处于一种模式。所以在控制GPIO进行操作之前,我们还需要先配置好我们所需要的GPIO口。
之后,我们就能够开始使用GPIO口了。
总结一下上面说的内容,我们所需要做的就是三步:
1、使用RCC开启GPIO的时钟,也就是打开 APB2 中的 GPIO
2、使用GPIO_Init函数初始化GPIO
3、使用输入或者输出的函数控制GPIO口
OK,这就是书写代码的所有逻辑,是不是很简单呀,相信大佬们已经能开始搓代码了。
你不要造谣嗷,我没有
代码跟写
首先大家如果想要跟着我一起写,可以按照我的接线方法先连一下,但其实都是一样的。
1、将stm32c8t6最小系统板插进面包板中;
2、ST-Link连上stm32芯片,记住一定对应相连;
GND ----- GND;
SWCLK ----- SWCLK
SWDIO ----- SWIO
3.3V ----- 3V3
3、将芯片的 3.3V 和 GND 连到面包板侧边的正负极位置;
4、二极管负极连到B5,正极连到面包板侧边正极位置。
这里,我们就按照上面的三个步骤,一点点开始写。
1、建主文件,导入头文件。
在User文件夹上右键,选添加新的文件。
.
创建新的文件,选择C文件,给它取个名字,修改文件地址到User文件夹下。
在main里面右键,选择这个头文件。
然后加上下面这些语句。
2、开时钟
我们使用的是GPIOB下的引脚,所以打开APB2下GPIO的时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
3、配GPIO配置
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//GPIO引脚,赋值为第5号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO速度,赋值为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
4、控制GPIO开关LED灯
GPIO_ResetBits(GPIOB, GPIO_Pin_5); //将PB5引脚设置为低电平,也就是开灯
GPIO_SetBits(GPIOB, GPIO_Pin_5); //将PB5引脚设置为高电平,也就是关灯
示例代码
#include "stm32f10x.h" // Device header
int main()
{
GPIO_InitTypeDef GPIO_InitStructure; //如果你的编译器不支持在下面初始化定义,就把它放这里
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*GPIO初始化*/
//GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//GPIO引脚,赋值为第5号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO速度,赋值为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
while(1)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_5); //将PB5引脚设置为低电平
}
}
流水灯实验
流水灯其实就是在上面打开一个灯的基础上多加一些,也就是多打开一些GPIO口,然后在打开下一个灯的时候关闭上一个灯。废话不多说,直接上代码咯~
电路图:
和上面的相比就是多了三个LED灯,分别接到PB6, PB7, PB8即可,也是负极接引脚口上,正极接到面包板正极上。
main代码:
#include "stm32f10x.h" // Device header
int main()
{
int i;
GPIO_InitTypeDef GPIO_InitStructure;
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*GPIO初始化*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;//GPIO引脚,赋值为第5,6,7,8号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO速度,赋值为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);
while(1)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_5); //将PB5引脚设置为低电平
for (i=0; i<1000000; i++); //增加延时,用运行时间占灯亮的时间
GPIO_SetBits(GPIOB, GPIO_Pin_5); //将PB5引脚设置为高电平
GPIO_ResetBits(GPIOB, GPIO_Pin_6); //将PB6引脚设置为低电平
for (i=0; i<1000000; i++);
GPIO_SetBits(GPIOB, GPIO_Pin_6); //将PB6引脚设置为高电平
GPIO_ResetBits(GPIOB, GPIO_Pin_7); //将PB7引脚设置为低电平
for (i=0; i<1000000; i++);
GPIO_SetBits(GPIOB, GPIO_Pin_7); //将PB7引脚设置为高电平
GPIO_ResetBits(GPIOB, GPIO_Pin_8); //将PB8引脚设置为低电平
for (i=0; i<1000000; i++);
GPIO_SetBits(GPIOB, GPIO_Pin_8); //将PB8引脚设置为高电平
}
}
总结:
OK了,大佬们,这期GPIO口的内容都明白了吧~期待一下 下一期的内容吧~。
如果需要本期的工程文件,可以私信我,也会提供给大家的。
标签:口及,引脚,InitStructure,低电平,模式,stm32,输出,GPIO From: https://blog.csdn.net/sikimayi/article/details/143434764