← 返回首页

第八课:模拟输入输出

第八课:模拟输入输出

首先,只有带波浪线的端口有模拟功能,即板子上标记的PWM~。

模拟输出analogWrite()

模拟电路的引脚端口在输出的时候会保持5V的电压,通过调节占空比PWM来调节输出的能量或信号翻转的频率,从而控制一个过程量,比如LED小灯泡由亮到暗,电机由快到慢等。对于大多数Arduino的引脚,PWM信号的频率大约为490Hz,也存在频率更高的高速引脚,具体参阅板子的说明手册。对于输出端,函数analogWrite(uint8_t pin, int val)的Value是一个0到255之间的PWM频率值, 0对应off, 255对应on。如果超过255或小于0,它会自动通过二进制移位变得物极必反换到另一端去,根源在于analogWrite()内部对数值的处理方式:它只关心传入数值的低8位,相当于对256进行取模运算。 贴心的Deepseek老师推荐了一个constrain函数,可以把超过最大值的输入值卡在上界,低于最小值的输入值卡在下界,中间保持不变以免出错。

brightness = constrain(brightness, 0, 255);
//以上为使用方式,以下为函数定义
#define constrain(amt, low, high) \
  ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))   

下面用一个明暗循环呼吸灯示例来说明输出函数的用法。

int brightness = 128;  //LED亮度参数
int LED_PIN = 9; //LED输出端口
uint16_t t = 128;  // 与 brightness 对应,范围 0..509
void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
}
void loop() {
  t = (t + 1) % 510; \\取 255*2的余数
  brightness = (t <= 255) ? t : 510 - t;
//三目运算符,等价于i = (条件) ? True值A : False值B;
  analogWrite(LED_PIN, brightness);
  Serial.println(brightness);
  delay(10);
}

模拟输入analogRead()

教学视频在讲这个模拟输入的时候用到了一个电子器件叫“电位器(Potentiometer)”,其实就是滑动变阻器的现实版,无论是有3个5个或是6个引脚,只要读取标称总电阻,并配合旋转旋钮,测量各个引脚之间电阻的差值,就可以确定与原理图中1,2,3对应的引脚功能。或者在压阻传感器中也常常可以用到这个模拟输入功能函数。将这样一个电位器的一端接到GND-0V,另一端接到5V电压输出,中间旋钮对应的挡位2接到ANALOG IN中的任一端口即可测量。
LCR探针测电位器引脚功能.jpg Arduino控制器有多个10位数模转换通道。这意味着Arduino可以将0-5V的电压输入信号映射到数值\(2^10 = 1024: (0-1023)\)。换句话说,我们可以将5伏特等分成1024份。0伏特的输入信号对应着数值0,而5伏特的输入信号对应着1023。比如说如果有4个数模转换通道,那就是可以把整段量程细分为\(2^4 = 16:(0-15)\),则每个步进的长度,即分辨率为总量程\(A * 1/16\)。引脚的输入范围以及解析度可以使用analogReference()指令进行调整。Arduino控制器读取一次模拟输入需要消耗100微秒的时间(0.0001秒)。控制器读取模拟输入的最大频率是每秒10,000次。

void setup() {
  Serial.begin(9600);
}
void loop() {
  int analogInputVal = analogRead(A0);  //读取模拟输入值
  Serial.println(analogInputVal);       //串口监视器显示结果
  int brightness = map(analogInputVal, 0, 1023, 0, 255);
  //将模拟输入数值(0-1023)等比例映射到模拟输出端口
}

在读取到0-1023的输入后,我们收获了一个比输出量0-255大得多的自变量数据范围(比如说输入端口从0-1023)。如果不想只简单的把除了0-255这部分的数据保留,其他部分全部按上下界归类到0或者255,而是想把它按照线性比例从0-1023一一映射到0-255区间,我们可以写一个函数让所有输入值除以4再取整。但当输入范围因为硬件或者其他原因需要调整时要重新修改自定义函数,现有一个现成的好函数map()可以方便又快捷的实现我们需要的功能。

👁️ 18 阅读 📝 最后修改于 2026-10-31

💬 评论 (0)