成为订阅者(免费)

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

数号

数号是允许您从Arduino引脚控制输出的功能。您可以使用它来控制IC,LED或 继电器等很容易。

在这里,您可以确定功能如何工作......

...以及如何使用宏来获得更快的操作。

 

在微控制器中,数据仅用为零和那些 但外部微控制器外部输出是电压 level:

  •  0伏表示零。
  •  5伏代表一个。

此功能可让您控制输出引脚电压所以 将一个引脚写入电压变为5伏,当您写时 输出零电压变为0伏。

笔记: 高输出电压取决于您的特定Arduino 有 - 一些使用3v3作为高水平。 Arduino Uno和Nano使用5V。

它是一个在整个Arduino代码中使用的函数,因为它 将物理引脚与软件中的微控制器分开 - 它 是一种抽象,可以轻松地接地到PIN。

这允许简单地连接外部IC。

注意:以下示波器波形显示如何加速 DigitalWrite操作。但是,并不总是需要这一点。事实上, 应用程序跳过非常愉快地使用标准数码错误 function.

这里显示了更快的宏操作,所以你知道 它(参见稍后的宏定义) - 例如您可能想要速度 由于应用程序中的时间约束,因此运行。

下面的示波器镜头显示使用左侧的DigityWrite()和使用右侧的Macros差异。 左边的时期是7us,而在右边它是〜0.4us。

arduino. Uno数字写入宏速度的比较

提示: (下面)比DigitalWrite()快〜17倍。

在Arduino使用DigitalWrite

为了 工作的功能必须首先设置PIN 输出方向。这通常在Setup()函数中进行一次。 所有引脚默认为电源UPI的输入,所以如果您不't set the pin as output it won't do anything.

这里's的基本用途。

pinMode(<pinnumber>, OUTPUT);    // Set the pin direction.

digitalWrite(<pinnumber>,HIGH);  // Set output pin high.

digitalWrite(<pinnumber>,LOW);   // Set output pin low.

为什么DigitalWrite有用?

unigurewwrite()函数是基石 Arduino系统创建一个简单的界面,通过参考a描述了外部Arduino连接 号码(Arduino PIN)。 PIN码在开发上印刷 电路板使其易于看出正在控制哪个输出。

笔记: arduino.引脚与芯片引脚数不同。

这听起来不错,但如果你想到一个arduino uno 处理器(14个I / O引脚,带有Atmega328P处理器)和Arduino到期(54 I / O引脚,带有Atmel Sam3x8e ARM Cortex-M3 CPU)。这些处理器 非常不同,例如UNO是一个8位处理器,并在16MHz上运行 然而,由于84MHz的32位处理器。

使用DigitalWrite函数您可以在不同的情况下运行相同的代码 处理器很容易,因为您可以选择要使用的PIN。 put LED在销5上,然后打开和关闭。在到期和UNO版本中 (或其他Arduino类型板)您可以使用相同的代码将引脚5打开和关闭引脚5作为数字输出。

这意味着代码重复使用很容易,不需要您知道 关于底层硬件的任何东西(以及如何访问数字 I/O).

使用DigitalWrite的成本

然而,这种灵活性确实以小成本为例,而且成本是 速度。弄清楚这需要时间"real" pin and which "real" 端口正在使用并将PIN号转换为端口和端口 面具。由于处理器无论如何都在运行 - UNO有16毫米 到期的100 MIPS - 失去少数MIPS不是一个大的 坏处。即使对于Uno 16MHz,也可以让您浪费几个周期 获得EasyWwrite操作。

唯一的时间是问题是你绝对必须的时候 以非常快速和精确的速率打开和关闭销钉 - 这将 取决于您试图控制的芯片的芯片规范。

数字字节优势和缺点

优点

代码是交叉处理器兼容。
代码易于理解。
代码控制电路板上的命名引脚,因此易于连接。
更改使用不同引脚的代码是微不足道的。

缺点

代码比直接访问端口慢。
无法在单个操作中执行多个位读取或写入。

使用DigitalWrite.

您可以从引脚读取,或写入PIN,但您可以't do 两者都同时为每个单独的内部硬件用于每个硬件 手术。处理器 需要知道您的程序如何使用PIN。

