嵌入式中GPIO的工作原理-面试工作必会技能

GPIO工作方式

1、4种输入模式

  • 输入浮空
  • 输入上拉
  • 输入下拉
  • 模拟输入

        如下图为GPIO的基本结构,它主要由4部分组成,其中我们所看到的的最右边的I/O引脚,也就是芯片外接可看到的引脚,其它的部分都是GPIO内部的结构。

 ①保护二极管

        保护二极管共有两个,用于保护引脚外部过高或过低的电压输入。当引脚输入电压高于 VDD 时,上面的二极管导通,当引脚输入电压低于 VSS 时,下面的二极管导通,从而使输入芯片内部的电压处于比较稳定的值。虽然有二极管的保护,但这样的保护却很有限,大电压大电流的接入很容易烧坏芯片。所以在实际的设计中我们要考虑设计引脚的保护电路。

②上拉、下拉电阻

        它们阻值大概在 30~50K 欧之间,可以通过上、下两个对应的开关控制,这两个开关由寄 存器控制。当引脚外部的器件没有干扰引脚的电压时,即没有外部的上、下拉电压,引脚的电 平由引脚内部上、下拉决定,开启内部上拉电阻工作,引脚电平为高,开启内部下拉电阻工作, 则引脚电平为低。同样,如果内部上、下拉电阻都不开启,这种情况就是我们所说的浮空模式。 浮空模式下,引脚的电平是不可确定的。引脚的电平可以由外部的上、下拉电平决定。需要注意的是,STM32 的内部上拉是一种“弱上拉”,这样的上拉电流很弱,如果有要求大电流还是 得外部上拉。

③施密特触发器

        对于标准施密特触发器,当输入电压高于正向阈值电压,输出为高;当输入电压低于负向阈值电压,输出为低;当输入在正负向阈值电压之间,输出不改变,也就是说输出由高电准位翻转为低电准位,或是由低电准位翻转为高电准位对应的阈值电压是不同的。只有当输入电压发生足够的变化时,输出才会变化,因此将这种元件命名为触发器。这种双阈值动作被称为迟滞现象,表明施密特触发器有记忆性。从本质上来说,施密特触发器是一种双稳态多谐振荡器。

        施密特触发器可作为波形整形电路,能将模拟信号波形整形为数字电路能够处理的方波波 形,而且由于施密特触发器具有滞回特性,所以可用于抗干扰,其应用包括在开回路配置中用于抗扰,以及在闭回路正回授/负回授配置中用于实现多谐振荡器。

④ P-MOS管和N-MOS管

        这个结构控制 GPIO 的开漏输出和推挽输出两种模式。开漏输出:输出端相当于三极管的集电极,要得到高电平状态需要上拉电阻才行。推挽输出:这两只对称的 MOS 管每次只有一 只导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载拉电流。推拉式输出既能提高电路的负载能力,又能提高开关速度。

        下面我们对GPIO八种工作模式对应的结构图的工作进行介绍

1、输入浮空:只有上边的输入部分起作用,下边的输出部分不起作用。

        处于浮空状态时,上拉或者下拉处于断开状态,此时施密特触发器是打开,输出被禁止 。输入浮空模式下,IO 口的电平完全是由外部电路决定。如果 IO 引脚没有连接其他的设备,那么检测其输 入电平是不确定的。该模式可以用于按键检测等场景。

2、输入上拉:只有上边的输入部分起作用,下边的输出部分不起作用。

        上拉电阻导通,施密特触发器打开,输出被禁止。在需要外部上拉电阻的时候,可以使用内部上拉电阻,这样可以节省一个外部电阻,但是内部上拉电阻的阻值较大,所以只是“弱上拉”,不适合做电流型驱动。

3、输入上拉:只有上边的输入部分起作用,下边的输出部分不起作用。

         下拉电阻导通,施密特触发器打开,输出被禁止。在需要外部下拉电阻 的时候,可以使用内部下拉电阻,这样可以节省一个外部电阻,但是内部下拉电阻的阻值较 大,所以不适合做电流型驱动。

4、模拟输入

         上下拉电阻断开,施密特触发器关闭,双 MOS 管也关闭。该模式用于 ADC 采 集或者 DAC 输出,或者低功耗下省电。

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
嵌入式系统GPIO驱动是控制IO口的重要手段。在点亮8个LED灯的场景,我们需要使用8个GPIO口,分别连接到每个LED灯的正极。下面给出一个简单的C语言程序,实现点亮8个LED灯的功能。 首先,我们需要初始化GPIO口,使其可以控制LED灯。以下代码使用Linux内核提供的GPIO API进行初始化: ```c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #define GPIO_BASE 0x3F200000 // GPIO控制器基地址 #define GPIO_SIZE 4096 // GPIO控制器内存大小 // GPIO寄存器偏移地址 #define GPFSEL0 0x00 #define GPSET0 0x1C #define GPCLR0 0x28 #define GPPUD 0x94 #define GPPUDCLK0 0x98 // 设置GPIO口的功能模式 void set_gpio_mode(int pin, int mode) { volatile unsigned *gpio = NULL; int fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd < 0) { perror("open"); exit(-1); } gpio = (volatile unsigned *)mmap(NULL, GPIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_BASE); if (gpio == MAP_FAILED) { perror("mmap"); exit(-1); } int offset = pin / 10; int shift = (pin % 10) * 3; gpio[offset] &= ~(0b111 << shift); // 清除原来的模式 gpio[offset] |= mode << shift; // 设置新的模式 munmap((void *)gpio, GPIO_SIZE); close(fd); } // 设置GPIO口的电平 void set_gpio_level(int pin, int level) { volatile unsigned *gpio = NULL; int fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd < 0) { perror("open"); exit(-1); } gpio = (volatile unsigned *)mmap(NULL, GPIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_BASE); if (gpio == MAP_FAILED) { perror("mmap"); exit(-1); } if (level) { gpio[GPSET0 / 4] = 1 << pin; } else { gpio[GPCLR0 / 4] = 1 << pin; } munmap((void *)gpio, GPIO_SIZE); close(fd); } int main() { // 设置GPIO口的功能模式为输出模式 for (int i = 0; i < 8; i++) { set_gpio_mode(i, 0b001); } // 点亮LED灯 for (int i = 0; i < 8; i++) { set_gpio_level(i, 1); usleep(500000); // 延时500ms } // 关闭LED灯 for (int i = 0; i < 8; i++) { set_gpio_level(i, 0); } return 0; } ``` 在上述代码,我们首先使用`set_gpio_mode`函数将8个GPIO设置为输出模式。然后,使用`set_gpio_level`函数将每个GPIO口的电平设置为高电平,从而点亮LED灯。为了让LED灯持续一段时间,我们使用`usleep`函数进行延时。最后,使用`set_gpio_level`函数将每个GPIO口的电平设置为低电平,关闭LED灯。 需要注意的是,上述代码使用了Linux内核提供的GPIO API进行GPIO口的控制。在不同的嵌入式系统GPIO口的控制方式可能有所不同,需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无限嚣张(菜菜)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值