Arduino编程参考手册
首页
程序结构
setup()
loop()
控制结构
if
if...else
for
switch case
while
do...while
break
continue
return
goto
相关语法
; 分号
{ 大括号
.else
与基本的if语句相比,由于允许多个测试组合在一起,if/else可以使用更多的控制流。例如,可以测试一个模拟量输入,如果输入值小于500,则采取一个动作,而如果输入值大于或等于500,则采取另一个动作。代码看起来像是这样:
if (pinFiveInput < 500)
{
.case通过允许程序员根据不同的条件指定不同的应被执行的代码来控制程序流。特别地,一个switch语句对一个变量的值与case语句中指定的值进行比较。当一个case语句被发现其值等于该变量的值。就会运行这个case语句下的代码。
break关键字将中止并跳出switch语句段,常常用于每个case语句的最后面。如果没有break语句,switch语句将继续执行下面的表达式(“持续下降”)直到遇到break,或者是到达switch语句的末尾。
示例:
switch (var) {
case 1:
.while
do循环
do循环与while循环使用相同方式工作,不同的是条件是在循环的末尾被测试的,所以do循环总是至少会运行一次。
do
{
.else]的分支控制结构的一部分。
布尔运算符
它们可用于if语句中的条件
&& (逻辑与)
只有在两个操作数都为真时才返回真,例如:
if (digitalRead(2) == HIGH && digitalRead(3) == HIGH) { .
}
只在两个输入都为高时返回真
|| (逻辑或)
任意一个为真时返回真,例如:
if (x > 0 || y > 0) {
.
}
x或y任意一个大于0时返回真
! (非)
当操作数为假时返回真,例如:
if (!x) {
.
}
若x为假返回真(即如果x等于0)
警告
确保你没有把布尔与运算符,&&(两个与符号)错认为按位与运算符&(单个与符号)。它们是完全不同的概念。
同样,不要混淆布尔或运算符||(双竖杠)与按位或运算符|(单竖杠)。
按位取反~(波浪号)看起来与布尔非!有很大不同(感叹号或程序员口中的“棒”),但是你仍然必须确保在什么地方用哪一个。
例如
if (a >= 10 && a <= 20){}
在a和b的16位的每一位将使用按位与处理。且所有16位结果存入C中,以二进制存入的结果值01000100,即十进制的68。
按位与的其中一个最常用的用途是从一个整型数中选择特定的位,常被称为掩码屏蔽。看如下示例:
位或
按位或(|)
在C++中按位或运算符是垂直的条杆符号,|。就像&运算符,|独立地计算它周围的两个整型表达式的每一位。(当然)它所做的是不同的(操作)。两个输入位其中一个或都是1按位或将得到1,否则为0。换句话说:
0 0 1 1 operand1
0 1 0 1 operand2
----------
0 1 1 1 (operand1 | operand2) - returned result
这是一个使用一小断C++代码描述的按位或(运算)的例子:
int a = 92;
按位与和按位或的一个共同的工作是在端口上进行程序员称之为读-改-写的操作。在微控制器中,每个端口是一个8位数字,每一位表示一个引脚的状态。写一个端口可以同时控制所有的引脚。PORTD是内建的参照数字口0,1,2,3,4,5,6,7的输出状态的常量。如果一个比特位是1,那么该引脚置高。(引脚总是需要用pinMode()指令设置为输出模式)。所以如果我们写入PORTD = B00110001;我们就会让引脚2,3和7输出高。一个小小的问题是,我们同时也改变了某些引脚的0,1状态。这用于Arduino与串口通讯,所以我们可能会干扰串口通讯。
我们的程序规则是:
仅仅获取和清除我们想控制的与相应引脚对应的位(使用按位与)。
合并要修改的PORTD值与所控制的引脚的新值(使用按位或)。
int i; .
1 << 8 == 256
1 << 9 == 512
1 << 10 == 1024
...
当把x右移y位,x的最高位为1,该行为依赖于x的确切的数据类型。如果x的类型是int,最高位为符号位,决定x是不是负数,正如我们在上面已经讨论过的。在这种情况下,符号位会复制到较低的位:
int x = -16;
复合运算符
自加++
i++; PI.
#define HALF_PI
二分之一PI
#define TWO_PI
二倍PI
#define DEG_TO_RAD
弧度转角度
#define RAD_TO_DEG
角度转弧度
整型常量
整数常量
整数常量是直接在程序中使用的数字,如123。默认情况下,这些数字被视为int,但你可以通过U 和L修饰符进行更多的限制(见下文)。通常情况下,整数常量默认为十进制,但可以加上特殊前缀表示为其他进制。
进制例子格式备注
10(十进制)123 无
2(二进制)B1111011 前缀'B' 只适用于8位的值(0到255)字符0-1有效
8(八进制)0173 前缀”0”字符0-7有效
16(十六进制)0x7B 前缀”0x”字符0-9,A-F,A-F有效
小数是十进制数。这是数学常识。如果一个数没有特定的前缀,则默认为十进制。
二进制以2为基底,只有数字0和1是有效的。
示例:
101 05; 浮点数可以用科学记数法表示。'E'和'e'都可以作为有效的指数标志。
浮点数被转换为被转换为
10
* 10^5 234000
67E-12 * 10^-12
数据类型
void
void只用在函数声明中。它表示该函数将不会被返回任何数据到它被调用的函数中。例子
.
}
void loop()
{
.
}
boolean
布尔
一个布尔变量拥有两个值,true或false。(每个布尔变量占用一个字节的内存。)例子
int LEDpin = 5; .
}
void loop()
{
int i; .
for (int j = 0; j <100; j++){
..
x = pi * 2; 78 N 110 n
15 47 / 79 O 111 o
16 48 0 80 P 112 p
17 49 1 81 Q 113 q
18 50 2 82 R 114 r
19 51 3 83 S 115 s
20 52 4 84 T 116 t
21 53 5 85 U 117 u
22 54 6 86 V 118 v
23 55 7 87 W 119 w
24 56 8 88 X 120 x
25 57 9 89 Y 121 y
26 58 : 90 Z 122 z
27 59 ; 91 [ 123 {
28 60 < 92 \ 124 |
29 61 = 93 ] 125 }
30 62 > 94 ^ 126 ~
31 63 ? 95 _ 127
基本函数
(本节由柴树杉[翻译整理]))
数字I/O
pinMode()
void pinMode (uint8_t pin, uint8_t mode)
设置引脚模式
配置引脚为输出或输出模式.
参数:
pin 引脚编号
mode: INPUT, OUTPUT, 或 INPUT_PULLUP.
例子:
int ledPin = 13;
digitalWrite()
void digitalWrite (uint8_t pin, uint8_t value)
写数字引脚
写数字引脚, 对应引脚的高低电平. 在写引脚之前, 需要将引脚设置为OUTPUT模式.参数:
pin 引脚编号
value HIGH 或 LOW
用法:
int ledPin = 13;
digitalRead()
int digitalRead (uint8_t pin)
读数字引脚
读数字引脚, 返回引脚的高低电平. 在读引脚之前, 需要将引脚设置为INPUT模式.
参数:
pin 引脚编号
返回:
HIGH或LOW
int ledPin = 13;
模拟I/O
analogReference()
void analogReference (uint8_t type)
配置参考电压
配置模式引脚的参考电压. 函数 analogRead 在读取模拟值之后, 将根据参考电压将模拟值转换到[0,1023]区间. 有以下类型:
DEFAULT : 默认5V. INTERNAL: 低功耗模式. ATmega168和ATmega8对应到. EXTERNAL: 扩展模式. 通过AREF引脚获取参考电压.
参数:
type 参考类型(DEFAULT/INTERNAL/EXTERNAL)
analogRead()
int analogRead (uint8_t pin)
读模拟引脚
读模拟引脚, 返回[0-1023]之间的值. 每读一次需要花1微妙的时间.
参数:
pin 引脚编号
返回:
0到1023之间的值
例子:
int analogPin = 3; 可以用来控制LED的亮度, 或者控制电机的转速. 在执行该操作后, 应该等待一定时间后才能对该引脚进行下一次的读或写操作. PWM的频率大约为490Hz.
在一些基于ATmega168的新的Arduino控制板(如Mini 和BT)中, 该函数支持以下引脚: 3, 5, 6, 9, 10, 11. 在基于ATmega8的型号中支持9, 10, 11引脚.
例子:
int ledPin = 9; 其中dataPin为连接DS的引脚号, clockPin为连接SH_CP的引脚号, bitOrder为设置数据位移顺序, 分别为高位先入MSBFIRST或者低位先入LSBFIRST.
参数:
dataPin 数据引脚
clockPin 时钟引脚
bitOrder 移位顺序 ( MSBFIRST 或 LSBFIRST)
val 数据
如果是 HIGH, 函数将先等引脚变为高电平, 然后开始计时, 一直到变为低电平为止. 返回脉冲持续的时间长短, 单位为毫秒. 如果超时还没有读到的话, 将返回0.
参数:
pin 引脚编号
state 脉冲状态
timeout 超时时间
下面的例子演示了统计高电平的继续时间:
int pin = 7;
unsigned long duration;
void setup()
{
pinMode(pin, INPUT);
}
void loop()
{
duration = pulseIn(pin, HIGH);
}
时间
millis()
unsigned long millis (void)
毫秒时间
获取机器运行的时间长度, 单位毫秒. 系统最长的记录时间为9小时22分, 如果超出时间将从0开始.
警告:
时间为 unsigned long类型, 如果用 int 保存时间将得到错误结果:
delay(ms)
void delay (unsigned long ms)
延时(毫秒)
延时, 单位毫秒(1秒有1000毫秒).
参数为unsigned long, 因此在延时参数超过32767(int型最大值)时, 需要用"UL"后缀表示为无符号长整型, 例如: delay(60000UL);. 同样在参数表达式, 切表达式中有int类型时, 需要强制转换为 unsigned long类型, 例如: delay((unsigned long)tdelay * 100UL);.
一下例子设置13引脚对应的LED等以1秒频率闪烁:
int ledPin = 13; 如果延时的时间有几千微妙, 那么建议使用 delay 函数. 目前参数最大支持16383微妙(不过以后的版本中可能会变化).
以下代码向第8号引脚发送脉冲, 每次脉冲持续50微妙的时间.
int outPin = 8; 例如:
sensVal = min(sensVal, 100);
max()
#define max(a, b) ((a)>(b)?(a):(b))
最大值
取两者之间最大值. 例如:
sensVal = max(senVal, 20); 一般可以用于将值归一化到某个区间.
例如:
sensVal = constrain(sensVal, 10, 150);
参数:
x 要映射的值
in_min 映射前区间
in_max 映射前区间
out_min 映射后区间
out_max 映射后区间
例如下面的代码中用 map 将模拟量从[0,1023]映射到[0,255]区间:
随机种子的设置对产生的随机序列有影响.
seed 随机种子
random()
long random (long howbig)
生成随机数
生成[0, howbig-1]范围的随机数.
参数:
howbig 最大值
long random (long howsmall, long howbig)
生成随机数
生成[howsmall, howbig-1]范围的随机数.
参数:
howsmall 最小值
howbig 最大值
位操作
位操作
#define lowByte(w) ((w) & 0xff)
外部中断有0和1两种, 一般对应2号和3号数字引脚.参数:
interrupt 中断类型, 0或1
fun 对应函数
mode 触发方式. 有以下几种:
LOW 低电平触发中断
CHANGE 变化时触发中断
RISING 低电平变为高电平触发中断
FALLING 高电平变为低电平触发中断
注解:
在中断函数中 delay 函数不能使用, millis 始终返回进入中断前的值. 读串口数据的话, 可能会丢失. 中断函数中使用的变量需要定义为 volatile 类型.
下面的例子如果通过外部引脚触发中断函数, 然后控制LED的闪烁.
int pin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}
void loop()
{
digitalWrite(pin, state);
}
void blink()
{
state = !state;
}
detachInterrupt()
void detachInterrupt (uint8_t interruptNum)
取消中断
取消指定类型的中断.
参数:
interrupt 中断的类型.
interrupts()
#define interrupts() sei()
开中断
例子:
void setup() {}
void loop()
{
noInterrupts();
发送 "Hello world."
可选的第二个参数用于指定数据的格式。允许的值为:BIN (binary二进制), OCT (octal八进制), DEC (decimal十进制), HEX (hexadecimal十六进制)。对于浮点数,该参数指定小数点的位数。例如:
(78, BIN) gives "1001110"
(78, OCT) gives "116"
(78, DEC) gives "78"
(78, HEX) gives "4E"
, 0) gives "1"
, 2) gives ""
, 4) gives ""
你可以用F()把待发送的字符串包装到flash存储器。例如:
(F(“Hello World”))
要发送单个字节数据,请使用()。
语法:
(val)
(val, format)
参数:
val: 要发送的数据(任何数据类型)
format: 指定数字的基数(用于整型数)或者小数的位数(用于浮点数)。返回值:<>
size_t (long): print()返回发送的字节数(可丢弃该返回值)。
示例:
/*
Uses a FOR loop for data and prints a number in various formats. */
int x = 0; // variable
void setup() {
(9600); // open the serial port at 9600 bps:
}
void loop() {
// print labels
("NO FORMAT"); // prints a label
("\t"); // prints a tab
("DEC");
("\t");
("HEX");
("\t");
("OCT");
("\t");
("BIN");
("\t");
for(x=0; x< 64; x++){ // only part of the ASCII chart, change to suit
// print it out in many formats:
(x); // print as an ASCII-encoded decimal - same as "DEC"
("\t"); // prints a tab
(x, DEC); // print as an ASCII-encoded decimal
("\t"); // prints a tab
(x, HEX); // print as an ASCII-encoded hexadecimal
("\t"); // prints a tab
(x, OCT); // print as an ASCII-encoded octal
("\t"); // prints a tab
(x, BIN); // print as an ASCII-encoded binary
// then adds the carriage return with "println" delay(200); // delay 200 milliseconds
}
(""); // prints another carriage return
}
编程技巧:
在版本时,串口传输是异步的,()会在数据发送完成前返回。
println()
往串口发数据,类似(),但有换行
write()
写二进制数据到串口,数据是一个字节一个字节地发送的,若以字符形式发送数字请使用print()代替。
语法:
(val)
(str)
(buf, len)
Arduino Mega也支持:Serial1, Serial2, Serial3(在Serial的位置)
参数:
val: 作为单个字节发送的数据
str: 由一系列字节组成的字符串
buf: 同一系列字节组成的数组
len: 要发送的数组的长度
返回:
byte
write()会返回发送的字节数,所以读取该返回值是可选的。
示例:
void setup(){
(9600);
}
void loop(){
(45); //以二进制形式发送数字45
int bytesSent = (“hello”); //发送字符串“hello”并返回该字符串的长度。
}
peak()
描述:
返回收到的串口数据的下一个字节(字符),但是并不把该数据从串口数据缓存中清除。就是说,每次成功调用peak()将返回相同的字符。与read()一样,peak()继承自Stream实用类。语法:可参照()
serialEvent()
描述:
当串口有数据到达时调用该函数(然后使用()捕获该数据)。
注意:目前serialEvent()并不兼容于Esplora, Leonardo, 或 Micro。
语法:
void serialEvent(){
//statements
}
Arduino Mega only:
void serialEvent1(){
//statements
}
void serialEvent2(){
//statements
}
void serialEvent3(){
//statements
}
statements可以是任何有效的语句。