语言参考-Functions

本篇文章均翻译自官方文档,为博主自用。方便博主提高英语水平。

必须注意的是,翻译不可能完全正确,若有矛盾之处或不能理解之处,需要查看原英文资料,并在comment中告知。

Arduino编程语言可以分为三个主要部分:函数、值(变量和常量)以及结构。

函数

用于控制Arduino板并执行计算。

数字输入/输出

digitalRead()

digitalRead()

Description

从指定的数字引脚读取值,值为 HIGHLOW

Syntax

digitalRead(pin)

Parameters
pin:你想要读取的 Arduino 引脚编号

Returns

HIGHLOW

Example Code

将13号引脚设置为与作为输入的7号引脚相同的值。

int ledPin = 13;  // LED连接到数字引脚13
int inPin = 7;    // 按钮连接到数字引脚7
int val = 0;      // 变量用于存储读取的值

void setup() {
  pinMode(ledPin, OUTPUT);  // 设置数字引脚13为输出
  pinMode(inPin, INPUT);    // 设置数字引脚7为输入
}

void loop() {
  val = digitalRead(inPin);   // 读取输入引脚
  digitalWrite(ledPin, val);  // 将LED设置为按钮的值
}

Notes and Warnings

如果引脚没有连接到任何东西,digitalRead() 可能返回 HIGH 或 LOW(这个结果可以随机变化)。

模拟输入引脚可以用作数字引脚,分别称为 A0、A1 等。例外情况是 Arduino Nano、Pro Mini 和 Mini 的 A6 和 A7 引脚,它们只能用作模拟输入。

See also

digitalWrite()

digitalWrite()

Description

向数字引脚写入一个 HIGHLOW 值。

如果引脚已经使用 pinMode() 配置为 OUTPUT,它的电压将被设置为相应的值:对于 HIGH 为5V(或3.3V板上的3.3V),对于 LOW 为0V(接地)。

如果引脚被配置为 INPUTdigitalWrite() 将启用(HIGH)或禁用(LOW)输入引脚上的内部上拉。建议将 pinMode() 设置为 INPUT_PULLUP 以启用内部上拉电阻。有关更多信息,请参阅 数字引脚 教程。

如果你没有将 pinMode() 设置为 OUTPUT,并且将一个 LED 连接到一个引脚上,在调用 digitalWrite(HIGH) 时,LED 可能看上去比较暗。如果没有显式设置 pinMode()digitalWrite() 将启用内部上拉电阻,它就像一个大的限流电阻。

Syntax

digitalWrite(pin, value)

Parameters

pin:Arduino引脚号。
valueHIGHLOW

Returns

Example Code

代码将数字引脚13设置为OUTPUT,并通过在HIGHLOW之间交替切换,以每秒钟的速度进行切换。

void setup() {
  pinMode(13, OUTPUT);    // 将数字引脚13设置为输出
}

void loop() {
  digitalWrite(13, HIGH); // 将数字引脚13设置为开
  delay(1000);            // 等待一秒钟
  digitalWrite(13, LOW);  // 将数字引脚13设置为关
  delay(1000);            // 等待一秒钟
}

Notes and Warnings

模拟输入引脚可以作为数字引脚使用,分别称为A0、A1等。但Arduino Nano、Pro Mini和Mini的A6和A7引脚除外,它们只能用作模拟输入。

See also

pinMode()

pinMode()

Description

配置指定的引脚以表现为输入或输出。有关引脚的功能详细信息,请查看数字引脚页面。

可以使用模式INPUT_PULLUP来启用内部上拉电阻。此外,INPUT模式会明确禁用内部上拉。

Syntax

pinMode(pin, mode)

Parameters

pin:要设置模式的Arduino引脚号。
modeINPUTOUTPUTINPUT_PULLUP。有关功能的更完整描述,请查看数字引脚页面。

Returns

Example Code

该代码将数字引脚13设置为OUTPUT并切换其为HIGHLOW

void setup() {
  pinMode(13, OUTPUT);    // 将数字引脚13设置为输出
}

void loop() {
  digitalWrite(13, HIGH); // 将数字引脚13设置为开
  delay(1000);            // 等待一秒钟
  digitalWrite(13, LOW);  // 将数字引脚13设置为关
  delay(1000);            // 等待一秒钟
}

Notes and Warnings

模拟输入引脚可以用作数字引脚,称为A0、A1等。

  1. 问:在arduino中,如果pinMode(pin,OUTPUT);了之后又digitalRead(pin);会发生什么?反之pinMode(pin,INPUT);了之后又digitalWrite(pin,HIGH);又会发生什么?

    答:在Arduino中,pinMode() 函数用于设置特定引脚的工作模式,而 digitalRead()digitalWrite() 函数则用于读取和设置引脚的电平状态。不同的引脚模式与这些函数的组合会有不同的行为:

    1. pinMode(pin, OUTPUT); 后使用 digitalRead(pin);

    当你将一个引脚设置为输出模式(OUTPUT)后,这个引脚被配置为向外提供电压。如果在设置为输出模式后使用 digitalRead() 读取这个引脚的状态,结果可能是不确定的。在大多数微控制器上,输出引脚的读值并不一定反映引脚实际的电平状态,因为输出引脚的设计主要是为了驱动电压而不是读取电压。因此,这种操作通常不推荐,也不保证能得到可靠的结果。

    1. pinMode(pin, INPUT); 后使用 digitalWrite(pin, HIGH);

    当你将一个引脚设置为输入模式(INPUT)后,这个引脚被配置为从外部读取电压状态。在这种模式下,如果使用 digitalWrite(pin, HIGH);,实际上并不会使引脚输出高电平。相反,这通常会启用内部的上拉电阻(如果微控制器支持这一功能)。这意味着引脚将通过一个内部电阻与电源电压(通常是5V或3.3V)相连,这样可以将引脚电平拉高,以便在没有外部电压输入的情况下读取为高电平。

    不过,如果你想明确地使用内部上拉电阻,更清晰的做法是使用 pinMode(pin, INPUT_PULLUP); 而不是 pinMode(pin, INPUT); 后跟 digitalWrite(pin, HIGH);。这样代码的意图更为明确,可读性也更好。

    总结一下,你提到的这两种情况在实际应用中可能会导致混淆或不可预测的行为,因此在编写代码时应尽量避免这样的用法,或者仔细阅读特定微控制器的硬件手册,了解具体的行为表现。

  2. 问:如果使用pinMode(pin, INPUT_PULLUP);那么引脚内部会自动启动上拉电阻是吗?还有,arduino的上电引脚会复位为什么状态?

    答:

    使用 pinMode(pin, INPUT_PULLUP);

    当你在Arduino代码中使用 pinMode(pin, INPUT_PULLUP);,确实会启动该引脚的内部上拉电阻。这意味着引脚将通过一个内部电阻连接到正电压(通常是5V或3.3V,取决于Arduino板的操作电压)。这样做的好处是可以确保当引脚未连接任何输入时,它自然地读取为高电平(HIGH),从而避免了引脚处于悬空状态而导致的不确定读值。

    使用内部上拉电阻是一个常见的做法,尤其是在处理开关和按钮时。当按钮按下时,引脚会被连接到地(GND),读取为低电平(LOW);当按钮释放时,内部上拉电阻将引脚拉高,读取为高电平(HIGH)。

    Arduino引脚的上电复位状态

    Arduino板上电时,所有的数字I/O引脚默认都被设置为输入模式(INPUT)。这是为了最小化启动时对外部电路的潜在干扰。在这种模式下,引脚是高阻抗状态,不会对外部电路产生显著的电流负载。

    这种默认设置有助于防止引脚意外输出高电流,从而可能损坏微控制器或外部连接的硬件。因此,如果你的应用中需要引脚在上电时具有特定的状态(如输出或启用内部上拉电阻),你需要在你的setup()函数中明确地配置这些引脚。

    总的来说,理解和正确设置Arduino引脚的模式对于开发稳定和可靠的应用程序是非常关键的。

  3. 问:那我设置了pinMode(pin,OUTPUT),这个时候引脚是什么状态?

    答:当你在Arduino中通过调用 pinMode(pin, OUTPUT); 将一个引脚设置为输出模式时,这个引脚的初始电平状态取决于之前该引脚的状态和微控制器的具体行为。一般来说,在调用 pinMode() 设置为 OUTPUT 后,引脚的电平状态并不由 pinMode() 函数直接设定,而是保持在最后一次通过 digitalWrite() 设置的状态,或者是微控制器复位后的默认低电平(LOW)状态。

    默认状态

    大多数Arduino板上,引脚在设置为输出模式后,默认状态通常是低电平(LOW)。这意味着,除非你在代码中显式地通过 digitalWrite(pin, HIGH); 将其设置为高电平,否则它将输出低电平。

    实际应用

    为了避免任何不确定性,最佳做法是在设置引脚为输出模式后立即使用 digitalWrite() 明确设置所需的电平状态。例如:

    pinMode(pin, OUTPUT);  // 设置引脚为输出模式
    digitalWrite(pin, LOW); // 明确设置引脚为低电平

    或者:

    pinMode(pin, OUTPUT);  // 设置引脚为输出模式
    digitalWrite(pin, HIGH); // 明确设置引脚为高电平

    这样做可以确保引脚的电平状态符合你的预期,避免在程序运行过程中出现由于引脚状态不明确导致的逻辑错误或硬件问题。

    结论

    总之,虽然在设置为输出模式时引脚可能默认为低电平,但为了编写清晰和可靠的代码,建议总是在设置引脚模式后明确指定其电平状态。这样可以减少错误和不一致的风险,确保程序的行为符合设计意图。

