工作笔记:GPIO(1)

gpio就是一个通用的输入输出口,每一个引脚都是一个gpio,单片机可以获取这个引脚上的电平的高低,也可以控制这个引脚的电平高低,往往一个gpio都会复用别的功能,例如I2C,SPI等用于通信的引脚

gpio的原理图如下所示

对于一般单片机来说,一个gpio口有以下几种工作模式

浮空输入、上拉输入、下拉输入、模拟输入和以及输出模式的推挽输出、开漏输出、复用输出,下面来一一讲一下这些工作模式

下图是一个浮空输入的链路,让我们依次从右往左看

1.保护二极管,引脚的输入就是两个保护二极管,当IO端口输入电平高于VDD,则上管导通,IO输入变为VDD;当输入电平低于VSS,则下管导通,输入电平变为VSS,这两个二极管起到了保护内部电路不被高电压烧毁;但如果持续给过高的输入,保护二极管也会烧毁,所以还是要注意外部的输入

2.再往里走,再TTL触发器和保护二极管之间,就是上下拉电阻,当把任意一个接通,则该IO变为上拉/下拉输入

3.TTL施密特触发器,这个器件起到了滤波的作用,假设你要去读取IO的电平状态,那么究竟什么时候是0,什么时候是1  我们用万用表可以测引脚上的电压假设为2V,那么究竟是1还是0 假设MCU认为高于2V为1,低于2V为0,那么外部一个2V的输入,就会因为电磁干扰不停的切换01的状态,TTL就能起到滤波的作用,当外部输入大于2.5V,从0切换至1;当外部输入低于1V,从1切换至0,那么输入再1V-2.5V之间的波动都会被过滤掉

4.模拟输入和复用输入,分别是单片机直接控制该引脚的电平高低,不依赖外部输入;以及把该IO复用为timer或i2c等功能使用,在STM32的初始化过程中,我们需要先配置GPIO,再把GPIO复用为某个功能,然后再初始化这个功能引脚;而HPM的芯片,如果我们复用某个引脚为GPIO,则直接选择功能复用,然后配置该功能引脚即可,省略了GPIO init的过程,同时也不需要根据不同功能开启不同时钟,再board_init中,已经做好了这一切

5.数据输入寄存器,没啥好说的,想知道里面的值就去读

接下来看一下输出的链路,从左往右看

1.输出这边有一些位设置/清楚寄存器,是因为当IO作为输出时,能够做翻转,置高置低等功能,所以会略微复杂一点,但暴露给软件的接口还是简单的,你想写高写低,还是翻转,都直接用函数去调用就可

2.复用功能输出就是把这个IO口当别的功能用

3.输出控制电路和右边的两个MOS,这决定了输出是什么模式,如果两个MOS都导通,那么这个输出就有输出高低电平的能力,也就是推挽输出;当PMOS截止,NMOS导通,那么这个IO的输出就只有输出低电平或浮空的能力,也就是开漏输出

4.从链路上可以看见,当这个GPIO被配置为输出,我们也能从输入数据读取寄存器中获取当前IO的状态

接下来HPM6300evk为例介绍一下用户手册中一些重要的寄存器,其余型号的板子在GPIO这块的功能都是一致的

PAD[FUNC_CTL]

共32个位域,该寄存器0-4位控制引脚的功能复用,8位选择模拟输入,16位控制是否回采,其余为预留位

PAD[PAD_CTL]

共32个位域,用于控制上下拉,中断使能等功能,下面列出一些重要的部分

24位用于控制中断使能

17位用于控制上下拉使能

18位用于选择上拉/下拉

通过以上两个寄存器,就可以实现所有工作模式的初始化

以下代码是gpio的example中对引脚初始化的部分

pad_ctl 中,将PE置1,把PS置1,对照上面的寄存器表,可以看到是上下拉使能,然后选择上拉

func_ctl则是引脚复用的选择

这部分代码让人困惑的是,尤其是对于习惯了STM32编程习惯的人来说,直接写寄存器来初始化IO,显得又不专业,也不优雅;

还有HPM_BIOC这一行代码,sample中注释写了PZ必须配置BIOC,这部分也让人很困惑

但这种配置的设计原因,是因为HPM同时提供了一种基于vscode的插件,可以一键生成这部分代码,使用该pimmux工具,可以通过UI的方式直接配置包括GPIO,I2C,SPI在内的一切功能,只要该引脚能复用这个功能,那么初始化部分就可以一键生成

生成代码如下

你只需要把把代码复制进工程,就能完成你引脚的初始化设置,从而专注于功能的实现上

最后讲一下常用的几个函数

1.引脚电平读取,对于外部可用的引脚,GPIO base address均为在hpm_soc.h内定义好的HPM_GPIO0

/* GPIO0 base pointer */
#define HPM_GPIO0 ((GPIO_Type *) HPM_GPIO0_BASE)

2.Port选择你是PX,PA就选A,PB就选B,可以在hom_gpio_regs.h内查看具体的值,本质上也是一个无符号整数,直接传值也可以

3.pin就是第几个引脚,PA09,那你就传个9进来,也就是如果要获取PA09的电平,你就这样

uint8_t pin_value = gpio_read_pin(HPM_GPIO0,GPIO_DI_GPIOA,9);

在初始化之后,如果还想改引脚的输入输出状态,可以调用这两个函数,当然你也可以用他们来初始化,本质都是写寄存器,不过初始化还是可以试试hpm的pinmux工具,非常好用

引脚电平翻转,以及写高写低

GPIO当然也支持中断,还有一个GPIOM管理器,用于控制多核之间的IO隔离

因为还不是很清楚,留着之后再讲

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值