您可以使用Pinmode()函数来告诉处理器配置PIN以阅读或写入。

笔记: 输入引脚的默认状态。

对于编写,您可以为数字输出设置PIN,如下所示:

const字节thingpin 1;
Pinmode(thispin,ouptut);

您只能在Setup()函数中放置上面的代码,因为您只设置了 程序开始时的引脚方向,通常仍然存在 相同的。我通常说,因为有时你可能需要改变PIN 方向允许某些设备进行操作。达拉斯1电线系统是 一个引脚上的双向。如果您需要这样做,您可以随时更改引脚方向。

那迪普特工作如何

对于这个解释,我们将看看aruduino uno代码库( 代码与任何其他处理器都不同,但是 相同的原则将适用)。

数字写源代码

(位置:C:/计划 文件/ arduino /硬件/ arduino / avr / cores / arduino / wiring_digital.c)

void digitalWrite(uint8_t pin, uint8_t val)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	volatile uint8_t *out;

	if (port == NOT_A_PIN) return;

	// If the pin that support PWM output, we need to turn it off
	// before doing a digital write.
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	out = portOutputRegister(port);

	uint8_t oldSREG = SREG;
	cli();

	if (val == LOW) {
		*out &= ~bit;
	} else {
		*out |= bit;
	}

	SREG = oldSREG;
}

数号内部结构

代码的第一部分介绍了三件事:
  1. 是否有与PIN相关联的硬件PWM?
  2. 引脚的位掩模。
  3. 引脚位于的端口。

有两项家庭清洁行动:

  1. 无效端口如此退出。
  2. 如果引脚有能力,请关闭PWM输出。

然后是设置高或低的输出比特的实际所需操作。

  1. 如果VAL低,则将输出引脚状态设置为零伏。
  2. 如果Val为高,则将输出引脚状态设置为高伏。

首先是数字舷外和别针的部分

这段代码的第一部分是魔法发生在哪里 将抽象引脚编号转换为端口和位掩码。在 此外,还有一个与PWM输出相关联的定时器参数。

	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);

使用DigitalPintotimer.

arduino..h.

#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_pgm. + (P) ) )

对于作为数字I / O的Arduino Uno R3端口从引脚0到13映射为端口D,然后是B B.

  • 引脚0到7映射到PD0至PD7
  • 引脚8至13映射到PB0至PB5
如果您查看源代码的话 digital_pin_to_timer_pgm. is written:

C:\ Program Files \ Arduino \硬件\ Arduino \ Avr \ Variants \ Standard \ Pins_arduino.h

注意:定义__avr_atmega8__用于atmega8版本 在Arduino Uno的R0版本中使用的芯片。不太可能 今天你会看到其中一个;你可以找到一个上的照片 Wikipedia page 这里.

理解此代码的关键是ATMEGA328P的硬件配置,具有PWM输出:
  • PIN 3,HWPIN 5(PD3),
  • 引脚5,HWPIN 11(PD5),
  • 引脚6,HWPIN 12(PD6),
  • 引脚9,HWPIN 15(PB1),
  • 引脚10,HWPIN 16(PB2),
  • 引脚11,HWPIN 17(PB3)。
Atmega168将PWM引脚添加为PD3,PD5和PD6,而Atmega8 PB1,PB2和PB3仅提供PWM输出。引脚的 Atmega328应该与Atmega168相同,因为没有 定义将它们分开在代码中。

这是这个问题 如果PIN用作数字输出引脚,则它不能用作PWM输出 并且使用数字输出的愿望覆盖PMW使用。

阵列允许代码检查PIN是否可以是PWM输出,并且哪个计时器与该引脚相关联。

注意:如果是PWM引脚,则硬件指示使用哪个计时器。这些是在Atmega328硬件架构中修复的。

如果引脚具有相关的计时器(由阵列值指示)输出 然后该功能关闭与该计时器相关联的PWM输出。 即,如果数组值不等于NOT_ON_TIMER,则关闭 PWM输出为该引脚。例如

如果您使用引脚2,则阵列返回NOT_ON_TIMER - PIN 2没有PWM。没有拍摄任何操作。