See also

模拟输入/输出

analogRead()

analogRead()

Description

从指定的模拟引脚读取值。Arduino 板包含一个多通道 10 位模拟数字转换器。这意味着它将在 0 和工作电压(5V 或 3.3V)之间的输入电压映射到 0 到 1023 之间的整数值。例如,在 Arduino UNO 上,这产生的读数分辨率为:5 伏/1024 单位,或每单位 0.0049 伏(4.9 mV)。请参阅下表,了解一些 Arduino 板的可用引脚、工作电压和最大分辨率。

可以使用 analogReference() 更改输入范围,而分辨率可以使用 analogReadResolution() 进行更改(仅适用于 Zero、Due 和 MKR 板)。

在基于 ATmega 的板(UNO、Nano、Mini、Mega)上,读取模拟输入需要约 100 微秒(0.0001 秒),因此最大读取速率约为每秒 10,000 次。

工作电压可用引脚最大分辨率
UNO R35 伏A0 到 A510 位
UNO R4 (Minima, WiFi)5 伏A0 到 A514 位**
Mini5 伏A0 到 A710 位
Nano, Nano Every5 伏A0 到 A710 位
Nano 33 (IoT, BLE, RP2040, ESP32)3.3 伏A0 到 A712 位**
Mega, Mega2560, MegaADK5 伏A0 到 A1410 位
Micro5 伏A0 到 A11*10 位
Leonardo5 伏A0 到 A11*10 位
Zero3.3 伏A0 到 A512 位**
Due3.3 伏A0 到 A1112 位**
GIGA R13.3 伏A0 到 A1116 位**
MKR 系列板3.3 伏A0 到 A612 位**

*A0 至 A5 在板上标记,A6 至 A11 分别位于引脚 4、6、8、9、10 和 12 上
**这些板的默认 analogRead() 分辨率为 10 位,以保持兼容性。您需要使用 analogReadResolution() 将其更改为更高分辨率。

Syntax

analogRead(pin)

Parameters

pin: 要读取的模拟输入引脚名称。

Returns

引脚上的模拟读数。尽管受制于模数转换器的分辨率(10 位为 0-1023,12 位为 0-4095)。数据类型:int

Example Code

该代码读取 analogPin 上的电压并显示。

int analogPin = A3; // 电位计游丝(中间端子)连接到模拟引脚 3
                    // 外引线接地和 +5V
int val = 0;  // 存储读取值的变量

void setup() {
  Serial.begin(9600);           //  设置串行
}

void loop() {
  val = analogRead(analogPin);  // 读取输入引脚
  Serial.println(val);          // 调试值
}

Notes and Warnings

如果模拟输入引脚未连接任何东西,analogRead() 返回的值将根据多个因素(例如其他模拟输入的值、您的手靠近板的程度等)而波动。

See also

analogReadResolution()

analogReadResolution()

Description

analogReadResolution() 是 Zero、Due、MKR 系列、Nano 33 (BLE 和 IoT) 和 Portenta 的模拟 API 的扩展。

它设置 analogRead() 返回值的大小(以位为单位)。为了与基于 AVR 的板向后兼容,默认值为 10 位(返回值在 0-1023 之间)。

Zero、Due、MKR 系列和 Nano 33 (BLE 和 IoT) 板具有 12 位 ADC 能力,可以通过将分辨率更改为 12 来访问。这将返回 analogRead() 介于 0 和 4095 之间的值。
Portenta H7 具有 16 位 ADC,将允许介于 0 和 65535 之间的值。

Syntax

analogReadResolution(bits)

Parameters

bits:确定 analogRead() 函数返回值的分辨率(以位为单位)。你可以将其设置为 1 到 32 之间的值。您可以设置高于支持的 12 或 16 位的分辨率,但 analogRead() 返回的值将会遭受近似值。有关详细信息,请参阅下面的注释。

Returns

Example Code

该代码显示了如何使用不同分辨率的 ADC。

void setup() {
  // 打开串行连接
  Serial.begin(9600);
}

void loop() {
  // 以默认分辨率(10 位)读取 A0 上的输入
  // 并通过串行连接发送出去
  analogReadResolution(10);
  Serial.print("ADC 10 位(默认): ");
  Serial.print(analogRead(A0));

  // 将分辨率更改为 12 位并读取 A0
  analogReadResolution(12);
  Serial.print(", 12 位: ");
  Serial.print(analogRead(A0));

  // 将分辨率更改为 16 位并读取 A0
  analogReadResolution(16);
  Serial.print(", 16 位: ");
  Serial.print(analogRead(A0));

  // 将分辨率更改为 8 位并读取 A0
  analogReadResolution(8);
  Serial.print(", 8 位: ");
  Serial.println(analogRead(A0));

  // 稍微延迟一下,不要占用太多串口监视器
  delay(100);
}

Notes and Warnings

如果将 analogReadResolution() 值设置为高于您的板能力的值,Arduino 将只报告其最高分辨率,并用零填充额外的位。

例如:在 Due 上使用 analogReadResolution(16) 将给你一个近似的 16 位数字,前 12 位包含实际 ADC 读数,最后 4 位用零填充

如果你将 analogReadResolution() 值设置为低于你的板能力的值,从 ADC 读取的额外最低有效位将被丢弃

使用 16 位分辨率(或任何高于实际硬件功能的分辨率)允许您编写草图,当未来的板上出现具有更高分辨率 ADC 的设备时,无需更改一行代码即可自动处理这些设备。

See also

analogReference()

analogReference()

Description

配置用于模拟输入的参考电压(即用作输入范围顶部的值)。选项如下:

Arduino AVR 板(Uno, Mega, Leonardo 等。)

  • DEFAULT: 默认模拟参考值为 5 伏(在 5V Arduino 板上)或 3.3 伏(在 3.3V Arduino 板上)
  • INTERNAL: 内置参考值,在 ATmega168 或 ATmega328P 上等于 1.1 伏,在 ATmega32U4 和 ATmega8 上等于 2.56 伏(Arduino Mega 不可用)
  • INTERNAL1V1: 内置 1.1V 参考值(仅限 Arduino Mega)
  • INTERNAL2V56: 内置 2.56V 参考值(仅限 Arduino Mega)
  • EXTERNAL: 使用应用于 AREF 引脚的电压(0 到 5V)作为参考值。

Arduino Renesas 板(UNO R4, Portenta C33)

  • AR_DEFAULT: 默认模拟参考值为 5 伏。
  • AR_INTERNAL: 内置参考值,在 UNO R4 的 RA4M1 上等于 1.5 伏
  • AR_INTERNAL_1_5V: 内置参考值,在 Portenta C33 的 R7FA6M5 上等于 1.5 V
  • AR_INTERNAL_2_0V: 内置参考值,在 Portenta C33 的 R7FA6M5 上等于 2.0 V
  • AR_INTERNAL_2_5V: 内置参考值,在 Portenta C33 的 R7FA6M5 上等于 2.5 V
  • AR_EXTERNAL: 使用应用于 AREF 引脚的电压(0 到 5V)作为参考值。

Arduino SAMD 板(Zero 等。)

  • AR_DEFAULT: 默认模拟参考值为 3.3V
  • AR_INTERNAL: 内置 2.23V 参考值
  • AR_INTERNAL1V0: 内置 1.0V 参考值
  • AR_INTERNAL1V65: 内置 1.65V 参考值
  • AR_INTERNAL2V23: 内置 2.23V 参考值
  • AR_EXTERNAL: 使用应用于 AREF 引脚的电压作为参考值

Arduino megaAVR 板(Uno WiFi Rev2)

  • DEFAULT: 内置 0.55V 参考值
  • INTERNAL: 内置 0.55V 参考值
  • VDD: ATmega4809 的 Vdd。Uno WiFi Rev2 上为 5V
  • INTERNAL0V55: 内置 0.55V 参考值
  • INTERNAL1V1: 内置 1.1V 参考值
  • INTERNAL1V5: 内置 1.5V 参考值
  • INTERNAL2V5: 内置 2.5V 参考值
  • INTERNAL4V3: 内置 4.3V 参考值
  • EXTERNAL: 使用应用于 AREF 引脚的电压(0 到 5V)作为参考值

