成为订阅者(免费)

加入29,000名其他订阅者以获得用户销售折扣和 其他免费资源。
:
:
大学教师'担心 - 您的邮件地址完全是 安全的。我保证使用它 只要 to send you MicroZine.

这MCP23017 I / O扩展器

您可以使用MCP23017增加任何可以使用I2C接口进行通信的任何微控制器的I / O引脚的数量。

此页面显示如何控制设备 用于驱动LED和阅读按钮按下,但您可以在任何地方使用它 您需要更多通用输入或输出 pin.

它也展示了你 how to use 由于存在一些问题(这里解决的)是非常棘手的中断 in 使用现有的Arduino代码。

MCP23017是一个端口扩展器,它为您提供几乎相同的端口 与标准微控制器相比,例如标准微控制器。 Arduino或Pic设备和它甚至 包括中断。它使用I2C接口为您提供额外的16个I / O引脚 以及全面的中断控制。这是一个非常通用的和 多种可配置的I / O扩展器。通过添加更多设备,您可以增加 总I / O到128引脚仍然使用两个I2C引脚!

此页面的其余部分显示了如何使用arduino使用MCP23017 detail.

注意:对于此芯片的多个23017中断教程,请参阅 这里.

对于某些应用,它可能有点超过顶部;例如,如果你 只想控制输出a 74HC595. would be cheaper.

IC2版本以100kHz,400kHz和1.7MHz的速度运行。它也是 操作从1.8V到5.5V。

中断输出是最重要的功能之一 MCP23017,因为微控制器不必不断调查 设备检测输入变化。相反,可以是中断服务例程 用于快速反应到任何引脚的输入变化。一个按键等。

MCP23017文本电路面包板布局

MCP23017为每个输入引脚(可配置)具有内部上拉,所以存在 无需添加外部上拉电阻,以便输入按钮等输入 etc.

该设备还提供了3个地址输入,因此您可以添加总共 8个设备到同一I2C总线上,为您提供128个新的I / O引脚只需 两个微控制器I2C引脚进行控制。

替代设备是MCP23S17,使用spi 可以在10MHz(比I2C版本快)运行的接口。这个 SPI设备具有相同的销钉和排列,但使用两个未使用 (I2C)引脚实现SPI接口。在所有其他方面它运作 与MCP23017相同。

为了使寿命更轻松地,每个GPIO输入引脚都可以配置 内部上拉(〜100k),这意味着你赢了'T必须加入外部拉力 用于键盘输入的电阻。您还可以混合和匹配输入和输出 与任何标准微控制器8位端口相同。

MCP23017引脚向上

MCP23017引脚向上

MCP23017规范

  Parameter
价值
  Voltage Supply (Vs)
1v8〜5v5
  Abs Max Voltage
-0v3〜5v5
  Interface
I2C
  I2C Address (取决于Alt Addr)
0x20〜0x27
  界面速度(kHz)
100,400,1700
  供电电流(空闲): 1mA
  Operational 当前最大的VSS [*] 150mA
  运行当前最大化为VDD [*] 125mA
  每个引脚的输出电流 25mA
  Standby Current 01uA
  工作温度
-40°C〜85°C
* 这是一 不寻常的参数规范。并涉及必须存在的事实 芯片中的不对称架构,可以只接受指定的芯片 当前的。整个沉降电流为150mA VSS和整体源电流 125mA.

凹槽电流是当引脚时流动的电流(来自外部电路) 低点。播放引脚时,源电流是流动的(到外部电路) high.

这"当前最大的VSS"是所有沉没的电流的总和。
这"Current Max into Vdd"是所有采购电流的总和。

MCP23017数据表

下载数据表 这里.

MCP23017寻址

23017有三个输入引脚,以允许您设置不同的地址 每个附加的MCP23017。可用的地址在I2C控件中指定 字节和每个设备由下面的I2C序列选择:

MCP23017硬件地址

以上对应于三行A0,A1,A2的硬件地址 对应于IC的输入引脚值。您必须设置值 这些硬件输入为0V或(高)伏特,而不是将它们留下浮动 否则它们会从电噪声和芯片上获取随机值 do nothing!

剩下的四个位数是固定的0100(由联盟指定) Doles Out Address Ranges向制造商)。

因此MCP23017 I2C地址范围为32位小数点至37个小数或0x20到 MCP23017的0x27。