如果您使用引脚3,则阵列返回Timer2B指示在那里 PWM在引脚上是否使用Timer2。然后代码关闭 使用功能TurnOffPWM(定时器)的PWM输出。

使用digitalpintobitmask.

发现特定Arduino引脚的位掩码值。

arduino.h:

#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )

pins_arduino.h:
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
	_BV(0), /* 0, port D */
	_BV(1),
   ...
   };

_bv(n)是返回8位比特掩码(或位的宏 值)并由编译器定义。 _bv(n)宏执行等效位偏移 操作但返回一个值,因此没有运行时间惩罚 操作代码即,使用了左命令没有左侧命令 - 它是预先计算的。例子:

_bv(0)返回0x01 //操作是(1<<0)
_bv(1)返回0x02 //操作是(1<<1)
_bv(7)返回0x80 /​​/操作是(1<<7)

因此,DigitalPintobitMask只返回PIN的位值。

使用DigitalPintoport.

查找特定Arduino PIN的端口地址。

arduino.h:

#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
digital_pin_to_port_pgm实际上是一个字节大小的端口地址阵列:
  • 前8个值是PD(PORTD) - 引脚0到7,
  • 接下来的6个值是PB(端口B) - 用于引脚8 RO 13,
  • 接下来的6个值是PC(端口C) - 用于引脚14至19 - 这些是模拟引脚。
提示:如果将Pinmode设置为数字引脚,则可以使用模拟引脚 输出或输入。将它们设置回模拟引脚,只需执行 从引脚读取的模拟。

最后,实际工作的部分

代码的最后一部分使用实际端口位操作使用 反转(〜)和逻辑和(&)和逻辑或(|)。这些用途 标准位设置或复位掩模技术。

	out = portOutputRegister(port);

	uint8_t oldSREG = SREG;
	cli();

	if (val == LOW) {
		*out &= ~bit;
	} else {
		*out |= bit;
	}

	SREG = oldSREG;

最后部分代码解释

首先,所有8位变量设置为有问题的端口的当前值。
	out = portOutputRegister(port);
然后保存当前状态寄存器值(SREG),并中断 被关闭了。状态寄存器包含当前全局 中断使能标志(B7)。执行CLI以关闭中断。什么时候 SREG后来更新了Oldsreg价值,中断状态 将保留在执行CLI之前的状态。
	uint8_t oldSREG = SREG;
	cli();
如果函数输入值(val)低,则转动特定位 离开。使用反相位模式和当前端口值(8 比特)设置特定的比特低(但只有该位)。
	*out &= ~bit;
否则,该位设置为高。或者仅使用比特为特定的比特高的当前端口值。
	*out |= bit;
最后,SREG恢复,将中断使能标志恢复到其先前的状态。

为什么DigitalWrite这么慢?

数号是较慢的,因为它被写入允许访问 到Arduino引脚,它确实有一些管家任务PWM检测, 端口计算和位掩码计算(如上所述)。

但是,DigitalWrite并不是那么慢(〜6us拨动)  您可以使用DigitalWrite控制大多数设备。它只出现 当您尝试控制更多苛刻的接口时,速度很慢。在这方面 案例使用下面显示的快速宏获得〜20x的速度增加。

如何加快数字交换

本节配有警告 - 这是:如果你使用 以下速度增加,然后您将进入未受保护的代码 区域。这只是软件工程师/硬件设计师良好的默认编程方法。

它只是意味着,如果你做愚蠢的事情,那么愚蠢的事情会发生!

数字手写开始时上面的Arduino代码保护用户 从打开PWM输出,同时尝试使用 它们是正常的数字I / O.此外,代码转换了一个简单的 号码到端口和引脚蒙版。

在商业化工程系统中,为特定任务设置为 由设计师提供适当使用它们。因此,如果使用PIN作为 PWM输出控制电机然后赢得了'用于任何东西 别的。因此,在这种情况下,您无法访问PIN作为正常数字I / O. 所以你不会需要保护代码。

保护代码是有缺乏经验的/粗心的 工程,所以你真的不'如果您指定和设置,则需要它 系统时的系统。这意味着你可以消除这些 保护和获得速度优势。但请注意DigitalWrite 非常方便,在大多数情况下它足够快。