Arduino SAM 板(Due)

  • AR_DEFAULT: 默认模拟参考值为 3.3V。这是 Due 唯一支持的选项。

Arduino Mbed OS Nano 板(Nano 33 BLE)、Arduino Mbed OS Edge 板(Edge Control)

  • AR_VDD: 默认 3.3 V 参考值
  • AR_INTERNAL: 内置 0.6 V 参考值
  • AR_INTERNAL1V2: 1.2 V 参考值(内置 0.6 V 参考值,增益为 2 倍)
  • AR_INTERNAL2V4: 2.4 V 参考值(内置 0.6 V 参考值,增益为 4 倍)

Syntax

analogReference(type)

Parameters

type: 使用哪种类型的参考值(请参阅描述中的选项列表)。

Returns

Notes and Warnings

更改模拟参考值后,从 analogRead() 获取的前几个读数可能不准确。

不要在 AREF 引脚上使用小于 0V 或大于 5V 的外部参考电压! 如果您在 AREF 引脚上使用外部参考电压,则必须在调用 analogRead() 之前将模拟参考值设置为 EXTERNAL。 否则,您将短路活动参考电压(内部生成)和 AREF 引脚,可能会损坏 Arduino 板上的微控制器。

或者,您可以通过 5K 电阻将外部参考电压连接到 AREF 引脚,从而允许您在外部和内部参考电压之间切换。请注意,该电阻会改变作为参考值使用的电压,因为 AREF 引脚上有一个内部 32K 电阻。两者组成一个电压分压器,因此,例如,通过电阻施加 2.5V 将在 AREF 引脚上产生 2.5 * 32 / (32 + 5) = ~2.2V。

See also

analogWrite()

analogWrite()

Description

将模拟值(PWM波形)写入引脚。可用于以不同亮度点亮 LED 或以不同速度驱动电机。在调用 analogWrite()之后,该引脚将生成指定占空比的稳定矩形波,直到对同一引脚再次调用 analogWrite()(或调用 digitalRead()digitalWrite())。

控制板PWM 引脚*PWM频率
UNO(R3及更早版本)、Nano、Mini3、5、6、9、10、11490 Hz(引脚5和6为980 Hz)
UNO R4(Minima、WiFi)*3、5、6、9、10、11490 Hz
Mega2 - 13、44 - 46490 Hz(引脚4和13为980 Hz)
GIGA R1**2 - 13500 Hz
Leonardo、Micro、Yún3、5、6、9、10、11、13490 Hz(引脚3和11为980 Hz)
UNO WiFi Rev2、Nano Every3、5、6、9、10976 Hz
MKR 系列*0 - 8、10、A3、A4732 Hz
MKR1000 WiFi**0 - 8、10、11、A3、A4732 Hz
Zero**3 - 13、A0、A1732 Hz
Nano 33 IoT**2、3、5、6、9 - 12、A2、A3、A5732 Hz
Nano 33 BLE/BLE Sense****1 - 13、A0 - A7500 Hz
Due***2-131000 Hz
1013、5、6、9引脚3和9为490 Hz,引脚5和6为980 Hz

* 这些是正式支持的PWM引脚。尽管某些板上有其他引脚可以实现PWM,但建议只有高级用户在考虑到定时器可用性和与这些引脚其他用途的潜在冲突的情况下使用。
** 除了上述引脚具有PWM功能外,MKR、Nano 33 IoT、Zero和UNO R4还可在使用analogWrite()时在DAC0(A0)引脚提供真模拟输出。
*** 除了上述引脚具有PWM功能外,Due和GIGA R1还可在使用analogWrite()时在DAC0DAC1引脚提供真模拟输出。
**** 同一时间只能使用4个不同的引脚。启用超过4个引脚的PWM将中止正在运行的程序,需要重置板并上传新程序。

在调用analogWrite()之前,不需要调用pinMode()将引脚设置为输出。
analogWrite函数与模拟引脚或analogRead函数无关。

Syntax

analogWrite(pin, value)

Parameters

pin:要写入的Arduino引脚。允许的数据类型:int
value:占空比,介于0(始终关闭)和255(始终打开)之间。允许的数据类型:int

Returns

Example Code

将输出设置为与从电位器读取的值成比例的LED。

int ledPin = 9;      // LED连接到数字引脚9
int analogPin = 3;   // 电位器连接到模拟引脚3
int val = 0;         // 存储读取值的变量

void setup() {
  pinMode(ledPin, OUTPUT);  // 设置引脚为输出
}

void loop() {
  val = analogRead(analogPin);  // 读取输入引脚
  analogWrite(ledPin, val / 4); // analogRead值范围0到1023,analogWrite值范围0到255
}

Notes and Warnings

在引脚5和6上生成的PWM输出将具有高于预期的占空比。这是由于与millis()delay()函数的交互,它们共享用于生成这些PWM输出的相同内部定时器。这主要会在低占空比设置(例如0-10)时观察到,并可能导致值0无法完全关闭引脚5和6上的输出。

See also

analogWriteResolution()

analogWriteResolution()

Description

analogWriteResolution() 是Arduino Due针对模拟API的扩展。

analogWriteResolution() 设置 analogWrite() 函数的分辨率。为了与基于AVR的板兼容,默认值为8位(值在0-255之间)。

Due 具有以下硬件功能:

  • 12个默认为8位PWM的引脚,与基于AVR的板类似。这些可以更改为12位分辨率。
  • 2个带有12位数字模拟转换器(DAC)的引脚。

通过将写入分辨率设置为12,您可以使用 analogWrite() 在0到4095之间的值来利用DAC的全分辨率,或设置PWM信号而不会溢出。

Zero 具有以下硬件功能:

  • 10个默认为8位PWM的引脚,与基于AVR的板类似。这些可以更改为12位分辨率。
  • 1个具有10位数字模拟转换器(DAC)的引脚。

通过将写入分辨率设置为10,您可以使用 analogWrite() 在0到1023之间的值来利用DAC的全分辨率。

MKR系列 板有以下硬件功能:

  • 4个默认为8位PWM的引脚,与基于AVR的板类似。这些可以从8位(默认)更改为12位分辨率。
  • 1个带有10位数字模拟转换器(DAC)的引脚。

通过将写入分辨率设置为12位,您可以使用 analogWrite() 在0到4095之间的值来设置PWM信号;对于DAC引脚,设置为10位以利用DAC的全1024值分辨率。

Syntax

analogWriteResolution(bits)

Parameters

bits:确定 analogWrite() 函数中使用的值的分辨率(以位为单位)。该值可以范围从1到32。如果您选择的分辨率高于或低于您的板的硬件功能,则在 analogWrite() 中使用的值将被截断(如果太高)或用零填充(如果太低)。有关详细信息,请参阅下面的注释。

Returns

Example Code

解释代码

void setup() {
  // 打开串行连接
  Serial.begin(9600);
  // 将我们的数字引脚设置为输出
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
}

void loop() {
  // 读取A0上的输入,并将其映射到连接有LED的PWM引脚
  int sensorVal = analogRead(A0);
  Serial.print("Analog Read) : ");
  Serial.print(sensorVal);

  // 默认PWM分辨率
  analogWriteResolution(8);
  analogWrite(11, map(sensorVal, 0, 1023, 0, 255));
  Serial.print(" , 8-bit PWM value : ");
  Serial.print(map(sensorVal, 0, 1023, 0, 255));

  // 将PWM分辨率更改为12位
  // 仅Due支持完整的12位分辨率
  analogWriteResolution(12);
  analogWrite(12, map(sensorVal, 0, 1023, 0, 4095));
  Serial.print(" , 12-bit PWM value : ");
  Serial.print(map(sensorVal, 0, 1023, 0, 4095));

  // 将PWM分辨率更改为4位
  analogWriteResolution(4);
  analogWrite(13, map(sensorVal, 0, 1023, 0, 15));
  Serial.print(", 4-bit PWM value : ");
  Serial.println(map(sensorVal, 0, 1023, 0, 15));

  delay(5);
}

Notes and Warnings

如果您将 analogWriteResolution() 值设置为高于您的板功能的值,Arduino将丢弃额外的位。例如:在Due上使用 analogWriteResolution(16) 时,在12位DAC引脚上,只有传递给 analogWrite() 的值的前12位将被使用,最后4位将被丢弃。

如果您将 analogWriteResolution() 值设置为低于您的板功能的值,则缺少的位将被用零填充以满足硬件所需的大小。例如:在Due上使用analogWriteResolution(8)时,在12位DAC引脚上,Arduino将向用于 analogWrite() 的8位值添加4个零位,以获得所需的12位。