笔记: 地址范围允许 3 bits and this means a 最多八个MCP23017 设备可以附加 to any 单一I2C总线。如果你想要更多你需要 使用第二个I2C总线或位爆炸一些引脚来模拟一个或做 巧妙的东西很聪明,即另一个微控制器拦截 未使用的I2C地址并转换它们以控制额外的 MCP23017s.

MCP23017 LED驾驶员

上面的规范表明该设备能够驾驶 但是LED的电流有16个输出,因此最大输出电流 整个设备必须由所有LED共享。

警告: 最大总电流芯片是 150mA, 并且单个引脚的最大值是 25mA.

如果您驱动16个LED,那么每GPIO引脚将是150mA / 16 = 9.38mA(最大值)。 这也假设当它被驱动为低电平时,您正在打开LED。笔记: 选择较低的电流以保持在限制范围内。

请记住,不同的LED颜色具有不同的正向电压降 驱动时(由于二极管如何表现,这是恒定的)以便控制 前进电流您必须指定正确的电流限制电阻 使用的电压源。

如果您在驾驶高电平时将其打开,则等式是 125 / 16ma = 7.8ma(最大值)。注意:选择较低的电流以保持限制。

提示: 如果你的 MCP23017正在热, 然后 通过计算电流来查看芯片的整体输出电流 从每个引脚然后加入这些结果。如果它超过150mA然后 通过增加每个限制电阻器来减少电流 pin.

显然减少了使用中的输出数量将允许增加 电流最多可达25mA,但是您可以仅开车6针 全电流! (150mA / 25mA = 6)。您必须始终保持最大的总体 150mA限制内芯片的输出电流否则芯片变热 并且可能会失败。

如果您保持最大值,MCP23017变热的事实并不是问题 整体电流消耗至150mA。你应该看看数据表 允许最大温度,并测量其表面的芯片温度。 数据表通常,我没有看在这种情况下,还指定了一个 解额定值参数(或图形),以便在热外壳中使用(或任何 环境)您必须降低消耗的最大电流!

MCP23017非中断 registers

IODIR I / O方向注册

用于控制每个引脚的I / O方向,寄存器IODIR(A / B)让您设置 当写入零时并在输入时向输出到输出'1' is 写入寄存器位。这对于大多数微控制器来说是相同的方案 - 关键是要记住零('0') equates to the 'O' in Output.

GPPU上拉寄存器

设置一点高设置对应I / O引脚的上拉有效。

OLAT输出闩锁寄存器

这与18F系列PIC片中的I / O端口完全相同 can read back the "desired"端口引脚的输出是否实际 达到该销的状态。即,考虑一个强大的当前领导 引脚 - 易于将输出电压拉到销钉上 低于逻辑阈值I.E.如果从中读取,您将读回零 当实际上它应该是一个。读取OLAT寄存器位 returns a 'one'正如您所期望的软件工程点 view.

IPOL引脚反转寄存器

iPol(A / B)寄存器允许您选择性地反转任何输入引脚。这个 从此减少将其他设备接口到MCP23017所需的胶水逻辑 you won'T需要添加变频器逻辑芯片以获得正确的信号极性 into the MCP23017.

通过正确的方式使信号提升为非常方便。它是 用于使用拉压电阻的共同输入,因此当用户按下输入时 键电压输入为零,所以在软件中,您必须记住测试 zero.

使用MCP23017您可以反转该输入并测试1(在我的脑海中 一个关键按钮更等于上的状态i.e.A'1')但我使用上拉 所有时间(和UC都在通过启用时使用内部上拉)所以必须 张贴零'pressed'。使用此设备会允许您纠正 this easily.

笔记: 在任何地方使用有效低信号的原因 是一个历史:TTL(晶体管晶体管逻辑)器件吸取更多的功率 由于内部电路,在有效的低状态下,重要的是 减少不必要的功耗 - 因此最无效的信号 时间例如芯片选择信号 - 定义为高。与cmos. 设备任一状态会导致相同的电源使用情况,因此它无关紧要 - 然而,使用有效低,因为每个人现在使用它并使用它 past.

SEQOP轮询模式:注册位:(内 IOCON register)

如果您有一个具有关键中断代码的设计,例如,用于执行A. 时间临界测量您可能不希望非关键输入生成 中断I.E.您为最重要的输入数据保留中断。

在这种情况下,允许轮询一些设备可能更有意义 输入。促进这一点"Byte mode"提供。在此模式下,您可以阅读 使用时钟但不是针刺提供其他控制的同一套GPIO 信息。即它留在同一组GPIO位,你可以 在没有寄存器地址更新本身的情况下,不断阅读它。在非字节中 模式您必须设置从(A或B Bank)读取的地址作为控制 input data.

