## Arduino 高级 I/O API 手册

### 1. 概述

高级 I/O 功能提供了更复杂的输入输出操作，包括音频信号生成（tone）、脉冲测量（pulseIn）和串行数据移位（shiftIn/shiftOut）等功能。这些功能适用于驱动蜂鸣器、测量脉冲宽度、与移位寄存器通信等应用场景。

### 2. API 介绍

#### 2.1 `tone` 函数

```cpp
void tone(uint8_t pin, unsigned int frequency, unsigned long duration = 0)
```

在指定引脚生成指定频率的方波信号。

**参数**

- `pin`: 输出引脚（必须支持 PWM）
- `frequency`: 频率（Hz）
- `duration`: 持续时间（毫秒），0 或省略表示持续输出

**返回值**
无

**注意**

- 同一时间只能有一个引脚输出 tone
- 需要调用 `noTone()` 停止输出

#### 2.2 `noTone` 函数

```cpp
void noTone(uint8_t pin)
```

停止指定引脚的音频输出。

**参数**

- `pin`: 要停止的引脚

**返回值**
无

#### 2.3 `pulseIn` 函数

```cpp
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000)
```

测量引脚上脉冲的持续时间。

**参数**

- `pin`: 输入引脚
- `state`: 要测量的脉冲电平（HIGH 或 LOW）
- `timeout`: 超时时间（微秒），默认 1 秒

**返回值**
脉冲持续时间（微秒），超时返回 0

**工作原理**

1. 等待引脚变为指定状态的相反状态
2. 等待引脚变为指定状态
3. 计时直到引脚再次改变状态

#### 2.4 `pulseInLong` 函数

```cpp
unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout = 1000000)
```

测量引脚上脉冲的持续时间（与 `pulseIn` 相同）。

**参数**
与 `pulseIn` 相同

**返回值**
与 `pulseIn` 相同

#### 2.5 `shiftIn` 函数

```cpp
uint8_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder)
```

从数据引脚串行读入一个字节。

**参数**

- `dataPin`: 数据输入引脚
- `clockPin`: 时钟引脚
- `bitOrder`: 位顺序
  - `LSBFIRST`: 低位先入
  - `MSBFIRST`: 高位先入

**返回值**
读取的字节值

**工作原理**
通过切换时钟引脚电平，逐位读取数据引脚状态

#### 2.6 `shiftOut` 函数

```cpp
void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val)
```

向数据引脚串行输出一个字节。

**参数**

- `dataPin`: 数据输出引脚
- `clockPin`: 时钟引脚
- `bitOrder`: 位顺序（LSBFIRST 或 MSBFIRST）
- `val`: 要输出的字节值

**返回值**
无

**工作原理**
逐位设置数据引脚，并切换时钟引脚发送数据

### 3. 使用说明

1. **Tone 功能**：
   - 基于 PWM 实现，占用一个 PWM 通道
   - 使用消息队列和独立线程处理
   - 支持非阻塞操作

2. **脉冲测量**：
   - 使用忙等待实现，会阻塞程序执行
   - 精度受 CPU 时钟影响
   - 适合测量微秒到毫秒级脉冲

3. **串行移位**：
   - 软件实现的同步串行通信
   - 时钟由软件控制，速度受限

4. **性能考虑**：
   - `pulseIn` 会阻塞程序执行
   - `shiftIn/shiftOut` 速度受 GPIO 操作延迟限制

### 4. 示例程序

```cpp
#include "Arduino.h"

const int ledPin = 52;  // LED连接到GPIO52

void setup() {
    Serial.begin(115200);
    delay(1000);
    
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
    
    Serial.println("Advanced I/O - Tone LED Blink Test");
    Serial.println("Using tone() to blink LED at different frequencies");
    Serial.println("==================================================");
}

void loop() {
    // 测试1: 1Hz闪烁（每秒1次）
    Serial.println("\n1. Blinking at 1Hz (1 blink/second)");
    tone(ledPin, 1);
    delay(5000);  // 持续5秒
    noTone(ledPin);
    digitalWrite(ledPin, LOW);  // 确保LED关闭
    delay(1000);
    
    // 测试2: 5Hz闪烁（每秒5次）
    Serial.println("\n2. Blinking at 5Hz (5 blinks/second)");
    tone(ledPin, 5);
    delay(5000);  // 持续5秒
    noTone(ledPin);
    digitalWrite(ledPin, LOW);
    delay(1000);
    
    // 测试3: 10Hz闪烁（每秒10次）
    Serial.println("\n3. Blinking at 10Hz (10 blinks/second)");
    tone(ledPin, 10);
    delay(5000);  // 持续5秒
    noTone(ledPin);
    digitalWrite(ledPin, LOW);
    delay(1000);
    
    // 测试4: 15Hz闪烁（每秒15次）
    Serial.println("\n4. Blinking at 15Hz (15 blinks/second)");
    tone(ledPin, 15);
    delay(5000);  // 持续5秒
    noTone(ledPin);
    digitalWrite(ledPin, LOW);
    delay(1000);
    
    // 测试5: 渐变频率
    Serial.println("\n5. Frequency sweep from 1Hz to 20Hz");
    for (int freq = 1; freq <= 20; freq++) {
        Serial.print("   Frequency: ");
        Serial.print(freq);
        Serial.println(" Hz");
        tone(ledPin, freq);
        delay(500);
    }
    noTone(ledPin);
    digitalWrite(ledPin, LOW);
    
    Serial.println("\nTest cycle completed. Restarting...\n");
    delay(3000);
}
```