See also

先进的输入/输出

noTone()

noTone()

Description

停止由 tone() 触发的方波生成。如果没有正在生成音调,则无效果。

Syntax

noTone(pin)

Parameters

pin:要停止生成音调的 Arduino 引脚

Returns

Notes and Warnings

如果您想在多个引脚上播放不同的音高,您需要在下一个引脚调用 tone() 之前,先在一个引脚上调用 noTone()

See also

pulseIn()

pulseIn()

Description

在一个引脚上读取一个脉冲(HIGHLOW)。例如,如果valueHIGHpulseIn()会等待该引脚从LOW变为HIGH,开始计时,然后等待引脚变回LOW并停止计时。返回脉冲的长度,单位为微秒,如果在超时期间没有接收到完整的脉冲,则放弃并返回0。

此函数的计时是根据经验确定的,可能会在较长的脉冲中显示出错误。适用于从10微秒到3分钟长度的脉冲。

注意如果使用了可选的超时,代码将执行得更快。

Syntax

pulseIn(pin, value)
pulseIn(pin, value, timeout)

Parameters

pin:你想读取脉冲的Arduino引脚号。允许的数据类型:int
value:要读取的脉冲类型:HIGHLOW。允许的数据类型:int
timeout(可选):等待脉冲开始的微秒数;默认值是一秒钟。允许的数据类型:unsigned long

Returns

脉冲的长度(以微秒为单位),如果在超时前没有脉冲开始,则返回0。数据类型:unsigned long

Example Code

该示例打印引脚7上一个脉冲的时间持续。

int pin = 7;
unsigned long duration;

void setup() {
  Serial.begin(9600);
  pinMode(pin, INPUT);
}

void loop() {
  duration = pulseIn(pin, HIGH);
  Serial.println(duration);
}

See also

pulseInLong()

pulseInLong()

Description

pulseInLong()pulseIn() 的替代方案,它更适合处理较长的脉冲和中断受影响的情况。

在一个引脚上读取一个脉冲(高电平或低电平)。例如,如果 valueHIGH,pulseInLong() 会等待引脚从低电平变为高电平,开始计时,然后等待引脚变为低电平并停止计时。如果在超时时间内没有收到完整的脉冲,则返回脉冲长度(以微秒为单位),否则返回 0。

该函数的时序已根据经验确定,在较短的脉冲中可能会出现误差。适用于 10 微秒到 3 分钟长度的脉冲。此例程只有在中断被激活的情况下才能使用。此外,间隔越大,分辨率越高。

Syntax

pulseInLong(pin, value)
pulseInLong(pin, value, timeout)

Parameters

pin: 要读取脉冲的 Arduino 引脚号。允许的数据类型: int
value: 要读取的脉冲类型: 可以是 HIGHLOW。允许的数据类型: int
timeout(可选): 等待脉冲开始的最大时间(以微秒为单位),默认为一秒。允许的数据类型: unsigned long

Returns

脉冲长度(以微秒为单位),如果在超时之前没有检测到脉冲开始,则返回 0。数据类型: unsigned long

Example Code

此示例打印引脚 7 上脉冲的时间持续时间。

int pin = 7;
unsigned long duration;

void setup() {
  Serial.begin(9600);
  pinMode(pin, INPUT);
}

void loop() {
  duration = pulseInLong(pin, HIGH);
  Serial.println(duration);
}

Notes and Warnings

该函数依赖于 micros(),因此不能在 noInterrupts() 上下文中使用。

See also

shiftIn()

shiftIn()

Description

按位移动一个字节中的数据。从最高(即最左边)或最低(最右边)有效位开始。对于每一位,时钟引脚被拉高,下一位从数据线读取,然后时钟引脚被拉低。

如果你正在与由上升沿触发的设备进行接口,你需要确保在第一次调用shiftIn()之前时钟引脚处于低电平,例如调用digitalWrite(clockPin, LOW)

注意:这是一个软件实现;Arduino还提供了一个SPI库,它使用硬件实现,速度更快,但只适用于特定的引脚。

Syntax

byte incoming = shiftIn(dataPin, clockPin, bitOrder)

Parameters

dataPin:输入每一位的引脚。允许的数据类型:int
clockPin:用于发出读取dataPin信号的切换引脚。
bitOrder:移位输入位的顺序;或者MSBFIRSTLSBFIRST(最高有效位先或最低有效位先)。

Returns

读取的值。数据类型:byte

See also

shiftOut()

shiftOut()

Description

逐位输出一个字节的数据。可以从最高位(即最左边的位)或最低位(最右边的位)开始。每个位依次写入数据引脚,之后脉冲一个时钟引脚(设为高电平,然后低电平),以表示该位数据可用。

注意-如果你要与一个通过上升沿进行时钟同步的设备接口,你需要确保在调用 shiftOut() 之前时钟引脚为低电平,例如,通过调用 digitalWrite(clockPin, LOW)

这是一个软件实现;另见 SPI库,它提供了一个硬件实现,速度更快但只能在特定的引脚上工作。

Syntax

shiftOut(dataPin, clockPin, bitOrder, value)

Parameters

dataPin:输出每个位的引脚。允许的数据类型:int
clockPin:一旦dataPin被设置为正确的值就切换的引脚。允许的数据类型:int
bitOrder:位输出的顺序;可以是 MSBFIRST 或 LSBFIRST。(最高有效位优先,或者,最低有效位优先)。
value:要输出的数据。允许的数据类型:byte

Returns

Example Code

有关配套电路,请参见 控制74HC595移位寄存器的教程

//**************************************************************//
//  名称    : shiftOutCode, Hello World                         //
//  作者    : Carlyn Maw,Tom Igoe                               //
//  日期    : 25 Oct, 2006                                      //
//  版本    : 1.0                                               //
//  注释    : 用于使用74HC595移位寄存器                         //
//          : 从0数到255的代码                                  //
//****************************************************************

//连接到74HC595的ST_CP的引脚
int latchPin = 8;
//连接到74HC595的SH_CP的引脚
int clockPin = 12;
//连接到74HC595的DS的引脚
int dataPin = 11;

void setup() {
  //因为在主循环中会寻址这些引脚,所以将它们设置为输出
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
  //计数上升程序
  for (int j = 0; j < 256; j++) {
    //接地latchPin并保持低电平,只要你在传输数据
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, j);
    //将latch pin置高电平,向芯片表示
    //不再需要监听信息
    digitalWrite(latchPin, HIGH);
    delay(1000);
  }
}

Notes and Warnings

dataPin和clockPin必须已经通过调用 pinMode() 配置为输出。

shiftOut目前被编写为输出1字节(8位),因此它需要一个两步操作来输出大于255的值。

// 对于MSBFIRST串行,这样做
int data = 500;
// 输出高字节
shiftOut(dataPin, clock, MSBFIRST, (data >> 8));
// 输出低字节
shiftOut(dataPin, clock, MSBFIRST, data);

// 或者对于LSBFIRST串行,这样做
data = 500;
// 输出低字节
shiftOut(dataPin, clock, LSBFIRST, data);
// 输出高字节
shiftOut(dataPin, clock, LSBFIRST, (data >> 8));

See also

tone()

tone()

Description

在一个引脚上生成指定频率(和50%的占空比)的方波。可以指定持续时间,否则波形将持续到调用 noTone()。该引脚可以连接到压电蜂鸣器或其他扬声器来播放音调。

一次只能生成一个音调。如果在不同的引脚上已经有一个音调在播放,调用 tone() 将没有任何效果。如果音调在同一引脚上播放,调用将设置其频率。

使用 tone() 函数会干扰引脚3和11(在Mega板之外的板上)的PWM输出。

无法生成低于31Hz的音调。有关技术细节,请参见 Brett Hagman的说明

Syntax

tone(pin, frequency)
tone(pin, frequency, duration)

Parameters

pin:生成音调的Arduino引脚。
frequency:音调的频率,单位为赫兹。允许的数据类型:unsigned int
duration:音调的持续时间,以毫秒为单位(可选)。允许的数据类型:unsigned long

Returns

Notes and Warnings

  • 如果你想在多个引脚上播放不同的音高,你需要在一个引脚上调用 noTone(),然后在下一个引脚上调用 tone()
  • 这个函数是非阻塞的,这意味着即使你提供了 duration 参数,草图执行也会立即继续,即使音调还没有播放完毕。

See also

时间

delay()

delay()

Description

程序将暂停参数指定的时间量(以毫秒为单位)。(一秒钟有1000毫秒。)

Syntax

delay(ms)

Parameters

ms:暂停的毫秒数。允许的数据类型:unsigned long

Returns

Example Code