注意:稍后讨论中断寄存器 这里.

软件库和版本

arduino. IDE版本

版本:1.8.3.

adafruit图书馆

McP23017 Aruduino图书馆

  • Adafruit MCP23017库1.0.3

这很容易从Arduino IDE安装。

如果您单击菜单时,如果您没有将库视为条目,那么 安装库如下:

草图 - >Include Library

然后选择管理库:

草图 - >Include Library -->Manage Libraries...

搜索并安装<lib name> using the "Filter Your Search" form.

图书馆运营

MCP23017的引脚定义 library

注意:在库中,引脚标记为0到15的位置:

引脚0是端口的位0

PIN 7是端口A的位7

PIN 8是B的位0

引脚15是端口B的位7

MCP23017 I / O控制 functions

单点I / O.

类似的成员函数用于Arduino上的PIN控件用于 控制MCP23017引脚:

mcp.pinmode(0,输出);

mcp.digitalwrite(0,高);

mcp.digitalread(0);

连接

简单的网表连接

以下网表和图表向您展示了MCP23017如何连接到 arduino很简单。

将扩展器的PIN#12连接到Arduino模拟5(I2C时钟)

将扩展器的引脚#13连接到Arduino模拟4(I2C数据)

将扩展器的引脚#19连接到Arduino引脚3(中断输入)。

将扩展器的销钉#15,16和17连接到Arduino地址(地址 selection)

将扩展器的PIN#9连接到Arduino 5V(POWER)

将扩展器的PIN#10连接到Arduino地面(共同的地面)

通过〜10kohm电阻连接膨胀机的销钉#18至5V(复位引脚, active low).

将扩展器的PIN#28连接到LED的+ VE端,然后将LED结束到A〜1kohm 电阻到GND(MCP_LED1)。

将扩展器的销#26连接到LED的+ VE端,然后〜1kohm 电阻到GND(MCP_LEDTOG1)。

将膨胀器的引脚#4连接到LED的+ + VE端,然后〜1kohm电阻 到gnd(mcp_ledtog2)。

将扩展器的PIN#1连接到常开按钮然后 连接到GND(MCP_Inputpin)。

笔记: 在I2C引脚中启用了上拉"Wire" library 所以未在上面的电路连接或布局(下面)中显示。他们是 高值(可能为50k〜100k),因此在I2C信号使用时更快的上升沿使用 较低值的物理上拉电阻将覆盖高值。

Fritzing布局:MCP23017电路

MCP23017文本电路面包板布局

arduino. MCP23017示例代码

示例1基本操作

此示例在MCP23017的不同端口上显示了三个LED,其中有两个 在口岸(绿色和红色)。两个LED交替闪现(红色) 第三个示出了Arduino读取了GPB0 I.E I.E GPB0上的输入的状态 然后更新绿色LED。这显示了个体的独立控制 端口位I.E.闪烁红色LED时,按钮读取和绿色一个 is updated.

它有助于展示中断如何有用(见下一个例子 中断代码)。尝试按下按钮并快速发布它 - 通常是 输出绿色LED不会立即改变状态 - 您可以找到按键 甚至没有检测到!

以下示例使用Arduino和MCP23017库显示。

// MCP23017 Example: Slow key press reaction.
//
// Toggle LEDs and detect keypress.
//
// Example code showing slow reaction of 'button'
// LED to keypress. Leading into why interrupts
// are useful (See next example).
//
// Copyright : John Main
// Free for non commercial use.

#include <Wire.h>
#include <Adafruit_MCP23017.h>

#define MCP_LED1 7
#define MCP_INPUTPIN 8
#define MCP_LEDTOG1 11
#define MCP_LEDTOG2 4

Adafruit_MCP23017 mcp;

void 设置() {
  mcp.begin();      // Default device address 0

  mcp.pinMode(MCP_LEDTOG1, OUTPUT);  // Toggle LED 1
  mcp.pinMode(MCP_LEDTOG2, OUTPUT);  // Toggle LED 2

  mcp.pinMode(MCP_LED1, OUTPUT);     // LED output
  mcp.digitalWrite(MCP_LED1, HIGH);

  mcp.pinMode(MCP_INPUTPIN,INPUT);   // Button i/p to GND
  mcp.pullUp(MCP_INPUTPIN,HIGH);     // Puled high to ~100k
}

