0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

可编程数字输入和输出详解

嵌入式应用开发 来源:嵌入式应用开发 作者:嵌入式应用开发 2022-06-18 19:30 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

数字型输入/输出外设仅有两种有效状态,习惯用On和Off、High和Low、打开和关闭、接通和断开等表示两种有效状态,譬如一个继电器触点的接通状态和断开状态、 一颗指示灯的on状态和off状态等。存储一个数字型输入/输出外设的状态信息仅需要一个二进制位。绝大多数MCU的可编程I/O引脚都可编程输出高电平和低电平, 这样的I/O引脚电平状态与相应接口电路即可控制数字型输出外设的状态,因此在MCU内部使用二进制位的“1”和“0”分别表示数字型输出外设的状态。 同时,通过读取MCU的I/O引脚的电平即可获取数字型输入外设的状态,并使用布尔型(Boolean)变量保存该状态。

很多编程语言都支持布尔型变量,尤其支持嵌入式系统的编程语言,譬如C/C++语言。虽然布尔型变量的有效值仅为“1”和“0”,如果目标计算机系统不支持位操作和位寻址, 布尔型变量仍占用一个字节或更多二进制位来存储一个二进制信息。现在的MCU绝大多数都支持位操作和位寻址,譬如ARM Cortex-M系列微内核支持“bit-band”操作, 允许存取指令访问单个数据位(详见 [1]_ 的6.7节)。

按钮和LED指示灯是最简单的数字型输入和输出外设,图4.1给出BlueFi上的按钮和LED指示灯的电路连接示意图。

../_images/gpio_examples_reset_di_do.jpg

图4.1 BlueFi上的按钮和LED指示灯的电路连接示意图

从上图中,我们不仅能够了解数字型输入/输出信号的电平电压、驱动电流、频率和复位期间的默认状态,还能了解如何读取数字型输入外设的状态到内部变量, 以及如何通过写外设存储区的地址单元来控制数字型输出状态。

BlueFi的主MCU(nRF52840)的外部复位信号的有效电平为低电平(详见nRF52840的产品说明文档 [2]_ ),且内部带有上电复位(即冷复位)电路(图中黄色的电阻电容), 图4.1给出最简单的外部复位电路:一个手动复位按钮,一端接地,另一端与“nRST”引脚连接。内部上电复位电路的电阻与MCU的工作电源连接,当外部手动复位按钮未被按下时保持复位引脚状态为高电平, 这个电平的电压显然与MCU的工作电压相等;当按下手动复位按钮时复位引脚的状态为低电平,这个电平的电压与电源地相同。当我们需要给nRF52840复位时,只需要按下复位按钮即可。 按下按钮时从“nRST”引脚强制施加低电平信号给MCU内核的内部复位电路单元将片上所有功能单元(含CPU)复位,当我们释放手动复位按钮后,片上的上电复位电路确保“nRST”引脚处于高电平, CPU开始工作。我们在第2.7节已经了解到MCU的多种复位源,在复位期间,nRF52840内部的“RESETREAS”寄存器(0x4000 0400地址单元)将保存本次复位的信号源, 应用程序可以根据这个寄存器的内容来识别复位源。单按一次BlueFi的复位按钮是正常的系统复位,而连续双击BlueFi的复位按钮,你会发现BlueFi进入Bootloader状态。 这个功能是使用“RESETREAS”寄存器的内容。

BlueFi的A和B按钮是可编程的,两个按钮的电路连接完全相似(除了使用不同的I/O引脚),图4.1中仅给出A按钮的电路连接。A按钮的接口电路不仅包含片外的按钮, 还包含片内的可配置上拉/下拉电阻,由于A按钮的一端与MCU工作电源连接、另一端与P1.7引脚连接,当A按钮按下时P1.7引脚被强制与电源连接;如果P1.7的内部配置为下拉电阻, 当A按钮释放时P1.7引脚被下拉到电源地。通过读取P1.7引脚的状态确定A按钮的状态,当A按钮按下时读取状态的结果为“1”(即高电平),当A按钮释放时读取状态的结果为“0”(即低电平)。 当我们将A按钮的状态保存到一个布尔型变量时,如果不采用DMA(直接存储器访问)方式,nRF52840的CPU的工作过程为:将P1.IN寄存器(即0x5000 0810地址单元)读入CPU内部某个寄存器, 然后再将D7位的值(即P1.7引脚的状态)保存到布尔型变量(即“Bit_Band”区的某个地址单元)。

