STM32初识及运用—GPIO_cph和cpl-程序员宅基地

技术标签: stm32  STM32学习  单片机  

(本博客所有关于32的文章都是基于stm32f103c8t648引脚))

GPIO初识——理论讲解

一.GPIO的工作模式

的啊实打实

四种输入模式

上拉输入
若GPIO引脚配置为上拉输入模式,在默认情况下(GPIO引脚无输入),读取 得的GPIO引脚数据位1,高电平。
下拉输入
若GPIO引脚配置为下拉输入模式,在默认情况下(GPIO引脚无输入),读取 得的GPIO引脚数据位0,低电平。
浮空输入
在芯片内部既没有接上拉,也没有接下拉电阻,经由触发器输入。配置成这个模式直接用电压表测量其引脚电压为1点几伏,这是个不确定值。由于其输入阻抗较大,一般把这种模式用于标准的通信协议如I2C,USART的接收端。
模拟输入
关闭了施密特触发器,不接上,下拉电阻,经由另一线路把电压信号传送到片上外设模块。如传送至ADC模块,由ADC采集电压信号。所以使用ADC外设时,必须设置为模拟输入模式。

四种输出模式
开漏输出
此种输出方式,输出寄存器写1时,mos管不导通,此时电平为浮空状态不确定,写0的时候,mos管导通,此时为低电平。此种方式在没有外部电路辅助的时候只能输出低电平。但是利用他这种特性,我们可以外接一个上拉电阻,此时不但可以输出高低电平,而且由于上拉电阻的存在大大的增强了单片机的驱动能力。
推挽式输出
最常用的一种GPIO模式,输出寄存器写1的时候为高电平,写0为低电平。能够快速的切换高低电平,适合做开关控制。
推挽式复用功能
此种方式大体与推挽式输出相同,区别在于其提供片内外设功能(I2C的SCL,SDA)
开漏复用功能
同样的,此种方式大体上与开漏输出模式一样,区别在于其提供片内外设功能(TX1,MOSI,MISO.SCK.SS)

二.GPIO的寄存器介绍

GPIO总共有七种寄存器
一.端口配置低寄存器GPIOX_CPL
二.端口配置高寄存器GPIOX_CRH
三.端口输入寄存器GPIO_IDR
四.端口输出寄存器GPIO_ODR
五.端口设置/清除寄存器GPIO_BSRR
六.端口清除寄存器GPIO_BRR
七.端口配置锁定寄存器GPIO_LCKR

(1)端口配置寄存器(CPL和CPH)

对于端口配置寄存器而言,端口配置高寄存器配置GPIO口的高八位,端口配置低寄存器则配置GPIO口的低八位。(每个GPIO口总共由16位)
GPL寄存器和CPH寄存器都总共有32位,每四个字节操控一个GPIO口
四个字节中的低两位是端口的模式位(MODE),四个字节中的高两位为配置位(CNF)
模式位操控输入输出模式和输出速率
配置位则是配合模式位确定GPIO口是具体是何种输出模式或者输入模式

(2)端口输入寄存器(IDR)

是一个32位寄存器,但是只有低16位可以用,高16位保留。
是一个只读寄存器,寄存器的每一位都对应的GPIO口状态

(3)端口输出寄存器(ODR)

是一个32位寄存器,但是只有低16位可以用,高16位保留。
是一个可读可写寄存器,只能以字(16位)的形式进行操控。(也就是每次操作必须对整个GPIO口进行读写,不能对某个单独的位进行操作(不支持位操作))

(4)端口设置/清除寄存器(BSRR)

此寄存器分为低十六位和高十六位。只写寄存器
低十六位是设置位,写入1则对相应的位设置,写入0则没有影响
高十六位是清除位,写入1则对相应的位清除,写入0则没有影响
且同时设置低十六位和高十六位是第十六位(设置位)起作用
操作BSRR寄存器的实质就是操作ODR寄存器

(5)端口清除寄存器(BRR)

是一个32位寄存器,但只有低16位才起作用,高16位保留。只写寄存器
跟其名字一样,是一个清除寄存器,对应位写入1则该位清除

(6)端口配置锁定寄存器(GPIO_LCKR)

这个寄存器几乎不会用到,这里不做讨论

GPIO初识——实际运用

注意:为了提高32在进行小项目开发的速度,本篇文章所用的代码都是笔者自己基于32标准库进行二次开发 ,方便能够快速调用单片机外设

关于代码,工程文件会附在文章的末尾。

一.GPIO的初始化