// Alternate LEDTOG1 and LEDTOG2.
// Transfer pin input to LED1.
void 环形() {

  delay(300);

  mcp.digitalWrite(MCP_LEDTOG1, HIGH);
  mcp.digitalWrite(MCP_LEDTOG2, LOW);

  delay(300);

  mcp.digitalWrite(MCP_LEDTOG1, LOW);
  mcp.digitalWrite(MCP_LEDTOG2, HIGH);

  // Transfer input pin state to LED1
  if (mcp.digitalRead(MCP_INPUTPIN)) {
     mcp.digitalWrite(MCP_LED1,HIGH);
  } else {
     mcp.digitalWrite(MCP_LED1,LOW);
  }

}

滞后关键的原因 detection

如果按下按钮以改变LED的状态(LED1),则存在 当你击中按钮时,有时会出现滞后 释放它时是真的。你可以说代码有一个相当放松的 在某些情况下显示关键更新的态度 - 这无关紧要 例如在温室中的窗口开启器的执行器非临界接通 (无论如何都很慢),但在其他人中,这将是至关重要的。一个 紧急电机停在机器中。

它慢慢反应的原因是代码内的长延迟 that are "do-nothing"延迟,如果您在其中一个击中按钮 期间,处理器忽略了按钮按下。

滞后钥匙检测解决方案

当然,这是一个略微创作的例子,因为你可以很容易地改变 用于更快轮询或使用动态延迟(使用Millis函数)的代码,但是 它以来展示了真实的世界经营"real"程序您需要的 处理器做得很多工作,这项工作将产生不可避免的 延迟(因为它一次只能做一件事)。

这是中断成为必不可少的地方。中断使其看起来很糟糕 处理器能够一次执行多个过程即i.e 执行延迟动作并检测按键。在这种情况下,你需要一个 中断以检测MCP23017上的按键。示例2使用中断到 克服循环函数内的延迟。

在线库上警告 and Interrupts

弄清楚了一会儿,但这是其中一个陷阱 与Arduino图书馆合作,你有时必须更深 在你看来之前了解引擎盖下发生的事情 something won't work.

示例2 MCP23017 Interrupts Don't Work

在第一个示例中,当您按下按钮到零输入端口(GPB0) 输出LED(LED1)需要一段时间才能降低。这里的想法是使用 一个简单的中断例程来服务外部中断,重新启动它们和 继续使输出LED立即切换,按钮是 按I.E.使用中断即时LED更新。

然而,这个想法中有一个主要的非明显的塔乔,这阻止了这一点 工作中的简单中断代码。

以下代码显示了将回调函数附加到的典型用途 interrupt [Source //www.arduino.cc/en/Reference/AttachInterrupt]

这following code 工作 ;这是一个正常的外部 仅在Arduino Uno R3上操作中断 - 只需将按钮连接到PIN 2 并且LED将切换。按下按钮时导致外部中断 拉引引脚2低发射中断例程'blink'然后切换 LED状态(写入主循环)。

const byte ledPin = 13;
const byte 在 terruptPin = 2;
volatile byte 英石ate = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(在 terruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(在 terruptPin), , CHANGE);
}

void loop() {
  digitalWrite(ledPin, 英石ate);
}

void () {
  英石ate = !英石ate;
}

这是我想要使用的代码(下面),当你看看它 看起来完全合理。

笔记: 下面的示例代码是显示的 教育学位 目的和 不起作用 正确(见下面的原因是这样的原因)。

这following code has three standard functions:

  • 设置()
  • ISR()
  • 环形()

设置函数在循环函数切换某些时初始化端口 LED和ISR对按钮按下(但代码发生故障)反应。

笔记: 此代码挂起等待中断查看下一个代码 解决方案的示例。

// MCP23017 Example: Unexpected Interrupt failure.
//
// This code sends an interrupt from the MCP23017
// to an Arduino external interrupt pin when an
// MCP23017 input button press is detected.
// At the same time MCP LEDs are toggled on button
// release. THIS CODE FAILS FOR A VERY SUBTLE REASON.
//
// Copyright : John Main
// Free for non commercial use.

#include <Wire.h>
#include <Adafruit_MCP23017.h>

// MCP23017 setup
#define MCP_LED1 7
#define MCP_INPUTPIN 8
#define MCP_LEDTOG1 11
#define MCP_LEDTOG2 4
// Register bits
#define MCP_INT_MIRROR true  // Mirror inta to intb.
#define MCP_INT_ODR    false // Open drain.