该代码使程序暂停一秒钟,然后切换输出引脚。

int ledPin = 13;              // LED连接到数字引脚13

void setup() {
  pinMode(ledPin, OUTPUT);    // 设置数字引脚为输出
}

void loop() {
  digitalWrite(ledPin, HIGH); // 点亮LED
  delay(1000);                // 等待一秒
  digitalWrite(ledPin, LOW);  // 熄灭LED
  delay(1000);                // 等待一秒
}

Notes and Warnings

虽然使用delay()函数很容易创建一个闪烁的LED,并且许多草图使用短暂的延迟来执行诸如开关去抖动之类的任务,但在草图中使用delay()有显著的缺点。在delay()函数运行期间,不能进行其他传感器的读取、数学计算或引脚操作,所以实际上,它会使大多数其他活动停止。对于控制时序的替代方法,请参见Blink Without Delay草图,它通过循环,轮询millis()函数,直到足够的时间已经过去。更有经验的程序员通常避免使用delay()来计时超过几十毫秒的事件,除非Arduino草图非常简单。

然而,当delay()函数控制Atmega芯片时,某些事情确实在进行,因为delay函数不会禁用中断。出现在RX引脚的串行通信会被记录,PWM(analogWrite)值和引脚状态会被保持,以及interrupts会正常工作。

See also

delayMicroseconds()

delayMicroseconds()

Description

该程序暂停运行指定的时间(以微秒为单位)。每毫秒有一千微秒,每秒有一百万微秒。

目前,能产生准确延迟的最大值是16383;更大的值可能会产生极短的延迟。这在未来的Arduino版本中可能会有所改变。对于几千微秒以上的延迟,您应该使用 delay() 函数。

Syntax

delayMicroseconds(us)

Parameters

us:暂停的微秒数。允许的数据类型:unsigned int

Returns

Example Code

代码配置数字引脚8作为输出引脚。它发送一个周期大约100微秒的脉冲列。这个近似值是由于代码中其他指令的执行。

int outPin = 8;               // 数字引脚8

void setup() {
  pinMode(outPin, OUTPUT);    // 设置数字引脚为输出
}

void loop() {
  digitalWrite(outPin, HIGH); // 设置引脚为高电平
  delayMicroseconds(50);      // 暂停50微秒
  digitalWrite(outPin, LOW);  // 设置引脚为低电平
  delayMicroseconds(50);      // 暂停50微秒
}

Notes and Warnings

此函数在3微秒到16383微秒的范围内工作非常准确。我们不能保证delayMicroseconds函数对于更小的延迟时间能够精确执行。更长的延迟时间可能实际上会延迟非常短的时间。

See also

数学

abs()

abs()

Description

计算一个数的绝对值。

Syntax

abs(x)

Parameters

x: 数字

Returns

x: 如果 x 大于或等于 0。
-x: 如果 x 小于 0。

Example Code

将变量 x 的绝对值打印到串行监视器。

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;  // 等待串行端口连接。仅对本地USB端口需要
  }
  int x = 42;
  Serial.print("The absolute value of ");
  Serial.print(x);
  Serial.print(" is ");
  Serial.println(abs(x));
  x = -42;
  Serial.print("The absolute value of ");
  Serial.print(x);
  Serial.print(" is ");
  Serial.println(abs(x));
}

void loop() {
}

Notes and Warnings

由于 abs() 函数的实现方式,请避免在括号内使用其他函数,这可能导致结果不正确。

abs(a++); // 避免这样使用 - 会产生不正确的结果

// 而应该这样使用:
abs(a);
a++;  // 将其他数学运算保持在函数外部

See also

constrain()

constrain()

Description

将一个数值限制在一个范围内。

Syntax

constrain(x, a, b)

Parameters

x: 要限制的数值。允许的数据类型: 所有数据类型。
a: 范围的下限。允许的数据类型: 所有数据类型。
b: 范围的上限。允许的数据类型: 所有数据类型。

Returns

x: 如果 x 在 a 和 b 之间。
a: 如果 x 小于 a。
b: 如果 x 大于 b。

Example Code

该代码将传感器值限制在 10 到 150 之间。

sensVal = constrain(sensVal, 10, 150);  // 将传感器值限制在 10 到 150 之间

Notes and Warnings

由于 constrain() 函数的实现方式,避免在括号内使用其他函数,这可能会导致不正确的结果。

这段代码会产生错误的结果:

int constrainedInput = constrain(Serial.parseInt(), minimumValue, maximumValue);   // 避免这样做

应该使用以下方式:

int input = Serial.parseInt();  // 将其他操作放在 constrain 函数之外
int constrainedInput = constrain(input, minimumValue, maximumValue);

See also

map()

map()

Description

重新映射一个数字从一个范围到另一个范围。也就是说,值 fromLow 会被映射到 toLow,值 fromHightoHigh,中间值到中间值,等等。

该函数不会将值限制在范围内,因为有时需要和有用的值超出范围。如果需要限制范围,可以在这个函数之前或之后使用 constrain() 函数。

请注意,任一范围的"下界"可能大于或小于"上界",因此 map() 函数可用于反转一系列数字,例如

y = map(x, 1, 50, 50, 1);

该函数还可以很好地处理负数,因此这个例子

y = map(x, 1, 50, 50, -100);

也是有效的并且运行良好。

map() 函数使用整数运算,因此即使数学上应该生成分数,也不会生成分数。分数的余数被截断,不会被四舍五入或取平均值。

Syntax

map(value, fromLow, fromHigh, toLow, toHigh)

Parameters

value:要映射的数字。
fromLow:值当前范围的下界。
fromHigh:值当前范围的上界。
toLow:值目标范围的下界。
toHigh:值目标范围的上界。

Returns

映射后的值。数据类型:long

Example Code

/* 将模拟值映射到 8 位 (0 到 255) */
void setup() {}

void loop() {
  int val = analogRead(0);
  val = map(val, 0, 1023, 0, 255);
  analogWrite(9, val);
}

Appendix

对于数学爱好者,这里是完整的函数