//-------------------------------------------------------------------------------------------------------------------
//  @brief      GPIO初始化
//  @param      pin         选择的引脚 (可选择范围由 HYJ_GPIO.h 内PIN_enum枚举值确定)
//  @param      GPIO_Mode   引脚的模式  
//  @param      dat         引脚初始化时设置的电平状态,输出时有效 0:低电平 1:高电平
//  @return     void
//  Sample usage:       HYJ_GPIO_Init(PA0,GPIO_Mode_Out_PP,1);//PA0初始化为GPIO功能、推挽输出、输出高电平
//  @note					需要特别注意P20_2是不能用于输出的,仅仅只有输入的功能
//-------------------------------------------------------------------------------------------------------------------
void HYJ_GPIO_Init(PIN_enum pin ,GPIOMode_TypeDef GPIO_Mode,int8_t data)
{
    

	GPIO_InitTypeDef  GPIO_InitStructure;//定义GPIO配置结构体  
	
	RCC_APB2PeriphClockCmd(get_clock(pin),ENABLE);//时钟使能

	//GPIO的端口配置	
	GPIO_InitStructure.GPIO_Pin = get_pin(pin);				 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode; 		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(get_port(pin), &GPIO_InitStructure);//将上述结构体传入真正的初始化函数(本质上在操作CPL CPH寄存器)					 

	if(GPIO_Mode==GPIO_Mode_Out_OD||GPIO_Mode==GPIO_Mode_Out_PP||GPIO_Mode==GPIO_Mode_AF_OD||GPIO_Mode==GPIO_Mode_AF_PP)
  HYJ_GPIO_Set(pin,data);//GPIO口初始化配置后,默认拉高电平(本质上在操作BSRR寄存器)						 	
}

(1)对引脚所拖挂的外设模块进行使能
(2)再利用一个结构体变量,将引脚的选择和GPIO的工作模式进行设置,这里实际上操作的是端口配置寄存器(CPL和CPH)
(3)再根据需求将端口初始化为低电平或者高电平**

二.GPIO的调用和实例

初始化完成后就可以进行调用

//-------------------------------------------------------------------------------------------------------------------
//  @brief      GPIO输出设置
//  @param      pin         选择的引脚 (可选择范围由 HYJ_GPIO.h 内PIN_enum枚举值确定)
//  @param      dat         0:低电平 1:高电平
//  @return     void
//  Sample usage:           HYJ_GPIO_Set(PA0, 1);//P00_0 输出高电平
//-------------------------------------------------------------------------------------------------------------------
void HYJ_GPIO_Set(PIN_enum pin,int8_t data)
{
    	
		if(data==1)  get_port(pin)->BSRR = get_pin(pin);
	  else				 get_port(pin)->BRR = get_pin(pin);
}
//-------------------------------------------------------------------------------------------------------------------
//  @brief      GPIO状态获取
//  @param      pin         选择的引脚 (可选择范围由 HYJ_GPIO.h 内PIN_enum枚举值确定)
//  @return     uint8       0:低电平 1:高电平
//  Sample usage:           uint8 status = gpio_get(PA0);//获取P00_0引脚电平
//-------------------------------------------------------------------------------------------------------------------
uint8_t HYJ_GPIO_Read(PIN_enum pin)
{
    
	return GPIO_ReadInputDataBit(get_port(pin),get_pin(pin));
}

根据初始化的模式,选择调用输出设置函数void HYJ_GPIO_Set(PIN_enum pin,int8_t data)还是状态读取函数uint8_t HYJ_GPIO_Read(PIN_enum pin)

示例:

 int main(void)
 {
    	
	HYJ_GPIO_Init(PA0,GPIO_Mode_Out_PP,1);
  while(1)		
	{
    
		HYJ_GPIO_Set(PA0, 1);
	}
 }

此时PA0引脚就被设置成输出高电平

工程文件链接地址:
链接:https://pan.baidu.com/s/1abTvUt44NiH5B_o7IiPa3Q
提取码:cxm6
复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V1的分享

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

智能推荐

STIHL EDI成功案例_edi案例-程序员宅基地

文章浏览阅读290次。STIHL斯蒂尔集团德国斯蒂尔集团STIHL是一家具有92年历史的顶尖机械用具品牌,发明了世界上第一台电锯,被称作“电锯之父”和“世界电锯之王”。2016年,知行软件助力供应商实现了与STIHL的EDI直连对接, 通过知行RSSBus EDI系统,供应商可以直接接收到STIHL的物料需求计划,并发送提前发货通知给STIHL。满足STIHL对于业务数据安全传输要求,增强供应商国际竞争..._edi案例

原生css实现滚动条显示_在css中如何在下拉滚动条图片一一显示-程序员宅基地

文章浏览阅读1k次。今天拿到设计图需要作出这样的一个效果,就是使用html加css实现滚动条的效果,效果图是这样的实现上面效果图的代码## html代码 <div style=" position: relative;"> <img src="assets/images/oa/集团OA/项目周期.png" alt="" class="project_modal_task" > <span class="project_modal_name_在css中如何在下拉滚动条图片一一显示

