Arduino编写程序
# Arduino编程
# 介绍
Arduino语言是一种基于C/C++的编程语言,专为Arduino硬件平台设计,我们可以通过Arduino编程来控制和操作Arduino板上的各种传感器、执行器和其他外设。
Arduino语言是基于C/C++的简化版本,它继承了C/C++的基本语法,并通过封装底层硬件操作,降低了硬件编程的门槛。
# 编程语法
Arduino语言的基础语法都是基于C/C++的,包括注释、变量、判断、循环、函数、类等等,所以不在此进行赘述。
其他的Arduino编程中常用的常量、函数、类库等,可以在太极创客的网站中学习。
太极创客Arduino编程中文文档:http://www.taichi-maker.com/homepage/arduino-coding-index/
# 初始化与主逻辑函数
Arduino程序中,有两个类似入口的函数,分别用来实现程序的初始化和主逻辑处理。
Arduino核心库中存在一个隐藏的main()函数,由该函数来负责初始化硬件和调用setup()、loop()函数。
这个隐藏的main()函数是程序的真正入口点,但我们无需直接编写或调用它,只需编写setup()、loop()函数供它调用即可。
setup()函数是初始化函数,会在Arduino程序启动时执行一次,用于初始化硬件和设置程序运行所需的环境。
例如,设置引脚模式、初始化串口通信等。
loop()函数会在setup()函数执行完毕后不间断的循环执行,直到断电或重置程序。
它是Arduino程序的核心部分,负责处理程序的主逻辑,如读取传感器数据、控制输出设备等。
# IDE示例程序
Arduino IDE提供基础示例以帮助我们快速了解Arduino程序的结构。
在菜单栏的文件选项下,可以找到示例选项,其中有很多官方提供的示例。
# Blink示例
示例选项卡→Basics→Blink,单击创建示例项目即可。
/*
示例:反复的点亮LED一秒,然后关闭LED一秒钟。
很多Arduino开发板都带有一个我们可以控制的LED灯,同时会有一个引脚作为该LED的电源,在UNO、MEGA、ZERO型号的开发板中这个LED连接在引脚13上,在MKR1000型号的开发板中这个LED连接在引脚6上。
为了方便记忆,IDE会帮我们把IDELED_BUILTIN关键字,替换为我们IDE当前开发板的LED引脚编号。
*/
// 初始化函数,只执行一次。
void setup() {
// 初始化LED数字引脚为输出模式。
pinMode(LED_BUILTIN, OUTPUT);
}
// 主逻辑函数,会循环执行。
void loop() {
// 将LED点亮,即将LED数字引脚电平设为高。
digitalWrite(LED_BUILTIN, HIGH);
// 等待1秒
delay(1000);
// 将LED熄灭,即将LED数字引脚电平设为低。
digitalWrite(LED_BUILTIN, LOW);
// 等待1秒
delay(1000);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
LED_BUILTIN是define预处理变量,指向IDE当前开发板的LED引脚编号。
# 数字信号
# 数字信号介绍
数字信号不同于模拟信号,数字信号只能用于表示两种状态,没有中间值。在电子领域中可以表示高电平和低电平,也可以用抽象符号0和1来表示逻辑状态。
# 数字IO函数
# 引脚模式配置
pinMode(引脚编号, IO模式)
用于设定指定数字引脚的IO模式,数字引脚一共有三种模式。
注意:当Arduino引脚设置为INPUT模式或者INPUT_PULLUP模式时,请勿将该引脚与负压或者高于5V的电压相连,否则可能会损坏Arduino控制器。
OUTOUT
模式
当引脚设置为OUTPUT输出模式时,引脚为低阻抗状态。这意味着Arduino可以向其它电路元器件提供电流。
也就是说,Arduino引脚在OUTPUT模式下可以点亮LED或者驱动电机。但如果被驱动的电机需要超过40mA的电流,则需要三极管或其它辅助元件来驱动他们。
INPUT
模式
当引脚设置为INPUT输入模式时,引脚为高阻抗状态(100兆欧)。此时该引脚可用于读取传感器信号或开关信号。
INPUT_PULLUP
模式
Arduino微控制器自带内部上拉电阻。如果你需要使用该内部上拉电阻,可以通过pinMode()将引脚设置为INPUT_PULLUP输入上拉模式。使用该模式后,该引脚就不用再外接上拉电阻。
# 信号输出
digitalWrite(引脚编号, 电平状态)
用于控制指定数字引脚的电平状态,即HIGH(高电平-5伏特)、LOW(低电平-0伏特/GND)两种状态。
注意,要操作的引脚必须先被设定为OUTPUT模式,否则该语句什么也不会做。
另外,由于数字引脚13内部串联了一个LED并焊接了一个限流电阻,所以该引脚比其他引脚更不易用来实现数字输入功能。
# 信号输入
digitalRead(引脚编号)
用于读取指定数字引脚的电平状态,即HIGH(高电平)、LOW(低电平)两种状态。
在引脚悬空的状态时,读到的状态将会受到多种因素影响,具有随机不确定性。
# 模拟信号
# 模拟信号介绍
模拟信号可以表示自然界中任何连续变化的物理量。而在电子系统中,电压是最常见的模拟信号表现形式,它可以是介于开和关之间的任何中间值电压。
# PWM脉宽调制
# 介绍
PWM(脉宽调制,Pulse Width Modulation) 是一种通过调节数字信号的脉冲宽度来模拟出模拟信号的技术,也就是将数字信号转换为模拟信号。
模拟信号可以表示自然界中任何连续变化的物理量,模拟信号是介于开和关之间的任何电压。
至于为什么要用数字信号来模拟,而不是直接使用模拟信号。是因为数字只有两种状态,抗干扰强、传输更加稳定、控制精度高。而模拟信号很容易受到电磁干扰,导致数值改变。
比如以前的电视机经常闪雪花就是因为以前的电视使用的是模拟信号,而现在的电视非常稳定是因为使了数字信号传输。
# 概念
周期指的是一个完整PWM波形的时间长度(高电平 + 低电平)。

频率指的是1秒内有多少个周期,即1秒除以一个周期的时间。
比如:1个周期1ms,那么PWM的频率就是1000Hz。
脉冲指的是有效电平,大多数情况为高电平。
脉冲宽度指的是信号处于有效电平的持续时间。
高电平时间越短,占空比就越小,直到0%。
高电平时间越长,占空比就越大,直到100%。
占空比指的是脉冲宽度(有效电平时间)占一个周期的百分比。
占空比=高电平时长/周期时长。
# 原理
PWM的核心原理是利用周期性的高电平与其占空比来形成的由高低电平组成的方波(PWM信号)。PWM信号可以等效模拟电压或功率输出,从而实现对电机、LED、电源等设备的精准控制。
PWM并非直接降低电流幅度来实现电压控制,而是通过控制脉冲宽度来调节占空比,并借助高频切换和负载惯性来形成稳定的平均电压。
例如:占空比为50%时,高电平的瞬时的功率仍是全压(例如5V),而非电流减半,只不过由于高频切换和负载惯性,5V的电压在一个周期内被平均成5V * 50% = 2.5V电压。
# 高频切换和负载惯性
当PWM频率远高于负载(即元器件)的响应速度时,负载的物理特性(如电感的电流惯性、电容的电荷存储能力)会通过自身的特性对高频脉冲信号进行"平滑",最终表现为稳定的平均电压或电流。
想象用高频PWM控制水流:
- 高频脉冲:用极快的速度(例如每秒1000次)开关水龙头,每次开1毫秒、关1毫秒(占空比50%)。
- 水桶的惯性:如果水桶很大(类似电感或电容的储能特性),水流来不及在每次开/关时剧烈波动。水流会趋于稳定,最终水位相当于平均流量(例如总水量减半,水位稳定在中间高度)。
- 关键点:水桶的"惯性"让高频的开关动作被平滑为连续的平均效果,而非剧烈波动。
# 实际负载电压
在电气领域中,负载通常指的是电路中接收电能并将其转换为其他形式能量(如光、热、机械能等)或进行信号处理的用电器、电子元件、子系统等。
实际负载电压的平滑程度取决于以下两点:
- PWM频率:频率越高,脉冲间隔越短,负载越来不及响应单个脉冲。
- 负载响应时间:负载的物理特性(如电感值、电容值)决定了其响应速度。
不同负载中低频PWM和高频PWM的区别:
案例1:LED调光
- 低频PWM(500Hz) :LED快速亮灭,若占空比50%,人眼会感知到闪烁(类似老式荧光灯)。
- 高频PWM(20kHz) :亮灭切换速度超过人眼分辨极限(约200Hz),人脑会将光强积分为平均亮度,实现无级调光。
案例2:电机调速
低频PWM(1kHz):每个周期内,电机电流会从0上升到峰值再下降,导致转矩波动和噪音。转速可能出现周期性波动。
高频PWM(20kHz):电机电感(时间常数约10ms)来不及响应单个脉冲(50μs),电流趋于稳定值。转速稳定,噪音降至人耳不可闻范围。
# ADC模数转换
模数转换就是将模拟信号转换为数字信号,用于将电压值(模拟信号)转换为具体的数值。由于微控制器无法直接处理模拟信号,需通过ADC(模数转换器)才能将其转换为数字值。
# 模拟IO函数
# 信号输出
analogWrite(引脚编号, 脉冲宽度)
用于控制模拟输出引脚的模拟信号(电压),脉冲宽度可以是0~255之间。
这个操作可以用来控制LED的亮度,或者控制电机的转速等。
在Arduino内置的数模转换功能作,PWM引脚的0-5V电压将被映射到数值0-1023之间。我们将这一数值除以4从而得到0-255之间的数字。
如果我们写入的数值超出255,会跳到0V然后开始随着数值的增大进行增压。如我们写入的数值小于0,会跳到5V开始随着数值的减小进行减压,而不会损坏用电器。
另外写入模拟数值时,无需事先使用pinMode()函数对引脚进行设置,当然设置了也没有影响。
# 信号输入
analogRead(引脚编号)
用于读取模拟输入引脚的模拟信号(电压),并将电压通过ADC模数转换为最长10位数字信号,将10位二进制换算成十进制,也就是说支持0~1023之间的具体的数值。
模拟输入引脚编号可以使用预定义变量A0~A5,也可以直接使用对应的编号值14~19。
默认的参考电压是5V,如果此时模拟输入引脚的输入电压为2.5V,则引脚读取的数值将是2.5V / 5V * 1024 = 512。
如果模拟输入引脚处于引脚悬空,那么读到的数值将会受到多种因素影响,具有随机不确定性。
# 引脚输入配置
analogReference()
用于设置模拟输入引脚的输入范围以及解析度。
# 串行通信
# 介绍
所有Arduino控制器都有至少一个串行端口,串行端口用于Arduino板和其他设备进行通信。
在Arduino控制器通过串口通信接收数据时,板子上的RX灯会闪烁。在控制器通过串口通信发送数据时,板子上的TX灯会闪烁。
# 通信原理
在进行串行通信时,Arduino的引脚0(RX)会与设备的TX进行连接,引脚1(TX)会与设备的RX进行连接,同时两者的GND互相连接。因此在进行串口通信时,Arduino控制器的引脚0和引脚1是不能再做其他用的。
计算机可以通过USB端口与Arduino控制器进行串口通信,我们可以使用Arduino IDE中的串口监视器来与Arduino控制器进行串口通信。

数据会以高低电平的形式通过串口进行串行传输,而波特率表示限定多长时间的高低电平为1位。Arduino每一次读取串口数据都是读取1个字节=8位。
TTL标准规定5V高电平代表逻辑1,0V低电平代表逻辑0。
另外串口通信传输的位信息并非全都是数据,有些位信息是用来控制串口通信的。
# 串口接收缓存
在Arduino控制器接收到串口数据时,会将数据先暂存到串口接收缓存中,以避免打断Arduino控制器当前正在执行的操作。但接收缓存的空间是有限的,为了避免数据丢失,我们需要及时让控制器取出缓存中的数据进行处理。
# 串口通信函数
# 获取缓存数据大小
Serial.available()
该方法用于获取串口接收缓存中数据的字节大小,缓存为空则返回0。
# 读取缓存数据
Serial.read()
该方法用于取出串口接收缓存中1个字节的数据,缓存为空则返回-1。
接收的数据会是字符类型。
# 读取缓存整数数据
Serial.parseInt()
该方法会取出并解析串口数据中的整数信息,作为整数返回值。