// Arduino pins
#define INTPIN 3   // Interrupt on this Arduino Uno pin.

volatile uint16_t dmy; // Dummy for use within interrupt.

Adafruit_MCP23017 mcp;

void 设置(){

  mcp.begin();      // use default address 0

  pinMode(INTPIN,INPUT);

  mcp.pinMode(MCP_LEDTOG1, OUTPUT);  // Toggle LED 1
  mcp.pinMode(MCP_LEDTOG2, OUTPUT);  // Toggle LED 2

  mcp.pinMode(MCP_LED1, OUTPUT);     // LED output
  mcp.digitalWrite(MCP_LED1,LOW);

  // This Input pin provides the interrupt source.
  mcp.pinMode(MCP_INPUTPIN,INPUT);   // Button i/p to GND
  mcp.pullUp(MCP_INPUTPIN,HIGH);     // Puled high ~100k

  // On interrupt, polariy is set HIGH/LOW (last parameter).
  mcp.setupInterrupts(MCP_INT_MIRROR, MCP_INT_ODR, LOW);
  mcp.setupInterruptPin(MCP_INPUTPIN,FALLING);

  mcp.readGPIOAB(); // Initialise for interrupts.

  // Enable interrupts - This is the Arduino interrupt control.
  attachInterrupt(digitalPinToInterrupt(INTPIN),isr,FALLING);
}

// The interrupt routine handles MCP_LED1
// This is the button press since this is the only active interrupt.
void ISR(){
英石atic uint8_t ledState=0;

   // Debounce. Slow I2C: extra debounce between interrupts anyway.
   // Can not use delay() in interrupt code.
   delayMicroseconds(1000);

   dmy = mcp.readGPIOAB();

   if ( ledState ) {
      mcp.digitalWrite(MCP_LED1, LOW);
   } else {
      mcp.digitalWrite(MCP_LED1, HIGH);
   }

  ledState = ! ledState;
}

//////////////////////////////////////////////
void 环形(){

  delay(300);

  mcp.digitalWrite(MCP_LEDTOG1, HIGH);
  mcp.digitalWrite(MCP_LEDTOG2, LOW);

  delay(300);

  mcp.digitalWrite(MCP_LEDTOG1, LOW);
  mcp.digitalWrite(MCP_LEDTOG2, HIGH);
}

示例3中断示例

此Arduino MCP23017中断示例代码显示了您究竟如何使用 并连接外部中断引脚并将中断正常工作。作为 你在上一个例子中看到 - 你不能只使用Arduino模板 代码因为有一个微妙的问题。这个例子解释了 问题并解决了它。

操作中断的要求是清除中断状态 您必须从INTCAP(中断数据捕获)或GPIO读取。

重要的: 清除中断,您必须从中读取数据 INTCAP(A / B)或GPIO(A / B)。

在上一个代码(示例2)中,在ISR()函数中读取GPIO 为了重置MCP23017中断。但代码挂在那之上 point!

如果您在赢取的图书馆代码中'看看它根本看到任何原因。

看起来有点深刻揭示了罪魁祸首 - 这是"Wire" library. 在此库中,I2C模块中的硬件中断正在使用。自从 执行代码挂起时,中断禁用中断 等待从未采取过的I2C中断。

这意味着你可以't使用MCP23017库代码清除中断 using the "read GPIO"功能(除非您使用特殊技术 - 请参阅下文) 因为线条库永远不会完成!

关键是允许当前ISR()例程中的其他中断但不是 那些将重新启动当前ISR的ISR即停止MCP23017中断 暂时地。 Arduino函数detatchinterrupt(),attachterrupt(), 中断(),nointerrupts()用于实现此目的。

笔记: 通过I2C访问MCP23017需要一段时间即可迈出一段时间 刷新I / O需要的时间可能会占用 expander.

值得研究代码,正如这项工作相当复杂的方式即, 允许中断在已在已运行的中断中触发的中断 routine.

// MCP23017 Example: Interrupt operation.
//
// This code sends an interrupt from the MCP23017
// to an Arduino external interrupt pin when an
// MCP23017 input button press is detected.
// At the same time MCP LEDs are toggled on button
// release.
//
// Copyright : John Main
// Free for non commercial use.

#include <Wire.h>
#include <Adafruit_MCP23017.h>