windows配置SVT-HEVC_enable svt hevc encoder-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏2次。Scalable Video Technology for HEVC Encoder (SVT-HEVC Encoder),用于HEVC编码器的可扩展视频技术(SVT-HEVC编码器)是符合HEVC标准的编码器库核心,针对英特尔Xeon可扩展处理器和XeonD处理器进行了高度优化。github地址:https://github.com/OpenVisualCloud/SVT-HEVC..._enable svt hevc encoder

java数据结构:双向链表结构与实现_java双向链表遍历-程序员宅基地

文章浏览阅读3.1k次,点赞2次,收藏13次。本教程的内容基本来自于《Java数据结构与算法》单向链表的缺点在于每个节点只能知道自己与下一个节点,无法寻找到上一个节点。而双向链表可以解决这个问题,通过在节点内部添加一个previous指针,指向它的前一节点。双向链表示意图图中所示为双向链表,与单向链表相比,只不过是多引入了一个指向前一节点的previous指针而已。优点:支持向前遍历,也支持向后遍历; 缺点:在对链表进行_java双向链表遍历

百度Q4财报解读:营收净利润加速增长 是时候重估百度了-程序员宅基地

文章浏览阅读2k次。北京时间2月28日,百度公布了截至2019年12月31日的第四季度及全年未经审计的财务报告。百度财报数据显示,2019年年营收为1074亿元人民币,2019年第四季度,百度营收289亿人民币,同比增长6%;归属百度的净利润达到92亿元人民币 (非美国通用会计准则),同比增长95%。从财报情况来看,高速增长的业务数据与强劲的现金流,将让百度迎来一次价值重估的机会。这对于投资者而言,是否是一次机会...

1 实现复数的加减乘除_实现两个复数的加减法及乘除法运算-程序员宅基地

文章浏览阅读236次,点赞2次,收藏2次。#include <stdio.h>#include <math.h>typedef struct { //构建复数的结构体类型(包含实部和虚部) float realpart; float imagpart;} Complex;// 函数声明Complex assign(float real,float imag); //赋值Complex add(Complex C1 ,Complex C2); //+Complex minus(Complex C_实现两个复数的加减法及乘除法运算

随便推点

ImportError: libcublas.so.9.0: cannot open shared object file: No such file...问题原因及解决方法-程序员宅基地

文章浏览阅读3.7k次,点赞2次,收藏5次。原因1:cuda9.0以及cudnn7未能安装或正确安装。解决方案:安装cuda及对应cudnn,已安装情况下检查路径usr/local/cuda-9.0/lib64下是否有 libcublas.so.9.0文件原因2:tensorflow版本与cuda不对应。解决方案:升级tensorflow原因3:路径未加入环境解决方案:sudo gedit ~/.bashrc ..._importerror: libcublas.so.9.0: cannot open shared object file: no such file

python socket bind端口报 permission denied_cannot bind netlink socket: permission denied-程序员宅基地

文章浏览阅读3.1k次。在绑定某个端口到socket的时候报权限问题1,使用sudo 去执行Python2,关闭selinux的权限_cannot bind netlink socket: permission denied

28、Flutter之Navigator进行局部跳转页面_navigator.of-程序员宅基地

文章浏览阅读5.1k次。NavigatorNavigator 是管理路由的控件,通常情况下直接使用Navigator.of(context)的方法来跳转页面,之所以可以直接使用Navigator.of(context)是因为在WidgetsApp中使用了此控件,应用程序的根控件通常是MaterialApp,MaterialApp包含WidgetsApp,所以可以直接使用Navigator的相关属性。基本用法:class MyNavigator extends StatefulWidget { const MyNa_navigator.of

ue4 android 交互,Android、IOS与Unity、UE4桥接详解-程序员宅基地

文章浏览阅读1.8k次。1.介绍业务需求需要提供较多native接口(Android、IOS)给Unity、Unreal来进行使用。为了方便开发,提供类似于阉割版的JSBridge的框架来实现通信。native需要给engine提供大量接口,即主要讨论Engine如果调用Native接口为主。2.原理Unity调用Android、IOS接口。Unity提供AndroidJavaClass工具类来进行通信,IOS则是直接通..._android ue4通讯

TCP / IP_tcp 127.0.0.1:62283 127.0.0.1:62284 established 13-程序员宅基地

文章浏览阅读729次。分层模型应用层一般为程序员经常使用的,就是和具体的协议,具体的程序打交道的层级_tcp 127.0.0.1:62283 127.0.0.1:62284 established 13764

Androidx Fragment两种懒加载_androidx.fragment懒加载-程序员宅基地

文章浏览阅读217次。1.viewPagerList<LazyFragment> fragmentList=new ArrayList<>();fragmentList.add(new MainFragment1(0));fragmentList.add(new MainFragment1(1));fragmentList.add(new MainFragment1(2));fragmentList.add(new MainFragment1(3));fragmentList.add(ne_androidx.fragment懒加载

推荐文章

热门文章

相关标签