入门STM32--GPIO(跑马灯)(保姆级别)_gpio_inittypedef-程序员宅基地

技术标签: stm32  STM32入门  单片机  

目录

前言

一、GPIO是什么?

二、GPIO干什么

三、GPIO怎么干

三、如何用GPIO点亮一个LED灯

        1.  GPIO_InitTypeDef 

2.GPIO_Init   

3.RCC_APB2PeriphClockCmd

四、初始化

五、合成

延时

头文件

初始化

六、两个灯


前言

这也是比较简单的一部分,我们就从这里正式开始咱们的32之路。

typedef 

结构体 

枚举 

上面这些是基础,如果想看懂程序,了解即可。 

一、GPIO是什么?

所有的嵌入式处理器内部均集成了通用输入输出(General Purpose Input Output,GPIO)接口,通俗地讲呢,其实就是你的开发版上面的插针,那个东西就是和你的单片机上面的IO口(GPIO)连起来了(连起来好用,方便开发)。 STM32的IO口被分成了若干组,PA、PB、PC等,每一组有16个管脚,PA0、PA1、PA2、PA3等等。

二、GPIO干什么

从 Output Input 这两个单词也可以看出来,他是做输入输出作用的。

我们的单片机一般就是做主控,来控制其他电路或者是电机,既然是控制肯定就要输出控制信号,所以说就需要IO口,来做输出。同样,单片机肯定也需要外部的信息,所以说也需要输入功能。

 最基本的输出功能是由STM32控制引脚输出高、低电平,实现开关控制,如把GPIO引脚接入到LED灯,那就可以控制LED灯的亮灭,引脚接入到继电器或三极管,那就可以通过继电器或三极管控制外部大功率电路的通断。

三、GPIO怎么干

简单地说一下,这个图呢可以被分为两部分, 上面是输入,下面是输出。

从右往左看,先是引脚然后是保护二极管(作用是保护你的管脚不会被一个比3V3该有可能是5V高一点,或者比0V低一点的电压伤害,但要记住是一点),让后就分别进入到两个部分。

输入部分是,进入后经过上拉或者下拉电阻,然后是TTL肖特基触发器(TTL肖特基触发器其实可以理解为用肖特基管构成的施密特触发器,作用简单说就是将相对缓慢变化的模拟信号变成矩形信号,便于后面读取。)然后就可以被读取。

输出部分,是经过MOS管的导通与断开来控制输出电平的高低。可以看到,输出最高电平时VDD(单片机工作电压,2.0~3.6V,一般是3.3V),最低电平是Vss(单片机电源地,0V)。

三、如何用GPIO点亮一个LED灯

 毫无疑问,我们肯定需要写代码嘛,通过我们写的代码,告诉单片机我们想干的事。

如果我们选择的功能是输入,那么我们需要的就是读取相关寄存器(可以理解为一个存储器,我们可以往里面写数,就可以控制单片机。同样,单片机的一些数据也存放在这里。)的值,就可以的得到相关IO口的电平,如果我们选择的是输出,我们需要做的就是控制MOS管的导通和关闭。

首先我们要做的确定我们要使用的IO口,我们应该查找原理图,然后找到LED灯对应的管脚。

 

我们可以看到,LED0对应的是PB5这个管脚,下面要做的就是写程序了。 

1.  GPIO_InitTypeDef 

 首先,我们要定义一个结构体,上面有提到,我们是通过往寄存器里面写数字来控制单片机,寄存器转化到程序里面被分成了许多结构体,我们要往里面写数字,也要通过结构体的方式。

 GPIO_InitTypeDef  GPIO_InitStructure;

 这个 GPIO_InitTypeDef是通过typedef得到的一个宏定义,方便用它来定义结构体中的变量和GPIO寄存器类型结构相符合结构体。后面的那个GPIO_InitStructure就是我们定义的结构体(名字随意,我学习的时候就叫这个)。