long map(long x, long in_min, long in_max, long out_min, long out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Notes & Warnings

如前所述,map() 函数使用整数运算。因此可能会抑制分数。例如,分数如 3/2、4/3、5/4 都将被 map() 函数返回为 1,尽管它们的实际值不同。所以如果你的项目需要精确计算(如精确到小数点后 3 位的电压值),请考虑避免使用 map()并在代码中自行实现计算。

See also

max()

max()

Description

计算两个数字中的最大值。

Syntax

max(x, y)

Parameters

x: 第一个数字。允许的数据类型: 任何数据类型。
y: 第二个数字。允许的数据类型: 任何数据类型。

Returns

两个参数值中较大的那个。

Example Code

该代码确保 sensVal 至少为 20。

sensVal = max(sensVal, 20); // 将 sensVal 赋值为 sensVal 或 20 中较大的值
                            // (实际上确保了它至少为 20)

Notes and Warnings

也许有些违反直觉, max() 通常用于限制变量值的下限, 而 min() 用于限制变量值的上限。

由于 max() 函数的实现方式, 避免在括号内使用其他函数, 可能会导致不正确的结果

max(a--, 0);  // 避免这种做法 - 会产生不正确的结果

// 使用这种方式:
max(a, 0);
a--;  // 将其他数学运算置于函数外部

See also

min()

min()

Description

计算两个数字的最小值。

Syntax

min(x, y)

Parameters

x:第一个数字。允许的数据类型:任何数据类型。
y:第二个数字。允许的数据类型:任何数据类型。

Returns

两个数字中较小的一个。

Example Code

该代码确保它永远不会超过 100。

sensVal = min(sensVal, 100);  // 将 sensVal 赋值为 sensVal 或 100 中较小的一个
                              // 确保它永远不会超过 100。

Notes and Warnings

也许有些违反直觉,max() 通常用于限制变量范围的下限,而 min() 用于限制范围的上限。

由于 min() 函数的实现方式,避免在括号内使用其他函数,否则可能会导致不正确的结果。

min(a++, 100);  // 避免这样做 - 会产生不正确的结果

min(a, 100);
a++;  // 使用这种方式 - 将其他数学运算保留在函数之外

See also

pow()

pow()

Description

计算一个数字被提升到一个幂之后的值。pow()可用于将一个数字提升到一个分数幂。这对于生成值或曲线的指数映射很有用。

Syntax

pow(base, exponent)

Parameters

base: 数字。允许的数据类型: float
exponent: 基数被提升到的幂。允许的数据类型: float

Returns

指数运算的结果。数据类型: double

Example Code

计算 x 的 y 次幂的值:

z = pow(x, y);

参见 (fscale) 草图以获取更复杂的 pow() 用法示例。

See also

sq()

sq()

Description

计算一个数字的平方: 该数字乘以它自己。

Syntax

sq(x)

Parameters

x: 数字。允许的数据类型: 任何数据类型。

Returns

该数字的平方。数据类型: double

Notes and Warnings

由于 sq() 函数的实现方式, 应避免在括号内使用其他函数, 否则可能导致不正确的结果。

以下代码将产生不正确的结果:

int inputSquared = sq(Serial.parseInt()); // 避免这种做法

应该使用以下方式:

int input = Serial.parseInt();  // 将其他操作置于 sq 函数之外
int inputSquared = sq(input);

See also

sqrt()

sqrt()

Description

计算一个数字的平方根。

Syntax

sqrt(x)

Parameters

x: 该数字。允许的数据类型: 任何数据类型。

Returns

该数字的平方根。数据类型: double

See also

三角学

cos()

cos()

Description

计算角度(以弧度表示)的余弦值。结果将位于 -1 和 1 之间。

Syntax

cos(rad)

Parameters

rad:以弧度表示的角度。允许的数据类型: float

Returns

该角度的余弦值。数据类型: double

See also

sin()

sin()

Description

计算一个角度(以弧度为单位)的正弦值。结果将介于 -1 和 1 之间。

Syntax

sin(rad)

Parameters

rad:以弧度为单位的角度。允许的数据类型: float

Returns

该角度的正弦值。数据类型: double

See also

tan()

tan()

Description

计算一个角度(以弧度为单位)的正切值。结果将介于负无穷大和正无穷大之间。

Syntax

tan(rad)

Parameters

rad:以弧度为单位的角度。允许的数据类型为 float

Returns

该角度的正切值。数据类型为 double

See also

字符

isAlpha()

isAlpha()

Description

分析字符是否为字母。如果 thisChar 包含字母则返回 true。

Syntax

isAlpha(thisChar)

Parameters

thisChar:变量。允许的数据类型:char

Returns

true:如果 thisChar 是字母。

Example Code

if (isAlpha(myChar)) {  // 测试 myChar 是否为字母
  Serial.println("该字符是字母");
}
else {
  Serial.println("该字符不是字母");
}

See also

isAlphaNumeric()

isAlphaNumeric()

Description

分析一个字符是否为字母数字(即字母或数字)。如果 thisChar 包含数字或字母,则返回 true。

Syntax

isAlphaNumeric(thisChar)

Parameters

thisChar:变量。允许的数据类型:char

Returns

true:如果 thisChar 是字母数字。

Example Code

if (isAlphaNumeric(myChar)) { // 测试 myChar 是否为字母或数字
  Serial.println("该字符是字母数字");
}
else {
  Serial.println("该字符不是字母数字");
}

See also

isAscii()

isAscii()

Description

分析字符是否为 ASCII 码。如果 thisChar 包含 ASCII 字符则返回真。

Syntax

isAscii(thisChar)

Parameters

thisChar:变量。允许的数据类型:char

Returns

true:如果 thisChar 是 ASCII 码。

Example Code

if (isAscii(myChar)) {  // 测试 myChar 是否为 ASCII 字符
  Serial.println("该字符是 ASCII 码");
}
else {
  Serial.println("该字符不是 ASCII 码");
}

See also

isControl()

isControl()

Description

分析一个字符是否为控制字符。如果 thisChar 是控制字符,则返回 true。

Syntax

isControl(thisChar)

Parameters

thisChar: 变量。允许的数据类型: char

Returns

如果 thisChar 是控制字符,则返回 true

Example Code

if (isControl(myChar)) {  // 测试 myChar 是否为控制字符
  Serial.println("该字符是控制字符");
}
else {
  Serial.println("该字符不是控制字符");
}

See also

isDigit()

isDigit()

Description

分析一个字符是否是数字。如果 thisChar 是数字则返回 true。

Syntax

isDigit(thisChar)

Parameters

thisChar:变量。允许的数据类型:char

Returns

true:如果 thisChar 是一个数字。

Example Code

if (isDigit(myChar)) {  // 测试 myChar 是否是数字
  Serial.println("该字符是一个数字");
}
else {
  Serial.println("该字符不是一个数字");
}

See also

isGraph()

isGraph()

Description

分析一个字符是否可打印并且具有某些内容(空格是可打印的,但没有内容)。如果thisChar可打印则返回true。

Syntax

isGraph(thisChar)

Parameters

thisChar:变量。允许的数据类型:char

Returns

如果thisChar可打印,则返回true

Example Code

if (isGraph(myChar)) {  // 测试myChar是否为可打印字符,但不是空格。
  Serial.println("该字符可打印");
}
else {
  Serial.println("该字符不可打印");
}

See also

isHexadecimalDigit()

isHexadecimalDigit()

Description

分析字符是否为十六进制数字 (A-F, 0-9)。如果 thisChar 包含十六进制数字则返回 true。

Syntax

isHexadecimalDigit(thisChar)

Parameters

thisChar:变量。允许的数据类型:char

Returns

true:如果 thisChar 是一个十六进制数字。

Example Code

if (isHexadecimalDigit(myChar)) { // 测试 myChar 是否为十六进制数字
  Serial.println("该字符是一个十六进制数字");
}
else {
  Serial.println("该字符不是一个十六进制数字");
}

See also

isLowerCase()

isLowerCase()

Description

分析一个字符是否为小写字母。如果 thisChar 包含一个小写字母,则返回 true。

Syntax

isLowerCase(thisChar)

Parameters

thisChar: 变量。允许的数据类型: char

Returns

如果 thisChar 为小写字母,则返回 true

Example Code

if (isLowerCase(myChar)) {  // 测试 myChar 是否为小写字母
  Serial.println("该字符为小写字母");
}
else {
  Serial.println("该字符不是小写字母");
}

See also

isPrintable()

isPrintable()

Description

分析一个字符是否可打印(任何产生输出的字符,即使是空格)。如果 thisChar 是可打印的,则返回 true。

Syntax

isPrintable(thisChar)

Parameters

thisChar:变量。允许的数据类型: char

Returns

true:如果 thisChar 是可打印的。

Example Code

if (isPrintable(myChar)) {  // 测试 myChar 是否为可打印字符
  Serial.println("该字符可打印");
}
else {
  Serial.println("该字符不可打印");
}

See also

isPunct()

isPunct()

Description

分析一个字符是否为标点符号(即逗号、分号、感叹号等)。如果该字符是标点符号,则返回 true。

Syntax

isPunct(thisChar)

Parameters

thisChar:变量。允许的数据类型:char

Returns

true:如果 thisChar 是标点符号。

Example Code

if (isPunct(myChar)) {  // 测试 myChar 是否为标点符号字符
  Serial.println("该字符是标点符号");
}
else {
  Serial.println("该字符不是标点符号");
}

See also

isSpace()

isSpace()

Description

分析一个字符是否是空白字符。如果该参数是空格( '\ f')、换行符('\ n')、回车('\ r')、水平制表符('\ t')或垂直制表符('\ v')则返回 true。

Syntax

isSpace(thisChar)

Parameters

thisChar:变量。允许的数据类型: char

Returns

true:如果 thisChar 是一个空白字符。

Example Code

if (isSpace(myChar)) {  // 测试 myChar 是否是一个空白字符
  Serial.println("The character is white-space");
}
else {
  Serial.println("The character is not white-space");
}

See also

isUpperCase()

isUpperCase()

Description

分析一个字符是否为大写字母(即大写字母)。如果thisChar是大写字母,则返回true。

Syntax

isUpperCase(thisChar)

Parameters

thisChar: 变量。允许的数据类型:char

Returns

如果thisChar是大写字母,则返回true

Example Code

if (isUpperCase(myChar)) {  // 测试myChar是否为大写字母
  Serial.println("该字符为大写字母");
}
else {
  Serial.println("该字符不是大写字母");
}

See also

isWhitespace()

isWhitespace()

Description

分析一个字符是否为空格字符。如果参数是空格或水平制表符('\t')则返回true。

Syntax

isWhitespace(thisChar)

Parameters

thisChar:变量。允许的数据类型: char

Returns

如果thisChar是空格字符,则返回true

Example Code

if (isWhitespace(myChar)) { // 测试myChar是否为空格字符
  Serial.println("该字符是空格或制表符");
}
else {
  Serial.println("该字符不是空格或制表符");
}

See also

随机数

random()

random()

Description

random函数生成伪随机数。

Syntax

random(max)
random(min, max)

Parameters

min: 随机值的下限,包含该值(可选)。
max: 随机值的上限,不包含该值。

Returns

一个位于min和max-1之间的随机数。数据类型:long

Example Code

该代码生成随机数并将它们显示出来。

long randNumber;

void setup() {
  Serial.begin(9600);

  // 如果模拟输入引脚0未连接,随机模拟
  // 噪声将导致对randomSeed()的调用在每次
  // 草图运行时生成不同的种子数字。
  // 然后randomSeed()将重新洗牌随机函数。
  randomSeed(analogRead(0));
}

void loop() {
  // 打印0到299之间的随机数
  randNumber = random(300);
  Serial.println(randNumber);

  // 打印10到19之间的随机数
  randNumber = random(10, 20);
  Serial.println(randNumber);

  delay(50);
}

Notes and Warnings

如果在随后执行草图时,由random()生成的值序列不同很重要,请使用randomSeed()通过诸如analogRead()在未连接的引脚上的相当随机输入来初始化随机数生成器。

相反,有时使用完全重复的伪随机序列也很有用。这可以通过在开始随机序列之前使用固定数字调用randomSeed()来实现。

应根据存储值的变量的数据类型选择max参数。在任何情况下,绝对最大值都受生成值的long性质的限制(32位 - 2,147,483,647)。将max设置为更高的值在编译期间不会产生错误,但在草图执行期间生成的数字将不如预期。

See also

randomSeed()

randomSeed()

Description

randomSeed() 初始化伪随机数发生器,使它从随机序列中的任意一点开始。虽然这个序列是非常长的,并且是随机的,但它总是相同的。

如果在草图的后续执行中生成的随机数序列需要不同,请使用 randomSeed() 通过相当随机的输入(如未连接引脚上的 analogRead())来初始化随机数发生器。

相反,在某些情况下,使用完全重复的伪随机序列也是有用的。这可以通过在开始随机序列之前调用带有固定数字的 randomSeed() 来实现。

Syntax

randomSeed(seed)

Parameters

seed: 用于初始化伪随机序列的非零数字。允许的数据类型: unsigned long

Returns

Example Code

该代码生成一个伪随机数,并将生成的数字发送到串行端口。

long randNumber;

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(0));
}