对于P1.7内部可配置的上拉/下拉电阻的使用,需要在BlueFi初始化期间根据A按钮的电路进行编程配置。按照图4.1,使用Arduino IDE平台,A按钮的初始化和使用代码参考如下:

void setup() {
  // put your setup code here, to run once:
  pinMode(PIN_BUTTON1, INPUT_PULLDOWN);
}

void loop() {
  // put your main code here, to run repeatedly:
  bool state_aBtn = digitalRead(PIN_BUTTON1);
  if (state_aBtn == HIGH) {
    // A button be pressed
  } else {
    // A button be released
  }
}

第3行代码是调用Arduino内部函数“pinMode(PIN_BUTTON1, INPUT_PULLDOWN)”将P1.7引脚(即与A按钮连接的I/O引脚)配置为输入模式且使用内部下拉电阻。在Arduin IDE平台, 有三种输入配置:浮空输入(INPUT)、上拉输入(INPUT_PULLUP)和下拉输入(INPUT_PULLDOWN)。第8行调用Arduino内部函数“digitalRead(PIN_BUTTON1)”读取A按钮的状态, 由于按钮的状态为二进制型信息,所以将A按钮的当前状态暂存在布尔型变量“state_aBtn”中。根据图4.1的电路结构,当A按钮被按下时布尔型变量“state_aBtn”的值为“true”或“HIGH”。 注意,“HIGH”是Arduino平台的布尔型常量,“true”是C/C++编程语言的标准常量。

BlueFi有两颗亮起时颜色分别为红色和白色的LED指示灯,他们的连接电路如图4.1所示,两颗LED分别受P1.12和P1.14引脚控制。当程序将P1.OUT寄存器(即0x5000 0804地址单元) 的D12位置位时,P1.12引脚将输“1”(即高电平),红色LED指示灯将亮起;当程序将P1.OUT寄存器的D12位清零时,P1.12引脚输入“0”(即低电平),红色LED指示灯将熄灭。 BlueFi与其他数字电路采用相同的设计习惯,I/O引脚为高电平时对应的电压等于MCU的I/O工作电压,低电平对应的电压等于电源地,按照前一章的BlueFi电路原理介绍, nRF52840使用3.3V作为I/O引脚电压。根据红色LED的正向压降、串联电阻的阻值和高电平的电压,我们可以计算出红色LED亮起时的电流(简称on电流),这个电流的大小决定指示灯的亮度。

根据A按钮的状态控制红色LED指示灯亮和灭的代码如下:

oid setup() {
  // put your setup code here, to run once:
  pinMode(PIN_BUTTON1, INPUT_PULLDOWN);
  pinMode(LED_RED, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  bool state_aBtn = digitalRead(PIN_BUTTON1);
  if (state_aBtn == HIGH) {
    // A button be pressed
    digitalWrite(LED_RED, HIGH);
  } else {
    // A button be released
    digitalWrite(LED_RED, LOW);
  }
}

按照“..Arduino15packagesadafruithardwarenrf520.20.5variantsbluefi_nrf52840variant.h“头文件中对BlueFi的I/O引脚用法的定义, 只需要将上述代码中的“LED_RED”引脚名称替换为“LED_WHITE”,然后编译并下载修改后的代码到BlueFi,可以使用A按钮控制白色LED的亮和灭。

与红色LED相比,你也许已经发现BlueFi的白色LED更亮一些。这说明,白色LED指示灯on电流大于红色LED。如果使用I/O引脚输出的高电平电压直接驱动LED,并不断地减小LED的串联电阻阻值, LED的亮度将会不断地增加吗?如果假设I/O引脚输出的高电平电压是理想的(即内阻为0且功率足够大),这个问题的答案是肯定的。事实上,所有MCU的I/O引脚的驱动能力都是有限的, 按拉电流和灌电流两种指标分别指定每一个I/O引脚的驱动能力。当I/O引脚的驱动能力无法满足LED指示灯on电流时,我们自然会想到外部驱动,如图4.1中使用外部NPN三极管驱动白色LED指示灯, 此时I/O引脚输出的拉电流被三极管放大数十倍(即三极管的放大倍数)作为白色LED指示灯on电流。当外部数字型输出外设需要更大的负载电流时,或许需要多级结构(如达林顿结构)的三极管提高放大倍数。

对于MCU的可编程I/O引脚,除了可配置的上拉/下拉电阻、可编程为输入/输出模式等,还有更多可配置的结构。以nRF52840为例,我们需要进一步了解其内部的结构,如图4.2所示。

../_images/nrf52840_gpio_pin_details_pin0.jpg

图4.2 nRF52840可编程I/O引脚的内部结构

在上图中,我们可以找到一个可编程输入/输出引脚的所有配置选项、输入通道、输出通道等。除了数字I/O功能之外,一个可编程输入/输出引脚也可以当作模拟I/O功能引脚使用, 图4.2中的“ANAEN”是编程配置一个引脚当作数字I/O或模拟I/O的控制位。关于模拟输入/输出的功能,详见下一节。在nRF52840的手册中,我们可以找到每一个可编程输入/输出引脚的 配置和控制相关的存储器地址和有效的控制位,“pinMode(pin,mode)”、“digitalRead(pin)”和“digitalWrite(pin,value)”等基本数字型I/O接口都是通过编程这些存储单元而实现的。

已经了解数字型I/O的电路和软件接口之后,我们可以接着第3章最后一节的任务:为BlueFi设计BSP,现在只涉及BlueFi的数字I/O相关的部分,即两个输入按钮和两个LED指示灯的BSP。 如果你是BlueFi的二次开发(编程应用)用户,你将会如何使用按钮和LED指示灯呢?BSP的目的是根据特定硬件电路封装API并加快二次用户开发的工作效率,譬如BlueFi的两个按钮的配置 (需根据按钮的电路结构)等,用户只需调用BSP封装的API即可得到“按钮被按下/释放/长按“,或直接控制“红色LED亮/灭/切换”等。

为了了解BSP的基本结构,我们首先来实现LED控制的API

审核编辑:符乾江

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5209

    文章

    20624

    浏览量

    336756
  • i/o控制
    +关注

    关注

    1

    文章

    4

    浏览量

    1155
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    电子工程师必看:MAX5420/MAX5421数字可编程精密分压器

    电子工程师必看:MAX5420/MAX5421数字可编程精密分压器 在电子设计领域,可编程增益放大器(PGA)是一个关键的组成部分,而数字可编程
    的头像 发表于 04-18 09:15 91次阅读

    AD5930可编程频率扫描与输出突发波形发生器:功能特性与应用解析

    AD5930可编程频率扫描与输出突发波形发生器:功能特性与应用解析 一、引言 在电子设计领域,波形发生器是一个非常重要的组件,它广泛应用于频率扫描、雷达、网络/阻抗测量等多个领域。今天我们要深入探讨
    的头像 发表于 04-14 16:40 56次阅读

    如何实现可编程直流电源的脉冲输出模式

    随着电子技术的不断发展,可编程直流电源已广泛应用于科研、工业测试和自动化生产等领域。其中,脉冲输出模式因其能够模拟瞬态负载、进行动态响应测试等特殊功能,成为许多高精度应用场景中的关键需求。那么,如何实现可编程直流电源的脉冲
    的头像 发表于 04-11 15:08 414次阅读
    如何实现<b class='flag-5'>可编程</b>直流电源的脉冲<b class='flag-5'>输出</b>模式

    探索CAT523:数字可编程电位器的卓越性能与应用

    探索CAT523:数字可编程电位器的卓越性能与应用 在电子设计领域,数字可编程电位器(DPP)是一种极为实用的器件,它为工程师们提供了灵活的电压控制解决方案。今天,我们将深入探讨Cat
    的头像 发表于 04-10 16:15 169次阅读

    探索CAT5110/5118/5119:32抽头数字可编程电位器的奥秘

    探索CAT5110/5118/5119:32抽头数字可编程电位器的奥秘 在电子设计领域,数字可编程电位器是一种非常实用的元件,它能为电路设计带来更高的灵活性和精确性。今天,我们就来深入
    的头像 发表于 04-10 16:05 150次阅读

    CAT5114:32抽头数字可编程电位器的技术解析与应用

    CAT5114:32抽头数字可编程电位器的技术解析与应用 在电子设计领域,数字可编程电位器(DPP)正逐渐成为替代传统机械电位器和微调电位器的理想选择。今天,我们就来深入探讨Catal
    的头像 发表于 04-10 16:05 142次阅读

    CAT5111:100抽头数字可编程电位器的特性与应用

    CAT5111:100抽头数字可编程电位器的特性与应用 在电子设计领域,数字可编程电位器为电路设计带来了极大的灵活性和便利性。今天我们就来深入了解一下CAT5111这款100抽头
    的头像 发表于 04-10 15:50 165次阅读

    AD7631:18位、250 kSPS差分可编程输入ADC的技术剖析

    AD7631:18位、250 kSPS差分可编程输入ADC的技术剖析 在电子设计领域,模数转换器(ADC)是连接模拟世界和数字世界的关键桥梁。今天我们要深入探讨的是Analog Devices公司
    的头像 发表于 04-02 10:35 151次阅读

    SGM795可编程USB Type - C端口控制器:设计与应用详解

    SGM795可编程USB Type - C端口控制器:设计与应用详解 在当今数字化时代,USB Type - C接口凭借其强大的功能和广泛的应用,成为电子设备中不可或缺的一部分。而SGM795作为
    的头像 发表于 03-16 17:25 437次阅读

    MAX4995系列可编程电流限制开关:设计与应用详解

    MAX4995系列可编程电流限制开关:设计与应用详解 在电子设备的设计中,电流限制开关起着至关重要的作用,它能够保护主机设备免受负载故障的影响。今天,我们就来详细探讨一下Maxim
    的头像 发表于 02-09 15:05 673次阅读

    MAX270/MAX271 数字可编程双二阶连续时间低通滤波器详解

    MAX270/MAX271 数字可编程双二阶连续时间低通滤波器详解 引言 在电子设计领域,滤波器的性能对于信号处理至关重要。Maxim Integrated公司的MAX270/MAX271数字
    的头像 发表于 01-19 16:30 293次阅读

    Zynq全可编程片上系统详解

    Zynq 是由赛灵思(Xilinx,现为 AMD 的一部分)推出的一系列全可编程片上系统。它的革命性创新在于,它不是传统的 FPGA,也不是传统的处理器,而是将高性能的 ARM Cortex-A 系列处理器与传统的 FPGA 可编程逻辑紧密地集成在单一芯片上。
    的头像 发表于 01-13 11:41 2208次阅读
    Zynq全<b class='flag-5'>可编程</b>片上系统<b class='flag-5'>详解</b>

    新品 | Chain DualKey,可编程双按键输入开发板

    ChainDualKey是一款可编程双按键输入开发板,搭载ESP32-S3FN8主控芯片。正面集成2个支持热插拔的青轴机械键盘按键及2个可编程RGBLED,交互反馈优异;内置350mAh锂电池,结合
    的头像 发表于 10-31 16:31 1887次阅读
    新品 | Chain DualKey,<b class='flag-5'>可编程</b>双按键<b class='flag-5'>输入</b>开发板

    PGA855可编程增益仪表放大器技术解析与应用指南

    Texas Instrument PGA855可编程增益仪表放大器是一款具有全差分输出的高带宽可编程增益仪表放大器。PGA855有八个二进制增益设置,衰减增益范围为0.125V/V到16V/V,使用三个
    的头像 发表于 08-08 14:53 1586次阅读
    PGA855<b class='flag-5'>可编程</b>增益仪表放大器技术解析与应用指南

    可编程SLIC语音芯片哪家好?

    在当今数字化快速发展的时代,语音芯片的应用越来越广泛,而可编程SLIC(用户线路接口电路)语音芯片更是凭借其独特的优势,受到众多行业的青睐。那么,面对众多的选择,哪家的可编程SLIC语音芯片更胜一筹
    的头像 发表于 06-12 13:55 877次阅读
    <b class='flag-5'>可编程</b>SLIC语音芯片哪家好?