typedef struct
{
  uint16_t GPIO_Pin;             /*!< Specifies the GPIO pins to be configured.
                                      This parameter can be any value of @ref GPIO_pins_define */

  GPIOSpeed_TypeDef GPIO_Speed;  /*!< Specifies the speed for the selected pins.
                                      This parameter can be a value of @ref GPIOSpeed_TypeDef */

  GPIOMode_TypeDef GPIO_Mode;    /*!< Specifies the operating mode for the selected pins.
                                      This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;

下面让我们来分析这个结构体里面的成员,

1. GPIO_Pin的意思是哪个管脚,例如GPIO_Pin_5,代表的是PX5这个管脚,其中X=A、B、C、D等。

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

2.GPIOSpeed_TypeDef GPIO_Speed,这里是一个的枚举定义,前面是枚举的类型,后面是枚举的名字。

GPIO 引脚速度: GPIO_Speed_2MHz     (10MHz, 50MHz) ;

又称输出驱动电路的响应速度:(芯片内部在I/O口的输出部分安排了多个响应速度不同的输出驱动电路,用户可以根据自己的需要选择合适的驱动电路,通过选择速度来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。)

简单的理解就是,IO口的响应速度。

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

typedef enum
{ 
  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz, 
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

 3.GPIOMode_TypeDef GPIO_Mode显而易见,这里又是一个枚举的定义,前面是类型,后面是名称。

typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;

这里有不同的模式,如果我们选择输出的话,GPIO_Mode_Out_PP就是我们想要的,叫推挽输出,还有很多种方式,我就不细讲了,可以参考其他文章。

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

2.GPIO_Init   

当我们配置好上面的结构体成员后,我们就完成了大部分,但是还没有结束,你会发现,我们只是把我们的定义的结构体里面的值确定了,并没有放到单片机的寄存器里面,这时候肯定不行啊。

怎么放进去呢,别人在就想到了这一点,直接调用函数就可以了。

GPIO_Init(GPIOB, &GPIO_InitStructure); 

 可以看到,这个函数需要输入两个参数,一个就是A、B、C、D等,确定我们要控制哪一组管脚。

另一个参数是我们定义的结构体的地址。

举一个例子,我们定义的结构体就更好比是一个包裹,这个函数就是快递员,我们要告诉的我们寄哪个快递,寄到哪。

到这你可能感觉差不多了,其实还没有。我们是不是要告诉收快递的那个人,你有快递了,怎么告诉呢,来一句函数就OK了。

3.RCC_APB2PeriphClockCmd

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   

 可以看到,这个函数也有两个参数,第一个参数是使能哪一组管脚的时钟,第二个管脚是使能(ENABLE)。
使能外设时钟的原因https://blog.csdn.net/weixin_43217963/article/details/97792677注意:一定要先使能PB端口的时钟然后在配置GPIO

void GPIO_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.5
 GPIO_SetBits(GPIOB,GPIO_Pin_5);						 //PB.5 输出高
}

四、初始化

初始化是一个比较重要的问题,很多新手在经历过千难万险把函数写好之后,把程序下进去,发现灯不亮。BBQ了,大部分原因都是初始化的原因。

 可能很多新手创建了一个新的文件LED,里面有 led.c 和 led.h 这两个文件,把自己写的函数放到led.c里面了,这样也是可以的,不过大可不必,我还是建议直接写到 main.c 这个文件里面,毕竟我们只是点个灯。

就想这样

 

 虽然没有写到 led.c里面简洁,但是初始化会方便很多(避免很多坑)。

如果你非要建立一个文件的话,千万记得在 led.h 里面声明 ,main.c文件要包括相关的头文件。

五、合成

把我们之前写的合到一起,像下面这样

 但是你会发现,灯是一直在亮,这是因为单片机的执行速度的是很快的,一瞬间就完成了高低电平的设置,人的肉眼反应不过来。

所以需要延时函数,就是让灯等一会亮,也等一会灭。

延时

延时的方法有两种,第一种是我们可以直接调用延时函数(别人写好的函数),也可以自己写一个循环进行延时。

我们就是用第一种吧,需要做的就是包括对应的头文件,和初始化延时函数。

头文件

直接在主函数里面包括就行

 初始化

加上一句 delay_init(); 即可

delay_ms(200); 就是延时200毫秒

delay_ms(500); 就是延时500毫秒

注意:单次延时时间不能超过1864ms

把延时函数加上后

灯就闪了起来 ~~~

六、两个灯

就像这样

 

 简单讲解一下,首先就是端口时钟多了一个PE的,直接使用一个函数就可以,但是注意有一个 或 的步骤。

第二个地方就是,在配置PE5时,仍然使用了上一次的结构体。因为第二个灯也是五号管脚,不需要做其他修改。

第三个地方就是主函数,这里也很简单,就是多了两句话。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_58670090/article/details/122846942

智能推荐

PYNQ初体验--AXI_GPIO实验_pynq fpga 控制gpio速度-程序员宅基地

目录PYNQ简介PYNQ是什么jupyter notebookPYNQ的学习资料如何使用PYNQ?PYNQ上跑的一个AXI_GPIO小例程PYNQ简介PYNQ是什么PYNQ是一个新的开源框架,使嵌入式编程人员能够在无需设计可编程逻辑 电路的情况下即可充分发挥 Xilinx Zynq All Programmable SoC(APSoC)的功能。 与常规方式不同的是,通过 PYNQ,用户可以使用 Python 进行 APSoC编程,并且 代码可直接在支持 PYNQ 的开发板上进行开发和测试。通过 PY_pynq fpga 控制gpio速度

(14)写一个函数,将两个字符串连接_写一个函数,将两个字符串连接-程序员宅基地

写一个函数,将两个字符串连接程序分析:用户在控制台输出第一个字符串后按下回车键继续输出下一个字符串。需要加上getchar()读取换行符,若不进行处理程序会将换行符也连接到新的字符串中。#include<stdio.h>#include<math.h>#include<stdlib.h>int main(){ void z(char a[], char b[], int n, int m); char a[6]; char b[3]; int i; p_写一个函数,将两个字符串连接

关于python中return的个人理解_python中return怎么返回空字符-程序员宅基地

昨天钻牛角尖了,总以为return返回的值可以运行,其实是return可以返回任何值,可以返回字符串,函数内存地址巴拉巴拉,然后出现了这么一个例子:def test1(): return 1def test2(): print('test2') return test1res = test2()print(res())这个代码里面首先声明两个函数,然后运行test2,打印一个te..._python中return怎么返回空字符

【菜单版】stata三天写论文!独立单因素F检验实战_f检验 stata-程序员宅基地

【菜单版】stata三天写论文!独立单因素F检验实战_f检验 stata

Struts2入门小案例-程序员宅基地

(1)下载Struts2的架包,下载完后打开找到lib目录,发现里面有很多架包,不是所有架包我们都用得上,因此我们只需要几个架包即可,下载好的文件里面有个文件夹叫apps,这个文件夹里主要放着一些示例程序,我们需要的架包都在这些例子里的lib文件夹中。apps->web->web-inf->lib打开复制到项目即可(2) 创建Actionimport com.opensymphony.xwork2.Action;import org.springframework.http

python程序设计与算法基础第二版课后答案_python算法与程序设计基础答案-程序员宅基地

python算法与程序设计基础答案更多相关问题[单选] 农产品质量安全法所称农产品,是指来源于农业的(),即在农业活动中获得的植物、动物、微生物及其产品。[单选] 设有关系Students(学号,姓名,年龄,性别,系别,家庭住址),用户要求访问“家庭地址”的某个成分,如邮编、省、市、街道以及门牌号,则“家庭地址”是一个()属性。[问答题,简答题] 什么是煤层厚度?[单选] 经营兽用生物制品的企业应..._python程序设计与算法基础帝2班课后习题答案

随便推点

《Python自动化运维》超清PDF完整版开发下载!转行零基础首选!_python自动化运维快速入门 pdf-程序员宅基地

随着技术的进步、业务需求的快速增长,一个运维人员通常要管理上百、上千台服务器,运维工作也变得重复、繁杂。将运维工作自动化,能够把运维人员从服务器的管理时间中释放出来,让运维工作变得简单、快速、准确。换句话来讲,运维自动化是一组将静态的设备结构转化为根据IT服务需求动态弹性响应的策略,主要目的就是实现IT运维的质量,降低成本。_python自动化运维快速入门 pdf

Apache与Tomcat整合-程序员宅基地

---------------本文转自:http://www.cnblogs.com/itech/archive/2009/08/18/1548723.html一 Apache与Tomcat比较联系apache支持静态页,tomcat支持动态的,比如servlet等。一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由tomcat来处理的。_apache与tomcat整合

spring boot+iview 前后端分离架构之组织管理的实现(二十九)_ivew 自定义tree 组织管理-程序员宅基地

spring boot 与 iview 前后端分离架构之组织管理的实现(二十九)组织管理前文错误本章修改相关工具类的实现OrgDto【实体转换类】OrgMapper【组织实体转换】OrgCascaderDto【组织下拉的实体类】OrgInstall【组织组装的工具类】组织管理的实现UserOrgDao.xml的实现UserOrgDao的实现OrgDao.xml的实现OrgDao的实现OrgServ..._ivew 自定义tree 组织管理

java/php/net/python流浪动物救助系统设计_宠物救助机构组织结构图-程序员宅基地

本系统带文档lw万字以上+答辩PPT+查重 如果这个题目不合适,可以去我上传的资源里面找题目,找不到的话,评论留下题目,或者站内私信我,有时间看到机会给您发流浪动物救助系统的结构图4-1所示: 图4-1 系统结构登录系统结构图,如图4-2所示: 图4-2 登录结构图系统结构图,如图4-3所示。 图4_宠物救助机构组织结构图

jeesite介绍-程序员宅基地

JeeSite特点:高效、高性能、强安全性属于开源、JavaEE快速开发平台;JeeSite是在Spring Framework基础上搭建的一个Java基础开发平台,以Spring MVC为模型视图控制器,MyBatis为数据访问层,Apache Shiro为权限授权层,Ehcahe对常用数据进行缓存,Activit为工作流引擎。是JavaEE界的最佳整合。JeeSite主要定位于信..._jeesite

阿木p200四旋翼配置经验笔记_px4 uwb_集智飞行的博客-程序员宅基地

本文初次写于2021/06/09我做编队试验用的阿木P200四旋翼,完成了机载计算机控制的编队飞行以及二维码引导降落。记录一下对到手的P200飞机仍需要更改调试的配置:_px4 uwb