以下两个示波器图像显示速度差异 在左边的digitewrite()之间,右侧更简单的宏代码(它们使用相同 规模:每分部1US):
数字写速度16MHz Arduino Uno 1US每分裂宏而不是数字写16MHz Arduino Uno

这些示波器图像适用于16MHz运行的Arduino Uno。

正如您所看到的那样,有相当的速度差异。在左边的左边 期限大约3.5us高,3.5us低。有时它需要 DigitalWrite要切换一次,宏已切换约18次。右侧的切换大约需要0.4us。

放大右手 one:

宏数字写16MHz Arduino Uno放大
范围设置为0.5us / div和x5乘法器。所以它很高 0.1us,低0.3us。 M:S比率的差异是由于跳跃 需要返回循环的开始时所需的指令。

示例素描DigiteWrite和Fast MacroS


用于比较DigitionWrite()和宏版本的代码如下所示:

#define setPin(b) ( (b)<8 ? PORTD |=(1<<(b)) : PORTB |=(1<<(b-8)) )

#define clrPin(b) ( (b)<8 ? PORTD &=~(1<<(b)) : PORTB &=~(1<<(b-8)) )

#define tstPin(b) ( (b)<8 ? (PORTD &(1<<(b)))!=0 : (PORTB &(1<<(b-8)))!=0 )


#define PIN_TST 12

void setup() {
  pinMode(PIN_TST,OUTPUT);
}

void loop() {

  while(1) {
    setPin(PIN_TST); // else
    clrPin(PIN_TST);

//    digitalWrite(PIN_TST,HIGH);
//    digitalWrite(PIN_TST,LOW);
  }
}

快速宏为引脚0到13而工作。延伸他们 Portc需要类似于以下内容的另一个条件(不是 tested):

#define setpinabc(b)(((b)>13) ?   PORTC |=(1<<(b-13))  : \
                  ( (b)<8 ? PORTD |=(1<<(b)) : PORTB |=(1<<(b-8)) )  )

这增加了另一个条件,所以会慢。它没有检查 输入大于最大引脚19,所以你可以让它出错!

笔记: 对于中断安全宏将宏包装在SRG代码中 如数字写作。这一切意味着输出不会是 interrupted i.e. won'T由执行中断扩展。

一些常见问题解答

为什么Dightwwrite没有't work?

这可能是因为在使用DigitionWrite之前,您忘了使用Pinmode将引脚设置为输出。

我需要数码错误吗?

在这方面没有arduino是不同的。在大多数编译器中 系统您必须包含您需要的一切,但在 Arduino此功能内置(与其他许多人一样 - 查看Arduino 参考)。你只需要'includes'纳入外部图书馆 functions.

我可以在中断中使用DigiteWrite吗?

是的,在中断中使用它是安全的,因为它本身并不依赖于任何其他中断。

我可以在设置功能中使用DigiteWrite吗?

是的

我可以使用DigiteWrite进行多个引脚吗?

否:您必须单独写入每个PIN。如果你想 同时编写多个引脚它们必须位于同一端口上。这 您使用按位运算符设置或清除同一引脚 时间(仅将位屏蔽设置为要控制的引脚)。

我的Arduino DigitalWrite不是5V

物理接口有限(具体电流)。如果 使用大电流绘图加载输出电压加载引脚 即使输出很高,也会下降。这个是正常的。

无论是那个,还是你正在使用不同的PSU级别的Arduino。 3v3。

我可以使用DigitalWrite驾驶电机吗?

输出电流太低。您需要一个接口电路 例如达林顿,MOSFET或继电器或电机驱动器芯片(例如L293D)或 带电机驱动器芯片的屏蔽。

Digitalwrite返回什么?

它返回void i.e.它不会返回任何内容。


新的! Comments

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




隐私政策 | 接触 | 关于我

网站地图 | 使用条款


ezoic.报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

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

    阅读更多

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

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

    阅读更多

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

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

    阅读更多

  4. TCS230颜色传感芯片:如何运作以及如何使用它。

    如何使用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.

回到顶部