void loop() {
  randNumber = random(300);
  Serial.println(randNumber);
  delay(50);
}

Notes and Warnings

如果 seed 为 0,randomSeed(seed) 将不会产生任何效果。

See also

比特和字节

bit()

bit()

Description

计算指定位的值(位0是1,位1是2,位2是4,依此类推)。

Syntax

bit(n)

Parameters

n:需要计算值的位。注意,n 需要在0到31之间(32位)。

Returns

该位的值。

See also

在Arduino编程中,bit(n) 函数用于计算在二进制中特定位置上的值。这个函数实际上是用来快速找出2的幂。比如,如果你想知道第n位的值,它会返回 (2^n)。这在处理位操作时非常有用,比如设置、清除或者切换特定的位。

使用 bit(n) 的例子:

如果你想设置、清除或者切换一个变量中的特定位,你可以使用 bit(n) 来帮助构建掩码(mask)。这里有一些基本的用法示例:

设置位

假设你有一个变量 x,你想设置第3位(注意,位从0开始计数),你可以这样做:

x |= bit(3);  // 位3现在被设置为1,因为 bit(3) 返回 8,即 00001000 in binary

清除位

如果你想清除变量 x 的第3位:

x &= ~bit(3);  // 位3现在被清除为0

切换位

如果你想切换变量 x 的第3位:

x ^= bit(3);  // 位3被切换,如果它是1则变为0,如果它是0则变为1

检查位

如果你想检查变量 x 的第3位是否被设置:

if (x & bit(3)) {
  // 位3是设置的
}

这些操作都是位级操作,非常快速和高效,适用于嵌入式系统和低级硬件操作。使用 bit(n) 可以使代码更清晰可读,避免直接使用复杂的二进制数,特别是当位操作涉及到高位时。

bitClear()

bitClear()

Description

清除(将一个数字变量的一个位写为0)。

Syntax

bitClear(x, n)

Parameters

x:要清除位的数字变量。
n:要清除的位,从最不重要的(最右边的)位开始,编号为0。

Returns

x:清除位置 n 的位后,数字变量的值。

Example Code

打印在两个给定整数上 bitClear(x,n) 的输出。6的二进制表示为0110,所以当 n=1 时,从右边数第二位被设置为0。之后我们得到二进制的0100,因此返回4。

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // 等待串口连接。仅限原生USB端口需要
  }

  int x = 6;
  int n = 1;
  Serial.print(bitClear(x, n)); // 打印 bitClear(x,n) 的输出
}

void loop() {
}

See also

在 Arduino 的 bitClear(x, n) 函数中,x 实际上是作为一个形参传递的。这意味着函数内对 x 的修改不会影响原始变量的值。bitClear 函数是通过位操作修改 x 的值并返回修改后的结果,但它不会改变传入的原始变量 x 本身。

如果你想在调用 bitClear 后改变原始变量的值,你需要将返回值重新赋值给原始变量,如下所示:

x = bitClear(x, n);

这样,x 的值就会更新为 bitClear 函数返回的值。

bitRead()

bitRead()

Description

读取变量的一个比特位,例如 boolint。注意 floatdouble 不被支持。您可以读取最多 unsigned long long(64 位/8 字节)类型变量的比特位。

Syntax

bitRead(x, n)

Parameters

x:要读取的数字。
n:要读取的比特位,从最低有效位(最右边)开始为 0。

Returns

该比特位的值(0 或 1)。

Example Code

这个示例代码演示了如何读取两个变量,一个递增的计数器,一个递减的计数器,并打印出两个变量的二进制值和十进制值。

readBit() 函数循环遍历变量的每一个比特位(从最右边的比特位开始),并打印出来。

long negative_var = -0;  //
unsigned long long positive_var = 0;

//预定义的大小,当循环遍历比特位时使用
//例如,long_size 是 32 位(范围是 0-31)。因此,我们减去 "1"。
const int bool_size = (1 - 1);
const int int_size = (8 - 1);
const int long_size = (32 - 1);

void setup() {
  Serial.begin(9600);
}

void loop() {
  //运行 readBit 函数,传入正/负变量
  readBit("Positive ", positive_var);
  readBit("Negative ", negative_var);
  Serial.println();

  //增加和减少变量
  negative_var--;
  positive_var++;

  delay(1000);
}

/*该函数获取一个变量,从右边开始逐个打印出每一位(比特位)
然后打印出十进制数值以供对比。*/
void readBit(String direction, long counter) {
  Serial.print(direction + "二进制数: ");
  //循环遍历每个比特位
  for (int b = long_size; b >= 0; b--) {
    byte bit = bitRead(counter, b);
    Serial.print(bit);
  }
  Serial.print(" 十进制数: ");
  Serial.println(counter);
}

See also

bitSet()

bitSet()

Description

设置(写入 1)一个数值变量的位。

Syntax

bitSet(x, n)

Parameters

x: 要设置位的数值变量。
n: 要设置的位,从 0 开始表示最低有效位(最右边)。

Returns

x: 在位置 n 的位被设置后数值变量的值。

Example Code

打印 bitSet(x,n) 对两个给定整数的输出。4 的二进制表示是 0100,所以当 n=1 时,从右边数第二位被设置为 1。在此之后,我们剩下 0110 的二进制表示,所以返回 6。

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // 等待串行端口连接。仅适用于本机 USB 端口
  }

  int x = 4;
  int n = 1;
  Serial.print(bitSet(x, n)); // 打印 bitSet(x,n) 的输出
}

void loop() {
}

See also

bitWrite()

bitWrite()

Description

将一些变量的一个位写入,例如 boolintlong。注意不支持 floatdouble。你可以写入最多 unsigned long (32 位/4 字节) 的变量的一个位。

Syntax

bitWrite(x, n, b)

Parameters

x:要写入的数值变量。
n:要写入的数字的位数,从最低有效位 (最右边) 的 0 开始。
b:要写入位的值 (0 或 1)。

Returns

Example Code

演示使用 bitWrite 在使用 bitWrite() 之前和之后向串行监视器打印变量的值。

void setup() {
  Serial.begin(9600);
  while (!Serial) {}  // 等待串行端口连接。仅对本机USB端口需要
  byte x = 0b10000000;  // 0b 前缀表示二进制常量
  Serial.println(x, BIN); // 10000000
  bitWrite(x, 0, 1);  // 将 1 写入 x 的最低有效位
  Serial.println(x, BIN); // 10000001
}

void loop() {}

See also

highByte()

highByte()

Description

提取一个字(或更大的数据类型)的高阶(最左边)字节(或第二低位字节)。

Syntax

highByte(x)

Parameters

x: 任何类型的值

Returns

数据类型: byte

See also

lowByte()

lowByte()

Description

提取变量(如单词)的低阶(最右边)字节。

Syntax

lowByte(x)

Parameters

x: 任何类型的值

Returns

数据类型: byte

See also

外部中断

中断

通讯

Serial

Description

用于Arduino板和计算机或其他设备之间的通信。所有Arduino板至少有一个串行端口(也称为UART或USART),有些有多个。