// MCP23017 setup
#define MCP_LED1 7
#define MCP_INPUTPIN 8
#define MCP_INPUTPIN2 10
#define MCP_LEDTOG1 11
#define MCP_LEDTOG2 4
// Register bits
#define MCP_INT_MIRROR true  // Mirror inta to intb.
#define MCP_INT_ODR    false // Open drain.

// Arduino pins
#define INTPIN 3   // Interrupt on this Arduino Uno pin.

#define controlArduioInt attachInterrupt(digitalPinToInterrupt(INTPIN),isr,FALLING)

Adafruit_MCP23017 mcp;

//////////////////////////////////////////////
void 设置(){

  mcp.begin();      // use default address 0

  pinMode(INTPIN,INPUT);

  mcp.pinMode(MCP_LEDTOG1, OUTPUT);  // Toggle LED 1
  mcp.pinMode(MCP_LEDTOG2, OUTPUT);  // Toggle LED 2

  mcp.pinMode(MCP_LED1, OUTPUT);     // LED output
  mcp.digitalWrite(MCP_LED1,LOW);

  // This Input pin provides the interrupt source.
  mcp.pinMode(MCP_INPUTPIN,INPUT);   // Button i/p to GND
  mcp.pullUp(MCP_INPUTPIN,HIGH);     // Puled high ~100k

  // Show a different value for interrupt capture data register = debug.
  mcp.pinMode(MCP_INPUTPIN2,INPUT);   // Button i/p to GND
  mcp.pullUp(MCP_INPUTPIN2,HIGH);     // Puled high ~100k

  // On interrupt, polariy is set HIGH/LOW (last parameter).
  mcp.setupInterrupts(MCP_INT_MIRROR, MCP_INT_ODR, LOW); // The mcp output interrupt pin.
  mcp.setupInterruptPin(MCP_INPUTPIN,CHANGE); // The mcp  action that causes an interrupt.

  mcp.setupInterruptPin(MCP_INPUTPIN2,CHANGE); // No button connected, see effect on code=none.

  mcp.digitalWrite(MCP_LED1,LOW);

  mcp.readGPIOAB(); // Initialise for interrupts.

  controlArduioInt; // Enable Arduino interrupt control.

}

//////////////////////////////////////////////
// The interrupt routine handles LED1
// This is the button press since this is the only active interrupt.
void ISR(){
uint8_t p,v;
英石atic uint16_t ledState=0;

   noInterrupts();

   // Debounce. Slow I2C: extra debounce between interrupts anyway.
   // Can not use delay() in interrupt code.
   delayMicroseconds(1000);

   // Stop interrupts from external pin.
   detachInterrupt(digitalPinToInterrupt(INTPIN));
   在 terrupts(); // re-start interrupts for mcp

   p = mcp.getLastInterruptPin();
   // This one resets the interrupt state as it reads from reg INTCAPA(B).
   v = mcp.getLastInterruptPinValue();

   // Here either the button has been pushed or released.
   if ( p==MCP_INPUTPIN && v == 1) { //  Test for release - pin pulled high
      if ( ledState ) {
         mcp.digitalWrite(MCP_LED1, LOW);
      } else {
         mcp.digitalWrite(MCP_LED1, HIGH);
      }

      ledState = ! ledState;
   }

   controlArduioInt;  // Reinstate interrupts from external pin.
}


//////////////////////////////////////////////
void 环形(){

  delay(300);

  mcp.digitalWrite(MCP_LEDTOG1, HIGH);
  mcp.digitalWrite(MCP_LEDTOG2, LOW);

  delay(300);

  mcp.digitalWrite(MCP_LEDTOG1, LOW);
  mcp.digitalWrite(MCP_LEDTOG2, HIGH);

}

警告: Arduino图书馆无法应对多个 由于写入库代码的方式(这适合于 Arduino哲学"抽象的PIN操作")。由于代码是以定向的 在Arduino中,找到活动的第一个中断标志值(在INTF中 寄存器)返回PIN值 - 任何都被忽略。对于多个中断 来源您需要编写自己的功能,这些功能不是基于密码的。

MCP23017中断寄存器

中断是全面的 设备,因此需要大量的控制寄存器。这 以下信息允许您轻松理解和控制MCP23017 使用中断操作时。

该设备分为两组8个GPIO寄存器,每个集合都可以 与IT相关联的单独中断(INTA和INTB输出)。