板卡SERIAL PINSSERIAL1 PINSSERIAL2 PINSSERIAL3 PINSSERIAL4 PINS
UNO R3, UNO R3 SMD Mini0(RX), 1(TX)
Nano (classic)0(RX), 1(TX)
UNO R4 Minima, UNO R4 WiFi 0(RX0), 1(TX0)
Leonardo, Micro, Yún Rev2 0(RX), 1(TX)
Uno WiFi Rev.2 0(RX), 1(TX)
MKR板 13(RX), 14(TX)
Zero 0(RX), 1(TX)
GIGA R1 WiFi 0(RX), 1(TX)19(RX1), 18(TX1)17(RX2), 16(TX2)15(RX3), 14(TX3)
Due0(RX), 1(TX)19(RX1), 18(TX1)17(RX2), 16(TX2)15(RX3), 14(TX3)
Mega 2560 Rev30(RX), 1(TX)19(RX1), 18(TX1)17(RX2), 16(TX2)15(RX3), 14(TX3)
Nano 33 IoT 0(RX0), 1(TX0)
Nano RP2040 Connect 0(RX0), 1(TX0)
Nano BLE / BLE Sense 0(RX0), 1(TX0)

Nano ESP32板是一个例外,因为它基于ESP32核心。这里,Serial0RX0TX0,而Serial1Serial2是可以分配给任何空闲GPIO的附加端口。

板卡Serial0 pinsSerial1 pinsSerial2 pinsSerial3 pinsSerial4 pins
Nano ESP320(RX0), 1(TX0)任意空闲GPIO任意空闲GPIO

您可以在这篇文章中进一步了解如何配置Nano ESP32的附加串行端口。

在旧板(Uno,Nano,Mini和Mega)上,使用0和1号引脚与计算机通信。连接任何设备到这些引脚可能会干扰通信,包括导致上传到板上的程序失败。

您可以使用Arduino环境内置的串行监视器与Arduino板进行通信。点击工具栏中的串行监视器按钮,并选择在调用begin()时使用的相同波特率。

TX/RX引脚上的串行通信使用TTL逻辑电平(根据板子的不同而是5V或3.3V)。不要将这些引脚直接连接到RS232串行端口;它们工作在±12V并且可能会损坏您的Arduino板。

要使用这些额外的串行端口与个人计算机通信,您将需要一个额外的USB转串行适配器,因为它们没有连接到Mega的USB转串行适配器。要用它们与外部TTL串行设备通信,连接TX引脚到设备的RX引脚,RX到设备的TX引脚,以及您的Mega的地线到设备的地线。


Functions

请参阅《Arduino Language Reference-Functions-Serial-Functions》


See also

SPI

在电子学和计算机科学中,CS、COPI、CIPO 和 SCK 都是与串行外设接口(SPI, Serial Peripheral Interface)通信相关的术语。SPI 是一种同步串行通信接口,用于短距离通信,主要应用在嵌入式系统中。下面是每个术语的含义:

  1. CS 或者 SS - Chip Select 或 Slave Select:
    这是一个控制信号,通常由主设备(如微控制器)用来激活或选择SPI总线上的一个特定的从设备(如传感器、存储器等)。当有多个从设备时,每个设备都会有一个独立的CS线。通常,CS信号是低电平有效,即当CS被拉低到地时,选中的从设备就会与主设备通信。
  2. COPI 或 MOSI - Controller Output/Peripheral Input 或 Master Out Slave In:
    这是主设备到从设备的数据线。在SPI通信中,主设备通过这条线发送数据到从设备。
  3. CIPO 或 MISO - Controller Input/Peripheral Output 或 Master In Slave Out:
    这是从设备到主设备的数据线。在SPI通信中,从设备通过这条线发送数据回主设备。
  4. SCK - Serial Clock:
    这是由主设备生成的时钟信号,用于同步数据传输。数据在SCK的一个特定边沿(上升沿或下降沿)上进行采样和变化。

这四个信号构成了SPI通信的基础。主设备通过SCK提供时钟,通过COPI发送数据,通过CIPO接收数据,并通过CS选择要通信的从设备。这种通信允许数据在主设备和从设备之间全双工(即同时双向)传输。

Description

这个库允许您与SPI设备通信,Arduino作为控制器设备。这个库与每个Arduino平台(avr, megaavr, mbed, samd, sam, arc32)一起捆绑,所以您不需要单独安装这个库。

要使用这个库

#include <SPI.h>

要了解更多关于Arduino和SPI的信息,您可以访问Arduino和串行外设接口(SPI)指南。

开发板默认SPI引脚额外SPI引脚注释
UNO R3, UNO R3 SMD, UNO WiFi Rev2, UNO Mini Ltd10(CS), 11(COPI), 12(CIPO), 13(SCK) SPI引脚可在ICSP头上获得
UNO R4 Minima, UNO R4 WiFi10(CS), 11(COPI), 12(CIPO), 13(SCK) SPI引脚可在ICSP头上获得
Leonardo, Yún Rev2, Zero10(CS), 11(COPI), 12(CIPO), 13(SCK) SPI引脚可在ICSP头上获得
Micro14(CIPO), 15(SCK), 16(COPI)
Nano开发板11(COPI), 12(CIPO), 13(SCK)
MKR开发板8(COPI), 9(SCK), 10(CIPO)
Due74(CIPO), 75(MOSI), 76(SCK)SPI引脚可在专用SPI头上获得
GIGA R1 WiFi89(CIPO), 90(COPI), 91(SCK)12(CIPO), 11(COPI), 13(SCK), 10(CS)注意引脚89,90,91位于SPI头上
Mega 2560 Rev350(CIPO), 51(COPI), 52(SCK), 53(CS) SPI引脚可在ICSP头上获得

Functions

请参阅《Arduino Language Reference-Functions-SPI-Functions》


Wire

Description

该库允许您与 I2C 设备进行通信,这是所有 Arduino 板上都有的一个功能。I2C 是一种非常常见的协议,主要用于从外部 I2C 组件读取/发送数据。要了解更多信息,请访问Arduino 与 I2C 的这篇文章

由于硬件设计和各种架构差异,I2C 引脚位于不同的位置。下面的引脚映射突出显示了默认引脚,以及某些板上可用的其他端口。

板级I2C 默认I2C1I2C2注释
UNO R3、UNO R3 SMD、UNO Mini LtdA4(SDA)、A5(SCL) I2C 也可在 SDA / SCL 引脚(数字头)上使用。
UNO R4 Minima、UNO R4 WiFiA4(SDA)、A5(SCL)Qwiic: D27(SDA)、D26(SCL) I2C 也可在 SDA / SCL 引脚(数字头)上使用。
UNO WiFi Rev2、Zero20(SDA)、21(SCL)
Leonardo、Micro、Yùn Rev2D2(SDA)、D3(SCL)
Nano 板A4(SDA)、A5(SCL)
MKR 板D11(SDA)、D12(SCL)
GIGA R1 WiFi20(SDA)、21(SCL)D102(SDA1)、D101 (SCL1)D9(SDA2)、D8 (SCL2)使用Wire1.begin() 用于 I2C1,Wire2.begin() 用于 I2C2。
Due20(SDA)、21(SCL)D70(SDA1)、D71(SCL1) 使用Wire1.begin() 用于 I2C1
Mega 2560 Rev3D20(SDA)、D21(SCL)

该库继承自 Stream 函数,从而与其他读/写库保持一致。由于这一点,send()receive() 已被替换为 read()write()

Wire 库的最新版本可以使用超时来防止在总线上出现某些问题时发生锁定,但默认情况下,当前版本并未启用该功能(暂未启用)。建议在使用 Wire 库时始终启用这些超时。有关更多详细信息,请参阅 Wire.setWireTimeout 函数。

注意: I2C 地址有 7 位和 8 位两种版本。7 位用于识别设备,第八位确定是读还是写。Wire 库在整个库中使用 7 位地址。如果您有使用 8 位地址的数据手册或示例代码,您需要丢弃最低位(即将该值右移一位),从而得到介于 0 到 127 之间的地址。但是,地址从 0 到 7 是不使用的,因为它们是保留的,所以可以使用的第一个地址是 8。请注意,需要在连接 SDA/SCL 引脚时使用上拉电阻。有关更多信息,请参考示例。MEGA 2560 板在引脚 20 和 21 上集成了上拉电阻。

Wire 库的实现使用 32 字节缓冲区,因此任何通信都应在此限制范围内。单次传输中超出的字节将被丢弃。

要使用此库:

#include <Wire.h>

Functions

请参阅《Arduino Language Reference-Functions-wire-Functions》


USB

最后修改:2024 年 04 月 30 日
如果觉得我的文章对你有用,请随意赞赏