这些是与MCP23017中的中断相关联的寄存器:

  • gpinten.
  • Intcon.
  • 诽谤
  • Iocon.mirror(Iocon寄存器中有点)
  • Iocon.intpol(Iocon注册中有点)
  • Iocon.odr(Iocon寄存器中有点)
  • 在 tcap.
  • 在 tf.

将A或B添加到名称以控制特定寄存器集。

注意:寄存器名称可能与芯片以来的图片名称类似 也由Microchip设计。

镜像寄存器位:(在Iocon中 register)

如果设置为控制位镜线或INTA和INTB,这意味着 任何端口上的任何中断条件都将导致INTA和INTB 活性。未设置时,您有两个单独的中断输出:INTA和INTB 每个与A或B寄存器相关联。

在 tpol注册位:(在Iocon中 register)

如果设置意味着中断输出很高。

odr寄存器位:(在Iocon中 register)

如果设置意味着中断引脚是开漏(覆盖INTPOL)。

在 tcon注册

Intcon控制如下所示中断条件如何:

有两种方法可以检测特定寄存器的中断状态 bit:

  1. 输入引脚更改(与PIN关联的特定INTCON位为0) - This is the default.
  2. 输入引脚更改与偏差中的定义值相比,(特定INTCON 与引脚相关联的位为1)

在第一种情况下,如果新的PIN值是这样的,则会生成中断 与旧的销价值不同。

在第二种情况下,如果新的引脚值是这样的,则会生成中断 与存储的默认值(Defval)不同。

诽谤寄存器

设置引脚的默认值,它是非非活动输入中断 state.

说你有两个中断源,例如一个有效的低警报(ALRM)和一个 有效高传感器(SENS),您希望其中中的任何一个导致中断。 使用您将设置的默认寄存器:

  • ALRM到高的诽谤值,
  • SEVES对低的诽谤值。

与析出值相反的任何信号将触发中断。因此,如果 ALRM信号转到0V将触发中断,如果是SENS 信号转到5V将触发中断。

这可以节省不得不将逆变器芯片放在最大位置 信号极性。您还将启用相应的INTCON和GPinten 对应于使用的寄存器中的位位置的比特位置 interrupts.

GPinten寄存器

你可能有一些引脚,因为LED输出,所以你赢了'想要他们造成一个 中断或您可能有一些输入,您只需要偶尔调查。 gpinten是寄存器,使得寄存器的每位能够充当 更改引脚(IOC)上的中断。使用GPinten,您可以启用特定的输入引脚 通过设置相应的比特高中中断。

INTA和INTB寄存器

该芯片还允许INTA的输出状态的最终配置 intb。这是非常不寻常的,因为芯片通常具有固定的输出状态 必须添加胶水逻辑以获得正确的信号极性。

对于每个INTA和INTB,您可以将输出设置为:

  • 活跃低
  • 活跃高
  • 开水

这些可以从IoCon寄存器中控制。

笔记: 只有MCP23017上的INTA和INTB引脚都是打开的 排水(如果您将其设置为开放)。

在 tf.中断标志寄存器

在 tf.寄存器是中断标志寄存器并告诉您 中断输入导致当前中断触发。当有点设置时 寄存器(已启用中断的)相关的引脚导致 interrupt.

在 tcap.中断数据 Capture register

芯片的另一个特征是捕获寄存器的值 触发中断时。 INTCAP存储输入引脚的输入状态 中断发生时。任何进一步的中断条件都不会导致 interrupt until 读取INTCAP或GPIO.

中断操作

在对INTF标记反应的过程中,您的代码可能会采取 读取中断数据寄存器的时间太长(请记住这是串行 接口设备所以需要时间才能从中获取串行数据 MCP23017).

即使它位于一个快速的串行接口,您也必须设置 一些命令寄存器地址,它们本身是串行输出数据突发。 您可以在中断触发到时间时错过任何更改 你到处依然读回哪个中断导致INTF变化!

为了避免这种情况,IntCAP在中断触发时保留该中断状态 只看到符合中断条件标志的正确状态数据 (INTF).

在读取GPIO寄存器或读取之前,没有其他中断可以发射 INTCAP寄存器。使用INTCAP意味着您可以确切地找到究竟是什么 PIN值在中断时。

因此,您可以在您的整体设计中弄清楚你的整体设计 软件可以跟上预期的中断输入速率。如果你只是 从用户检测键压制输入速率将是低电平所以会有 没有问题,但如果检测到高频信号可能是一个 保持与之相关的问题,但这一切都取决于确切的速度和方法 快速I2C接口正在运行,如果中断例程是 efficient!

多个中断 Connections

如果您想在I2C总线上拥有几种MCP23017设备,并且您需要 还允许他们中的任何一个中断处理器,然后您需要使用 中断输出引脚的开路功能。使用单个电阻 将开放式排放量拉高,从每个MCP23017中绑住所有中断输出 将INTA和INTB输出设置为电线'OR' mode.

注意:打开此链接 详细的多个中断教程。

如果任何一个输入导致中断,则该开口排出"wire or" 连接将被拉低。然后是你去找出哪个 设备导致中断。

警告: 这表明你必须有一个活跃的低位 在微控制器上输入输入或使用下降沿中断模式。

清除中断

为了清除中断条件,以便可以收到更多中断 阅读INTCAP或GPIO.

您必须在初始化期间读取其中任何一个中断 可能根本无法启动。

警告: 如果您未读取,中断似乎失败 INTCAP or GPIO.
如果您阅读INTCAP,可以在调试时捕捉到OUT的一件事 寄存器然后MCP23017清除INTF寄存器和INTCAP寄存器所以 再次读取它会导致零的零点。

重要的

使用MCP23017使用中断的一个非常重要的部分是以下内容 从数据表中提取:

MCP23017中断原因

注意2n 表明中断将会的条件 从INTCAP或GPIO阅读后不清楚。在这种情况下,你会有 删除中断源(例如,释放密钥)或重新编程 中断条件。你应该只使用2n case where you know 中断源将很短。

例如,如果您使用按键作为中断源和第二个案例 设置,用户可以通过按住按钮来强制处理器停止!

因此最好雇用1英石 method for detecting 中断状态只是因为它更容易关闭它们!

警告: 数据表(第3.6.4节)谈到 中断更改寄存器然后谈论INEINGEN寄存器(不是 存在),然后它谈论IOC寄存器(除了位之外,此信号不存在 在INTCON中)。它实际上是INTCONA / B寄存器 包含IOC位的中断更改寄存器。

注册参考

以下是银行设置为零时的线性地址范围

Iocon.Bank = 0.

进入:

00h iodira

01h iodirb.

02h ipola.

03h ipolb.

04h Gpintena.

05h gpintenb.

06h defvala.

07h defvalb.

08h Intcona.

09h Intconb.

0ah Iocon.

0bh Iocon.

0ch gppua.

0dh Gppub.

0eh Intfa.

0FH INTFB.

10h Intcapa.

11h Intcapb.

12h gpioa.

13h gpiob.

14h olata.

15小时olatb.

进一步进一步: 学习如何使用多个 MCP23017设备并将其中断输出连接在一起; 遵循本教程:单击此处.

新的! Comments

让你说到你刚刚阅读的东西!留下下面的框中的评论。




隐私政策 | 接触 | 关于我

网站地图 | 使用条款


ezoic.报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

    使用ADS1115精度16位ADC进行教程进行低功耗。

    阅读更多

  2. arduino.模拟输出...易模拟输出生成

    arduino.模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。

    阅读更多

  3. 数号和等效的快速宏。加快代码!

    了解DigitalWrite()的工作原理......现在使用17倍宏宏!

    阅读更多

  4. 这TCS230 Color Sensing Chip: How it works and how to use it.

    如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。

    阅读更多

  5. 如何使用ADXL345进行运动感测等。

    使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。

    阅读更多

  6. HMC5883L 3轴数字MAGENTOMTER如何运作

    HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。

    阅读更多



读者 Comments

"I wanted to thank
你这么好
对于所有信息
你已经提供了
你的网站's

高超极好的."

- 逃亡Potthath.

"This site really is
最好的和我最喜欢的。
我发现这里有很多很有用
项目和提示。"

- 米兰

Bursach.<at>gmail.com<

"Awesome site,
非常,非常容易和好
导航!"


-
镭_tr.<at>
wolf359.cjb.net.


学习微控制器

"Interested in
微控制器?"

注册
免费7天指南:

自由 GUIDE : CLICK HERE


"I am a newbie to PIC
我想说
 how great your
网站一直在为我。"


- 戴夫

de_scott.<at>bellsouth.net

"Your site is a great
和完美的工作。
恭喜。"


- SURESH.

IntegratedInfosys.<at>
Yahoo.com.

"I couldn't find the correct
要定义的词语
你的网页。

非常有用,揭开,
诚实明确。

非常感谢
你的时间和作品。
问候。"


- Anon.

回到顶部